From 8dbe4ca71801aa5cbf7a9ea053f6909a07fb150f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20Fl=C3=B6tzinger?= Date: Mon, 29 Mar 2021 14:43:18 +0200 Subject: [PATCH] Change svg creation to be able to get filled --- svgwrite.go | 144 +++++++++++++++++++++++++++------------------------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/svgwrite.go b/svgwrite.go index 398a6dae..34f3a3f7 100644 --- a/svgwrite.go +++ b/svgwrite.go @@ -14,72 +14,80 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -package gofpdf + package gofpdf -// SVGBasicWrite renders the paths encoded in the basic SVG image specified by -// sb. The scale value is used to convert the coordinates in the path to the -// unit of measure specified in New(). The current position (as set with a call -// to SetXY()) is used as the origin of the image. The current line cap style -// (as set with SetLineCapStyle()), line width (as set with SetLineWidth()), -// and draw color (as set with SetDrawColor()) are used in drawing the image -// paths. -func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { - originX, originY := f.GetXY() - var x, y, newX, newY float64 - var cx0, cy0, cx1, cy1 float64 - var path []SVGBasicSegmentType - var seg SVGBasicSegmentType - var startX, startY float64 - sval := func(origin float64, arg int) float64 { - return origin + scale*seg.Arg[arg] - } - xval := func(arg int) float64 { - return sval(originX, arg) - } - yval := func(arg int) float64 { - return sval(originY, arg) - } - val := func(arg int) (float64, float64) { - return xval(arg), yval(arg + 1) - } - for j := 0; j < len(sb.Segments) && f.Ok(); j++ { - path = sb.Segments[j] - for k := 0; k < len(path) && f.Ok(); k++ { - seg = path[k] - switch seg.Cmd { - case 'M': - x, y = val(0) - startX, startY = x, y - f.SetXY(x, y) - case 'L': - newX, newY = val(0) - f.Line(x, y, newX, newY) - x, y = newX, newY - case 'C': - cx0, cy0 = val(0) - cx1, cy1 = val(2) - newX, newY = val(4) - f.CurveCubic(x, y, cx0, cy0, newX, newY, cx1, cy1, "D") - x, y = newX, newY - case 'Q': - cx0, cy0 = val(0) - newX, newY = val(2) - f.Curve(x, y, cx0, cy0, newX, newY, "D") - x, y = newX, newY - case 'H': - newX = xval(0) - f.Line(x, y, newX, y) - x = newX - case 'V': - newY = yval(0) - f.Line(x, y, x, newY) - y = newY - case 'Z': - f.Line(x, y, startX, startY) - x, y = startX, startY - default: - f.SetErrorf("Unexpected path command '%c'", seg.Cmd) - } - } - } -} + // SVGBasicWrite renders the paths encoded in the basic SVG image specified by + // sb. The scale value is used to convert the coordinates in the path to the + // unit of measure specified in New(). The current position (as set with a call + // to SetXY()) is used as the origin of the image. The current line cap style + // (as set with SetLineCapStyle()), line width (as set with SetLineWidth()), + // and draw color (as set with SetDrawColor()) are used in drawing the image + // paths. + // styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for + // outlined and filled. An empty string will be replaced with "D". + // Path-painting operators as defined in the PDF specification are also + // allowed: "S" (Stroke the path), "s" (Close and stroke the path), + // "f" (fill the path, using the nonzero winding number), "f*" + // (Fill the path, using the even-odd rule), "B" (Fill and then stroke + // the path, using the nonzero winding number rule), "B*" (Fill and + // then stroke the path, using the even-odd rule), "b" (Close, fill, + // and then stroke the path, using the nonzero winding number rule) and + // "b*" (Close, fill, and then stroke the path, using the even-odd + // rule). + func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64, styleStr string) { + originX, originY := f.GetXY() + var x, y, newX, newY float64 + var cx0, cy0, cx1, cy1 float64 + var path []SVGBasicSegmentType + var seg SVGBasicSegmentType + var startX, startY float64 + sval := func(origin float64, arg int) float64 { + return origin + scale*seg.Arg[arg] + } + xval := func(arg int) float64 { + return sval(originX, arg) + } + yval := func(arg int) float64 { + return sval(originY, arg) + } + val := func(arg int) (float64, float64) { + return xval(arg), yval(arg + 1) + } + for j := 0; j < len(sb.Segments) && f.Ok(); j++ { + path = sb.Segments[j] + for k := 0; k < len(path) && f.Ok(); k++ { + seg = path[k] + switch seg.Cmd { + case 'M': + x, y = val(0) + startX, startY = x, y + f.MoveTo(x, y) + case 'L': + newX, newY = val(0) + f.LineTo(newX, newY) + case 'C': + cx0, cy0 = val(0) + cx1, cy1 = val(2) + newX, newY = val(4) + f.CurveBezierCubicTo(cx0, cy0, cx1, cy1, newX, newY) + x, y = newX, newY + case 'Q': + cx0, cy0 = val(0) + newX, newY = val(2) + f.CurveTo(cx0, cy0, newX, newY) + x, y = newX, newY + case 'H': + newX = xval(0) + f.LineTo(newX, f.GetY()) + case 'V': + newY = yval(0) + f.LineTo(f.GetX(), newY) + case 'Z': + f.LineTo(startX, startY) + default: + f.SetErrorf("Unexpected path command '%c'", seg.Cmd) + } + } + } + f.DrawPath(styleStr) + }