dev/import-beats/images_svg.go (85 lines of code) (raw):
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.
package main
import (
"encoding/xml"
"image"
"io"
"io/ioutil"
"strconv"
"strings"
"github.com/pkg/errors"
)
type svgFile struct {
Width string `xml:"width,attr"`
Height string `xml:"height,attr"`
ViewBox string `xml:"viewBox,attr"`
}
func SvgDecodeConfig(r io.Reader) (image.Config, error) {
data, err := ioutil.ReadAll(r)
if err != nil {
return image.Config{}, errors.Wrapf(err, "reading SVG file failed")
}
var svgFile svgFile
err = xml.Unmarshal(data, &svgFile)
if err != nil {
return image.Config{}, errors.Wrapf(err, "unmarshalling SVG file failed")
}
var width, height float64
if svgFile.Width != "" && svgFile.Height != "" {
width, err = svgParseToPixels(svgFile.Width)
if err != nil {
return image.Config{}, errors.Wrapf(err, "parsing width failed (value: %s)", svgFile.Width)
}
height, err = svgParseToPixels(svgFile.Height)
if err != nil {
return image.Config{}, errors.Wrapf(err, "parsing width failed (value: %s)", svgFile.Width)
}
}
if width > 0 && height > 0 {
return image.Config{
Width: int(width),
Height: int(height),
}, nil
}
dims := strings.Split(svgFile.ViewBox, " ")
var dimX, dimY string
if len(dims) == 2 {
dimX = dims[0]
dimY = dims[1]
} else if len(dims) == 4 {
dimX = dims[2]
dimY = dims[3]
}
width, err = strconv.ParseFloat(dimX, 32)
if err != nil {
return image.Config{}, errors.Wrapf(err, "parsing viewBox failed (value: %s)", svgFile.ViewBox)
}
height, err = strconv.ParseFloat(dimY, 32)
if err != nil {
return image.Config{}, errors.Wrapf(err, "parsing viewBox failed (value: %s)", svgFile.ViewBox)
}
return image.Config{
Width: int(width),
Height: int(height),
}, nil
}
func svgParseToPixels(value string) (float64, error) {
v, err := strconv.ParseFloat(value, 32)
if err != nil {
var unit string
var scale float64
if strings.Contains(value, "pt") {
unit = "pt"
scale = 4.0 / 3
} else if strings.Contains(value, "mm") {
unit = "mm"
scale = 3.77
}
value = strings.ReplaceAll(value, unit, "")
v, err = strconv.ParseFloat(value, 32)
if err != nil {
return -1, errors.Wrapf(err, "parsing width failed (value: %s)", value)
}
v = v * scale
}
return v, nil
}