Merge pull request #125 from guzba/master

basic css support, path parse bugfixes, iconset test improvements
This commit is contained in:
treeform 2021-02-23 14:48:37 -08:00 committed by GitHub
commit 2dfe06ca60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 59 additions and 16 deletions

View file

@ -1,4 +1,4 @@
## Load and Save SVG files.
## Load SVG files.
import chroma, pixie/common, pixie/images, pixie/paths, strutils, vmath,
xmlparser, xmltree
@ -31,7 +31,7 @@ proc initCtx(): Ctx =
proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
result = inherited
let
var
fillRule = node.attr("fill-rule")
fill = node.attr("fill")
stroke = node.attr("stroke")
@ -39,6 +39,29 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
strokeLineCap = node.attr("stroke-linecap")
strokeLineJoin = node.attr("stroke-linejoin")
transform = node.attr("transform")
style = node.attr("style")
let pairs = style.split(';')
for pair in pairs:
let parts = pair.split(':')
if parts.len == 2:
# Do not override element properties
case parts[0].strip():
of "fill":
if fill.len == 0:
fill = parts[1].strip()
of "stroke":
if stroke.len == 0:
stroke = parts[1].strip()
of "stroke-linecap":
if strokeLineCap.len == 0:
strokeLineCap = parts[1].strip()
of "stroke-linejoin":
if strokeLineJoin.len == 0:
strokeLineJoin = parts[1].strip()
of "stroke-width":
if strokeWidth.len == 0:
strokeWidth = parts[1].strip()
if fillRule == "":
discard # Inherit
@ -68,6 +91,8 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
if strokeWidth == "":
discard # Inherit
else:
if strokeWidth.endsWith("px"):
strokeWidth = strokeWidth[0 .. ^3]
result.strokeWidth = parseFloat(strokeWidth)
if strokeLineCap == "":

View file

@ -124,6 +124,9 @@ proc parsePath*(path: string): Path =
armed = true
template expectsArcFlag(): bool =
kind in {Arc, RArc} and numbers.len mod 7 in {3, 4}
while p < path.len:
case path[p]:
# Relative
@ -195,7 +198,7 @@ proc parsePath*(path: string): Path =
finishNumber()
numberStart = p
of '.':
if hitDecimal:
if hitDecimal or expectsArcFlag():
finishNumber()
hitDecimal = true
if numberStart == 0:
@ -203,6 +206,12 @@ proc parsePath*(path: string): Path =
of ' ', ',', '\r', '\n', '\t':
finishNumber()
else:
if numberStart > 0 and expectsArcFlag():
finishNumber()
if p - 1 == numberStart and path[p - 1] == '0':
# If the number starts with 0 and we've hit another digit, finish the 0
# .. 01.3.. -> [..0, 1.3..]
finishNumber()
if numberStart == 0:
numberStart = p
@ -698,6 +707,9 @@ proc commandsToShapes*(path: Path, pixelScale: float32 = 1.0): seq[seq[Vec2]] =
case command.kind:
of Move:
if shape.len > 0:
result.add(shape)
shape.setLen(0)
at.x = command.numbers[0]
at.y = command.numbers[1]
start = at
@ -769,6 +781,9 @@ proc commandsToShapes*(path: Path, pixelScale: float32 = 1.0): seq[seq[Vec2]] =
at = to
of RMove:
if shape.len > 0:
result.add(shape)
shape.setLen(0)
at.x += command.numbers[0]
at.y += command.numbers[1]
start = at
@ -1256,7 +1271,9 @@ proc strokeShapes(
if strokeShape.len > 0:
result.add(strokeShape)
proc parseSomePath(path: SomePath, pixelScale:float32 = 1.0): seq[seq[Vec2]] {.inline.} =
proc parseSomePath(
path: SomePath, pixelScale: float32 = 1.0
): seq[seq[Vec2]] {.inline.} =
when type(path) is string:
parsePath(path).commandsToShapes(pixelScale)
elif type(path) is Path:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 KiB

After

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 KiB

After

Width:  |  Height:  |  Size: 519 KiB

View file

@ -25,7 +25,7 @@ const
IconSet(name: "flat-color-icons", path: "../flat-color-icons/svg/*"),
IconSet(name: "ionicons", path: "../ionicons/src/svg/*"),
# IconSet(name: "tabler-icons", path: "../tabler-icons/icons/*"),
# IconSet(name: "simple-icons", path: "../simple-icons/icons/*")
IconSet(name: "simple-icons", path: "../simple-icons/icons/*")
]
width = 32
height = 32

View file

@ -202,3 +202,15 @@ block:
path.arcTo(x, y, x + w, y, r)
mask.fillPath(path)
writeFile("tests/images/paths/pathRoundRectMask.png", mask.encodePng())
block:
let image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255))
var p = parsePath("M1 0.5C1 0.776142 0.776142 1 0.5 1C0.223858 1 0 0.776142 0 0.5C0 0.223858 0.223858 0 0.5 0C0.776142 0 1 0.223858 1 0.5Z")
image.fillPath(p, rgba(255, 0, 0, 255), scale(vec2(200, 200)))
image.strokePath(p, rgba(0, 255, 0, 255), scale(vec2(200, 200)),
strokeWidth = 0.01)
image.writeFile("tests/images/paths/pixelScale.png")

View file

@ -1,11 +0,0 @@
import pixie
let image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255))
var p = parsePath("M1 0.5C1 0.776142 0.776142 1 0.5 1C0.223858 1 0 0.776142 0 0.5C0 0.223858 0.223858 0 0.5 0C0.776142 0 1 0.223858 1 0.5Z")
image.fillPath(p, rgba(255, 0, 0, 255), scale(vec2(200, 200)))
image.strokePath(p, rgba(0, 255, 0, 255), scale(vec2(200, 200)), strokeWidth=0.01)
image.writeFile("tests/images/paths/pixelScale.png")