public static void DrawTo(Graphics2D graphics2D, Mesh meshToDraw, Vector2 offset, double scale, RGBA_Bytes silhouetteColor) { graphics2D.Rasterizer.gamma(new gamma_power(.3)); PathStorage polygonProjected = new PathStorage(); foreach (Face face in meshToDraw.Faces) { if (face.normal.z > 0) { polygonProjected.remove_all(); bool first = true; foreach (FaceEdge faceEdge in face.FaceEdges()) { Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y); position += offset; position *= scale; if (first) { polygonProjected.MoveTo(position.x, position.y); first = false; } else { polygonProjected.LineTo(position.x, position.y); } } graphics2D.Render(polygonProjected, silhouetteColor); } } graphics2D.Rasterizer.gamma(new gamma_none()); }
public static PathStorage PolygonToPathStorage(Polygons polygons) { PathStorage output = new PathStorage(); foreach (Polygon polygon in polygons) { bool first = true; foreach (IntPoint point in polygon) { if (first) { output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandMoveTo); first = false; } else { output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandLineTo); } } output.ClosePolygon(); } output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop); return output; }
private void CheckTestAgainstControl(IVertexSource testVertexSource, string testTypeString) { // there is an assumtion that we got to save valid vertex lists at least once. string controlFileTxt = testTypeString + " Control.Txt"; string vertexSourceFolder = "ControlVertexSources"; PathStorage controlVertexSource = new PathStorage(); if (!Directory.Exists(vertexSourceFolder)) { Directory.CreateDirectory(vertexSourceFolder); } string controlPathAndFileName = Path.Combine(vertexSourceFolder, controlFileTxt); if (File.Exists(controlPathAndFileName)) { VertexSourceIO.Load(controlVertexSource, controlPathAndFileName); // this test the old vertex getting code { string testOldToOldFailPathAndFileName = Path.Combine(vertexSourceFolder, testTypeString + " Test Old Fail.Txt"); bool testOldToOldIsSameAsControl = controlVertexSource.Equals(testVertexSource, oldStyle: true); if (!testOldToOldIsSameAsControl) { // this VertexSource will be in the current output folder inside of VertexSourceFolder VertexSourceIO.Save(testVertexSource, testOldToOldFailPathAndFileName, oldStyle: true); } else if (File.Exists(testOldToOldFailPathAndFileName)) { // we don't want to have these confounding our results. File.Delete(testOldToOldFailPathAndFileName); } Assert.IsTrue(testOldToOldIsSameAsControl); } // this test the new vertex generator code if (true) { string testOldToNewFailPathAndFileName = Path.Combine(vertexSourceFolder, testTypeString + " Test New Fail.Txt"); bool testOldToNewIsSameAsControl = controlVertexSource.Equals(testVertexSource, oldStyle: false); if (!testOldToNewIsSameAsControl) { // this VertexSource will be in the current output folder inside of VertexSourceFolder VertexSourceIO.Save(testVertexSource, testOldToNewFailPathAndFileName, oldStyle: false); } else if (File.Exists(testOldToNewFailPathAndFileName)) { // we don't want to have these confounding our results. File.Delete(testOldToNewFailPathAndFileName); } Assert.IsTrue(testOldToNewIsSameAsControl); } // If you want to create new control VertexSources select SetNextStatement to inside the else condition to creat them. } else { VertexSourceIO.Save(testVertexSource, controlPathAndFileName); } }
public void join_path(PathStorage vs, int path_id) { double x, y; vs.rewind(path_id); ShapePath.FlagsAndCommand PathAndFlags = vs.vertex(out x, out y); if (!ShapePath.is_stop(PathAndFlags)) { if (ShapePath.is_vertex(PathAndFlags)) { double x0, y0; ShapePath.FlagsAndCommand PathAndFlags0 = last_vertex(out x0, out y0); if (ShapePath.is_vertex(PathAndFlags0)) { if (agg_math.calc_distance(x, y, x0, y0) > agg_math.vertex_dist_epsilon) { if (ShapePath.is_move_to(PathAndFlags)) { PathAndFlags = ShapePath.FlagsAndCommand.CommandLineTo; } vertices.AddVertex(x, y, PathAndFlags); } } else { if (ShapePath.is_stop(PathAndFlags0)) { PathAndFlags = ShapePath.FlagsAndCommand.CommandMoveTo; } else { if (ShapePath.is_move_to(PathAndFlags)) { PathAndFlags = ShapePath.FlagsAndCommand.CommandLineTo; } } vertices.AddVertex(x, y, PathAndFlags); } } while (!ShapePath.is_stop(PathAndFlags = vs.vertex(out x, out y))) { vertices.AddVertex(x, y, ShapePath.is_move_to(PathAndFlags) ? ShapePath.FlagsAndCommand.CommandLineTo : PathAndFlags); } } }
public static void Load(PathStorage vertexSource, string pathAndFileName) { vertexSource.remove_all(); string[] allLines = File.ReadAllLines(pathAndFileName); foreach (string line in allLines) { string[] elements = line.Split(','); double x = double.Parse(elements[0]); double y = double.Parse(elements[1]); ShapePath.FlagsAndCommand flagsAndCommand = (ShapePath.FlagsAndCommand)System.Enum.Parse(typeof(ShapePath.FlagsAndCommand), elements[2].Trim()); for (int i = 3; i < elements.Length; i++) { flagsAndCommand |= (ShapePath.FlagsAndCommand)System.Enum.Parse(typeof(ShapePath.FlagsAndCommand), elements[i].Trim()); } vertexSource.Add(x, y, flagsAndCommand); } }
public static bool get_bounding_rect(PathStorage vs, int[] gi, int start, int num, out double x1, out double y1, out double x2, out double y2) { int i; double x = 0; double y = 0; bool first = true; x1 = 1; y1 = 1; x2 = 0; y2 = 0; for (i = 0; i < num; i++) { vs.rewind(gi[start + i]); ShapePath.FlagsAndCommand PathAndFlags; while (!ShapePath.is_stop(PathAndFlags = vs.vertex(out x, out y))) { if (ShapePath.is_vertex(PathAndFlags)) { if (first) { x1 = x; y1 = y; x2 = x; y2 = y; first = false; } else { if (x < x1) x1 = x; if (y < y1) y1 = y; if (x > x2) x2 = x; if (y > y2) y2 = y; } } } } return x1 <= x2 && y1 <= y2; }
public override void OnDraw(Graphics2D graphics2D) { GammaLookUpTable gamma = new GammaLookUpTable(gammaSlider.Value); IRecieveBlenderByte NormalBlender = new BlenderBGR(); IRecieveBlenderByte GammaBlender = new BlenderGammaBGR(gamma); ImageBuffer rasterNormal = new ImageBuffer(); rasterNormal.Attach(graphics2D.DestImage, NormalBlender); ImageBuffer rasterGamma = new ImageBuffer(); rasterGamma.Attach(graphics2D.DestImage, GammaBlender); ImageClippingProxy clippingProxyNormal = new ImageClippingProxy(rasterNormal); ImageClippingProxy clippingProxyGamma = new ImageClippingProxy(rasterGamma); clippingProxyNormal.clear(new RGBA_Floats(1, 1, 1)); ScanlineRasterizer ras = new ScanlineRasterizer(); scanline_unpacked_8 sl = new scanline_unpacked_8(); int size_mul = (int)pixelSizeSlider.Value; renderer_enlarged ren_en = new renderer_enlarged(size_mul); StyledTypeFace type = new StyledTypeFace(LiberationSansFont.Instance, 12); IVertexSource character = type.GetGlyphForCharacter('E'); character.rewind(0); ras.reset(); ras.add_path(character); ren_en.RenderSolid(clippingProxyGamma, ras, sl, RGBA_Bytes.Black); ScanlineRenderer scanlineRenderer = new ScanlineRenderer(); scanlineRenderer.RenderSolid(clippingProxyGamma, ras, sl, RGBA_Bytes.Black); ras.gamma(new gamma_none()); PathStorage ps = new PathStorage(); Stroke pg = new Stroke(ps); pg.width(2); DrawBigA(graphics2D); base.OnDraw(graphics2D); }
private PathStorage CombinePaths(IVertexSource a, IVertexSource b, ClipType clipType) { List<List<IntPoint>> aPolys = CreatePolygons(a); List<List<IntPoint>> bPolys = CreatePolygons(b); Clipper clipper = new Clipper(); clipper.AddPaths(aPolys, PolyType.ptSubject, true); clipper.AddPaths(bPolys, PolyType.ptClip, true); List<List<IntPoint>> intersectedPolys = new List<List<IntPoint>>(); clipper.Execute(clipType, intersectedPolys); PathStorage output = new PathStorage(); foreach (List<IntPoint> polygon in intersectedPolys) { bool first = true; foreach (IntPoint point in polygon) { if (first) { output.Add(point.X / 1000.0, point.Y / 1000.0, ShapePath.FlagsAndCommand.CommandMoveTo); first = false; } else { output.Add(point.X / 1000.0, point.Y / 1000.0, ShapePath.FlagsAndCommand.CommandLineTo); } } output.ClosePolygon(); } output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop); return output; }
public static PathStorage CreatePathStorage(List<List<IntPoint>> intersectedPolys, double scaling = 1000) { PathStorage output = new PathStorage(); foreach (List<IntPoint> polygon in intersectedPolys) { bool first = true; foreach (IntPoint point in polygon) { if (first) { output.Add(point.X / scaling, point.Y / scaling, ShapePath.FlagsAndCommand.CommandMoveTo); first = false; } else { output.Add(point.X / scaling, point.Y / scaling, ShapePath.FlagsAndCommand.CommandLineTo); } } output.ClosePolygon(); } return output; }
protected override void DoDrawDirectionalArrow(Graphics2D graphics2D) { PathStorage littleArrow = new PathStorage(); if (this.MenuDirection == Direction.Down) { littleArrow.MoveTo(-4, 0); littleArrow.LineTo(4, 0); littleArrow.LineTo(0, -5); } else if (this.MenuDirection == Direction.Up) { littleArrow.MoveTo(-4, -5); littleArrow.LineTo(4, -5); littleArrow.LineTo(0, 0); } else { throw new NotImplementedException("Pulldown direction has not been implemented"); } if (!hasText) { if (UnderMouseState != UI.UnderMouseState.NotUnderMouse) { graphics2D.Render(littleArrow, LocalBounds.Right / 2, LocalBounds.Bottom + Height / 2 + 4, NormalArrowColor); } else { graphics2D.Render(littleArrow, LocalBounds.Right / 2, LocalBounds.Bottom + Height / 2 + 4, HoverArrowColor); } } else { base.DoDrawDirectionalArrow(graphics2D); } }
private void make_arrows(PathStorage ps) { ps.remove_all(); ps.MoveTo(1330.599999999999909, 1282.399999999999864); ps.LineTo(1377.400000000000091, 1282.399999999999864); ps.LineTo(1361.799999999999955, 1298.000000000000000); ps.LineTo(1393.000000000000000, 1313.599999999999909); ps.LineTo(1361.799999999999955, 1344.799999999999955); ps.LineTo(1346.200000000000045, 1313.599999999999909); ps.LineTo(1330.599999999999909, 1329.200000000000045); ps.ClosePolygon(); ps.MoveTo(1330.599999999999909, 1266.799999999999955); ps.LineTo(1377.400000000000091, 1266.799999999999955); ps.LineTo(1361.799999999999955, 1251.200000000000045); ps.LineTo(1393.000000000000000, 1235.599999999999909); ps.LineTo(1361.799999999999955, 1204.399999999999864); ps.LineTo(1346.200000000000045, 1235.599999999999909); ps.LineTo(1330.599999999999909, 1220.000000000000000); ps.ClosePolygon(); ps.MoveTo(1315.000000000000000, 1282.399999999999864); ps.LineTo(1315.000000000000000, 1329.200000000000045); ps.LineTo(1299.400000000000091, 1313.599999999999909); ps.LineTo(1283.799999999999955, 1344.799999999999955); ps.LineTo(1252.599999999999909, 1313.599999999999909); ps.LineTo(1283.799999999999955, 1298.000000000000000); ps.LineTo(1268.200000000000045, 1282.399999999999864); ps.ClosePolygon(); ps.MoveTo(1268.200000000000045, 1266.799999999999955); ps.LineTo(1315.000000000000000, 1266.799999999999955); ps.LineTo(1315.000000000000000, 1220.000000000000000); ps.LineTo(1299.400000000000091, 1235.599999999999909); ps.LineTo(1283.799999999999955, 1204.399999999999864); ps.LineTo(1252.599999999999909, 1235.599999999999909); ps.LineTo(1283.799999999999955, 1251.200000000000045); ps.ClosePolygon(); }
public static bool get_bounding_rect(PathStorage vs, int[] gi, int start, int num, out RectangleDouble boundingRect) { return get_bounding_rect(vs, gi, start, num, out boundingRect.Left, out boundingRect.Bottom, out boundingRect.Right, out boundingRect.Top); }
public void Line(double x1, double y1, double x2, double y2, RGBA_Bytes color, double strokeWidth = 1) { PathStorage m_LinesToDraw = new PathStorage(); m_LinesToDraw.remove_all(); m_LinesToDraw.MoveTo(x1, y1); m_LinesToDraw.LineTo(x2, y2); Stroke StrockedLineToDraw = new Stroke(m_LinesToDraw, strokeWidth); Render(StrockedLineToDraw, color); }
public override void OnDraw(Graphics2D graphics2D) { RectangleDouble backgroundRect = new RectangleDouble(LocalBounds.Left - m_border_extra, LocalBounds.Bottom - m_border_extra, LocalBounds.Right + m_border_extra, LocalBounds.Top + m_border_extra); graphics2D.FillRectangle(backgroundRect, m_background_color); PathStorage border = new PathStorage(); border.LineTo(LocalBounds.Left, LocalBounds.Bottom); border.LineTo(LocalBounds.Right, LocalBounds.Bottom); border.LineTo(LocalBounds.Right, LocalBounds.Top); border.LineTo(LocalBounds.Left, LocalBounds.Top); border.LineTo(LocalBounds.Left + m_border_width, LocalBounds.Bottom + m_border_width); border.LineTo(LocalBounds.Left + m_border_width, LocalBounds.Top - m_border_width); border.LineTo(LocalBounds.Right - m_border_width, LocalBounds.Top - m_border_width); border.LineTo(LocalBounds.Right - m_border_width, LocalBounds.Bottom + m_border_width); graphics2D.Render(border, m_border_color); rewind(0); graphics2D.Render(this, m_curve_color); rewind(1); graphics2D.Render(this, m_grid_color); rewind(2); graphics2D.Render(this, m_inactive_pnt_color); rewind(3); graphics2D.Render(this, m_active_pnt_color); rewind(4); graphics2D.Render(this, m_text_color); base.OnDraw(graphics2D); }
private void DrawDirectionalArrow(Graphics2D graphics2D) { PathStorage littleArrow = new PathStorage(); if (this.MenuDirection == Direction.Down) { littleArrow.MoveTo(-4, 0); littleArrow.LineTo(4, 0); littleArrow.LineTo(0, -5); } else if (this.MenuDirection == Direction.Up) { littleArrow.MoveTo(-4, -5); littleArrow.LineTo(4, -5); littleArrow.LineTo(0, 0); } else { throw new NotImplementedException("Pulldown direction has not been implemented"); } graphics2D.Render(littleArrow, LocalBounds.Right - 8, LocalBounds.Top - 4, borderColor); }
public override void Render(Graphics2D graphics2D, Affine transform, double layerScale, RenderType renderType) { if ((renderType & RenderType.Extrusions) == RenderType.Extrusions) { double extrusionLineWidths = 0.2 * layerScale; RGBA_Bytes extrusionColor = RGBA_Bytes.Black; //extrusionColor = color; PathStorage pathStorage = new PathStorage(); VertexSourceApplyTransform transformedPathStorage = new VertexSourceApplyTransform(pathStorage, transform); Stroke stroke = new Stroke(transformedPathStorage, extrusionLineWidths); stroke.line_cap(LineCap.Round); stroke.line_join(LineJoin.Round); pathStorage.Add(start.x, start.y, ShapePath.FlagsAndCommand.CommandMoveTo); pathStorage.Add(end.x, end.y, ShapePath.FlagsAndCommand.CommandLineTo); graphics2D.Render(stroke, 0, extrusionColor); } }
private void MakeArrowIcons() { var center = TrackBallController.ScreenCenter; var radius = TrackBallController.TrackBallRadius; insideArrows.Clear(); // create the inside arrows { var svg = new PathStorage("M560.512 0.570216 C560.512 2.05696 280.518 560.561 280.054 560 C278.498 558.116 0 0.430888 0.512416 0.22416 C0.847112 0.089136 63.9502 27.1769 140.742 60.4192 C140.742 60.4192 280.362 120.86 280.362 120.86 C280.362 120.86 419.756 60.4298 419.756 60.4298 C496.422 27.1934 559.456 0 559.831 0 C560.205 0 560.512 0.2566 560.512 0.570216 Z"); RectangleDouble bounds = svg.GetBounds(); double arrowWidth = radius / 10; var centered = Affine.NewTranslation(-bounds.Center); var scaledTo1 = Affine.NewScaling(1 / bounds.Width); var scaledToSize = Affine.NewScaling(arrowWidth); var moveToRadius = Affine.NewTranslation(new Vector2(0, radius * 9 / 10)); var moveToScreenCenter = Affine.NewTranslation(center); for (int i = 0; i < 4; i++) { var arrowLeftTransform = centered * scaledTo1 * scaledToSize * moveToRadius * Affine.NewRotation(MathHelper.Tau / 4 * i) * moveToScreenCenter; insideArrows.Add(new VertexSourceApplyTransform(svg, arrowLeftTransform)); } } outsideArrows.Clear(); // and the outside arrows { //var svg = new PathStorage("m 271.38288,545.86543 c -10.175,-4.94962 -23,-11.15879 -28.5,-13.79816 -5.5,-2.63937 -24.34555,-11.82177 -41.87901,-20.40534 -17.53346,-8.58356 -32.21586,-15.60648 -32.62756,-15.60648 -0.4117,0 -1.28243,-0.64329 -1.93495,-1.42954 -0.98148,-1.1826 -0.0957,-1.94177 5.12755,-4.39484 3.47268,-1.63091 16.21397,-7.7909 28.31397,-13.68887 12.1,-5.89797 30.55,-14.8788 41,-19.9574 10.45,-5.07859 25.64316,-12.49628 33.76258,-16.48374 8.11942,-3.98746 15.43192,-6.99308 16.25,-6.67916 2.02527,0.77717 1.8755,5.19031 -0.56452,16.63355 -1.11411,5.225 -2.29208,10.9625 -2.6177,12.75 l -0.59204,3.25 80.19823,0 c 75.90607,0 80.17104,-0.0937 79.69036,-1.75 -2.47254,-8.51983 -5.62648,-24.42623 -5.62674,-28.37756 -3.6e-4,-5.51447 1.61726,-5.18356 21.01872,4.29961 10.16461,4.96833 22.98111,11.1892 28.48111,13.82415 5.5,2.63496 24.34555,11.81375 41.87901,20.39732 17.53346,8.58356 32.21586,15.60648 32.62756,15.60648 0.4117,0 1.28243,0.64329 1.93495,1.42954 0.98144,1.18256 0.0956,1.94283 -5.12755,4.40048 -3.47268,1.63401 -15.98897,7.68875 -27.81397,13.45496 -11.825,5.76621 -31.625,15.41743 -44,21.44716 -12.375,6.02972 -27.79146,13.55332 -34.2588,16.71911 -6.99025,3.42175 -12.41867,5.50276 -13.38597,5.13157 -2.11241,-0.81061 -1.37413,-8.85503 2.14722,-23.39653 1.37365,-5.67253 2.49755,-10.73503 2.49755,-11.25 0,-0.57397 -31.15148,-0.93629 -80.5,-0.93629 -76.11526,0 -80.5,0.0957 -80.5,1.7566 0,0.96613 0.45587,3.32863 1.01304,5.25 1.68077,5.79599 4.98696,23.01922 4.98696,25.97902 0,5.59974 -1.53004,5.29551 -21,-4.17564 z"); var svg = new PathStorage("M560.512 0.570216 C560.512 2.05696 280.518 560.561 280.054 560 C278.498 558.116 0 0.430888 0.512416 0.22416 C0.847112 0.089136 63.9502 27.1769 140.742 60.4192 C140.742 60.4192 280.362 120.86 280.362 120.86 C280.362 120.86 419.756 60.4298 419.756 60.4298 C496.422 27.1934 559.456 0 559.831 0 C560.205 0 560.512 0.2566 560.512 0.570216 Z"); RectangleDouble bounds = svg.GetBounds(); double arrowWidth = radius / 15; var centered = Affine.NewTranslation(-bounds.Center); var scaledTo1 = Affine.NewScaling(1 / bounds.Width); var scaledToSize = Affine.NewScaling(arrowWidth); var moveToRadius = Affine.NewTranslation(new Vector2(0, radius * 16 / 15)); var moveToScreenCenter = Affine.NewTranslation(center); for (int i = 0; i < 4; i++) { var arrowLeftTransform = centered * scaledTo1 * scaledToSize * Affine.NewRotation(MathHelper.Tau / 4) * moveToRadius * Affine.NewRotation(MathHelper.Tau / 8 + MathHelper.Tau / 4 * i + MathHelper.Tau / 80) * moveToScreenCenter; outsideArrows.Add(new VertexSourceApplyTransform(svg, arrowLeftTransform)); var arrowRightTransform = centered * scaledTo1 * scaledToSize * Affine.NewRotation(-MathHelper.Tau / 4) * moveToRadius * Affine.NewRotation(MathHelper.Tau / 8 + MathHelper.Tau / 4 * i - MathHelper.Tau / 80) * moveToScreenCenter; outsideArrows.Add(new VertexSourceApplyTransform(svg, arrowRightTransform)); } } }
private void DrawStuffForSelectedPart(Graphics2D graphics2D) { if (SelectedMeshGroup != null) { AxisAlignedBoundingBox selectedBounds = SelectedMeshGroup.GetAxisAlignedBoundingBox(SelectedMeshGroupTransform.TotalTransform); Vector3 boundsCenter = selectedBounds.Center; Vector3 centerTop = new Vector3(boundsCenter.x, boundsCenter.y, selectedBounds.maxXYZ.z); Vector2 centerTopScreenPosition = meshViewerWidget.TrackballTumbleWidget.GetScreenPosition(centerTop); centerTopScreenPosition = meshViewerWidget.TransformToParentSpace(this, centerTopScreenPosition); //graphics2D.Circle(screenPosition.x, screenPosition.y, 5, RGBA_Bytes.Cyan); PathStorage zArrow = new PathStorage(); zArrow.MoveTo(-6, -2); zArrow.curve3(0, -4); zArrow.LineTo(6, -2); zArrow.LineTo(0, 12); zArrow.LineTo(-6, -2); VertexSourceApplyTransform translate = new VertexSourceApplyTransform(zArrow, Affine.NewTranslation(centerTopScreenPosition)); //graphics2D.Render(translate, RGBA_Bytes.Black); } }
private static void DrawBorderBounds(Graphics2D graphics2D, RectangleDouble bounds, BorderDouble border, RGBA_Bytes color) { if (border.Width != 0 || border.Height != 0) { PathStorage borderPath = new PathStorage(); borderPath.MoveTo(bounds.Left, bounds.Bottom); borderPath.LineTo(bounds.Left, bounds.Top); borderPath.LineTo(bounds.Right, bounds.Top); borderPath.LineTo(bounds.Right, bounds.Bottom); borderPath.LineTo(bounds.Left, bounds.Bottom); borderPath.MoveTo(bounds.Left + border.Left, bounds.Bottom + border.Bottom); borderPath.LineTo(bounds.Right - border.Right, bounds.Bottom + border.Bottom); borderPath.LineTo(bounds.Right - border.Right, bounds.Top - border.Top); borderPath.LineTo(bounds.Left + border.Left, bounds.Top - border.Top); borderPath.LineTo(bounds.Left + border.Left, bounds.Bottom + border.Bottom); graphics2D.Render(borderPath, color); } }
//直线 public UIGraphic AddLine(float x1, float y1, float x2, float y2, CCColor4B stroke, double strokeThickness = 1) { if (stroke.A > 0) { //g.Line没有厚度 PathStorage linesToDraw = new PathStorage(); linesToDraw.remove_all(); linesToDraw.MoveTo(x1, y1); linesToDraw.LineTo(x2, y2); Stroke StrockedLineToDraw = new Stroke(linesToDraw, strokeThickness); this.graphics2D.Render(StrockedLineToDraw, new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); } return this; }
public static IVertexSource CreatePathStorage(string data) { PathStorage path = new PathStorage(); bool hasCurves = false; //todo 依次输入多个同一类型的命令时,可以省略重复的命令项;例如,L 100,200 300,400 等同于 L 100,200 L 300,400。 StringBuilder buffer = new StringBuilder(); for (int i = 0; i < data.Length; i++) { if (data[i] == '-' && i > 0 && data[i - 1] != ',' && data[i - 1] != ' ' && char.IsLetter(data[i - 1]) == false) { buffer.Append(','); } if (data[i] != 'F' && (char.IsLetter(data[i]))) { buffer.Append(','); buffer.Append(data[i]); if (i < data.Length - 1 && data[i + 1] != ' ') buffer.Append(','); } else { buffer.Append(data[i]); } } string[] commands = buffer.ToString().Split(new char[] { ' ', ',' }); MatterHackers.VectorMath.Vector2 polyStart = new MatterHackers.VectorMath.Vector2(0, 0); MatterHackers.VectorMath.Vector2 lastXY = new MatterHackers.VectorMath.Vector2(0, 0); MatterHackers.VectorMath.Vector2 curXY = new MatterHackers.VectorMath.Vector2(); for (int i = 0; i < commands.Length; i++) { switch (commands[i]) { // F0 指定 EvenOdd 填充规则。F1 指定 Nonzero 填充规则。 // 如果省略此命令,则子路径使用默认行为,即 EvenOdd。 如果指定此命令,则必须将其置于最前面。 case "F1": break; case " ": break; case "m": case "M": { curXY.x = double.Parse(commands[i + 1]); curXY.y = double.Parse(commands[i + 2]); if (commands[i] == "m") { curXY += lastXY; } path.MoveTo(curXY.x, curXY.y); polyStart = curXY; i += 2; } break; case "l": case "L": { curXY.x = double.Parse(commands[i + 1]); curXY.y = double.Parse(commands[i + 2]); if (commands[i] == "l") { curXY += lastXY; } path.LineTo(curXY.x, curXY.y); } break; case "h": case "H": { curXY.y = lastXY.y; curXY.x = double.Parse(commands[i + 1]); if (commands[i] == "h") { curXY.x += lastXY.x; } path.HorizontalLineTo(curXY.x); i += 1; } break; case "v": case "V": { curXY.x = lastXY.x; curXY.y = double.Parse(commands[i + 1]); if (commands[i] == "v") { curXY.y += lastXY.y; } path.VerticalLineTo(curXY.y); i += 1; } break; //三次方贝塞尔曲线命令。通过使用两个指定的控制点(controlPoint1 和 controlPoint2)在当前点与指定的终点之间创建一条三次方贝塞尔曲线 case "c": case "C": { MatterHackers.VectorMath.Vector2 controlPoint1; MatterHackers.VectorMath.Vector2 controlPoint2; controlPoint1.x = double.Parse(commands[i + 1]); controlPoint1.y = double.Parse(commands[i + 2]); controlPoint2.x = double.Parse(commands[i + 3]); controlPoint2.y = double.Parse(commands[i + 4]); curXY.x = double.Parse(commands[i + 5]); curXY.y = double.Parse(commands[i + 6]); if (commands[i] == "c") { controlPoint1 += lastXY; controlPoint2 += lastXY; curXY += lastXY; } path.curve4(controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, curXY.x, curXY.y); i += 6; hasCurves = true; } break; //二次贝塞尔曲线命令。通过使用指定的控制点 (controlPoint) 在当前点与指定的终点之间创建一条二次贝塞尔曲线。 case "q": case "Q": { MatterHackers.VectorMath.Vector2 controlPoint; controlPoint.x = double.Parse(commands[i + 1]); controlPoint.y = double.Parse(commands[i + 2]); curXY.x = double.Parse(commands[i + 3]); curXY.y = double.Parse(commands[i + 4]); if (commands[i] == "q") { controlPoint += lastXY; curXY += lastXY; } path.curve3(controlPoint.x, controlPoint.y, curXY.x, curXY.y); i += 4; hasCurves = true; } break; //在当前点与指定的终点之间创建一条三次方贝塞尔曲线。 //第一个控制点假定为前一个命令的第二个控制点相对于当前点的反射。 //如果前一个命令不存在,或者前一个命令不是三次方贝塞尔曲线命令或平滑的三次方贝塞尔曲线命令,则假定第一个控制点就是当前点。 //第二个控制点,即曲线终端的控制点,由 controlPoint2 指定。 case "s": case "S": { MatterHackers.VectorMath.Vector2 controlPoint2; controlPoint2.x = double.Parse(commands[i + 1]); controlPoint2.y = double.Parse(commands[i + 2]); curXY.x = double.Parse(commands[i + 3]); curXY.y = double.Parse(commands[i + 4]); if (commands[i] == "s") { controlPoint2 += lastXY; curXY += lastXY; } path.curve4(controlPoint2.x, controlPoint2.y, curXY.x, curXY.y); i += 4; hasCurves = true; } break; //二次贝塞尔曲线命令。在当前点与指定的终点之间创建一条二次贝塞尔曲线。 //控制点假定为前一个命令的控制点相对于当前点的反射。 //如果前一个命令不存在,或者前一个命令不是二次贝塞尔曲线命令或平滑的二次贝塞尔曲线命令,则此控制点就是当前点。 case "t": case "T": { curXY.x = double.Parse(commands[i + 1]); curXY.y = double.Parse(commands[i + 2]); if (commands[i] == "t") { curXY += lastXY; } path.curve3(curXY.x, curXY.y); i += 2; hasCurves = true; } break; case "z": case "Z": { curXY = lastXY; // value not used this is to remove an error. path.ClosePolygon(); // svg fonts are stored cw and agg expects its shapes to be ccw. cw shapes are holes. // We stored the position of the start of this polygon, no we flip it as we colse it. //path.invert_polygon(0); } break; case "\r": { curXY = lastXY; // value not used this is to remove an error. } break; } lastXY = curXY; } if (hasCurves == true) return new FlattenCurves(path); return path; }
public static CCSprite CreateLine( int width, int height, CCColor4B stroke, double strokeThickness = 1 ) { ImageBuffer buffer = new ImageBuffer(width, height, 32, new BlenderRGBA()); Graphics2D g = buffer.NewGraphics2D(); if (stroke.A > 0) { //g.Line没有厚度 PathStorage linesToDraw = new PathStorage(); linesToDraw.remove_all(); linesToDraw.MoveTo(0, 0); linesToDraw.LineTo(width, height); Stroke StrockedLineToDraw = new Stroke(linesToDraw, strokeThickness); g.Render(StrockedLineToDraw, new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); } Texture2D xnaTexture = XnaTexture((int)width, (int)height); xnaTexture.SetData<byte>(buffer.GetBuffer()); CCTexture2D ccTexture = new CCTexture2D(); ccTexture.InitWithTexture(xnaTexture); return new CCSprite(ccTexture); }
private void render_gpc(Graphics2D graphics2D) { switch (m_polygons.SelectedIndex) { case 0: { //------------------------------------ // Two simple paths // PathStorage ps1 = new PathStorage(); PathStorage ps2 = new PathStorage(); double x = m_x - Width / 2 + 100; double y = m_y - Height / 2 + 100; ps1.MoveTo(x + 140, y + 145); ps1.LineTo(x + 225, y + 44); ps1.LineTo(x + 296, y + 219); ps1.ClosePolygon(); ps1.LineTo(x + 226, y + 289); ps1.LineTo(x + 82, y + 292); ps1.MoveTo(x + 220, y + 222); ps1.LineTo(x + 363, y + 249); ps1.LineTo(x + 265, y + 331); ps1.MoveTo(x + 242, y + 243); ps1.LineTo(x + 268, y + 309); ps1.LineTo(x + 325, y + 261); ps1.MoveTo(x + 259, y + 259); ps1.LineTo(x + 273, y + 288); ps1.LineTo(x + 298, y + 266); ps2.MoveTo(100 + 32, 100 + 77); ps2.LineTo(100 + 473, 100 + 263); ps2.LineTo(100 + 351, 100 + 290); ps2.LineTo(100 + 354, 100 + 374); graphics2D.Render(ps1, new RGBA_Floats(0, 0, 0, 0.1).GetAsRGBA_Bytes()); graphics2D.Render(ps2, new RGBA_Floats(0, 0.6, 0, 0.1).GetAsRGBA_Bytes()); CreateAndRenderCombined(graphics2D, ps1, ps2); } break; case 1: { //------------------------------------ // Closed stroke // PathStorage ps1 = new PathStorage(); PathStorage ps2 = new PathStorage(); Stroke stroke = new Stroke(ps2); stroke.width(10.0); double x = m_x - Width / 2 + 100; double y = m_y - Height / 2 + 100; ps1.MoveTo(x + 140, y + 145); ps1.LineTo(x + 225, y + 44); ps1.LineTo(x + 296, y + 219); ps1.ClosePolygon(); ps1.LineTo(x + 226, y + 289); ps1.LineTo(x + 82, y + 292); ps1.MoveTo(x + 220 - 50, y + 222); ps1.LineTo(x + 265 - 50, y + 331); ps1.LineTo(x + 363 - 50, y + 249); ps1.close_polygon(ShapePath.FlagsAndCommand.FlagCCW); ps2.MoveTo(100 + 32, 100 + 77); ps2.LineTo(100 + 473, 100 + 263); ps2.LineTo(100 + 351, 100 + 290); ps2.LineTo(100 + 354, 100 + 374); ps2.ClosePolygon(); graphics2D.Render(ps1, new RGBA_Floats(0, 0, 0, 0.1).GetAsRGBA_Bytes()); graphics2D.Render(stroke, new RGBA_Floats(0, 0.6, 0, 0.1).GetAsRGBA_Bytes()); CreateAndRenderCombined(graphics2D, ps1, stroke); } break; case 2: { //------------------------------------ // Great Britain and Arrows // PathStorage gb_poly = new PathStorage(); PathStorage arrows = new PathStorage(); GreatBritanPathStorage.Make(gb_poly); make_arrows(arrows); Affine mtx1 = Affine.NewIdentity(); Affine mtx2 = Affine.NewIdentity(); mtx1 *= Affine.NewTranslation(-1150, -1150); mtx1 *= Affine.NewScaling(2.0); mtx2 = mtx1; mtx2 *= Affine.NewTranslation(m_x - Width / 2, m_y - Height / 2); VertexSourceApplyTransform trans_gb_poly = new VertexSourceApplyTransform(gb_poly, mtx1); VertexSourceApplyTransform trans_arrows = new VertexSourceApplyTransform(arrows, mtx2); graphics2D.Render(trans_gb_poly, new RGBA_Floats(0.5, 0.5, 0, 0.1).GetAsRGBA_Bytes()); Stroke stroke_gb_poly = new Stroke(trans_gb_poly); stroke_gb_poly.Width = 0.1; graphics2D.Render(stroke_gb_poly, new RGBA_Floats(0, 0, 0).GetAsRGBA_Bytes()); graphics2D.Render(trans_arrows, new RGBA_Floats(0.0, 0.5, 0.5, 0.1).GetAsRGBA_Bytes()); CreateAndRenderCombined(graphics2D, trans_gb_poly, trans_arrows); } break; case 3: { //------------------------------------ // Great Britain and a Spiral // spiral sp = new spiral(m_x, m_y, 10, 150, 30, 0.0); Stroke stroke = new Stroke(sp); stroke.width(15.0); PathStorage gb_poly = new PathStorage(); GreatBritanPathStorage.Make(gb_poly); Affine mtx = Affine.NewIdentity(); ; mtx *= Affine.NewTranslation(-1150, -1150); mtx *= Affine.NewScaling(2.0); VertexSourceApplyTransform trans_gb_poly = new VertexSourceApplyTransform(gb_poly, mtx); graphics2D.Render(trans_gb_poly, new RGBA_Floats(0.5, 0.5, 0, 0.1).GetAsRGBA_Bytes()); Stroke stroke_gb_poly = new Stroke(trans_gb_poly); stroke_gb_poly.width(0.1); graphics2D.Render(stroke_gb_poly, new RGBA_Floats(0, 0, 0).GetAsRGBA_Bytes()); graphics2D.Render(stroke, new RGBA_Floats(0.0, 0.5, 0.5, 0.1).GetAsRGBA_Bytes()); CreateAndRenderCombined(graphics2D, trans_gb_poly, stroke); } break; case 4: { //------------------------------------ // Spiral and glyph // spiral sp = new spiral(m_x, m_y, 10, 150, 30, 0.0); Stroke stroke = new Stroke(sp); stroke.width(15.0); PathStorage glyph = new PathStorage(); glyph.MoveTo(28.47, 6.45); glyph.curve3(21.58, 1.12, 19.82, 0.29); glyph.curve3(17.19, -0.93, 14.21, -0.93); glyph.curve3(9.57, -0.93, 6.57, 2.25); glyph.curve3(3.56, 5.42, 3.56, 10.60); glyph.curve3(3.56, 13.87, 5.03, 16.26); glyph.curve3(7.03, 19.58, 11.99, 22.51); glyph.curve3(16.94, 25.44, 28.47, 29.64); glyph.LineTo(28.47, 31.40); glyph.curve3(28.47, 38.09, 26.34, 40.58); glyph.curve3(24.22, 43.07, 20.17, 43.07); glyph.curve3(17.09, 43.07, 15.28, 41.41); glyph.curve3(13.43, 39.75, 13.43, 37.60); glyph.LineTo(13.53, 34.77); glyph.curve3(13.53, 32.52, 12.38, 31.30); glyph.curve3(11.23, 30.08, 9.38, 30.08); glyph.curve3(7.57, 30.08, 6.42, 31.35); glyph.curve3(5.27, 32.62, 5.27, 34.81); glyph.curve3(5.27, 39.01, 9.57, 42.53); glyph.curve3(13.87, 46.04, 21.63, 46.04); glyph.curve3(27.59, 46.04, 31.40, 44.04); glyph.curve3(34.28, 42.53, 35.64, 39.31); glyph.curve3(36.52, 37.21, 36.52, 30.71); glyph.LineTo(36.52, 15.53); glyph.curve3(36.52, 9.13, 36.77, 7.69); glyph.curve3(37.01, 6.25, 37.57, 5.76); glyph.curve3(38.13, 5.27, 38.87, 5.27); glyph.curve3(39.65, 5.27, 40.23, 5.62); glyph.curve3(41.26, 6.25, 44.19, 9.18); glyph.LineTo(44.19, 6.45); glyph.curve3(38.72, -0.88, 33.74, -0.88); glyph.curve3(31.35, -0.88, 29.93, 0.78); glyph.curve3(28.52, 2.44, 28.47, 6.45); glyph.ClosePolygon(); glyph.MoveTo(28.47, 9.62); glyph.LineTo(28.47, 26.66); glyph.curve3(21.09, 23.73, 18.95, 22.51); glyph.curve3(15.09, 20.36, 13.43, 18.02); glyph.curve3(11.77, 15.67, 11.77, 12.89); glyph.curve3(11.77, 9.38, 13.87, 7.06); glyph.curve3(15.97, 4.74, 18.70, 4.74); glyph.curve3(22.41, 4.74, 28.47, 9.62); glyph.ClosePolygon(); Affine mtx = Affine.NewIdentity(); mtx *= Affine.NewScaling(4.0); mtx *= Affine.NewTranslation(220, 200); VertexSourceApplyTransform trans = new VertexSourceApplyTransform(glyph, mtx); FlattenCurves curve = new FlattenCurves(trans); CreateAndRenderCombined(graphics2D, stroke, curve); graphics2D.Render(stroke, new RGBA_Floats(0, 0, 0, 0.1).GetAsRGBA_Bytes()); graphics2D.Render(curve, new RGBA_Floats(0, 0.6, 0, 0.1).GetAsRGBA_Bytes()); } break; } }
//-------------------------------------------------------------------- // Join path. The path is joined with the existing one, that is, // it behaves as if the pen of a plotter was always down (drawing) //template<class VertexSource> public void join_path(PathStorage vs) { join_path(vs, 0); }
internal IVertexSource GetGlyphForCharacter(char character) { // TODO: check for multi character glyphs (we don't currently support them in the reader). Glyph glyph; if (glyphs.TryGetValue(character, out glyph)) { PathStorage writeableGlyph = new PathStorage(); writeableGlyph.ShareVertexData(glyph.glyphData); return writeableGlyph; } return null; }
public void ShareVertexData(PathStorage pathStorageToShareFrom) { vertices = pathStorageToShareFrom.vertices; }
public override void Render(Graphics2D graphics2D, Affine transform, double layerScale, RenderType renderType) { if ((renderType & RenderType.Moves) == RenderType.Moves) { double movementLineWidth = 0.35 * layerScale; RGBA_Bytes movementColor = new RGBA_Bytes(10, 190, 15); PathStorage pathStorage = new PathStorage(); VertexSourceApplyTransform transformedPathStorage = new VertexSourceApplyTransform(pathStorage, transform); Stroke stroke = new Stroke(transformedPathStorage, movementLineWidth); stroke.line_cap(LineCap.Round); stroke.line_join(LineJoin.Round); pathStorage.Add(start.x, start.y, ShapePath.FlagsAndCommand.CommandMoveTo); if (end.x != start.x || end.y != start.y) { pathStorage.Add(end.x, end.y, ShapePath.FlagsAndCommand.CommandLineTo); } else { pathStorage.Add(end.x + .01, end.y, ShapePath.FlagsAndCommand.CommandLineTo); } graphics2D.Render(stroke, 0, movementColor); } }
public override void OnDraw(Graphics2D graphics2D) { ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect()); GammaLookUpTable gamma = new GammaLookUpTable(gammaSlider.Value); IRecieveBlenderByte NormalBlender = new BlenderBGRA(); IRecieveBlenderByte GammaBlender = new BlenderGammaBGRA(gamma); ImageBuffer rasterGamma = new ImageBuffer(); rasterGamma.Attach(widgetsSubImage, GammaBlender); ImageClippingProxy clippingProxyNormal = new ImageClippingProxy(widgetsSubImage); ImageClippingProxy clippingProxyGamma = new ImageClippingProxy(rasterGamma); clippingProxyNormal.clear(new RGBA_Floats(1, 1, 1)); ScanlineRasterizer rasterizer = new ScanlineRasterizer(); scanline_unpacked_8 sl = new scanline_unpacked_8(); int size_mul = (int)pixelSizeSlider.Value; renderer_enlarged ren_en = new renderer_enlarged(size_mul); rasterizer.reset(); rasterizer.move_to_d(m_x[0] / size_mul, m_y[0] / size_mul); rasterizer.line_to_d(m_x[1] / size_mul, m_y[1] / size_mul); rasterizer.line_to_d(m_x[2] / size_mul, m_y[2] / size_mul); ren_en.RenderSolid(clippingProxyGamma, rasterizer, sl, RGBA_Bytes.Black); ScanlineRenderer scanlineRenderer = new ScanlineRenderer(); scanlineRenderer.RenderSolid(clippingProxyGamma, rasterizer, sl, RGBA_Bytes.Black); rasterizer.gamma(new gamma_none()); PathStorage ps = new PathStorage(); Stroke pg = new Stroke(ps); pg.width(2); ps.remove_all(); ps.MoveTo(m_x[0], m_y[0]); ps.LineTo(m_x[1], m_y[1]); ps.LineTo(m_x[2], m_y[2]); ps.LineTo(m_x[0], m_y[0]); rasterizer.add_path(pg); scanlineRenderer.RenderSolid(clippingProxyNormal, rasterizer, sl, new RGBA_Bytes(0, 150, 160, 200)); base.OnDraw(graphics2D); }
static public int parse_lion(PathStorage path, RGBA_Bytes[] colors, int[] path_idx) { // Parse the lion and then detect its bounding // box and arrange polygons orientations (make all polygons // oriented clockwise or counterclockwise) int npaths = 0; string[] splitOnNL = g_lion.Split('\n'); foreach (string LineString in splitOnNL) { int c; if (LineString.Length > 0 && LineString[0] != 'M' && Int32.TryParse(LineString, NumberStyles.HexNumber, null, out c)) { // New color. Every new color creates new path in the path object. path.ClosePolygon(); colors[npaths] = RGBA_Bytes.rgb8_packed((int)c); path_idx[npaths] = path.start_new_path(); npaths++; } else { bool startedPoly = false; string[] splitOnSpace = LineString.Split(' '); for (int i = 0; i < splitOnSpace.Length; i++) { string[] splitOnComma = splitOnSpace[i].Split(','); if (splitOnComma.Length > 1) { double x = 0.0; double y = 0.0; double.TryParse(splitOnComma[0], NumberStyles.Number, null, out x); double.TryParse(splitOnComma[1], NumberStyles.Number, null, out y); if (!startedPoly) { startedPoly = true; path.ClosePolygon(); path.MoveTo(x, y); } else { path.LineTo(x, y); } } } } } path.arrange_orientations_all_paths(ShapePath.FlagsAndCommand.FlagCW); return npaths; }
public void join_path(PathStorage vs, int path_id) { double x, y; vs.rewind(path_id); ShapePath.FlagsAndCommand PathAndFlags = vs.vertex(out x, out y); if (!ShapePath.is_stop(PathAndFlags)) { if (ShapePath.is_vertex(PathAndFlags)) { double x0, y0; ShapePath.FlagsAndCommand PathAndFlags0 = last_vertex(out x0, out y0); if (ShapePath.is_vertex(PathAndFlags0)) { if(agg_math.calc_distance(x, y, x0, y0) > agg_math.vertex_dist_epsilon) { if (ShapePath.is_move_to(PathAndFlags)) PathAndFlags = ShapePath.FlagsAndCommand.CommandLineTo; vertices.AddVertex(x, y, PathAndFlags); } } else { if (ShapePath.is_stop(PathAndFlags0)) { PathAndFlags = ShapePath.FlagsAndCommand.CommandMoveTo; } else { if (ShapePath.is_move_to(PathAndFlags)) PathAndFlags = ShapePath.FlagsAndCommand.CommandLineTo; } vertices.AddVertex(x, y, PathAndFlags); } } while (!ShapePath.is_stop(PathAndFlags = vs.vertex(out x, out y))) { vertices.AddVertex(x, y, ShapePath.is_move_to(PathAndFlags) ? ShapePath.FlagsAndCommand.CommandLineTo : PathAndFlags); } } }
public static void Main(string[] args) { // first we will show how to use the simple drawing functions in graphics 2D { ImageBuffer simpleImage = new ImageBuffer(640, 480, 32, new BlenderBGRA()); Graphics2D simpleImageGraphics2D = simpleImage.NewGraphics2D(); // clear the image to white simpleImageGraphics2D.Clear(RGBA_Bytes.White); // draw a circle simpleImageGraphics2D.Circle(50, 50, 30, RGBA_Bytes.Blue); // draw a line simpleImageGraphics2D.Line(10, 100, 520, 50, new RGBA_Bytes(20, 200, 200)); // draw a filled box simpleImageGraphics2D.FillRectangle(60, 260, 200, 280, RGBA_Bytes.Yellow); // and an outline around it simpleImageGraphics2D.Rectangle(60, 260, 200, 280, RGBA_Bytes.Magenta); // draw some text simpleImageGraphics2D.DrawString("A Simple Example", 300, 400, 20); // and save this image out ImageTgaIO.Save(simpleImage, "SimpleDrawAndSave.tga"); } // now we will we will show how to use the render function to draw more complex things { ImageBuffer lessSimpleImage = new ImageBuffer(640, 480, 32, new BlenderBGRA()); Graphics2D lessSimpleImageGraphics2D = lessSimpleImage.NewGraphics2D(); // clear the image to white lessSimpleImageGraphics2D.Clear(RGBA_Bytes.White); // draw a circle Ellipse ellipseTest = new Ellipse(0, 0, 100, 50); for (double angleDegrees = 0; angleDegrees < 180; angleDegrees += 22.5) { VertexSourceApplyTransform rotatedTransform = new VertexSourceApplyTransform(ellipseTest, Affine.NewRotation(MathHelper.DegreesToRadians(angleDegrees))); VertexSourceApplyTransform rotatedAndTranslatedTransform = new VertexSourceApplyTransform(rotatedTransform, Affine.NewTranslation(lessSimpleImage.Width / 2, 150)); lessSimpleImageGraphics2D.Render(rotatedAndTranslatedTransform, RGBA_Bytes.Yellow); Stroke ellipseOutline = new Stroke(rotatedAndTranslatedTransform, 3); lessSimpleImageGraphics2D.Render(ellipseOutline, RGBA_Bytes.Blue); } // and a little polygon PathStorage littlePoly = new PathStorage(); littlePoly.MoveTo(50, 50); littlePoly.LineTo(150, 50); littlePoly.LineTo(200, 200); littlePoly.LineTo(50, 150); littlePoly.LineTo(50, 50); lessSimpleImageGraphics2D.Render(littlePoly, RGBA_Bytes.Cyan); // draw some text TypeFacePrinter textPrinter = new TypeFacePrinter("Printing from a printer", 30, justification: Justification.Center); IVertexSource translatedText = new VertexSourceApplyTransform(textPrinter, Affine.NewTranslation(new Vector2(lessSimpleImage.Width / 2, lessSimpleImage.Height / 4 * 3))); lessSimpleImageGraphics2D.Render(translatedText, RGBA_Bytes.Red); Stroke strokedText = new Stroke(translatedText); lessSimpleImageGraphics2D.Render(strokedText, RGBA_Bytes.Black); IVertexSource rotatedText = new VertexSourceApplyTransform(textPrinter, Affine.NewRotation(MathHelper.DegreesToRadians(90))); IVertexSource rotatedTranslatedText = new VertexSourceApplyTransform(rotatedText, Affine.NewTranslation(new Vector2(40, lessSimpleImage.Height / 2))); lessSimpleImageGraphics2D.Render(rotatedTranslatedText, RGBA_Bytes.Black); // and save this image out ImageTgaIO.Save(lessSimpleImage, "LessSimpleDrawAndSave.tga"); } }