1package drawing 2 3// NewDashVertexConverter creates a new dash converter. 4func NewDashVertexConverter(dash []float64, dashOffset float64, flattener Flattener) *DashVertexConverter { 5 var dasher DashVertexConverter 6 dasher.dash = dash 7 dasher.currentDash = 0 8 dasher.dashOffset = dashOffset 9 dasher.next = flattener 10 return &dasher 11} 12 13// DashVertexConverter is a converter for dash vertexes. 14type DashVertexConverter struct { 15 next Flattener 16 x, y, distance float64 17 dash []float64 18 currentDash int 19 dashOffset float64 20} 21 22// LineTo implements the pathbuilder interface. 23func (dasher *DashVertexConverter) LineTo(x, y float64) { 24 dasher.lineTo(x, y) 25} 26 27// MoveTo implements the pathbuilder interface. 28func (dasher *DashVertexConverter) MoveTo(x, y float64) { 29 dasher.next.MoveTo(x, y) 30 dasher.x, dasher.y = x, y 31 dasher.distance = dasher.dashOffset 32 dasher.currentDash = 0 33} 34 35// LineJoin implements the pathbuilder interface. 36func (dasher *DashVertexConverter) LineJoin() { 37 dasher.next.LineJoin() 38} 39 40// Close implements the pathbuilder interface. 41func (dasher *DashVertexConverter) Close() { 42 dasher.next.Close() 43} 44 45// End implements the pathbuilder interface. 46func (dasher *DashVertexConverter) End() { 47 dasher.next.End() 48} 49 50func (dasher *DashVertexConverter) lineTo(x, y float64) { 51 rest := dasher.dash[dasher.currentDash] - dasher.distance 52 for rest < 0 { 53 dasher.distance = dasher.distance - dasher.dash[dasher.currentDash] 54 dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash) 55 rest = dasher.dash[dasher.currentDash] - dasher.distance 56 } 57 d := distance(dasher.x, dasher.y, x, y) 58 for d >= rest { 59 k := rest / d 60 lx := dasher.x + k*(x-dasher.x) 61 ly := dasher.y + k*(y-dasher.y) 62 if dasher.currentDash%2 == 0 { 63 // line 64 dasher.next.LineTo(lx, ly) 65 } else { 66 // gap 67 dasher.next.End() 68 dasher.next.MoveTo(lx, ly) 69 } 70 d = d - rest 71 dasher.x, dasher.y = lx, ly 72 dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash) 73 rest = dasher.dash[dasher.currentDash] 74 } 75 dasher.distance = d 76 if dasher.currentDash%2 == 0 { 77 // line 78 dasher.next.LineTo(x, y) 79 } else { 80 // gap 81 dasher.next.End() 82 dasher.next.MoveTo(x, y) 83 } 84 if dasher.distance >= dasher.dash[dasher.currentDash] { 85 dasher.distance = dasher.distance - dasher.dash[dasher.currentDash] 86 dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash) 87 } 88 dasher.x, dasher.y = x, y 89} 90