github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/app/imaging/svg.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package imaging 5 6 import ( 7 "encoding/xml" 8 "io" 9 "regexp" 10 "strconv" 11 12 "github.com/pkg/errors" 13 ) 14 15 // SVGInfo holds information for a SVG image. 16 type SVGInfo struct { 17 Width int 18 Height int 19 } 20 21 // ParseSVG returns information for the given SVG input data. 22 func ParseSVG(svgReader io.Reader) (SVGInfo, error) { 23 var parsedSVG struct { 24 Width string `xml:"width,attr,omitempty"` 25 Height string `xml:"height,attr,omitempty"` 26 ViewBox string `xml:"viewBox,attr,omitempty"` 27 } 28 svgInfo := SVGInfo{ 29 Width: 0, 30 Height: 0, 31 } 32 viewBoxPattern := regexp.MustCompile("^([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)$") 33 dimensionPattern := regexp.MustCompile("(?i)^([0-9]+)(?:px)?$") 34 35 // decode provided SVG 36 if err := xml.NewDecoder(svgReader).Decode(&parsedSVG); err != nil { 37 return svgInfo, err 38 } 39 40 // prefer viewbox for SVG dimensions over width/height 41 if viewBoxMatches := viewBoxPattern.FindStringSubmatch(parsedSVG.ViewBox); len(viewBoxMatches) == 5 { 42 svgInfo.Width, _ = strconv.Atoi(viewBoxMatches[3]) 43 svgInfo.Height, _ = strconv.Atoi(viewBoxMatches[4]) 44 } else if parsedSVG.Width != "" && parsedSVG.Height != "" { 45 widthMatches := dimensionPattern.FindStringSubmatch(parsedSVG.Width) 46 heightMatches := dimensionPattern.FindStringSubmatch(parsedSVG.Height) 47 if len(widthMatches) == 2 && len(heightMatches) == 2 { 48 svgInfo.Width, _ = strconv.Atoi(widthMatches[1]) 49 svgInfo.Height, _ = strconv.Atoi(heightMatches[1]) 50 } 51 } 52 53 // if width and/or height are still zero, create new error 54 if svgInfo.Width == 0 || svgInfo.Height == 0 { 55 return svgInfo, errors.New("unable to extract SVG dimensions") 56 } 57 return svgInfo, nil 58 }