Optimize svg output sligtly
This commit is contained in:
parent
99cc16d0ac
commit
1588b49f0d
2 changed files with 63 additions and 16 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,19 +20,19 @@ func toSvgRGBA(c color.Color) string {
|
||||||
r, g, b, a := c.RGBA()
|
r, g, b, a := c.RGBA()
|
||||||
r, g, b, a = r>>8, g>>8, b>>8, a>>8
|
r, g, b, a = r>>8, g>>8, b>>8, a>>8
|
||||||
if a == 255 {
|
if a == 255 {
|
||||||
return fmt.Sprintf("#%02X%02X%02X", r, g, b)
|
return optiSprintf("#%02X%02X%02X", r, g, b)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("rgba(%v,%v,%v,%.3f)", r, g, b, float64(a)/255)
|
return optiSprintf("rgba(%v,%v,%v,%f)", r, g, b, float64(a)/255)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSvgLength(l float64) string {
|
func toSvgLength(l float64) string {
|
||||||
return fmt.Sprintf("%.4f", l)
|
return optiSprintf("%f", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSvgArray(nums []float64) string {
|
func toSvgArray(nums []float64) string {
|
||||||
arr := make([]string, len(nums))
|
arr := make([]string, len(nums))
|
||||||
for i, num := range nums {
|
for i, num := range nums {
|
||||||
arr[i] = fmt.Sprintf("%.4f", num)
|
arr[i] = optiSprintf("%f", num)
|
||||||
}
|
}
|
||||||
return strings.Join(arr, ",")
|
return strings.Join(arr, ",")
|
||||||
}
|
}
|
||||||
|
@ -49,16 +50,16 @@ func toSvgPathDesc(p *draw2d.Path) string {
|
||||||
for i, cmp := range p.Components {
|
for i, cmp := range p.Components {
|
||||||
switch cmp {
|
switch cmp {
|
||||||
case draw2d.MoveToCmp:
|
case draw2d.MoveToCmp:
|
||||||
parts[i] = fmt.Sprintf("M %.4f,%.4f", ps[0], ps[1])
|
parts[i] = optiSprintf("M %f,%f", ps[0], ps[1])
|
||||||
ps = ps[2:]
|
ps = ps[2:]
|
||||||
case draw2d.LineToCmp:
|
case draw2d.LineToCmp:
|
||||||
parts[i] = fmt.Sprintf("L %.4f,%.4f", ps[0], ps[1])
|
parts[i] = optiSprintf("L %f,%f", ps[0], ps[1])
|
||||||
ps = ps[2:]
|
ps = ps[2:]
|
||||||
case draw2d.QuadCurveToCmp:
|
case draw2d.QuadCurveToCmp:
|
||||||
parts[i] = fmt.Sprintf("Q %.4f,%.4f %.4f,%.4f", ps[0], ps[1], ps[2], ps[3])
|
parts[i] = optiSprintf("Q %f,%f %f,%f", ps[0], ps[1], ps[2], ps[3])
|
||||||
ps = ps[4:]
|
ps = ps[4:]
|
||||||
case draw2d.CubicCurveToCmp:
|
case draw2d.CubicCurveToCmp:
|
||||||
parts[i] = fmt.Sprintf("C %.4f,%.4f %.4f,%.4f %.4f,%.4f", ps[0], ps[1], ps[2], ps[3], ps[4], ps[5])
|
parts[i] = optiSprintf("C %f,%f %f,%f %f,%f", ps[0], ps[1], ps[2], ps[3], ps[4], ps[5])
|
||||||
ps = ps[6:]
|
ps = ps[6:]
|
||||||
case draw2d.ArcToCmp:
|
case draw2d.ArcToCmp:
|
||||||
cx, cy := ps[0], ps[1] // center
|
cx, cy := ps[0], ps[1] // center
|
||||||
|
@ -83,15 +84,15 @@ func toSvgPathDesc(p *draw2d.Path) string {
|
||||||
// dirty hack to ensure whole arc is drawn
|
// dirty hack to ensure whole arc is drawn
|
||||||
// if start point equals end point
|
// if start point equals end point
|
||||||
if sweep == 1 {
|
if sweep == 1 {
|
||||||
x += 0.001 * sinfi
|
x += 0.0001 * sinfi
|
||||||
y += 0.001 * -cosfi
|
y += 0.0001 * -cosfi
|
||||||
} else {
|
} else {
|
||||||
x += 0.001 * sinfi
|
x += 0.0001 * sinfi
|
||||||
y += 0.001 * cosfi
|
y += 0.0001 * cosfi
|
||||||
}
|
}
|
||||||
|
|
||||||
// rx ry x-axis-rotation large-arc-flag sweep-flag x y
|
// rx ry x-axis-rotation large-arc-flag sweep-flag x y
|
||||||
parts[i] = fmt.Sprintf("A %.4f %.4f %v %v %v %.4f %.4f",
|
parts[i] = optiSprintf("A %f %f %v %v %v %F %F",
|
||||||
rx, ry, 0, large, sweep, x, y,
|
rx, ry, 0, large, sweep, x, y,
|
||||||
)
|
)
|
||||||
ps = ps[6:]
|
ps = ps[6:]
|
||||||
|
@ -108,9 +109,9 @@ func toSvgTransform(mat draw2d.Matrix) string {
|
||||||
}
|
}
|
||||||
if mat.IsTranslation() {
|
if mat.IsTranslation() {
|
||||||
x, y := mat.GetTranslation()
|
x, y := mat.GetTranslation()
|
||||||
return fmt.Sprintf("translate(%f,%f)", x, y)
|
return optiSprintf("translate(%f,%f)", x, y)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("matrix(%f,%f,%f,%f,%f,%f)",
|
return optiSprintf("matrix(%f,%f,%f,%f,%f,%f)",
|
||||||
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5],
|
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -122,3 +123,49 @@ func imageToSvgHref(image image.Image) string {
|
||||||
out += base64.RawStdEncoding.EncodeToString(pngBuf.Bytes())
|
out += base64.RawStdEncoding.EncodeToString(pngBuf.Bytes())
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do the same thing as fmt.Sprintf
|
||||||
|
// except it uses the optimal precition for floats: (0-3) for f and (0-6) for F
|
||||||
|
// eg.:
|
||||||
|
// optiSprintf("%f", 3.0) => fmt.Sprintf("%.0f", 3.0)
|
||||||
|
// optiSprintf("%f", 3.33) => fmt.Sprintf("%.2f", 3.33)
|
||||||
|
// optiSprintf("%f", 3.3001) => fmt.Sprintf("%.1f", 3.3001)
|
||||||
|
// optiSprintf("%f", 3.333333333333333) => fmt.Sprintf("%.3f", 3.333333333333333)
|
||||||
|
// optiSprintf("%F", 3.333333333333333) => fmt.Sprintf("%.6f", 3.333333333333333)
|
||||||
|
func optiSprintf(format string, a ...interface{}) string {
|
||||||
|
chunks := strings.Split(format, "%")
|
||||||
|
newChunks := make([]string, len(chunks))
|
||||||
|
for i, chunk := range chunks {
|
||||||
|
if i != 0 {
|
||||||
|
verb := chunk[0]
|
||||||
|
if verb == 'f' || verb == 'F' {
|
||||||
|
num := a[i-1].(float64)
|
||||||
|
p := strconv.Itoa(getPrec(num, verb == 'F'))
|
||||||
|
chunk = strings.Replace(chunk, string(verb), "."+p+"f", 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newChunks[i] = chunk
|
||||||
|
}
|
||||||
|
format = strings.Join(newChunks, "%")
|
||||||
|
return fmt.Sprintf(format, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPrec(num float64, better bool) int {
|
||||||
|
max := 3
|
||||||
|
eps := 0.0005
|
||||||
|
if better {
|
||||||
|
max = 6
|
||||||
|
eps = 0.0000005
|
||||||
|
}
|
||||||
|
prec := 0
|
||||||
|
for math.Mod(num, 1) > eps {
|
||||||
|
num *= 10
|
||||||
|
eps *= 10
|
||||||
|
prec++
|
||||||
|
}
|
||||||
|
|
||||||
|
if max < prec {
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
return prec
|
||||||
|
}
|
||||||
|
|
|
@ -369,7 +369,7 @@ func (gc *GraphicContext) DrawImage(image image.Image) {
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// TODO implement following methods (or remove if not neccesary)
|
// TODO implement following methods (or remove if not neccesary)
|
||||||
|
|
||||||
// GetFontName gets the current FontData as a string
|
// GetFontName gets the current FontData with fontSize as a string
|
||||||
func (gc *GraphicContext) GetFontName() string {
|
func (gc *GraphicContext) GetFontName() string {
|
||||||
fontData := gc.Current.FontData
|
fontData := gc.Current.FontData
|
||||||
return fmt.Sprintf("%s:%d:%d:%d", fontData.Name, fontData.Family, fontData.Style, gc.Current.FontSize)
|
return fmt.Sprintf("%s:%d:%d:%d", fontData.Name, fontData.Family, fontData.Style, gc.Current.FontSize)
|
||||||
|
|
Loading…
Reference in a new issue