parseSvg + newImage(svg)
This commit is contained in:
parent
993fa0750e
commit
a08a989a47
|
@ -28,7 +28,7 @@ proc decodeImage*(data: string): Image {.raises: [PixieError].} =
|
||||||
decodeBmp(data)
|
decodeBmp(data)
|
||||||
elif data.len > 5 and
|
elif data.len > 5 and
|
||||||
(data.readStr(0, 5) == xmlSignature or data.readStr(0, 4) == svgSignature):
|
(data.readStr(0, 5) == xmlSignature or data.readStr(0, 4) == svgSignature):
|
||||||
decodeSvg(data)
|
newImage(parseSvg(data))
|
||||||
elif data.len > 6 and data.readStr(0, 6) in gifSignatures:
|
elif data.len > 6 and data.readStr(0, 6) in gifSignatures:
|
||||||
decodeGif(data)
|
decodeGif(data)
|
||||||
elif data.len > (14+8) and data.readStr(0, 4) == qoiSignature:
|
elif data.len > (14+8) and data.readStr(0, 4) == qoiSignature:
|
||||||
|
|
|
@ -12,6 +12,7 @@ const
|
||||||
|
|
||||||
type
|
type
|
||||||
Svg* = ref object
|
Svg* = ref object
|
||||||
|
width*, height*: int
|
||||||
elements: seq[(Path, SvgProperties)]
|
elements: seq[(Path, SvgProperties)]
|
||||||
linearGradients: Table[string, LinearGradient]
|
linearGradients: Table[string, LinearGradient]
|
||||||
|
|
||||||
|
@ -498,10 +499,10 @@ proc parseSvgElement(
|
||||||
else:
|
else:
|
||||||
raise newException(PixieError, "Unsupported SVG tag: " & node.tag)
|
raise newException(PixieError, "Unsupported SVG tag: " & node.tag)
|
||||||
|
|
||||||
proc decodeSvg*(
|
proc parseSvg*(
|
||||||
data: string | XmlNode, width = 0, height = 0
|
data: string | XmlNode, width = 0, height = 0
|
||||||
): Image {.raises: [PixieError].} =
|
): Svg {.raises: [PixieError].} =
|
||||||
## Render SVG XML and return the image. Defaults to the SVG's view box size.
|
## Parse SVG XML. Defaults to the SVG's view box size.
|
||||||
try:
|
try:
|
||||||
let root = parseXml(data)
|
let root = parseXml(data)
|
||||||
if root.tag != "svg":
|
if root.tag != "svg":
|
||||||
|
@ -518,26 +519,38 @@ proc decodeSvg*(
|
||||||
var rootProps = initSvgProperties()
|
var rootProps = initSvgProperties()
|
||||||
rootProps = root.parseSvgProperties(rootProps)
|
rootProps = root.parseSvgProperties(rootProps)
|
||||||
|
|
||||||
|
|
||||||
if viewBoxMinX != 0 or viewBoxMinY != 0:
|
if viewBoxMinX != 0 or viewBoxMinY != 0:
|
||||||
let viewBoxMin = vec2(-viewBoxMinX.float32, -viewBoxMinY.float32)
|
let viewBoxMin = vec2(-viewBoxMinX.float32, -viewBoxMinY.float32)
|
||||||
rootprops.transform = rootprops.transform * translate(viewBoxMin)
|
rootprops.transform = rootprops.transform * translate(viewBoxMin)
|
||||||
|
|
||||||
|
result = Svg()
|
||||||
|
|
||||||
if width == 0 and height == 0: # Default to the view box size
|
if width == 0 and height == 0: # Default to the view box size
|
||||||
result = newImage(viewBoxWidth, viewBoxHeight)
|
result.width = viewBoxWidth
|
||||||
|
result.height = viewBoxHeight
|
||||||
else:
|
else:
|
||||||
result = newImage(width, height)
|
result.width = width
|
||||||
|
result.height = height
|
||||||
|
|
||||||
let
|
let
|
||||||
scaleX = width.float32 / viewBoxWidth.float32
|
scaleX = width.float32 / viewBoxWidth.float32
|
||||||
scaleY = height.float32 / viewBoxHeight.float32
|
scaleY = height.float32 / viewBoxHeight.float32
|
||||||
rootprops.transform = rootprops.transform * scale(vec2(scaleX, scaleY))
|
rootprops.transform = rootprops.transform * scale(vec2(scaleX, scaleY))
|
||||||
|
|
||||||
let svg = Svg()
|
|
||||||
|
|
||||||
var propertiesStack = @[rootProps]
|
var propertiesStack = @[rootProps]
|
||||||
for node in root.items:
|
for node in root.items:
|
||||||
svg.elements.add node.parseSvgElement(svg, propertiesStack)
|
result.elements.add node.parseSvgElement(result, propertiesStack)
|
||||||
|
except PixieError as e:
|
||||||
|
raise e
|
||||||
|
except:
|
||||||
|
raise currentExceptionAsPixieError()
|
||||||
|
|
||||||
|
proc newImage*(svg: Svg): Image {.raises: [PixieError].} =
|
||||||
|
## Render SVG and return the image.
|
||||||
|
result = newImage(svg.width, svg.height)
|
||||||
|
|
||||||
|
try:
|
||||||
for (path, props) in svg.elements:
|
for (path, props) in svg.elements:
|
||||||
if props.display and props.opacity > 0:
|
if props.display and props.opacity > 0:
|
||||||
if props.fill != "none":
|
if props.fill != "none":
|
||||||
|
@ -580,4 +593,4 @@ proc decodeSvg*(
|
||||||
except PixieError as e:
|
except PixieError as e:
|
||||||
raise e
|
raise e
|
||||||
except:
|
except:
|
||||||
raise newException(PixieError, "Unable to load SVG")
|
raise currentExceptionAsPixieError()
|
||||||
|
|
|
@ -2,5 +2,5 @@ import benchy, pixie/fileformats/svg
|
||||||
|
|
||||||
let data = readFile("tests/fileformats/svg/Ghostscript_Tiger.svg")
|
let data = readFile("tests/fileformats/svg/Ghostscript_Tiger.svg")
|
||||||
|
|
||||||
timeIt "svg decode":
|
timeIt "svg parse + render":
|
||||||
discard decodeSvg(data)
|
discard newImage(parseSvg(data))
|
||||||
|
|
|
@ -35,7 +35,7 @@ proc renderEmojiSet(index: int) =
|
||||||
let (_, name, _) = splitFile(filePath)
|
let (_, name, _) = splitFile(filePath)
|
||||||
var image: Image
|
var image: Image
|
||||||
try:
|
try:
|
||||||
image = decodeSvg(readFile(filePath), width, height)
|
image = newImage(parseSvg(readFile(filePath), width, height))
|
||||||
except PixieError:
|
except PixieError:
|
||||||
echo &"Failed decoding {name}"
|
echo &"Failed decoding {name}"
|
||||||
image = newImage(width, height)
|
image = newImage(width, height)
|
||||||
|
|
|
@ -38,7 +38,7 @@ proc renderIconSet(index: int) =
|
||||||
for filePath in walkFiles(iconSet.path):
|
for filePath in walkFiles(iconSet.path):
|
||||||
let
|
let
|
||||||
(_, name, _) = splitFile(filePath)
|
(_, name, _) = splitFile(filePath)
|
||||||
image = decodeSvg(readFile(filePath), width, height)
|
image = newImage(parseSvg(readFile(filePath), width, height))
|
||||||
|
|
||||||
images.add((name, image))
|
images.add((name, image))
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,8 @@ proc doDiff(rendered: Image, name: string) =
|
||||||
diffImage.writeFile(&"tests/fileformats/svg/diffs/{name}.png")
|
diffImage.writeFile(&"tests/fileformats/svg/diffs/{name}.png")
|
||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
doDiff(decodeSvg(readFile(&"tests/fileformats/svg/{file}.svg")), file)
|
doDiff(readImage(&"tests/fileformats/svg/{file}.svg"), file)
|
||||||
|
|
||||||
doDiff(
|
block:
|
||||||
decodeSvg(readFile("tests/fileformats/svg/accessibility-outline.svg"), 512, 512),
|
let svg = parseSvg(readFile("tests/fileformats/svg/accessibility-outline.svg"), 512, 512)
|
||||||
"accessibility-outline"
|
doDiff(newImage(svg), "accessibility-outline")
|
||||||
)
|
|
||||||
|
|
Loading…
Reference in a new issue