From 9ad15b3288dccd21c95c328f388d87a47b17d503 Mon Sep 17 00:00:00 2001 From: Will Charczuk Date: Fri, 15 Jul 2016 18:19:29 -0700 Subject: [PATCH] fixing dash arrays and style handling in vector renderer. --- style.go | 40 ++++++++++++++++++++++++++----- vector_renderer.go | 59 +++++++++++++++++----------------------------- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/style.go b/style.go index c446f80..7c5e2f2 100644 --- a/style.go +++ b/style.go @@ -160,14 +160,17 @@ func (s Style) SVG(dpi float64) string { if !fnc.IsZero() { fillText = "fill:" + fnc.String() } - return strings.Join([]string{strokeWidthText, strokeText, fillText, fontSizeText}, ";") + + fontText := s.SVGFontFace() + return strings.Join([]string{strokeWidthText, strokeText, fillText, fontSizeText, fontText}, ";") } // SVGStroke returns the stroke components. func (s Style) SVGStroke() Style { return Style{ - StrokeColor: s.StrokeColor, - StrokeWidth: s.StrokeWidth, + StrokeDashArray: s.StrokeDashArray, + StrokeColor: s.StrokeColor, + StrokeWidth: s.StrokeWidth, } } @@ -181,9 +184,10 @@ func (s Style) SVGFill() Style { // SVGFillAndStroke returns the fill and stroke components. func (s Style) SVGFillAndStroke() Style { return Style{ - FillColor: s.FillColor, - StrokeColor: s.StrokeColor, - StrokeWidth: s.StrokeWidth, + StrokeDashArray: s.StrokeDashArray, + FillColor: s.FillColor, + StrokeColor: s.StrokeColor, + StrokeWidth: s.StrokeWidth, } } @@ -194,3 +198,27 @@ func (s Style) SVGText() Style { FontSize: s.FontSize, } } + +// SVGFontFace returns the font face for the style. +func (s Style) SVGFontFace() string { + family := "sans-serif" + if s.GetFont() != nil { + name := s.GetFont().Name(truetype.NameIDFontFamily) + if len(name) != 0 { + family = fmt.Sprintf(`'%s',%s`, name, family) + } + } + return fmt.Sprintf("font-family:%s", family) +} + +// SVGStrokeDashArray returns the stroke-dasharray property of a style. +func (s Style) SVGStrokeDashArray() string { + if len(s.StrokeDashArray) > 0 { + var values []string + for _, v := range s.StrokeDashArray { + values = append(values, fmt.Sprintf("%0.1f", v)) + } + return "stroke-dasharray=\"" + strings.Join(values, ", ") + "\"" + } + return "" +} diff --git a/vector_renderer.go b/vector_renderer.go index 9a7e4a1..606c7e2 100644 --- a/vector_renderer.go +++ b/vector_renderer.go @@ -31,7 +31,6 @@ type vectorRenderer struct { b *bytes.Buffer c *canvas s *Style - f *truetype.Font p []string fc *font.Drawer } @@ -44,6 +43,7 @@ func (vr *vectorRenderer) GetDPI() float64 { // SetDPI implements the interface method. func (vr *vectorRenderer) SetDPI(dpi float64) { vr.dpi = dpi + vr.c.dpi = dpi } // SetStrokeColor implements the interface method. @@ -93,23 +93,25 @@ func (vr *vectorRenderer) Fill() { // FillStroke draws the path with both fill and stroke. func (vr *vectorRenderer) FillStroke() { - vr.drawPath(vr.s.SVGFillAndStroke()) + s := vr.s.SVGFillAndStroke() + vr.drawPath(s) } // drawPath draws a path. func (vr *vectorRenderer) drawPath(s Style) { - vr.c.Path(strings.Join(vr.p, "\n"), s.SVG(vr.dpi)) + vr.c.Path(strings.Join(vr.p, "\n"), &s) vr.p = []string{} // clear the path } // Circle implements the interface method. func (vr *vectorRenderer) Circle(radius float64, x, y int) { - vr.c.Circle(x, y, int(radius), vr.s.SVG(vr.dpi)) + style := vr.s.SVGFillAndStroke() + vr.c.Circle(x, y, int(radius), &style) } // SetFont implements the interface method. func (vr *vectorRenderer) SetFont(f *truetype.Font) { - vr.f = f + vr.s.Font = f } // SetFontColor implements the interface method. @@ -122,29 +124,17 @@ func (vr *vectorRenderer) SetFontSize(size float64) { vr.s.FontSize = size } -// svgFontFace returns the font face component of an svg element style. -func (vr *vectorRenderer) svgFontFace() string { - family := "sans-serif" - if vr.f != nil { - name := vr.f.Name(truetype.NameIDFontFamily) - if len(name) != 0 { - family = fmt.Sprintf(`'%s',%s`, name, family) - } - } - return fmt.Sprintf("font-family:%s", family) -} - // Text draws a text blob. func (vr *vectorRenderer) Text(body string, x, y int) { - s := vr.s.SVGText() - vr.c.Text(x, y, body, s.SVG(vr.dpi)+";"+vr.svgFontFace()) + style := vr.s.SVGText() + vr.c.Text(x, y, body, &style) } // MeasureText uses the truetype font drawer to measure the width of text. func (vr *vectorRenderer) MeasureText(body string) (box Box) { - if vr.f != nil { + if vr.s.GetFont() != nil { vr.fc = &font.Drawer{ - Face: truetype.NewFace(vr.f, &truetype.Options{ + Face: truetype.NewFace(vr.s.GetFont(), &truetype.Options{ DPI: vr.dpi, Size: vr.s.FontSize, }), @@ -172,6 +162,7 @@ func newCanvas(w io.Writer) *canvas { type canvas struct { w io.Writer + dpi float64 width int height int } @@ -182,28 +173,20 @@ func (c *canvas) Start(width, height int) { c.w.Write([]byte(fmt.Sprintf(`\n`, c.width, c.height))) } -func (c *canvas) Path(d string, style ...string) { - if len(style) > 0 { - c.w.Write([]byte(fmt.Sprintf(`\n`, d, style[0]))) - } else { - c.w.Write([]byte(fmt.Sprintf(`\n`, d))) +func (c *canvas) Path(d string, style *Style) { + var strokeDashArrayProperty string + if len(style.StrokeDashArray) > 0 { + strokeDashArrayProperty = style.SVGStrokeDashArray() } + c.w.Write([]byte(fmt.Sprintf(`\n`, strokeDashArrayProperty, d, style.SVG(c.dpi)))) } -func (c *canvas) Text(x, y int, body string, style ...string) { - if len(style) > 0 { - c.w.Write([]byte(fmt.Sprintf(`%s`, x, y, style[0], body))) - } else { - c.w.Write([]byte(fmt.Sprintf(`%s`, x, y, body))) - } +func (c *canvas) Text(x, y int, body string, style *Style) { + c.w.Write([]byte(fmt.Sprintf(`%s`, x, y, style.SVG(c.dpi), body))) } -func (c *canvas) Circle(x, y, r int, style ...string) { - if len(style) > 0 { - c.w.Write([]byte(fmt.Sprintf(``, x, y, r, style[0]))) - } else { - c.w.Write([]byte(fmt.Sprintf(``, x, y, r))) - } +func (c *canvas) Circle(x, y, r int, style *Style) { + c.w.Write([]byte(fmt.Sprintf(``, x, y, r, style.SVG(c.dpi)))) } func (c *canvas) End() {