(sv *SVG)
| 62 | } |
| 63 | |
| 64 | func (g *Path) Render(sv *SVG) { |
| 65 | sz := len(g.Data) |
| 66 | if sz < 2 { |
| 67 | return |
| 68 | } |
| 69 | vis, pc := g.PushTransform(sv) |
| 70 | if !vis { |
| 71 | return |
| 72 | } |
| 73 | PathDataRender(g.Data, pc) |
| 74 | pc.FillStrokeClear() |
| 75 | |
| 76 | g.BBoxes(sv) |
| 77 | |
| 78 | if mrk := sv.MarkerByName(g, "marker-start"); mrk != nil { |
| 79 | // todo: could look for close-path at end and find angle from there.. |
| 80 | stv, ang := PathDataStart(g.Data) |
| 81 | mrk.RenderMarker(sv, stv, ang, g.Paint.StrokeStyle.Width.Dots) |
| 82 | } |
| 83 | if mrk := sv.MarkerByName(g, "marker-end"); mrk != nil { |
| 84 | env, ang := PathDataEnd(g.Data) |
| 85 | mrk.RenderMarker(sv, env, ang, g.Paint.StrokeStyle.Width.Dots) |
| 86 | } |
| 87 | if mrk := sv.MarkerByName(g, "marker-mid"); mrk != nil { |
| 88 | var ptm2, ptm1, pt math32.Vector2 |
| 89 | gotidx := 0 |
| 90 | PathDataIterFunc(g.Data, func(idx int, cmd PathCmds, ptIndex int, cp math32.Vector2, ctrls []math32.Vector2) bool { |
| 91 | ptm2 = ptm1 |
| 92 | ptm1 = pt |
| 93 | pt = cp |
| 94 | if gotidx < 2 { |
| 95 | gotidx++ |
| 96 | return true |
| 97 | } |
| 98 | if idx >= sz-3 { // todo: this is approximate... |
| 99 | return false |
| 100 | } |
| 101 | ang := 0.5 * (math32.Atan2(pt.Y-ptm1.Y, pt.X-ptm1.X) + math32.Atan2(ptm1.Y-ptm2.Y, ptm1.X-ptm2.X)) |
| 102 | mrk.RenderMarker(sv, ptm1, ang, g.Paint.StrokeStyle.Width.Dots) |
| 103 | gotidx++ |
| 104 | return true |
| 105 | }) |
| 106 | } |
| 107 | |
| 108 | g.RenderChildren(sv) |
| 109 | pc.PopTransform() |
| 110 | } |
| 111 | |
| 112 | // AddPath adds given path command to the PathData |
| 113 | func (g *Path) AddPath(cmd PathCmds, args ...float32) { |
nothing calls this directly
no test coverage detected