public SymColor AddColorBottom(string name, short ocadId, float cyan, float magenta, float yellow, float black) { CheckWritable(); SymColor color = new SymColor(); color.Name = name; color.OcadId = ocadId; color.SetCMYK(cyan, magenta, yellow, black); colors.Insert(0, color); color.SetMap(this); symdefsDirty = true; return color; }
public LineSymDef(string name, int ocadID, SymColor color, float thick, LineStyle lineStyle) : base(name, ocadID) { lineColor = color; thickness = thick; this.lineStyle = lineStyle; }
public void SetSecondLine(SymColor secondLineColor, float secondThickness, LineStyle secondLineStyle) { CheckModifiable(); this.secondLineColor = secondLineColor; this.secondThickness = secondThickness; this.secondLineStyle = secondLineStyle; }
// Draw a set of rows of the pattern with the given rectangle void DrawPatternRows(GraphicsTarget g, RectangleF boundingRect, SymColor color, RenderOptions renderOpts) { double topLine = Math.Round(boundingRect.Top / patternHeight) * patternHeight; double bottomLine = (Math.Round(boundingRect.Bottom / patternHeight) + 0.5) * patternHeight; double leftLine = Math.Round(boundingRect.Left / patternWidth) * patternWidth; double rightLine = (Math.Round(boundingRect.Right / patternWidth) + 0.5) * patternWidth; double offsetLeftLine = leftLine - (patternWidth / 2); double offsetRightLine = rightLine + (patternWidth / 2); bool firstLineOffset = ((long) Math.Round(boundingRect.Top / patternHeight) & 1) != 0; bool offsetThisLine = offsetRows && firstLineOffset; for (double y = topLine; y <= bottomLine; y += patternHeight) { if (offsetThisLine) { for (double x = offsetLeftLine; x <= offsetRightLine; x += patternWidth) { patternGlyph.Draw(g, new PointF((float) x, (float) y), -patternAngle, GraphicsUtil.IdentityMatrix, null, color, renderOpts); } } else { for (double x = leftLine; x <= rightLine; x += patternWidth) { patternGlyph.Draw(g, new PointF((float) x, (float) y), -patternAngle, GraphicsUtil.IdentityMatrix, null, color, renderOpts); } } if (offsetRows) offsetThisLine = !offsetThisLine; } }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. public override bool HasColor(SymColor color) { // Always return true, because graphics objects could be any color! (except image layer) if (color == null) return false; else return true; }
// Draw this area symbol in the graphics inside/around the path provided, with // the given color only. internal void Draw(GraphicsTarget g, SymPathWithHoles path, SymColor color, float angle, RenderOptions renderOpts) { if (!pensAndBrushesCreated) CreatePensAndBrushes(); if (color == fillColor) { path.Fill(g, color.Brush); } if (hatchMode != 0 && hatchColor == color) { DrawHatching(g, path, angle, renderOpts); } if (drawPattern && patternGlyph.HasColor(color)) { // Faster to draw the pattern with a texture brush that has a bitmap // of the pattern in it. Better quality to do it all with glyph drawing. // Choose based on the renderOptions. #if false DrawPatternWithTexBrush(g, path, angle, color, renderOpts); #else if (renderOpts.usePatternBitmaps) { CreatePatternBrush(renderOpts.minResolution); DrawPatternWithTexBrush(g, path, angle, color, renderOpts); } else DrawPattern(g, path, angle, color, renderOpts); #endif } // Draw the border. Take into account the subpaths defined by start/stop flags along the paths. if (borderSymdef != null && borderSymdef.HasColor(color)) { // Draw main part of border. foreach (SymPath subpath in path.MainPath.GetSubpaths(SymPath.AREA_BOUNDARY_STARTSTOPFLAG)) borderSymdef.Draw(g, subpath, color, renderOpts); // Draw the holes. if (path.Holes != null) foreach (SymPath hole in path.Holes) foreach (SymPath subpath in hole.GetSubpaths(SymPath.AREA_BOUNDARY_STARTSTOPFLAG)) borderSymdef.Draw(g, subpath, color, renderOpts); } }
// Draw an underline under the text, if applicable. private void DrawUnderline(GraphicsTarget g, SymColor color, float baseline, float width, float indent) { if (underline.underlineOn && color == underline.underlineColor) { // Figure out the left and right sides of the underline. float l, r; if (fontAlign == TextSymDefAlignment.Right) l = -width; else if (fontAlign == TextSymDefAlignment.Center) l = -(width / 2F); else l = indent; r = l + width; // figure out y coordinate of line. float y = baseline + underline.underlineDistance + underline.underlineWidth / 2; // draw the line. g.DrawLine(underlinePen, new PointF(l, y), new PointF(r, y)); } }
public void GetHatching(out int hatchMode, out SymColor hatchColor, out float hatchWidth, out float hatchSpacing, out float angle1, out float angle2) { hatchMode = this.hatchMode; hatchColor = this.hatchColor; hatchWidth = this.hatchWidth; hatchSpacing = this.hatchSpacing; angle1 = this.hatchAngle1; angle2 = this.hatchAngle2; }
// Draw this point symbol at point pt with angle ang in this graphics (given color only). internal void Draw(GraphicsTarget g, PointF pt, float angle, float[] gaps, SymColor color, RenderOptions renderOpts) { glyph.Draw(g, pt, angle, GraphicsUtil.IdentityMatrix, gaps, color, renderOpts); }
// Draw the glyphs along the path. "longPath" is the same as path unless shortening of the ends has occurred, in which case // path is the shortened path (used for all glyphs except start and end), and longPath is used for the start and end. private void DrawGlyphs(GraphicsTarget g, GlyphInfo glyphInfo, SymPath path, SymPath longPath, SymColor color, RenderOptions renderOpts) { float[] distances; PointF[] points; float[] perpAngles, subtendedAngles; float firstDistance; // Figure out the distances of the glyphs along the line. switch (glyphInfo.location) { case GlyphLocation.Corners: // Corner points are done somewhat differently. Only can have 1 symbol. // There is an interesting feature in OCAD where the dimensions of corner glyphs are stretched a certain amount at // very acute angles. This is so that power line crossbars always extend beyond the power lines themselves. // This is handled by stretching the glyph based on the subtended angle at the corner. points = path.FindCornerPoints(out perpAngles, out subtendedAngles); if (points != null) { for (int i = 0; i < points.Length; ++i) { float subtendedAngle = subtendedAngles[i]; float stretch; if (subtendedAngle != 0) stretch = Util.MiterFactor(subtendedAngle); else stretch = 1.0F; stretch = Math.Min(stretch, CORNER_GLYPH_STRETCH_LIMIT); Matrix stretchMatrix = new Matrix(); stretchMatrix.Scale(1.0F, stretch); glyphInfo.glyph.Draw(g, points[i], perpAngles[i] + 90.0F, stretchMatrix, null, color, renderOpts); } } return; case GlyphLocation.Spaced: distances = ComputeDashDistances(path, LocationKind.GapCenters, glyphInfo.distance, glyphInfo.firstDistance, glyphInfo.lastDistance, 0, glyphInfo.minimum, 0, 0, 0, 0, 0, 1.0F, false); break; case GlyphLocation.SpacedOffset: distances = ComputeDashDistances(path, LocationKind.GapCentersOffset, glyphInfo.distance, glyphInfo.firstDistance, glyphInfo.lastDistance, 0, glyphInfo.minimum, glyphInfo.offset, 0, 0, 0, 0, 1.0F, false); break; case GlyphLocation.SpacedDecrease: distances = ComputeDashDistances(path, LocationKind.GapCentersDecrease, glyphInfo.distance, glyphInfo.firstDistance, glyphInfo.lastDistance, 0, glyphInfo.minimum, 0, 0, 0, 0, 0, glyphInfo.decreaseLimit, glyphInfo.decreaseBothEnds); if (distances != null && distances.Length > 0) { firstDistance = distances[0]; for (int n = 0; n < glyphInfo.number; ++n) { distances[0] = Math.Max(0.0F, firstDistance - ((glyphInfo.number - 1 - n * 2) * (glyphInfo.spacing / 2.0F))); points = path.FindPointsAlongLineBizzarro(distances, out perpAngles); for (int i = 0; i < points.Length; ++i) { float decreaseFactor; if (glyphInfo.decreaseBothEnds) { if (points.Length <= 2) decreaseFactor = glyphInfo.decreaseLimit; else decreaseFactor = 1.0F - (Math.Abs(i - ((points.Length-1) / 2F)) * (1 - glyphInfo.decreaseLimit) / ((points.Length-1) / 2F)); } else { if (i == 0) decreaseFactor = 1.0F; else decreaseFactor = 1.0F - (i * (1 - glyphInfo.decreaseLimit) / (points.Length - 1)); } Matrix matrixTransform = new Matrix(); matrixTransform.Scale(decreaseFactor, decreaseFactor); glyphInfo.glyph.Draw(g, points[i], perpAngles[i], matrixTransform, null, color, renderOpts); } } } return; case GlyphLocation.DashCenters: distances = ComputeDashDistances(path, LocationKind.DashCenters, dashInfo.dashLength, dashInfo.firstDashLength, dashInfo.lastDashLength, dashInfo.gapLength, dashInfo.minGaps, 0, 0, 0, 0, 0, 1.0F, false); break; case GlyphLocation.MiddleDashCenters: distances = ComputeDashDistances(path, LocationKind.MiddleDashCenters, dashInfo.dashLength, dashInfo.firstDashLength, dashInfo.lastDashLength, dashInfo.gapLength, dashInfo.minGaps, 0, 0, 0, 0, 0, 1.0F, false); break; case GlyphLocation.GapCenters: // OCAD doesn't respect the "0 minimum gaps" for the symbols, although it does for the gaps. Always have at least one symbol. This is handled on import by having glyphInfo.minimum be 1. distances = ComputeDashDistances(path, LocationKind.GapCenters, dashInfo.dashLength, dashInfo.firstDashLength, dashInfo.lastDashLength, dashInfo.gapLength, Math.Max(glyphInfo.minimum, dashInfo.minGaps), 0, 0, 0, 0, 0, 1.0F, false); break; case GlyphLocation.Start: distances = new float[1] { 0 }; break; case GlyphLocation.End: distances = new float[1] { longPath.BizzarroLength }; break; default: Debug.Fail("bad glyph location"); return; } if (distances == null || distances.Length == 0) return; firstDistance = distances[0]; for (int n = 0; n < glyphInfo.number; ++n) { distances[0] = Math.Max(0.0F, firstDistance - ((glyphInfo.number - 1 - n * 2) * (glyphInfo.spacing / 2.0F))); if (glyphInfo.location == GlyphLocation.Start || glyphInfo.location == GlyphLocation.End) points = longPath.FindPointsAlongLineBizzarro(distances, out perpAngles); else points = path.FindPointsAlongLineBizzarro(distances, out perpAngles); for (int i = 0; i < points.Length; ++i) { glyphInfo.glyph.Draw(g, points[i], perpAngles[i], GraphicsUtil.IdentityMatrix, null, color, renderOpts); } } }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. public override bool HasColor(SymColor color) { if (color == null) return false; return glyph.HasColor(color); }
float pixelSizeCached; // pixel size in mm that the patternBrushes are created for. (WPF brushes are resolution independent). #endif #region Constructors public AreaSymDef(string name, int ocadID, SymColor color, LineSymDef borderSymdef) : base(name, ocadID) { fillColor = color; this.borderSymdef = borderSymdef; }
// Draw a particular color layer. If curColor is null, draw the image layer. private void DrawColor(GraphicsTarget g, SymColor curColor, RectangleF rect, bool clipRegionIsRectangle, RenderOptions renderOpts) { foreach (SymDef symdef in symdefs) { if (IsSymdefVisible(symdef) && symdef.HasColor(curColor)) { foreach (Symbol curSym in symdef.symbols) { // Only draw the symbol if it may intersect. Check // the bounding box first as it's faster exclusion than MayIntersectRect. RectangleF bounds = curSym.BoundingBox; if (bounds.IntersectsWith(rect) && #if true (clipRegionIsRectangle || g.Graphics.IsVisible(Util.InflateRect(bounds, renderOpts.minResolution))) && #endif curSym.MayIntersectRect(rect)) { curSym.Draw(g, curColor, renderOpts); if (renderOpts.showSymbolBounds) g.DrawRectangle(boundsPen, bounds); } } } } //TraceLine("Drawing color {0}: drew {1} of {2} symbols.", curColor, cDrawn, cSymbols); }
// Determine which symdefs use a color. public SymDef[] SymdefsUsingColor(SymColor color) { CheckReadable(); List<SymDef> list = new List<SymDef>(); foreach (SymDef symdef in symdefs) { if (symdef.HasColor(color)) list.Add(symdef); } if (list.Count > 0) return list.ToArray(); else return null; }
// Draw this text symbol along a path. internal void DrawTextOnPath(GraphicsTarget g, SymPath path, string text, SymColor color, RenderOptions renderOpts) { if (color == null) return; if (color != fontColor && (framing.framingStyle == FramingStyle.None || color != framing.framingColor)) return; if (!objectsCreated) CreateObjects(); // Get the location of each grapheme to print. List<GraphemePlacement> graphemeList = GetLineTextGraphemePlacement(path, text); PointF topAscentPoint = new PointF(0, -FontAscent); // Drawing is relative to top of char, we want to draw at baseline. foreach (GraphemePlacement grapheme in graphemeList) { object graphicsState; graphicsState = g.Save(); try { // Move location to draw at to the origin, set angle for drawing text. Matrix matrix = GraphicsUtil.TranslationMatrix(grapheme.pointStart.X, grapheme.pointStart.Y); matrix = GraphicsUtil.Multiply(GraphicsUtil.ScalingMatrix(1, -1), matrix); // Reverse Y so text is correct way aroun matrix = GraphicsUtil.Multiply(GraphicsUtil.RotationMatrix(-grapheme.angle, new PointF(0,0)), matrix); g.Transform(matrix); DrawStringWithEffects(g, color, grapheme.grapheme, topAscentPoint); } finally { g.Restore(graphicsState); // restore transform } } }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. // If color is null, return if draws in the image layer (below all color layers). public abstract bool HasColor(SymColor color);
// Draw the framing rectangle around some text. The top of the text is at 0, and the bottom baseline of text is at "bottomOfText". private void DrawFramingRectangle(GraphicsTarget g, float[] lineWidths, float fullWidth, SymColor color, float bottomOfText) { if (framing.framingStyle == FramingStyle.Rectangle && color == framing.framingColor) { // First, figure out the width of the rectangle. If fullWidth is zero, used the maximum line width. fullWidth = CalcFullWidth(lineWidths, fullWidth); // Next, figure out the rectangle, not counting padding. float l, t, r, b; if (fontAlign == TextSymDefAlignment.Right) l = -fullWidth; else if (fontAlign == TextSymDefAlignment.Center) l = -(fullWidth / 2F); else l = 0; r = l + fullWidth; t = FontAscent - WHeight; // Place the top of the rectangle at top of letter "W", not top of accents. b = bottomOfText; // Add padding. t -= framing.rectBorderTop; b += framing.rectBorderBottom; l -= framing.rectBorderLeft; r += framing.rectBorderRight; // Draw the rectangle g.FillRectangle(color.Brush, new RectangleF(l, t, r - l, b - t)); } }
protected void CheckColor(SymColor color) { if (color != null && color.ContainingMap != map) throw new MapUsageException("Color in SymDef is not part of the containing map"); }
// Draw a string with shadow or line framing effects, if specified. The font from this symdef is used. private void DrawStringWithEffects(GraphicsTarget g, SymColor color, string text, PointF pt) { if (color == fontColor) { DrawSingleLineString(g, text, fontColor.Brush, pt); } if (framing.framingStyle != FramingStyle.None && color == framing.framingColor) { if (framing.framingStyle == FramingStyle.Line) { #if false FormattedText formattedText = new FormattedText(text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black); Geometry geometry = formattedText.BuildGeometry(new Point(pt.X, pt.Y)); foreach (Pen p in framingPens) g.DrawingContext.DrawGeometry(null, p, geometry); #else GraphicsPath grPath = new GraphicsPath(FillMode.Winding); Debug.Assert(font.Unit == GraphicsUnit.World); grPath.AddString(text, font.FontFamily, (int) font.Style, font.Size, pt, stringFormat); foreach (Pen p in framingPens) g.Graphics.DrawPath(p, grPath); #endif } else if (framing.framingStyle == FramingStyle.Shadow) { DrawSingleLineString(g, text, framing.framingColor.Brush, new PointF(pt.X + framing.shadowX, pt.Y - framing.shadowY)); } } }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. public override bool HasColor(SymColor color) { if (color == null) return false; return (color == fillColor) || (hatchMode != 0 && hatchColor == color) || (drawPattern && patternGlyph.HasColor(color)) || (borderSymdef != null && borderSymdef.HasColor(color)); }
// Draw the pattern (at the given angle) inside the path. void DrawPattern(GraphicsTarget g, SymPathWithHoles path, float angle, SymColor color, RenderOptions renderOpts) { object graphicsState = g.Save(); try { // Set the clipping region to draw only inside the area. g.SetClip(path); // use a transform to rotate Matrix matrix = GraphicsUtil.RotationMatrix(patternAngle + angle, new PointF(0, 0)); g.Transform(matrix); // Get the correct bounding rect. RectangleF bounding = Util.BoundsOfRotatedRectangle(path.BoundingBox, new PointF(), -(patternAngle + angle)); DrawPatternRows(g, bounding, color, renderOpts); } finally { // restore the clip region and the transform g.Restore(graphicsState); } }
public void SetHatching(int hatchMode, SymColor hatchColor, float hatchWidth, float hatchSpacing, float angle1, float angle2) { CheckModifiable(); if (hatchMode < 0 || hatchMode > 2) throw new ArgumentOutOfRangeException("hatchMode", "hatching mode must be 0, 1, 2"); this.hatchMode = hatchMode; this.hatchColor = hatchColor; this.hatchWidth = hatchWidth; this.hatchSpacing = hatchSpacing; this.hatchAngle1 = angle1; this.hatchAngle2 = angle2; }
// Draw the pattern using the texture brush. void DrawPatternWithTexBrush(GraphicsTarget g, SymPathWithHoles path, float angle, SymColor color, RenderOptions renderOpts) { Brush brush = (Brush) patternBrushes[color]; Debug.Assert(brush != null); if (angle != 0.0F) { object graphicsState = g.Save(); try { // Set the clipping region to draw only inside the area. g.SetClip(path); // use a transform to rotate. Matrix matrix = GraphicsUtil.RotationMatrix(angle, new PointF(0, 0)); g.Transform(matrix); // Get the correct bounding rect. RectangleF bounding = Util.BoundsOfRotatedRectangle(path.BoundingBox, new PointF(), -angle); g.FillRectangle(brush, bounding); } finally { // restore the clip region and the transform g.Restore(graphicsState); } } else { path.Fill(g, brush); } }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. public override bool HasColor(SymColor color) { if (color == null) return false; return color == fontColor || (framing.framingStyle != FramingStyle.None && color == framing.framingColor) || (underline.underlineOn && color == underline.underlineColor); }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. public override bool HasColor(SymColor color) { return (color == null); // only draw in the image layer. }
public void SetFont(string fontName, float fontSize, bool bold, bool italic, SymColor fontColor, float lineSpacing, float paraSpacing, float firstIndent, float restIndent, float[] tabs, float charSpacing, float wordSpacing, TextSymDefAlignment fontAlign) { CheckModifiable(); this.fontName = fontName; this.fontSize = fontSize; this.bold = bold; this.italic = italic; this.fontColor = fontColor; this.lineSpacing = lineSpacing; this.paraSpacing = paraSpacing; this.firstIndent = firstIndent; this.restIndent = restIndent; this.charSpacing = charSpacing; this.wordSpacing = wordSpacing; this.fontAlign = fontAlign; this.tabs = tabs; }
// Does this symbol definition draw the given color. Used to determine // if this symbol definition draws into the current layer being draw. public override bool HasColor(SymColor color) { if (color == null) return false; if ((color == lineColor && thickness > 0.0F) || (color == secondLineColor && secondThickness > 0.0F) || (isDoubleLine && doubleLines.doubleFillColor == color) || (isDoubleLine && doubleLines.doubleLeftWidth > 0.0F && doubleLines.doubleLeftColor == color) || (isDoubleLine && doubleLines.doubleRightWidth > 0.0F && doubleLines.doubleRightColor == color)) { return true; } if (glyphs != null) { foreach (GlyphInfo glyphInfo in glyphs) { if (glyphInfo.glyph.HasColor(color)) return true; } } return false; }
// Draw this text symbol at point pt with angle ang in this graphics (given color only). internal void Draw(GraphicsTarget g, string[] text, float[] lineWidths, PointF location, float angle, float fullWidth, SymColor color, RenderOptions renderOpts) { if (color == null) return; if (color != fontColor && (framing.framingStyle == FramingStyle.None || color != framing.framingColor) && (!underline.underlineOn || color != underline.underlineColor)) return; if (!objectsCreated) CreateObjects(); // Move location to draw at to the origin. object graphicsState = g.Save(); Matrix matrix = GraphicsUtil.TranslationMatrix(location.X, location.Y); matrix = GraphicsUtil.Multiply(GraphicsUtil.ScalingMatrix(1, -1), matrix); // Reverse Y direction so text is correct way around. if (angle != 0) matrix = GraphicsUtil.Multiply(GraphicsUtil.RotationMatrix(-angle, new PointF(0,0)), matrix); g.Transform(matrix); try { // Draw all the lines of text. PointF pt = new PointF(0F, 0F); float baselineOfLine = 0; // y coordinate of baseline of line. bool firstLineOfPara = true, lastLineOfPara; for (int lineIndex = 0; lineIndex < text.Length; ++lineIndex) { string line = text[lineIndex]; float lineWidth = lineWidths[lineIndex]; lastLineOfPara = (lineIndex == text.Length - 1 || text[lineIndex + 1] == ParagraphMark); // are we on the last line of a paragraph? if (line == ParagraphMark) { pt.Y += paraSpacing; firstLineOfPara = true; } else { float indent = 0; float leftEdge; // tabs are relative to this X position. if (fontAlign == TextSymDefAlignment.Right) pt.X = leftEdge = -lineWidth; else if (fontAlign == TextSymDefAlignment.Center) pt.X = leftEdge = -(lineWidth / 2F); else { leftEdge = 0; pt.X = indent = firstLineOfPara ? firstIndent : restIndent; // indents only used for left align or justified } // Get the size of spaces. Justification is done by adjusting this. float sizeOfSpace = wordSpacing * spaceWidth; // basic width of spaces as set by the symdef if (fontAlign == TextSymDefAlignment.Justified && !lastLineOfPara && fullWidth > 0) sizeOfSpace += JustifyText(line, lineWidth, fullWidth - indent); // Draw all the text segments in the line. (A text segment is a word, unless charSpacing>0, in which case it is graphemes). int index = 0; for (; ; ) { string textSegment; if (charSpacing > 0) textSegment = StringInfo.GetNextTextElement(line.Substring(index)); else textSegment = GetNextTextSegment(line.Substring(index)); if (string.IsNullOrEmpty(textSegment)) break; if (textSegment == " ") pt.X += sizeOfSpace; else if (textSegment == "\t") pt.X += WidthOfTextSegment("\t", pt.X - leftEdge); else { DrawStringWithEffects(g, color, textSegment, pt); pt.X += MeasureStringWidth(textSegment); if (charSpacing > 0) pt.X += charSpacing * spaceWidth; } index += textSegment.Length; } baselineOfLine = pt.Y + FontAscent; // Set the bottom of the text. if (lastLineOfPara) DrawUnderline(g, color, baselineOfLine, Math.Max(fullWidth, lineWidth), (fullWidth == 0) ? indent : 0); pt.Y += lineSpacing; firstLineOfPara = false; } } // Draw the framing rectangle, if any. if (underline.underlineOn) baselineOfLine += underline.underlineDistance + underline.underlineWidth; DrawFramingRectangle(g, lineWidths, fullWidth, color, baselineOfLine); } finally { g.Restore(graphicsState); } }
// Draw this line symbol in the graphics along the path provided, with // the given color only. internal void Draw(GraphicsTarget g, SymPath path, SymColor color, RenderOptions renderOpts) { Debug.Assert(map != null); if (path.Length == 0) return; // Don't draw anything for a zero-length path. if (!pensCreated) CreatePens(); SymPath mainPath = path; // the path for the main part of the line (might be shortened). if (shortenInfo.shortenBeginning > 0.0F || shortenInfo.shortenEnd > 0.0F) { mainPath = path.ShortenBizzarro(shortenInfo.shortenBeginning, shortenInfo.shortenEnd); // NOTE: mainPath can be NULL below here!!! } if (color == lineColor && thickness > 0.0F && mainPath != null) { if (!isDashed) { // simple drawing. mainPath.Draw(g, mainPen); } else { // Draw the dashed line. DrawDashed(g, mainPath, mainPen, dashInfo, renderOpts); } } // Draw the pointy ends of the line. If mainPath is null, this is all the line! if (color == lineColor && shortenInfo.pointyEnds && thickness > 0.0F && (shortenInfo.shortenBeginning > 0.0F || shortenInfo.shortenEnd > 0.0F)) DrawPointyEnds(g, path, shortenInfo.shortenBeginning, shortenInfo.shortenEnd, thickness); if (color == secondLineColor && secondThickness > 0.0F && path != null) { // note that shortened path not used for secondary line, the full length path is. path.Draw(g, secondPen); } // Double lines don't use the shortened path, but the full-length path. if (isDoubleLine) { if (doubleLines.doubleFillColor == color) { if (doubleLines.doubleFillDashed) DrawDashed(g, path, doubleFillPen, doubleLines.doubleDashes, renderOpts); else path.Draw(g, doubleFillPen); } if (doubleLines.doubleLeftColor == color && doubleLines.doubleLeftWidth > 0.0F) { foreach (SymPath subpath in path.GetSubpaths(SymPath.DOUBLE_LEFT_STARTSTOPFLAG)) { float offsetRight = -(doubleLines.doubleThick + doubleLines.doubleLeftWidth) / 2F; if (doubleLines.doubleLeftDashed) { DrawDashedWithOffset(g, subpath, doubleLeftPen, doubleLines.doubleDashes, offsetRight, GraphicsUtil.MITER_LIMIT, renderOpts); } else { SymPath leftPath = subpath.OffsetRight(offsetRight, GraphicsUtil.MITER_LIMIT); leftPath.Draw(g, doubleLeftPen); } } } if (doubleLines.doubleRightColor == color && doubleLines.doubleRightWidth > 0.0F) { foreach (SymPath subpath in path.GetSubpaths(SymPath.DOUBLE_RIGHT_STARTSTOPFLAG)) { float offsetRight = (doubleLines.doubleThick + doubleLines.doubleRightWidth) / 2F; if (doubleLines.doubleRightDashed) { DrawDashedWithOffset(g, subpath, doubleRightPen, doubleLines.doubleDashes, offsetRight, GraphicsUtil.MITER_LIMIT, renderOpts); } else { SymPath rightPath = subpath.OffsetRight(offsetRight, GraphicsUtil.MITER_LIMIT); rightPath.Draw(g, doubleRightPen); } } } } if (glyphs != null && mainPath != null) { foreach (GlyphInfo glyphInfo in glyphs) { if (glyphInfo.glyph.HasColor(color)) DrawGlyphs(g, glyphInfo, mainPath, path, color, renderOpts); } } }
public SymColor AddColor(string name, short ocadId, float red, float green, float blue) { CheckWritable(); SymColor color = new SymColor(); color.Name = name; color.OcadId = ocadId; color.SetRGB(red, green, blue); colors.Add(color); color.SetMap(this); symdefsDirty = true; return color; }