1// Copyright 2017 The oksvg Authors. All rights reserved.
2// created: 2/12/2017 by S.R.Wiley
3//
4// utils.go implements translation of an SVG2.0 path into a rasterx Path.
5
6package oksvg
7
8import (
9 "image/color"
10
11 "github.com/srwiley/rasterx"
12 "golang.org/x/image/math/fixed"
13)
14
15// SvgPath binds a style to a path.
16type SvgPath struct {
17 PathStyle
18 Path rasterx.Path
19}
20
21// Draw the compiled SvgPath into the Dasher.
22func (svgp *SvgPath) Draw(r *rasterx.Dasher, opacity float64) {
23 svgp.DrawTransformed(r, opacity, rasterx.Identity)
24}
25
26// DrawTransformed draws the compiled SvgPath into the Dasher while applying transform t.
27func (svgp *SvgPath) DrawTransformed(r *rasterx.Dasher, opacity float64, t rasterx.Matrix2D) {
28 m := svgp.mAdder.M
29 svgp.mAdder.M = t.Mult(m)
30 defer func() { svgp.mAdder.M = m }() // Restore untransformed matrix
31 if svgp.fillerColor != nil {
32 r.Clear()
33 rf := &r.Filler
34 rf.SetWinding(svgp.UseNonZeroWinding)
35 svgp.mAdder.Adder = rf // This allows transformations to be applied
36 svgp.Path.AddTo(&svgp.mAdder)
37
38 switch fillerColor := svgp.fillerColor.(type) {
39 case color.Color:
40 rf.SetColor(rasterx.ApplyOpacity(fillerColor, svgp.FillOpacity*opacity))
41 case rasterx.Gradient:
42 if fillerColor.Units == rasterx.ObjectBoundingBox {
43 fRect := rf.Scanner.GetPathExtent()
44 mnx, mny := float64(fRect.Min.X)/64, float64(fRect.Min.Y)/64
45 mxx, mxy := float64(fRect.Max.X)/64, float64(fRect.Max.Y)/64
46 fillerColor.Bounds.X, fillerColor.Bounds.Y = mnx, mny
47 fillerColor.Bounds.W, fillerColor.Bounds.H = mxx-mnx, mxy-mny
48 }
49 rf.SetColor(fillerColor.GetColorFunction(svgp.FillOpacity * opacity))
50 }
51 rf.Draw()
52 // default is true
53 rf.SetWinding(true)
54 }
55 if svgp.linerColor != nil {
56 r.Clear()
57 svgp.mAdder.Adder = r
58 lineGap := svgp.LineGap
59 if lineGap == nil {
60 lineGap = DefaultStyle.LineGap
61 }
62 lineCap := svgp.LineCap
63 if lineCap == nil {
64 lineCap = DefaultStyle.LineCap
65 }
66 leadLineCap := lineCap
67 if svgp.LeadLineCap != nil {
68 leadLineCap = svgp.LeadLineCap
69 }
70 r.SetStroke(fixed.Int26_6(svgp.LineWidth*64),
71 fixed.Int26_6(svgp.MiterLimit*64), leadLineCap, lineCap,
72 lineGap, svgp.LineJoin, svgp.Dash, svgp.DashOffset)
73 svgp.Path.AddTo(&svgp.mAdder)
74 switch linerColor := svgp.linerColor.(type) {
75 case color.Color:
76 r.SetColor(rasterx.ApplyOpacity(linerColor, svgp.LineOpacity*opacity))
77 case rasterx.Gradient:
78 if linerColor.Units == rasterx.ObjectBoundingBox {
79 fRect := r.Scanner.GetPathExtent()
80 mnx, mny := float64(fRect.Min.X)/64, float64(fRect.Min.Y)/64
81 mxx, mxy := float64(fRect.Max.X)/64, float64(fRect.Max.Y)/64
82 linerColor.Bounds.X, linerColor.Bounds.Y = mnx, mny
83 linerColor.Bounds.W, linerColor.Bounds.H = mxx-mnx, mxy-mny
84 }
85 r.SetColor(linerColor.GetColorFunction(svgp.LineOpacity * opacity))
86 }
87 r.Draw()
88 }
89}
90
91// GetFillColor returns the fill color of the SvgPath if one is defined and otherwise returns colornames.Black
92func (svgp *SvgPath) GetFillColor() color.Color {
93 return getColor(svgp.fillerColor)
94}
95
96// GetLineColor returns the stroke color of the SvgPath if one is defined and otherwise returns colornames.Black
97func (svgp *SvgPath) GetLineColor() color.Color {
98 return getColor(svgp.linerColor)
99}
100
101// SetFillColor sets the fill color of the SvgPath
102func (svgp *SvgPath) SetFillColor(clr color.Color) {
103 svgp.fillerColor = clr
104}
105
106// SetLineColor sets the line color of the SvgPath
107func (svgp *SvgPath) SetLineColor(clr color.Color) {
108 svgp.linerColor = clr
109}