fixing dash arrays and style handling in vector renderer.
This commit is contained in:
parent
98cda14767
commit
9ad15b3288
2 changed files with 55 additions and 44 deletions
40
style.go
40
style.go
|
@ -160,14 +160,17 @@ func (s Style) SVG(dpi float64) string {
|
||||||
if !fnc.IsZero() {
|
if !fnc.IsZero() {
|
||||||
fillText = "fill:" + fnc.String()
|
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.
|
// SVGStroke returns the stroke components.
|
||||||
func (s Style) SVGStroke() Style {
|
func (s Style) SVGStroke() Style {
|
||||||
return Style{
|
return Style{
|
||||||
StrokeColor: s.StrokeColor,
|
StrokeDashArray: s.StrokeDashArray,
|
||||||
StrokeWidth: s.StrokeWidth,
|
StrokeColor: s.StrokeColor,
|
||||||
|
StrokeWidth: s.StrokeWidth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,9 +184,10 @@ func (s Style) SVGFill() Style {
|
||||||
// SVGFillAndStroke returns the fill and stroke components.
|
// SVGFillAndStroke returns the fill and stroke components.
|
||||||
func (s Style) SVGFillAndStroke() Style {
|
func (s Style) SVGFillAndStroke() Style {
|
||||||
return Style{
|
return Style{
|
||||||
FillColor: s.FillColor,
|
StrokeDashArray: s.StrokeDashArray,
|
||||||
StrokeColor: s.StrokeColor,
|
FillColor: s.FillColor,
|
||||||
StrokeWidth: s.StrokeWidth,
|
StrokeColor: s.StrokeColor,
|
||||||
|
StrokeWidth: s.StrokeWidth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,3 +198,27 @@ func (s Style) SVGText() Style {
|
||||||
FontSize: s.FontSize,
|
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 ""
|
||||||
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ type vectorRenderer struct {
|
||||||
b *bytes.Buffer
|
b *bytes.Buffer
|
||||||
c *canvas
|
c *canvas
|
||||||
s *Style
|
s *Style
|
||||||
f *truetype.Font
|
|
||||||
p []string
|
p []string
|
||||||
fc *font.Drawer
|
fc *font.Drawer
|
||||||
}
|
}
|
||||||
|
@ -44,6 +43,7 @@ func (vr *vectorRenderer) GetDPI() float64 {
|
||||||
// SetDPI implements the interface method.
|
// SetDPI implements the interface method.
|
||||||
func (vr *vectorRenderer) SetDPI(dpi float64) {
|
func (vr *vectorRenderer) SetDPI(dpi float64) {
|
||||||
vr.dpi = dpi
|
vr.dpi = dpi
|
||||||
|
vr.c.dpi = dpi
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStrokeColor implements the interface method.
|
// SetStrokeColor implements the interface method.
|
||||||
|
@ -93,23 +93,25 @@ func (vr *vectorRenderer) Fill() {
|
||||||
|
|
||||||
// FillStroke draws the path with both fill and stroke.
|
// FillStroke draws the path with both fill and stroke.
|
||||||
func (vr *vectorRenderer) FillStroke() {
|
func (vr *vectorRenderer) FillStroke() {
|
||||||
vr.drawPath(vr.s.SVGFillAndStroke())
|
s := vr.s.SVGFillAndStroke()
|
||||||
|
vr.drawPath(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawPath draws a path.
|
// drawPath draws a path.
|
||||||
func (vr *vectorRenderer) drawPath(s Style) {
|
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
|
vr.p = []string{} // clear the path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Circle implements the interface method.
|
// Circle implements the interface method.
|
||||||
func (vr *vectorRenderer) Circle(radius float64, x, y int) {
|
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.
|
// SetFont implements the interface method.
|
||||||
func (vr *vectorRenderer) SetFont(f *truetype.Font) {
|
func (vr *vectorRenderer) SetFont(f *truetype.Font) {
|
||||||
vr.f = f
|
vr.s.Font = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFontColor implements the interface method.
|
// SetFontColor implements the interface method.
|
||||||
|
@ -122,29 +124,17 @@ func (vr *vectorRenderer) SetFontSize(size float64) {
|
||||||
vr.s.FontSize = size
|
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.
|
// Text draws a text blob.
|
||||||
func (vr *vectorRenderer) Text(body string, x, y int) {
|
func (vr *vectorRenderer) Text(body string, x, y int) {
|
||||||
s := vr.s.SVGText()
|
style := vr.s.SVGText()
|
||||||
vr.c.Text(x, y, body, s.SVG(vr.dpi)+";"+vr.svgFontFace())
|
vr.c.Text(x, y, body, &style)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MeasureText uses the truetype font drawer to measure the width of text.
|
// MeasureText uses the truetype font drawer to measure the width of text.
|
||||||
func (vr *vectorRenderer) MeasureText(body string) (box Box) {
|
func (vr *vectorRenderer) MeasureText(body string) (box Box) {
|
||||||
if vr.f != nil {
|
if vr.s.GetFont() != nil {
|
||||||
vr.fc = &font.Drawer{
|
vr.fc = &font.Drawer{
|
||||||
Face: truetype.NewFace(vr.f, &truetype.Options{
|
Face: truetype.NewFace(vr.s.GetFont(), &truetype.Options{
|
||||||
DPI: vr.dpi,
|
DPI: vr.dpi,
|
||||||
Size: vr.s.FontSize,
|
Size: vr.s.FontSize,
|
||||||
}),
|
}),
|
||||||
|
@ -172,6 +162,7 @@ func newCanvas(w io.Writer) *canvas {
|
||||||
|
|
||||||
type canvas struct {
|
type canvas struct {
|
||||||
w io.Writer
|
w io.Writer
|
||||||
|
dpi float64
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
}
|
}
|
||||||
|
@ -182,28 +173,20 @@ func (c *canvas) Start(width, height int) {
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="%d" height="%d">\n`, c.width, c.height)))
|
c.w.Write([]byte(fmt.Sprintf(`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="%d" height="%d">\n`, c.width, c.height)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *canvas) Path(d string, style ...string) {
|
func (c *canvas) Path(d string, style *Style) {
|
||||||
if len(style) > 0 {
|
var strokeDashArrayProperty string
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<path d="%s" style="%s"/>\n`, d, style[0])))
|
if len(style.StrokeDashArray) > 0 {
|
||||||
} else {
|
strokeDashArrayProperty = style.SVGStrokeDashArray()
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<path d="%s"/>\n`, d)))
|
|
||||||
}
|
}
|
||||||
|
c.w.Write([]byte(fmt.Sprintf(`<path %s d="%s" style="%s"/>\n`, strokeDashArrayProperty, d, style.SVG(c.dpi))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *canvas) Text(x, y int, body string, style ...string) {
|
func (c *canvas) Text(x, y int, body string, style *Style) {
|
||||||
if len(style) > 0 {
|
c.w.Write([]byte(fmt.Sprintf(`<text x="%d" y="%d" style="%s">%s</text>`, x, y, style.SVG(c.dpi), body)))
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<text x="%d" y="%d" style="%s">%s</text>`, x, y, style[0], body)))
|
|
||||||
} else {
|
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<text x="%d" y="%d">%s</text>`, x, y, body)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *canvas) Circle(x, y, r int, style ...string) {
|
func (c *canvas) Circle(x, y, r int, style *Style) {
|
||||||
if len(style) > 0 {
|
c.w.Write([]byte(fmt.Sprintf(`<circle cx="%d" cy="%d" r="%d" style="%s">`, x, y, r, style.SVG(c.dpi))))
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<circle cx="%d" cy="%d" r="%d" style="%s">`, x, y, r, style[0])))
|
|
||||||
} else {
|
|
||||||
c.w.Write([]byte(fmt.Sprintf(`<circle cx="%d" cy="%d" r="%d">`, x, y, r)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *canvas) End() {
|
func (c *canvas) End() {
|
||||||
|
|
Loading…
Reference in a new issue