svg_path.go

  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}