// Copyright 2017 The oksvg Authors. All rights reserved. // created: 2/12/2017 by S.R.Wiley // // utils.go implements translation of an SVG2.0 path into a rasterx Path. package oksvg import ( "image/color" "github.com/srwiley/rasterx" "golang.org/x/image/math/fixed" ) // SvgPath binds a style to a path. type SvgPath struct { PathStyle Path rasterx.Path } // Draw the compiled SvgPath into the Dasher. func (svgp *SvgPath) Draw(r *rasterx.Dasher, opacity float64) { svgp.DrawTransformed(r, opacity, rasterx.Identity) } // DrawTransformed draws the compiled SvgPath into the Dasher while applying transform t. func (svgp *SvgPath) DrawTransformed(r *rasterx.Dasher, opacity float64, t rasterx.Matrix2D) { m := svgp.mAdder.M svgp.mAdder.M = t.Mult(m) defer func() { svgp.mAdder.M = m }() // Restore untransformed matrix if svgp.fillerColor != nil { r.Clear() rf := &r.Filler rf.SetWinding(svgp.UseNonZeroWinding) svgp.mAdder.Adder = rf // This allows transformations to be applied svgp.Path.AddTo(&svgp.mAdder) switch fillerColor := svgp.fillerColor.(type) { case color.Color: rf.SetColor(rasterx.ApplyOpacity(fillerColor, svgp.FillOpacity*opacity)) case rasterx.Gradient: if fillerColor.Units == rasterx.ObjectBoundingBox { fRect := rf.Scanner.GetPathExtent() mnx, mny := float64(fRect.Min.X)/64, float64(fRect.Min.Y)/64 mxx, mxy := float64(fRect.Max.X)/64, float64(fRect.Max.Y)/64 fillerColor.Bounds.X, fillerColor.Bounds.Y = mnx, mny fillerColor.Bounds.W, fillerColor.Bounds.H = mxx-mnx, mxy-mny } rf.SetColor(fillerColor.GetColorFunction(svgp.FillOpacity * opacity)) } rf.Draw() // default is true rf.SetWinding(true) } if svgp.linerColor != nil { r.Clear() svgp.mAdder.Adder = r lineGap := svgp.LineGap if lineGap == nil { lineGap = DefaultStyle.LineGap } lineCap := svgp.LineCap if lineCap == nil { lineCap = DefaultStyle.LineCap } leadLineCap := lineCap if svgp.LeadLineCap != nil { leadLineCap = svgp.LeadLineCap } r.SetStroke(fixed.Int26_6(svgp.LineWidth*64), fixed.Int26_6(svgp.MiterLimit*64), leadLineCap, lineCap, lineGap, svgp.LineJoin, svgp.Dash, svgp.DashOffset) svgp.Path.AddTo(&svgp.mAdder) switch linerColor := svgp.linerColor.(type) { case color.Color: r.SetColor(rasterx.ApplyOpacity(linerColor, svgp.LineOpacity*opacity)) case rasterx.Gradient: if linerColor.Units == rasterx.ObjectBoundingBox { fRect := r.Scanner.GetPathExtent() mnx, mny := float64(fRect.Min.X)/64, float64(fRect.Min.Y)/64 mxx, mxy := float64(fRect.Max.X)/64, float64(fRect.Max.Y)/64 linerColor.Bounds.X, linerColor.Bounds.Y = mnx, mny linerColor.Bounds.W, linerColor.Bounds.H = mxx-mnx, mxy-mny } r.SetColor(linerColor.GetColorFunction(svgp.LineOpacity * opacity)) } r.Draw() } } // GetFillColor returns the fill color of the SvgPath if one is defined and otherwise returns colornames.Black func (svgp *SvgPath) GetFillColor() color.Color { return getColor(svgp.fillerColor) } // GetLineColor returns the stroke color of the SvgPath if one is defined and otherwise returns colornames.Black func (svgp *SvgPath) GetLineColor() color.Color { return getColor(svgp.linerColor) } // SetFillColor sets the fill color of the SvgPath func (svgp *SvgPath) SetFillColor(clr color.Color) { svgp.fillerColor = clr } // SetLineColor sets the line color of the SvgPath func (svgp *SvgPath) SetLineColor(clr color.Color) { svgp.linerColor = clr }