public ClosedLoopGlyphData(VertexStorage source) { storage = new VertexStorage(); var vertexData = source.Vertices().Where(v => v.command != ShapePath.FlagsAndCommand.FlagNone).ToArray(); VertexData previous = default(VertexData); for (var i = 0; i < vertexData.Length; i++) { var current = vertexData[i]; // All MoveTo operations should be preceded by ClosePolygon if (i > 0 && current.IsMoveTo && ShapePath.is_vertex(previous.command)) { storage.ClosePolygon(); } // Add original VertexData storage.Add(current.position.X, current.position.Y, current.command); // Hold prior item previous = current; } // Ensure closed storage.ClosePolygon(); }
public void AddVertex(double x, double y, ShapePath.FlagsAndCommand cmd) { m_status = StrokeMath.status_e.initial; if (ShapePath.is_move_to(cmd)) { m_src_vertices.modify_last(new VertexDistance(x, y)); } else { if (ShapePath.is_vertex(cmd)) { m_src_vertices.add(new VertexDistance(x, y)); } else { if (ShapePath.is_end_poly(cmd)) { m_closed = (ShapePath.get_close_flag(cmd) == ShapePath.FlagsAndCommand.FlagClose); if (m_orientation == ShapePath.FlagsAndCommand.FlagNone) { m_orientation = ShapePath.get_orientation(cmd); } } } } }
public void invert_polygon(int start) { // Skip all non-vertices at the beginning while (start < vertices.total_vertices() && !ShapePath.is_vertex(vertices.command(start))) { ++start; } // Skip all insignificant move_to while (start + 1 < vertices.total_vertices() && ShapePath.is_move_to(vertices.command(start)) && ShapePath.is_move_to(vertices.command(start + 1))) { ++start; } // Find the last vertex int end = start + 1; while (end < vertices.total_vertices() && !ShapePath.is_next_poly(vertices.command(end))) { ++end; } invert_polygon(start, end); }
public void end_poly(ShapePath.FlagsAndCommand flags) { if (ShapePath.is_vertex(vertexDataManager.last_command())) { vertexDataManager.AddVertex(0.0, 0.0, ShapePath.FlagsAndCommand.EndPoly | flags); } }
public void end_poly(ShapePath.FlagsAndCommand flags) { if (ShapePath.is_vertex(vertices.last_command())) { vertices.AddVertex(0.0, 0.0, ShapePath.FlagsAndCommand.CommandEndPoly | flags); } }
public ShapePath.FlagsAndCommand vertex(out double x, out double y) { ShapePath.FlagsAndCommand cmd = VertexSource.vertex(out x, out y); if (ShapePath.is_vertex(cmd)) { transformToApply.transform(ref x, ref y); } return(cmd); }
public void flip_y(double y1, double y2) { for (int i = 0; i < vertexDataManager.total_vertices(); i++) { ShapePath.FlagsAndCommand PathAndFlags = vertexDataManager.vertex(i, out double x, out double y); if (ShapePath.is_vertex(PathAndFlags)) { vertexDataManager.modify_vertex(i, x, y2 - y + y1); } } }
public IEnumerable <VertexData> Vertices() { foreach (VertexData vertexData in VertexSource.Vertices()) { VertexData transformedVertex = vertexData; if (ShapePath.is_vertex(transformedVertex.command)) { transformToApply.transform(ref transformedVertex.position.x, ref transformedVertex.position.y); } yield return(transformedVertex); } }
public void rel_to_abs(ref double x, ref double y) { if (vertices.total_vertices() != 0) { double x2; double y2; if (ShapePath.is_vertex(vertices.last_vertex(out x2, out y2))) { x += x2; y += y2; } } }
public void flip_y(double y1, double y2) { int i; double x, y; for (i = 0; i < vertices.total_vertices(); i++) { ShapePath.FlagsAndCommand PathAndFlags = vertices.vertex(i, out x, out y); if (ShapePath.is_vertex(PathAndFlags)) { vertices.modify_vertex(i, x, y2 - y + y1); } } }
// Flip all vertices horizontally or vertically, // between x1 and x2, or between y1 and y2 respectively //-------------------------------------------------------------------- public void flip_x(double x1, double x2) { int i; double x, y; for (i = 0; i < vertexDataManager.total_vertices(); i++) { ShapePath.FlagsAndCommand PathAndFlags = vertexDataManager.vertex(i, out x, out y); if (ShapePath.is_vertex(PathAndFlags)) { vertexDataManager.modify_vertex(i, x2 - x + x1, y); } } }
//-------------------------------------------------------------------- public void transform_all_paths(Transform.Affine trans) { int index; int num_ver = vertices.total_vertices(); for (index = 0; index < num_ver; index++) { double x, y; if (ShapePath.is_vertex(vertices.vertex(index, out x, out y))) { trans.transform(ref x, ref y); vertices.modify_vertex(index, x, y); } } }
public void translate_all_paths(double dx, double dy) { int index; int num_ver = vertices.total_vertices(); for (index = 0; index < num_ver; index++) { double x, y; if (ShapePath.is_vertex(vertices.vertex(index, out x, out y))) { x += dx; y += dy; vertices.modify_vertex(index, x, y); } } }
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); } } }
// Arrange the orientation of a polygon, all polygons in a path, // or in all paths. After calling arrange_orientations() or // arrange_orientations_all_paths(), all the polygons will have // the same orientation, i.e. path_flags_cw or path_flags_ccw //-------------------------------------------------------------------- public int arrange_polygon_orientation(int start, ShapePath.FlagsAndCommand orientation) { if (orientation == ShapePath.FlagsAndCommand.FlagNone) { return(start); } // Skip all non-vertices at the beginning while (start < vertices.total_vertices() && !ShapePath.is_vertex(vertices.command(start))) { ++start; } // Skip all insignificant move_to while (start + 1 < vertices.total_vertices() && ShapePath.is_move_to(vertices.command(start)) && ShapePath.is_move_to(vertices.command(start + 1))) { ++start; } // Find the last vertex int end = start + 1; while (end < vertices.total_vertices() && !ShapePath.is_next_poly(vertices.command(end))) { ++end; } if (end - start > 2) { if (perceive_polygon_orientation(start, end) != orientation) { // Invert polygon, set orientation flag, and skip all end_poly invert_polygon(start, end); ShapePath.FlagsAndCommand PathAndFlags; while (end < vertices.total_vertices() && ShapePath.is_end_poly(PathAndFlags = vertices.command(end))) { vertices.modify_command(end++, PathAndFlags | orientation); // Path.set_orientation(cmd, orientation)); } } } return(end); }
private conv_poly_counter(IVertexSource src) { m_contours = 0; m_points = 0; foreach (VertexData vertexData in src.Vertices()) { if (ShapePath.is_vertex(vertexData.command)) { ++m_points; } if (ShapePath.is_move_to(vertexData.command)) { ++m_contours; } } }
public void AddVertex(double x, double y, ShapePath.FlagsAndCommand cmd) { m_status = StrokeMath.status_e.initial; if (ShapePath.is_move_to(cmd)) { m_src_vertices.modify_last(new VertexDistance(x, y)); } else { if (ShapePath.is_vertex(cmd)) { m_src_vertices.add(new VertexDistance(x, y)); } else { m_closed = (int)ShapePath.get_close_flag(cmd); } } }
public void transform(Transform.Affine trans, int path_id) { int num_ver = vertices.total_vertices(); for (; path_id < num_ver; path_id++) { double x, y; ShapePath.FlagsAndCommand PathAndFlags = vertices.vertex(path_id, out x, out y); if (ShapePath.is_stop(PathAndFlags)) { break; } if (ShapePath.is_vertex(PathAndFlags)) { trans.transform(ref x, ref y); vertices.modify_vertex(path_id, x, y); } } }
public void translate(double dx, double dy, int path_id) { int num_ver = vertices.total_vertices(); for (; path_id < num_ver; path_id++) { double x, y; ShapePath.FlagsAndCommand PathAndFlags = vertices.vertex(path_id, out x, out y); if (ShapePath.is_stop(PathAndFlags)) { break; } if (ShapePath.is_vertex(PathAndFlags)) { x += dx; y += dy; vertices.modify_vertex(path_id, x, y); } } }
/// <summary> /// <para>Draws a quadratic Bézier curve from the current point to (x,y).</para> /// <para>The control point is assumed to be the reflection of the control point on the previous command relative to the current point.</para> /// <para>(If there is no previous command or if the previous command was not a curve, assume the control point is coincident with the current point.)</para> /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void curve3(double x, double y) { double x0; double y0; if (ShapePath.is_vertex(vertices.last_vertex(out x0, out y0))) { double x_ctrl; double y_ctrl; ShapePath.FlagsAndCommand cmd = vertices.prev_vertex(out x_ctrl, out y_ctrl); if (ShapePath.is_curve(cmd)) { x_ctrl = x0 + x0 - x_ctrl; y_ctrl = y0 + y0 - y_ctrl; } else { x_ctrl = x0; y_ctrl = y0; } curve3(x_ctrl, y_ctrl, x, y); } }
public void curve4(double x_ctrl2, double y_ctrl2, double x_to, double y_to) { double x0; double y0; if (ShapePath.is_vertex(last_vertex(out x0, out y0))) { double x_ctrl1; double y_ctrl1; ShapePath.FlagsAndCommand cmd = prev_vertex(out x_ctrl1, out y_ctrl1); if (ShapePath.is_curve(cmd)) { x_ctrl1 = x0 + x0 - x_ctrl1; y_ctrl1 = y0 + y0 - y_ctrl1; } else { x_ctrl1 = x0; y_ctrl1 = y0; } curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); } }
public ShapePath.FlagsAndCommand vertex(out double x, out double y) { x = 0; y = 0; ShapePath.FlagsAndCommand command = ShapePath.FlagsAndCommand.CommandStop; bool done = false; while (!done) { switch (m_status) { case status.initial: markers.remove_all(); m_last_cmd = VertexSource.vertex(out m_start_x, out m_start_y); m_status = status.accumulate; goto case status.accumulate; case status.accumulate: if (ShapePath.is_stop(m_last_cmd)) { return(ShapePath.FlagsAndCommand.CommandStop); } generator.RemoveAll(); generator.AddVertex(m_start_x, m_start_y, ShapePath.FlagsAndCommand.CommandMoveTo); markers.add_vertex(m_start_x, m_start_y, ShapePath.FlagsAndCommand.CommandMoveTo); for (; ;) { command = VertexSource.vertex(out x, out y); //DebugFile.Print("x=" + x.ToString() + " y=" + y.ToString() + "\n"); if (ShapePath.is_vertex(command)) { m_last_cmd = command; if (ShapePath.is_move_to(command)) { m_start_x = x; m_start_y = y; break; } generator.AddVertex(x, y, command); markers.add_vertex(x, y, ShapePath.FlagsAndCommand.CommandLineTo); } else { if (ShapePath.is_stop(command)) { m_last_cmd = ShapePath.FlagsAndCommand.CommandStop; break; } if (ShapePath.is_end_poly(command)) { generator.AddVertex(x, y, command); break; } } } generator.Rewind(0); m_status = status.generate; goto case status.generate; case status.generate: command = generator.Vertex(ref x, ref y); //DebugFile.Print("x=" + x.ToString() + " y=" + y.ToString() + "\n"); if (ShapePath.is_stop(command)) { m_status = status.accumulate; break; } done = true; break; } } return(command); }
private List <Vertex> TesselateLines(List <Vector2> points, Pen p) { List <ContourVertex> vecs = new List <ContourVertex>(); List <Vertex> ret = new List <Vertex>(); if (points.Count < 2) { return(ret); } var co = color(p.Color); MatterHackers.Agg.VertexSource.PathStorage ps = new MatterHackers.Agg.VertexSource.PathStorage(); ps.remove_all(); ps.MoveTo(points[0].X, points[0].Y); for (int i = 1; i < points.Count; i++) { ps.LineTo(points[i].X, points[i].Y); } ps.end_poly(); MatterHackers.Agg.VertexSource.Stroke str = new MatterHackers.Agg.VertexSource.Stroke(ps, p.Width); switch (p.Join) { case LineJoin.Round: str.line_join(MatterHackers.Agg.VertexSource.LineJoin.Round); str.inner_join(MatterHackers.Agg.VertexSource.InnerJoin.Round); break; case LineJoin.Miter: str.line_join(MatterHackers.Agg.VertexSource.LineJoin.Miter); str.inner_join(MatterHackers.Agg.VertexSource.InnerJoin.Miter); str.inner_miter_limit(p.MiterLimit); str.miter_limit(p.MiterLimit); break; } switch (p.Cap) { case LineCaps.Butt: str.line_cap(MatterHackers.Agg.VertexSource.LineCap.Butt); break; case LineCaps.Round: str.line_cap(MatterHackers.Agg.VertexSource.LineCap.Round); break; case LineCaps.Square: str.line_cap(MatterHackers.Agg.VertexSource.LineCap.Square); break; } str.rewind(0); double x, y; LibTessDotNet.Tess t = new LibTessDotNet.Tess(); ShapePath.FlagsAndCommand cmd; do { cmd = str.vertex(out x, out y); if (ShapePath.is_vertex(cmd)) { vecs.Add(new ContourVertex() { Position = new Vec3() { X = (float)x, Y = (float)y } }); } if (ShapePath.is_end_poly(cmd)) { t.AddContour(vecs.ToArray()); vecs.Clear(); } } while (!ShapePath.is_stop(cmd)); /* * foreach (var v in vertices) * { * if (!ShapePath.is_close(v.command) && !ShapePath.is_stop(v.command)) * vecs.Add(new Vector2((float)v.position.x, (float)v.position.y)); * }*/ if (vecs.Count != 0) { t.AddContour(vecs.ToArray()); } t.Tessellate(LibTessDotNet.WindingRule.NonZero, LibTessDotNet.ElementType.Polygons, 3); for (var i = 0; i < t.ElementCount; i++) { for (var tri = 0; tri < 3; tri++) { var v = t.Vertices[t.Elements[(i * 3) + tri]].Position; ret.Add(new Vertex(v.X, v.Y, co)); } } return(ret); }
public ShapePath.FlagsAndCommand vertex(out double x, out double y) { x = 0; y = 0; if (text != null && text.Length > 0) { ShapePath.FlagsAndCommand curCommand = ShapePath.FlagsAndCommand.CommandStop; if (currentGlyph != null) { curCommand = currentGlyph.vertex(out x, out y); } double xAlignOffset = 0; Vector2 size = GetSize(); switch (Justification) { case Justification.Left: xAlignOffset = 0; break; case Justification.Center: xAlignOffset = -size.x / 2; break; case Justification.Right: xAlignOffset = -size.x; break; default: throw new NotImplementedException(); } double yAlignOffset = 0; switch (Baseline) { case Baseline.Text: //yAlignOffset = -typeFaceStyle.DescentInPixels; yAlignOffset = 0; break; case Baseline.BoundsTop: yAlignOffset = -typeFaceStyle.AscentInPixels; break; case Baseline.BoundsCenter: yAlignOffset = -typeFaceStyle.AscentInPixels / 2; break; default: throw new NotImplementedException(); } while (curCommand == ShapePath.FlagsAndCommand.CommandStop && currentChar < text.Length - 1) { if (currentChar == 0 && text[currentChar] == '\n') { currentOffset.x = 0; currentOffset.y -= typeFaceStyle.EmSizeInPixels; } else { if (currentChar < text.Length) { // pass the next char so the typeFaceStyle can do kerning if it needs to. currentOffset.x += typeFaceStyle.GetAdvanceForCharacter(text[currentChar], text[currentChar + 1]); } else { currentOffset.x += typeFaceStyle.GetAdvanceForCharacter(text[currentChar]); } } currentChar++; currentGlyph = typeFaceStyle.GetGlyphForCharacter(text[currentChar]); if (currentGlyph != null) { currentGlyph.rewind(0); curCommand = currentGlyph.vertex(out x, out y); } else if (text[currentChar] == '\n') { if (currentChar + 1 < text.Length - 1 && (text[currentChar + 1] == '\n') && text[currentChar] != text[currentChar + 1]) { currentChar++; } currentOffset.x = 0; currentOffset.y -= typeFaceStyle.EmSizeInPixels; } } if (ShapePath.is_vertex(curCommand)) { x += currentOffset.x + xAlignOffset + Origin.x; y += currentOffset.y + yAlignOffset + Origin.y; } return(curCommand); } return(ShapePath.FlagsAndCommand.CommandStop); }