Merge pull request #254 from guzba/master

path as ref object
This commit is contained in:
treeform 2021-08-06 14:36:19 -07:00 committed by GitHub
commit 5a655bf543
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 130 additions and 115 deletions

View file

@ -127,19 +127,20 @@ image.fillText(font.typeset(text, bounds = vec2(180, 180)), vec2(10, 10))
### Text spans ### Text spans
[examples/text_spans.nim](examples/text_spans.nim) [examples/text_spans.nim](examples/text_spans.nim)
```nim ```nim
let font = readFont("tests/fonts/Ubuntu-Regular_1.ttf") let typeface = readTypeface("tests/fonts/Ubuntu-Regular_1.ttf")
proc style(font: Font, size: float32, color: ColorRGBA): Font = proc newFont(typeface: Typeface, size: float32, color: ColorRGBA): Font =
result = font result = newFont(typeface)
result.size = size result.size = size
result.paint.color = color result.paint.color = color
let spans = @[ let spans = @[
newSpan("verb [with object] ", font.style(12, rgba(200, 200, 200, 255))), newSpan("verb [with object] ",
newSpan("strallow\n", font.style(36, rgba(0, 0, 0, 255))), typeface.newFont(12, rgba(200, 200, 200, 255))),
newSpan("\nstral·low\n", font.style(13, rgba(0, 127, 244, 255))), newSpan("strallow\n", typeface.newFont(36, rgba(0, 0, 0, 255))),
newSpan("\nstral·low\n", typeface.newFont(13, rgba(0, 127, 244, 255))),
newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ", newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ",
font.style(14, rgba(80, 80, 80, 255))) typeface.newFont(14, rgba(80, 80, 80, 255)))
] ]
image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10)) image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))
@ -265,7 +266,7 @@ image.fillPath(
### Image tiled ### Image tiled
[examples/image_tiled.nim](examples/image_tiled.nim) [examples/image_tiled.nim](examples/image_tiled.nim)
```nim ```nim
var path: Path let path = newPath()
path.polygon( path.polygon(
vec2(100, 100), vec2(100, 100),
70, 70,

View file

@ -3,7 +3,7 @@ import pixie
let image = newImage(200, 200) let image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255)) image.fill(rgba(255, 255, 255, 255))
var path: Path let path = newPath()
path.polygon( path.polygon(
vec2(100, 100), vec2(100, 100),
70, 70,

View file

@ -3,19 +3,20 @@ import pixie
let image = newImage(200, 200) let image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255)) image.fill(rgba(255, 255, 255, 255))
let font = readFont("tests/fonts/Ubuntu-Regular_1.ttf") let typeface = readTypeface("tests/fonts/Ubuntu-Regular_1.ttf")
proc style(font: Font, size: float32, color: ColorRGBA): Font = proc newFont(typeface: Typeface, size: float32, color: ColorRGBA): Font =
result = font result = newFont(typeface)
result.size = size result.size = size
result.paint.color = color result.paint.color = color
let spans = @[ let spans = @[
newSpan("verb [with object] ", font.style(12, rgba(200, 200, 200, 255))), newSpan("verb [with object] ",
newSpan("strallow\n", font.style(36, rgba(0, 0, 0, 255))), typeface.newFont(12, rgba(200, 200, 200, 255))),
newSpan("\nstral·low\n", font.style(13, rgba(0, 127, 244, 255))), newSpan("strallow\n", typeface.newFont(36, rgba(0, 0, 0, 255))),
newSpan("\nstral·low\n", typeface.newFont(13, rgba(0, 127, 244, 255))),
newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ", newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ",
font.style(14, rgba(80, 80, 80, 255))) typeface.newFont(14, rgba(80, 80, 80, 255)))
] ]
image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10)) image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -103,7 +103,7 @@ proc fillRect*(
transform: Vec2 | Mat3 = vec2(0, 0) transform: Vec2 | Mat3 = vec2(0, 0)
) = ) =
## Fills a rectangle. ## Fills a rectangle.
var path: Path let path = newPath()
path.rect(rect) path.rect(rect)
mask.fillPath(path, transform) mask.fillPath(path, transform)
@ -114,7 +114,7 @@ proc strokeRect*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes a rectangle. ## Strokes a rectangle.
var path: Path let path = newPath()
path.rect(rect) path.rect(rect)
mask.strokePath(path, transform, strokeWidth) mask.strokePath(path, transform, strokeWidth)
@ -125,7 +125,7 @@ proc fillRoundedRect*(
transform: Vec2 | Mat3 = vec2(0, 0) transform: Vec2 | Mat3 = vec2(0, 0)
) = ) =
## Fills a rounded rectangle. ## Fills a rounded rectangle.
var path: Path let path = newPath()
path.roundedRect(rect, nw, ne, se, sw) path.roundedRect(rect, nw, ne, se, sw)
mask.fillPath(path, transform) mask.fillPath(path, transform)
@ -136,7 +136,7 @@ proc fillRoundedRect*(
transform: Vec2 | Mat3 = vec2(0, 0) transform: Vec2 | Mat3 = vec2(0, 0)
) = ) =
## Fills a rounded rectangle. ## Fills a rounded rectangle.
var path: Path let path = newPath()
path.roundedRect(rect, radius, radius, radius, radius) path.roundedRect(rect, radius, radius, radius, radius)
mask.fillPath(path, transform) mask.fillPath(path, transform)
@ -148,7 +148,7 @@ proc strokeRoundedRect*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes a rounded rectangle. ## Strokes a rounded rectangle.
var path: Path let path = newPath()
path.roundedRect(rect, nw, ne, se, sw) path.roundedRect(rect, nw, ne, se, sw)
mask.strokePath(path, transform, strokeWidth) mask.strokePath(path, transform, strokeWidth)
@ -160,7 +160,7 @@ proc strokeRoundedRect*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes a rounded rectangle. ## Strokes a rounded rectangle.
var path: Path let path = newPath()
path.roundedRect(rect, radius, radius, radius, radius) path.roundedRect(rect, radius, radius, radius, radius)
mask.strokePath(path, transform, strokeWidth) mask.strokePath(path, transform, strokeWidth)
@ -171,7 +171,7 @@ proc strokeSegment*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes a segment (draws a line from segment.at to segment.to). ## Strokes a segment (draws a line from segment.at to segment.to).
var path: Path let path = newPath()
path.moveTo(segment.at) path.moveTo(segment.at)
path.lineTo(segment.to) path.lineTo(segment.to)
mask.strokePath(path, transform, strokeWidth) mask.strokePath(path, transform, strokeWidth)
@ -183,7 +183,7 @@ proc fillEllipse*(
transform: Vec2 | Mat3 = vec2(0, 0) transform: Vec2 | Mat3 = vec2(0, 0)
) = ) =
## Fills an ellipse. ## Fills an ellipse.
var path: Path let path = newPath()
path.ellipse(center, rx, ry) path.ellipse(center, rx, ry)
mask.fillPath(path, transform) mask.fillPath(path, transform)
@ -195,7 +195,7 @@ proc strokeEllipse*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes an ellipse. ## Strokes an ellipse.
var path: Path let path = newPath()
path.ellipse(center, rx, ry) path.ellipse(center, rx, ry)
mask.strokePath(path, transform, strokeWidth) mask.strokePath(path, transform, strokeWidth)
@ -206,7 +206,7 @@ proc fillCircle*(
transform: Vec2 | Mat3 = vec2(0, 0) transform: Vec2 | Mat3 = vec2(0, 0)
) = ) =
## Fills a circle. ## Fills a circle.
var path: Path let path = newPath()
path.ellipse(center, radius, radius) path.ellipse(center, radius, radius)
mask.fillPath(path, transform) mask.fillPath(path, transform)
@ -218,7 +218,7 @@ proc strokeCircle*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes a circle. ## Strokes a circle.
var path: Path let path = newPath()
path.ellipse(center, radius, radius) path.ellipse(center, radius, radius)
mask.fillPath(path, transform, strokeWidth) mask.fillPath(path, transform, strokeWidth)
@ -230,7 +230,7 @@ proc fillPolygon*(
transform: Vec2 | Mat3 = vec2(0, 0) transform: Vec2 | Mat3 = vec2(0, 0)
) = ) =
## Fills a polygon. ## Fills a polygon.
var path: Path let path = newPath()
path.polygon(pos, size, sides) path.polygon(pos, size, sides)
mask.fillPath(path, transform) mask.fillPath(path, transform)
@ -243,6 +243,6 @@ proc strokePolygon*(
strokeWidth = 1.0 strokeWidth = 1.0
) = ) =
## Strokes a polygon. ## Strokes a polygon.
var path: Path let path = newPath()
path.polygon(pos, size, sides) path.polygon(pos, size, sides)
mask.strokePath(path, transform, strokeWidth) mask.strokePath(path, transform, strokeWidth)

View file

@ -1,5 +1,5 @@
import bumpy, chroma, tables, pixie/blends, pixie/common, pixie/fonts, import bumpy, chroma, pixie/blends, pixie/common, pixie/fonts, pixie/images,
pixie/images, pixie/masks, pixie/paints, pixie/paths, vmath pixie/masks, pixie/paints, pixie/paths, tables, vmath
## This file provides a Nim version of the Canvas 2D API commonly used on the ## This file provides a Nim version of the Canvas 2D API commonly used on the
## web. The goal is to make picking up Pixie easy for developers familiar with ## web. The goal is to make picking up Pixie easy for developers familiar with
@ -49,6 +49,7 @@ proc newContext*(image: Image): Context =
result = Context() result = Context()
result.image = image result.image = image
result.mat = mat3() result.mat = mat3()
result.path = newPath()
result.globalAlpha = 1 result.globalAlpha = 1
result.lineWidth = 1 result.lineWidth = 1
result.miterLimit = 10 result.miterLimit = 10
@ -164,7 +165,7 @@ proc stroke(ctx: Context, image: Image, path: Path) =
ctx.layer.applyOpacity(ctx.globalAlpha) ctx.layer.applyOpacity(ctx.globalAlpha)
ctx.restore() ctx.restore()
proc createFont(ctx: Context): Font = proc newFont(ctx: Context): Font =
if ctx.font == "": if ctx.font == "":
raise newException(PixieError, "No font has been set on this Context") raise newException(PixieError, "No font has been set on this Context")
@ -175,7 +176,7 @@ proc createFont(ctx: Context): Font =
result.size = ctx.fontSize result.size = ctx.fontSize
proc fillText(ctx: Context, image: Image, text: string, at: Vec2) = proc fillText(ctx: Context, image: Image, text: string, at: Vec2) =
let font = ctx.createFont() let font = newFont(ctx)
# Canvas positions text relative to the alphabetic baseline by default # Canvas positions text relative to the alphabetic baseline by default
var at = at var at = at
@ -201,7 +202,7 @@ proc fillText(ctx: Context, image: Image, text: string, at: Vec2) =
ctx.restore() ctx.restore()
proc strokeText(ctx: Context, image: Image, text: string, at: Vec2) = proc strokeText(ctx: Context, image: Image, text: string, at: Vec2) =
let font = ctx.createFont() let font = newFont(ctx)
# Canvas positions text relative to the alphabetic baseline by default # Canvas positions text relative to the alphabetic baseline by default
var at = at var at = at
@ -233,7 +234,7 @@ proc strokeText(ctx: Context, image: Image, text: string, at: Vec2) =
proc beginPath*(ctx: Context) {.inline.} = proc beginPath*(ctx: Context) {.inline.} =
## Starts a new path by emptying the list of sub-paths. ## Starts a new path by emptying the list of sub-paths.
ctx.path = Path() ctx.path = newPath()
proc moveTo*(ctx: Context, v: Vec2) {.inline.} = proc moveTo*(ctx: Context, v: Vec2) {.inline.} =
## Begins a new sub-path at the point (x, y). ## Begins a new sub-path at the point (x, y).
@ -355,7 +356,7 @@ proc stroke*(ctx: Context) {.inline.} =
proc clearRect*(ctx: Context, rect: Rect) = proc clearRect*(ctx: Context, rect: Rect) =
## Erases the pixels in a rectangular area. ## Erases the pixels in a rectangular area.
var path: Path let path = newPath()
path.rect(rect) path.rect(rect)
if ctx.layer != nil: if ctx.layer != nil:
ctx.layer.fillPath( ctx.layer.fillPath(
@ -376,7 +377,7 @@ proc clearRect*(ctx: Context, x, y, width, height: float32) {.inline.} =
proc fillRect*(ctx: Context, rect: Rect) = proc fillRect*(ctx: Context, rect: Rect) =
## Draws a rectangle that is filled according to the current fillStyle. ## Draws a rectangle that is filled according to the current fillStyle.
var path: Path let path = newPath()
path.rect(rect) path.rect(rect)
ctx.fill(path) ctx.fill(path)
@ -387,7 +388,7 @@ proc fillRect*(ctx: Context, x, y, width, height: float32) {.inline.} =
proc strokeRect*(ctx: Context, rect: Rect) = proc strokeRect*(ctx: Context, rect: Rect) =
## Draws a rectangle that is stroked (outlined) according to the current ## Draws a rectangle that is stroked (outlined) according to the current
## strokeStyle and other context settings. ## strokeStyle and other context settings.
var path: Path let path = newPath()
path.rect(rect) path.rect(rect)
ctx.stroke(path) ctx.stroke(path)
@ -434,7 +435,7 @@ proc measureText*(ctx: Context, text: string): TextMetrics =
## Returns a TextMetrics object that contains information about the measured ## Returns a TextMetrics object that contains information about the measured
## text (such as its width, for example). ## text (such as its width, for example).
let let
font = ctx.createFont() font = newFont(ctx)
bounds = typeset(font, text).computeBounds() bounds = typeset(font, text).computeBounds()
result.width = bounds.x result.width = bounds.x
@ -520,7 +521,7 @@ proc polygon*(ctx: Context, pos: Vec2, size: float32, sides: int) {.inline.} =
proc fillRoundedRect*(ctx: Context, rect: Rect, nw, ne, se, sw: float32) = proc fillRoundedRect*(ctx: Context, rect: Rect, nw, ne, se, sw: float32) =
## Draws a rounded rectangle that is filled according to the current fillStyle. ## Draws a rounded rectangle that is filled according to the current fillStyle.
var path: Path let path = newPath()
path.roundedRect(rect, nw, ne, se, sw) path.roundedRect(rect, nw, ne, se, sw)
ctx.fill(path) ctx.fill(path)
@ -531,7 +532,7 @@ proc fillRoundedRect*(ctx: Context, rect: Rect, radius: float32) {.inline.} =
proc strokeRoundedRect*(ctx: Context, rect: Rect, nw, ne, se, sw: float32) = proc strokeRoundedRect*(ctx: Context, rect: Rect, nw, ne, se, sw: float32) =
## Draws a rounded rectangle that is stroked (outlined) according to the ## Draws a rounded rectangle that is stroked (outlined) according to the
## current strokeStyle and other context settings. ## current strokeStyle and other context settings.
var path: Path let path = newPath()
path.roundedRect(rect, nw, ne, se, sw) path.roundedRect(rect, nw, ne, se, sw)
ctx.stroke(path) ctx.stroke(path)
@ -543,61 +544,61 @@ proc strokeRoundedRect*(ctx: Context, rect: Rect, radius: float32) {.inline.} =
proc strokeSegment*(ctx: Context, segment: Segment) = proc strokeSegment*(ctx: Context, segment: Segment) =
## Strokes a segment (draws a line from segment.at to segment.to) according ## Strokes a segment (draws a line from segment.at to segment.to) according
## to the current strokeStyle and other context settings. ## to the current strokeStyle and other context settings.
var path: Path let path = newPath()
path.moveTo(segment.at) path.moveTo(segment.at)
path.lineTo(segment.to) path.lineTo(segment.to)
ctx.stroke(path) ctx.stroke(path)
proc fillEllipse*(ctx: Context, center: Vec2, rx, ry: float32) = proc fillEllipse*(ctx: Context, center: Vec2, rx, ry: float32) =
## Draws an ellipse that is filled according to the current fillStyle. ## Draws an ellipse that is filled according to the current fillStyle.
var path: Path let path = newPath()
path.ellipse(center, rx, ry) path.ellipse(center, rx, ry)
ctx.fill(path) ctx.fill(path)
proc strokeEllipse*(ctx: Context, center: Vec2, rx, ry: float32) = proc strokeEllipse*(ctx: Context, center: Vec2, rx, ry: float32) =
## Draws an ellipse that is stroked (outlined) according to the current ## Draws an ellipse that is stroked (outlined) according to the current
## strokeStyle and other context settings. ## strokeStyle and other context settings.
var path: Path let path = newPath()
path.ellipse(center, rx, ry) path.ellipse(center, rx, ry)
ctx.stroke(path) ctx.stroke(path)
proc fillCircle*(ctx: Context, circle: Circle) = proc fillCircle*(ctx: Context, circle: Circle) =
## Draws a circle that is filled according to the current fillStyle ## Draws a circle that is filled according to the current fillStyle
var path: Path let path = newPath()
path.circle(circle.pos, circle.radius) path.circle(circle.pos, circle.radius)
ctx.fill(path) ctx.fill(path)
proc fillCircle*(ctx: Context, center: Vec2, radius: float32) = proc fillCircle*(ctx: Context, center: Vec2, radius: float32) =
## Draws a circle that is filled according to the current fillStyle. ## Draws a circle that is filled according to the current fillStyle.
var path: Path let path = newPath()
path.ellipse(center, radius, radius) path.ellipse(center, radius, radius)
ctx.fill(path) ctx.fill(path)
proc strokeCircle*(ctx: Context, circle: Circle) = proc strokeCircle*(ctx: Context, circle: Circle) =
## Draws a circle that is stroked (outlined) according to the current ## Draws a circle that is stroked (outlined) according to the current
## strokeStyle and other context settings. ## strokeStyle and other context settings.
var path: Path let path = newPath()
path.circle(circle.pos, circle.radius) path.circle(circle.pos, circle.radius)
ctx.stroke(path) ctx.stroke(path)
proc strokeCircle*(ctx: Context, center: Vec2, radius: float32) = proc strokeCircle*(ctx: Context, center: Vec2, radius: float32) =
## Draws a circle that is stroked (outlined) according to the current ## Draws a circle that is stroked (outlined) according to the current
## strokeStyle and other context settings. ## strokeStyle and other context settings.
var path: Path let path = newPath()
path.ellipse(center, radius, radius) path.ellipse(center, radius, radius)
ctx.stroke(path) ctx.stroke(path)
proc fillPolygon*(ctx: Context, pos: Vec2, size: float32, sides: int) = proc fillPolygon*(ctx: Context, pos: Vec2, size: float32, sides: int) =
## Draws an n-sided regular polygon at (x, y) of size that is filled according ## Draws an n-sided regular polygon at (x, y) of size that is filled according
## to the current fillStyle. ## to the current fillStyle.
var path: Path let path = newPath()
path.polygon(pos, size, sides) path.polygon(pos, size, sides)
ctx.fill(path) ctx.fill(path)
proc strokePolygon*(ctx: Context, pos: Vec2, size: float32, sides: int) = proc strokePolygon*(ctx: Context, pos: Vec2, size: float32, sides: int) =
## Draws an n-sided regular polygon at (x, y) of size that is stroked ## Draws an n-sided regular polygon at (x, y) of size that is stroked
## (outlined) according to the current strokeStyle and other context settings. ## (outlined) according to the current strokeStyle and other context settings.
var path: Path let path = newPath()
path.polygon(pos, size, sides) path.polygon(pos, size, sides)
ctx.stroke(path) ctx.stroke(path)
@ -610,7 +611,7 @@ proc drawImage*(ctx: Context, image: Image, dx, dy, dWidth, dHeight: float32) =
)) ))
savedStyle = ctx.fillStyle savedStyle = ctx.fillStyle
ctx.fillStyle = Paint(kind: pkImage, image: image, imageMat: imageMat) ctx.fillStyle = Paint(kind: pkImage, image: image, imageMat: imageMat)
var path: Path let path = newPath()
path.rect(rect(dx, dy, dWidth, dHeight)) path.rect(rect(dx, dy, dWidth, dHeight))
ctx.fill(path) ctx.fill(path)
ctx.fillStyle = savedStyle ctx.fillStyle = savedStyle

View file

@ -376,7 +376,7 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
x2 = parseFloat(node.attrOrDefault("x2", "0")) x2 = parseFloat(node.attrOrDefault("x2", "0"))
y2 = parseFloat(node.attrOrDefault("y2", "0")) y2 = parseFloat(node.attrOrDefault("y2", "0"))
var path: Path let path = newPath()
path.moveTo(x1, y1) path.moveTo(x1, y1)
path.lineTo(x2, y2) path.lineTo(x2, y2)
@ -405,7 +405,7 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
if vecs.len == 0: if vecs.len == 0:
failInvalid() failInvalid()
var path: Path let path = newPath()
path.moveTo(vecs[0]) path.moveTo(vecs[0])
for i in 1 ..< vecs.len: for i in 1 ..< vecs.len:
path.lineTo(vecs[i]) path.lineTo(vecs[i])
@ -434,7 +434,7 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
rx = max(parseFloat(node.attrOrDefault("rx", "0")), 0) rx = max(parseFloat(node.attrOrDefault("rx", "0")), 0)
ry = max(parseFloat(node.attrOrDefault("ry", "0")), 0) ry = max(parseFloat(node.attrOrDefault("ry", "0")), 0)
var path: Path let path = newPath()
if rx > 0 or ry > 0: if rx > 0 or ry > 0:
if rx == 0: if rx == 0:
rx = ry rx = ry
@ -473,7 +473,7 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
rx = parseFloat(node.attrOrDefault("rx", "0")) rx = parseFloat(node.attrOrDefault("rx", "0"))
ry = parseFloat(node.attrOrDefault("ry", "0")) ry = parseFloat(node.attrOrDefault("ry", "0"))
var path: Path let path = newPath()
path.ellipse(cx, cy, rx, ry) path.ellipse(cx, cy, rx, ry)
img.fill(ctx, path) img.fill(ctx, path)

View file

@ -1229,6 +1229,9 @@ proc parseGlyph(opentype: OpenType, glyphId: uint16): Path
proc parseGlyphPath(buf: string, offset, numberOfContours: int): Path = proc parseGlyphPath(buf: string, offset, numberOfContours: int): Path =
if numberOfContours < 0: if numberOfContours < 0:
raise newException(PixieError, "Glyph numberOfContours must be >= 0") raise newException(PixieError, "Glyph numberOfContours must be >= 0")
result = newPath()
if numberOfContours == 0: if numberOfContours == 0:
return return
@ -1357,6 +1360,8 @@ proc parseGlyphPath(buf: string, offset, numberOfContours: int): Path =
result.closePath() result.closePath()
proc parseCompositeGlyph(opentype: OpenType, offset: int): Path = proc parseCompositeGlyph(opentype: OpenType, offset: int): Path =
result = newPath()
var var
i = offset i = offset
moreComponents = true moreComponents = true
@ -1458,7 +1463,7 @@ proc parseGlyph(opentype: OpenType, glyphId: uint16): Path =
if glyphId.int + 1 < opentype.glyf.offsets.len and if glyphId.int + 1 < opentype.glyf.offsets.len and
glyphOffset == opentype.glyf.offsets[glyphId + 1]: glyphOffset == opentype.glyf.offsets[glyphId + 1]:
# Empty glyph # Empty glyph
return return Path()
var i = glyphOffset.int var i = glyphOffset.int
opentype.buf.eofCheck(i + 10) opentype.buf.eofCheck(i + 10)

View file

@ -1,5 +1,6 @@
import bumpy, chroma, common, os, pixie/fontformats/opentype, pixie/fontformats/svgfont, import bumpy, chroma, common, os, pixie/fontformats/opentype,
pixie/images, pixie/masks, pixie/paints, pixie/paths, strutils, unicode, vmath pixie/fontformats/svgfont, pixie/images, pixie/masks, pixie/paints,
pixie/paths, strutils, unicode, vmath
const const
AutoLineHeight* = -1.float32 ## Use default line height for the font size AutoLineHeight* = -1.float32 ## Use default line height for the font size
@ -93,11 +94,12 @@ proc strikeoutThickness(typeface: Typeface): float32 {.inline.} =
proc getGlyphPath*(typeface: Typeface, rune: Rune): Path {.inline.} = proc getGlyphPath*(typeface: Typeface, rune: Rune): Path {.inline.} =
## The glyph path for the rune. ## The glyph path for the rune.
result = newPath()
if rune.uint32 > SP.uint32: # Empty paths for control runes (not tofu) if rune.uint32 > SP.uint32: # Empty paths for control runes (not tofu)
if typeface.opentype != nil: if typeface.opentype != nil:
result = typeface.opentype.getGlyphPath(rune) result.addPath(typeface.opentype.getGlyphPath(rune))
else: else:
result = typeface.svgFont.getGlyphPath(rune) result.addPath(typeface.svgFont.getGlyphPath(rune))
proc getAdvance*(typeface: Typeface, rune: Rune): float32 {.inline.} = proc getAdvance*(typeface: Typeface, rune: Rune): float32 {.inline.} =
## The advance for the rune in pixels. ## The advance for the rune in pixels.

View file

@ -28,7 +28,7 @@ type
kind: PathCommandKind kind: PathCommandKind
numbers: seq[float32] numbers: seq[float32]
Path* = object Path* = ref object
## Used to hold paths and create paths. ## Used to hold paths and create paths.
commands: seq[PathCommand] commands: seq[PathCommand]
start, at: Vec2 # Maintained by moveTo, lineTo, etc. Used by arcTo. start, at: Vec2 # Maintained by moveTo, lineTo, etc. Used by arcTo.
@ -46,6 +46,10 @@ const
when defined(release): when defined(release):
{.push checks: off.} {.push checks: off.}
proc newPath*(): Path =
## Create a new Path.
Path()
proc pixelScale(transform: Vec2 | Mat3): float32 = proc pixelScale(transform: Vec2 | Mat3): float32 =
## What is the largest scale factor of this transform? ## What is the largest scale factor of this transform?
when type(transform) is Vec2: when type(transform) is Vec2:
@ -104,6 +108,7 @@ proc `$`*(path: Path): string =
proc parsePath*(path: string): Path = proc parsePath*(path: string): Path =
## Converts a SVG style path string into seq of commands. ## Converts a SVG style path string into seq of commands.
result = newPath()
if path.len == 0: if path.len == 0:
return return
@ -123,7 +128,7 @@ proc parsePath*(path: string): Path =
numberStart = 0 numberStart = 0
hitDecimal = false hitDecimal = false
proc finishCommand(result: var Path) = proc finishCommand(result: Path) =
finishNumber() finishNumber()
if armed: # The first finishCommand() arms if armed: # The first finishCommand() arms
@ -247,7 +252,7 @@ proc parsePath*(path: string): Path =
finishCommand(result) finishCommand(result)
proc transform*(path: var Path, mat: Mat3) = proc transform*(path: Path, mat: Mat3) =
## Apply a matrix transform to a path. ## Apply a matrix transform to a path.
if mat == mat3(): if mat == mat3():
return return
@ -312,39 +317,39 @@ proc transform*(path: var Path, mat: Mat3) =
command.numbers[5] = to.x command.numbers[5] = to.x
command.numbers[6] = to.y command.numbers[6] = to.y
proc addPath*(path: var Path, other: Path) = proc addPath*(path: Path, other: Path) =
## Adds a path to the current path. ## Adds a path to the current path.
path.commands.add(other.commands) path.commands.add(other.commands)
proc closePath*(path: var Path) = proc closePath*(path: Path) =
## Attempts to add a straight line from the current point to the start of ## Attempts to add a straight line from the current point to the start of
## the current sub-path. If the shape has already been closed or has only ## the current sub-path. If the shape has already been closed or has only
## one point, this function does nothing. ## one point, this function does nothing.
path.commands.add(PathCommand(kind: Close)) path.commands.add(PathCommand(kind: Close))
path.at = path.start path.at = path.start
proc moveTo*(path: var Path, x, y: float32) = proc moveTo*(path: Path, x, y: float32) =
## Begins a new sub-path at the point (x, y). ## Begins a new sub-path at the point (x, y).
path.commands.add(PathCommand(kind: Move, numbers: @[x, y])) path.commands.add(PathCommand(kind: Move, numbers: @[x, y]))
path.start = vec2(x, y) path.start = vec2(x, y)
path.at = path.start path.at = path.start
proc moveTo*(path: var Path, v: Vec2) {.inline.} = proc moveTo*(path: Path, v: Vec2) {.inline.} =
## Begins a new sub-path at the point (x, y). ## Begins a new sub-path at the point (x, y).
path.moveTo(v.x, v.y) path.moveTo(v.x, v.y)
proc lineTo*(path: var Path, x, y: float32) = proc lineTo*(path: Path, x, y: float32) =
## Adds a straight line to the current sub-path by connecting the sub-path's ## Adds a straight line to the current sub-path by connecting the sub-path's
## last point to the specified (x, y) coordinates. ## last point to the specified (x, y) coordinates.
path.commands.add(PathCommand(kind: Line, numbers: @[x, y])) path.commands.add(PathCommand(kind: Line, numbers: @[x, y]))
path.at = vec2(x, y) path.at = vec2(x, y)
proc lineTo*(path: var Path, v: Vec2) {.inline.} = proc lineTo*(path: Path, v: Vec2) {.inline.} =
## Adds a straight line to the current sub-path by connecting the sub-path's ## Adds a straight line to the current sub-path by connecting the sub-path's
## last point to the specified (x, y) coordinates. ## last point to the specified (x, y) coordinates.
path.lineTo(v.x, v.y) path.lineTo(v.x, v.y)
proc bezierCurveTo*(path: var Path, x1, y1, x2, y2, x3, y3: float32) = proc bezierCurveTo*(path: Path, x1, y1, x2, y2, x3, y3: float32) =
## Adds a cubic Bézier curve to the current sub-path. It requires three ## Adds a cubic Bézier curve to the current sub-path. It requires three
## points: the first two are control points and the third one is the end ## points: the first two are control points and the third one is the end
## point. The starting point is the latest point in the current path, ## point. The starting point is the latest point in the current path,
@ -355,14 +360,14 @@ proc bezierCurveTo*(path: var Path, x1, y1, x2, y2, x3, y3: float32) =
)) ))
path.at = vec2(x3, y3) path.at = vec2(x3, y3)
proc bezierCurveTo*(path: var Path, ctrl1, ctrl2, to: Vec2) {.inline.} = proc bezierCurveTo*(path: Path, ctrl1, ctrl2, to: Vec2) {.inline.} =
## Adds a cubic Bézier curve to the current sub-path. It requires three ## Adds a cubic Bézier curve to the current sub-path. It requires three
## points: the first two are control points and the third one is the end ## points: the first two are control points and the third one is the end
## point. The starting point is the latest point in the current path, ## point. The starting point is the latest point in the current path,
## which can be changed using moveTo() before creating the Bézier curve. ## which can be changed using moveTo() before creating the Bézier curve.
path.bezierCurveTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, to.x, to.y) path.bezierCurveTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, to.x, to.y)
proc quadraticCurveTo*(path: var Path, x1, y1, x2, y2: float32) = proc quadraticCurveTo*(path: Path, x1, y1, x2, y2: float32) =
## Adds a quadratic Bézier curve to the current sub-path. It requires two ## Adds a quadratic Bézier curve to the current sub-path. It requires two
## points: the first one is a control point and the second one is the end ## points: the first one is a control point and the second one is the end
## point. The starting point is the latest point in the current path, ## point. The starting point is the latest point in the current path,
@ -374,7 +379,7 @@ proc quadraticCurveTo*(path: var Path, x1, y1, x2, y2: float32) =
)) ))
path.at = vec2(x2, y2) path.at = vec2(x2, y2)
proc quadraticCurveTo*(path: var Path, ctrl, to: Vec2) {.inline.} = proc quadraticCurveTo*(path: Path, ctrl, to: Vec2) {.inline.} =
## Adds a quadratic Bézier curve to the current sub-path. It requires two ## Adds a quadratic Bézier curve to the current sub-path. It requires two
## points: the first one is a control point and the second one is the end ## points: the first one is a control point and the second one is the end
## point. The starting point is the latest point in the current path, ## point. The starting point is the latest point in the current path,
@ -383,7 +388,7 @@ proc quadraticCurveTo*(path: var Path, ctrl, to: Vec2) {.inline.} =
path.quadraticCurveTo(ctrl.x, ctrl.y, to.x, to.y) path.quadraticCurveTo(ctrl.x, ctrl.y, to.x, to.y)
proc ellipticalArcTo*( proc ellipticalArcTo*(
path: var Path, path: Path,
rx, ry: float32, rx, ry: float32,
xAxisRotation: float32, xAxisRotation: float32,
largeArcFlag, sweepFlag: bool, largeArcFlag, sweepFlag: bool,
@ -399,7 +404,7 @@ proc ellipticalArcTo*(
)) ))
path.at = vec2(x, y) path.at = vec2(x, y)
proc arc*(path: var Path, x, y, r, a0, a1: float32, ccw: bool) = proc arc*(path: Path, x, y, r, a0, a1: float32, ccw: bool) =
## Adds a circular arc to the current sub-path. ## Adds a circular arc to the current sub-path.
if r == 0: # When radius is zero, do nothing. if r == 0: # When radius is zero, do nothing.
return return
@ -436,11 +441,11 @@ proc arc*(path: var Path, x, y, r, a0, a1: float32, ccw: bool) =
path.at.y = y + r * sin(a1) path.at.y = y + r * sin(a1)
path.ellipticalArcTo(r, r, 0, angle >= PI, cw, path.at.x, path.at.y) path.ellipticalArcTo(r, r, 0, angle >= PI, cw, path.at.x, path.at.y)
proc arc*(path: var Path, pos: Vec2, r: float32, a: Vec2, ccw: bool = false) = proc arc*(path: Path, pos: Vec2, r: float32, a: Vec2, ccw: bool = false) =
## Adds a circular arc to the current sub-path. ## Adds a circular arc to the current sub-path.
path.arc(pos.x, pos.y, r, a.x, a.y, ccw) path.arc(pos.x, pos.y, r, a.x, a.y, ccw)
proc arcTo*(path: var Path, x1, y1, x2, y2, r: float32) = proc arcTo*(path: Path, x1, y1, x2, y2, r: float32) =
## Adds a circular arc using the given control points and radius. ## Adds a circular arc using the given control points and radius.
## Commonly used for making rounded corners. ## Commonly used for making rounded corners.
if r < 0: # When radius is negative, error. if r < 0: # When radius is negative, error.
@ -481,11 +486,11 @@ proc arcTo*(path: var Path, x1, y1, x2, y2, r: float32) =
path.at.y = y1 + t21 * y21 path.at.y = y1 + t21 * y21
path.ellipticalArcTo(r, r, 0, false, y01 * x20 > x01 * y20, path.at.x, path.at.y) path.ellipticalArcTo(r, r, 0, false, y01 * x20 > x01 * y20, path.at.x, path.at.y)
proc arcTo*(path: var Path, a, b: Vec2, r: float32) = proc arcTo*(path: Path, a, b: Vec2, r: float32) =
## Adds a circular arc using the given control points and radius. ## Adds a circular arc using the given control points and radius.
path.arcTo(a.x, a.y, b.x, b.y, r) path.arcTo(a.x, a.y, b.x, b.y, r)
proc rect*(path: var Path, x, y, w, h: float32, clockwise = true) = proc rect*(path: Path, x, y, w, h: float32, clockwise = true) =
## Adds a rectangle. ## Adds a rectangle.
## Clockwise param can be used to subtract a rect from a path when using ## Clockwise param can be used to subtract a rect from a path when using
## even-odd winding rule. ## even-odd winding rule.
@ -502,13 +507,13 @@ proc rect*(path: var Path, x, y, w, h: float32, clockwise = true) =
path.lineTo(x + w, y) path.lineTo(x + w, y)
path.closePath() path.closePath()
proc rect*(path: var Path, pos: Vec2, wh: Vec2, clockwise = true) {.inline.} = proc rect*(path: Path, pos: Vec2, wh: Vec2, clockwise = true) {.inline.} =
## Adds a rectangle. ## Adds a rectangle.
## Clockwise param can be used to subtract a rect from a path when using ## Clockwise param can be used to subtract a rect from a path when using
## even-odd winding rule. ## even-odd winding rule.
path.rect(pos.x, pos.y, wh.x, wh.y, clockwise) path.rect(pos.x, pos.y, wh.x, wh.y, clockwise)
proc rect*(path: var Path, rect: Rect, clockwise = true) {.inline.} = proc rect*(path: Path, rect: Rect, clockwise = true) {.inline.} =
## Adds a rectangle. ## Adds a rectangle.
## Clockwise param can be used to subtract a rect from a path when using ## Clockwise param can be used to subtract a rect from a path when using
## even-odd winding rule. ## even-odd winding rule.
@ -519,7 +524,7 @@ const splineCircleK = 4.0 * (-1.0 + sqrt(2.0)) / 3
## https://dl3.pushbulletusercontent.com/a3fLVC8boTzRoxevD1OgCzRzERB9z2EZ/unknown.png ## https://dl3.pushbulletusercontent.com/a3fLVC8boTzRoxevD1OgCzRzERB9z2EZ/unknown.png
proc roundedRect*( proc roundedRect*(
path: var Path, x, y, w, h, nw, ne, se, sw: float32, clockwise = true path: Path, x, y, w, h, nw, ne, se, sw: float32, clockwise = true
) = ) =
## Adds a rounded rectangle. ## Adds a rounded rectangle.
## Clockwise param can be used to subtract a rect from a path when using ## Clockwise param can be used to subtract a rect from a path when using
@ -586,7 +591,7 @@ proc roundedRect*(
path.closePath() path.closePath()
proc roundedRect*( proc roundedRect*(
path: var Path, pos, wh: Vec2, nw, ne, se, sw: float32, clockwise = true path: Path, pos, wh: Vec2, nw, ne, se, sw: float32, clockwise = true
) {.inline.} = ) {.inline.} =
## Adds a rounded rectangle. ## Adds a rounded rectangle.
## Clockwise param can be used to subtract a rect from a path when using ## Clockwise param can be used to subtract a rect from a path when using
@ -594,14 +599,14 @@ proc roundedRect*(
path.roundedRect(pos.x, pos.y, wh.x, wh.y, nw, ne, se, sw, clockwise) path.roundedRect(pos.x, pos.y, wh.x, wh.y, nw, ne, se, sw, clockwise)
proc roundedRect*( proc roundedRect*(
path: var Path, rect: Rect, nw, ne, se, sw: float32, clockwise = true path: Path, rect: Rect, nw, ne, se, sw: float32, clockwise = true
) {.inline.} = ) {.inline.} =
## Adds a rounded rectangle. ## Adds a rounded rectangle.
## Clockwise param can be used to subtract a rect from a path when using ## Clockwise param can be used to subtract a rect from a path when using
## even-odd winding rule. ## even-odd winding rule.
path.roundedRect(rect.x, rect.y, rect.w, rect.h, nw, ne, se, sw, clockwise) path.roundedRect(rect.x, rect.y, rect.w, rect.h, nw, ne, se, sw, clockwise)
proc ellipse*(path: var Path, cx, cy, rx, ry: float32) = proc ellipse*(path: Path, cx, cy, rx, ry: float32) =
## Adds a ellipse. ## Adds a ellipse.
let let
magicX = splineCircleK * rx magicX = splineCircleK * rx
@ -614,23 +619,23 @@ proc ellipse*(path: var Path, cx, cy, rx, ry: float32) =
path.bezierCurveTo(cx + magicX, cy - ry, cx + rx, cy - magicY, cx + rx, cy) path.bezierCurveTo(cx + magicX, cy - ry, cx + rx, cy - magicY, cx + rx, cy)
path.closePath() path.closePath()
proc ellipse*(path: var Path, center: Vec2, rx, ry: float32) {.inline.} = proc ellipse*(path: Path, center: Vec2, rx, ry: float32) {.inline.} =
## Adds a ellipse. ## Adds a ellipse.
path.ellipse(center.x, center.y, rx, ry) path.ellipse(center.x, center.y, rx, ry)
proc circle*(path: var Path, cx, cy, r: float32) {.inline.} = proc circle*(path: Path, cx, cy, r: float32) {.inline.} =
## Adds a circle. ## Adds a circle.
path.ellipse(cx, cy, r, r) path.ellipse(cx, cy, r, r)
proc circle*(path: var Path, center: Vec2, r: float32) {.inline.} = proc circle*(path: Path, center: Vec2, r: float32) {.inline.} =
## Adds a circle. ## Adds a circle.
path.ellipse(center.x, center.y, r, r) path.ellipse(center.x, center.y, r, r)
proc circle*(path: var Path, circle: Circle) {.inline.} = proc circle*(path: Path, circle: Circle) {.inline.} =
## Adds a circle. ## Adds a circle.
path.ellipse(circle.pos.x, circle.pos.y, circle.radius, circle.radius) path.ellipse(circle.pos.x, circle.pos.y, circle.radius, circle.radius)
proc polygon*(path: var Path, x, y, size: float32, sides: int) = proc polygon*(path: Path, x, y, size: float32, sides: int) =
## Adds an n-sided regular polygon at (x, y) with the parameter size. ## Adds an n-sided regular polygon at (x, y) with the parameter size.
path.moveTo(x + size * cos(0.0), y + size * sin(0.0)) path.moveTo(x + size * cos(0.0), y + size * sin(0.0))
for side in 0 .. sides: for side in 0 .. sides:
@ -639,7 +644,7 @@ proc polygon*(path: var Path, x, y, size: float32, sides: int) =
y + size * sin(side.float32 * 2.0 * PI / sides.float32) y + size * sin(side.float32 * 2.0 * PI / sides.float32)
) )
proc polygon*(path: var Path, pos: Vec2, size: float32, sides: int) {.inline.} = proc polygon*(path: Path, pos: Vec2, size: float32, sides: int) {.inline.} =
## Adds a n-sided regular polygon at (x, y) with the parameter size. ## Adds a n-sided regular polygon at (x, y) with the parameter size.
path.polygon(pos.x, pos.y, size, sides) path.polygon(pos.x, pos.y, size, sides)
@ -1611,7 +1616,7 @@ proc strokeShapes(
miterAngleLimit = miterLimitToAngle(miterLimit) miterAngleLimit = miterLimitToAngle(miterLimit)
proc makeCircle(at: Vec2): seq[Vec2] = proc makeCircle(at: Vec2): seq[Vec2] =
var path: Path let path = newPath()
path.ellipse(at, halfStroke, halfStroke) path.ellipse(at, halfStroke, halfStroke)
path.commandsToShapes()[0] path.commandsToShapes()[0]

View file

@ -51,7 +51,7 @@ block:
block: block:
let ctx = newContext(newImage(300, 150)) let ctx = newContext(newImage(300, 150))
var region: Path let region = newPath()
region.moveTo(30, 90) region.moveTo(30, 90)
region.lineTo(110, 20) region.lineTo(110, 20)
region.lineTo(240, 130) region.lineTo(240, 130)
@ -438,7 +438,7 @@ block:
block: block:
let ctx = newContext(newImage(300, 150)) let ctx = newContext(newImage(300, 150))
var region: Path let region = newPath()
region.rect(80, 10, 20, 130) region.rect(80, 10, 20, 130)
region.rect(40, 50, 100, 50) region.rect(40, 50, 100, 50)
ctx.clip(region, wrEvenOdd) ctx.clip(region, wrEvenOdd)
@ -453,9 +453,9 @@ block:
let ctx = newContext(image) let ctx = newContext(image)
var circlePath: Path var circlePath = newPath()
circlePath.circle(150, 75, 75) circlePath.circle(150, 75, 75)
var squarePath: Path var squarePath = newPath()
squarePath.rect(85, 10, 130, 130) squarePath.rect(85, 10, 130, 130)
ctx.clip(circlePath) ctx.clip(circlePath)
@ -476,7 +476,7 @@ block:
ctx.saveLayer() ctx.saveLayer()
var circlePath: Path var circlePath = newPath()
circlePath.circle(150, 75, 75) circlePath.circle(150, 75, 75)
ctx.clip(circlePath) ctx.clip(circlePath)

View file

@ -144,7 +144,7 @@ block: # Test conversion between image and mask
originalImage = newImage(100, 100) originalImage = newImage(100, 100)
originalMask = newMask(100, 100) originalMask = newMask(100, 100)
var p: Path let p = newPath()
p.rect(10, 10, 80, 80) p.rect(10, 10, 80, 80)
originalImage.fillPath(p, rgba(255, 0, 0, 255)) originalImage.fillPath(p, rgba(255, 0, 0, 255))
@ -157,7 +157,7 @@ block: # Test conversion between image and mask
doAssert newImage(newMask(originalImage)).data == newImage(originalMask).data doAssert newImage(newMask(originalImage)).data == newImage(originalMask).data
block: block:
var p: Path let p = newPath()
p.roundedRect(10, 10, 80, 80, 10, 10, 10, 10) p.roundedRect(10, 10, 80, 80, 10, 10, 10, 10)
let image = newImage(100, 100) let image = newImage(100, 100)

View file

@ -21,7 +21,7 @@ block:
y = 10.0 y = 10.0
h = 80.0 h = 80.0
w = 80.0 w = 80.0
var path: Path let path = newPath()
path.moveTo(x + r, y) path.moveTo(x + r, y)
# path.arcTo(x + w, y, x + w, y + h, r) # path.arcTo(x + w, y, x + w, y + h, r)
# path.arcTo(x + w, y + h, x, y + h, r) # path.arcTo(x + w, y + h, x, y + h, r)
@ -40,7 +40,7 @@ block:
let image = newImage(100, 100) let image = newImage(100, 100)
image.fill(rgba(255, 100, 100, 255)) image.fill(rgba(255, 100, 100, 255))
var path: Path let path = newPath()
path.ellipse(image.width / 2, image.height / 2, 25, 25) path.ellipse(image.width / 2, image.height / 2, 25, 25)
let mask = newMask(image.width, image.height) let mask = newMask(image.width, image.height)
@ -53,7 +53,7 @@ block:
let a = newMask(100, 100) let a = newMask(100, 100)
a.fill(255) a.fill(255)
var path: Path let path = newPath()
path.ellipse(a.width / 2, a.height / 2, 25, 25) path.ellipse(a.width / 2, a.height / 2, 25, 25)
let b = newMask(a.width, a.height) let b = newMask(a.width, a.height)
@ -66,7 +66,7 @@ block:
let a = newMask(100, 100) let a = newMask(100, 100)
a.fill(255) a.fill(255)
var path: Path let path = newPath()
path.ellipse(a.width / 2, a.height / 2, 25, 25) path.ellipse(a.width / 2, a.height / 2, 25, 25)
let b = newImage(a.width, a.height) let b = newImage(a.width, a.height)
@ -82,7 +82,7 @@ block:
writeFile("tests/images/masks/shifted.png", a.encodePng()) writeFile("tests/images/masks/shifted.png", a.encodePng())
block: block:
var path: Path let path = newPath()
path.rect(40, 40, 20, 20) path.rect(40, 40, 20, 20)
let a = newMask(100, 100) let a = newMask(100, 100)
@ -95,7 +95,7 @@ block:
block: block:
let mask = newMask(100, 100) let mask = newMask(100, 100)
var path: Path let path = newPath()
path.ellipse(mask.width / 2, mask.height / 2, 25, 25) path.ellipse(mask.width / 2, mask.height / 2, 25, 25)
mask.fillPath(path) mask.fillPath(path)

View file

@ -98,7 +98,7 @@ block:
image.writeFile("tests/images/paths/pathYellowRectangle.png") image.writeFile("tests/images/paths/pathYellowRectangle.png")
block: block:
var path: Path let path = newPath()
path.moveTo(10, 10) path.moveTo(10, 10)
path.lineTo(10, 90) path.lineTo(10, 90)
path.lineTo(90, 90) path.lineTo(90, 90)
@ -163,7 +163,7 @@ block:
# y = 10.0 # y = 10.0
# h = 80.0 # h = 80.0
# w = 80.0 # w = 80.0
# var path: Path # let path = newPath()
# path.moveTo(x + r, y) # path.moveTo(x + r, y)
# path.arcTo(x + w, y, x + w, y + h, r) # path.arcTo(x + w, y, x + w, y + h, r)
# path.arcTo(x + w, y + h, x, y + h, r) # path.arcTo(x + w, y + h, x, y + h, r)
@ -187,7 +187,7 @@ block:
# y = 10.0 # y = 10.0
# h = 80.0 # h = 80.0
# w = 80.0 # w = 80.0
# var path: Path # let path = newPath()
# path.moveTo(x + r, y) # path.moveTo(x + r, y)
# path.arcTo(x + w, y, x + w, y + h, r) # path.arcTo(x + w, y, x + w, y + h, r)
# path.arcTo(x + w, y + h, x, y + h, r) # path.arcTo(x + w, y + h, x, y + h, r)
@ -304,7 +304,7 @@ block:
let let
image = newImage(60, 60) image = newImage(60, 60)
image.fill(rgba(255, 255, 255, 255)) image.fill(rgba(255, 255, 255, 255))
var path: Path let path = newPath()
path.moveTo(-20, 0) path.moveTo(-20, 0)
path.lineTo(0, 0) path.lineTo(0, 0)
let th = angle.float32.degToRad() + PI/2 let th = angle.float32.degToRad() + PI/2
@ -532,7 +532,7 @@ block:
surface.writeFile("tests/images/paths/arcTo3.png") surface.writeFile("tests/images/paths/arcTo3.png")
block: block:
var path: Path let path = newPath()
path.rect(0, 0, 10, 10) path.rect(0, 0, 10, 10)
doAssert path.fillOverlaps(vec2(5, 5)) doAssert path.fillOverlaps(vec2(5, 5))
@ -542,7 +542,7 @@ block:
doAssert not path.fillOverlaps(vec2(10, 10)) doAssert not path.fillOverlaps(vec2(10, 10))
block: block:
var path: Path let path = newPath()
path.ellipse(20, 20, 20, 10) path.ellipse(20, 20, 20, 10)
doAssert not path.fillOverlaps(vec2(0, 0)) doAssert not path.fillOverlaps(vec2(0, 0))
@ -551,7 +551,7 @@ block:
doAssert path.fillOverlaps(vec2(30, 20)) doAssert path.fillOverlaps(vec2(30, 20))
block: block:
var path: Path let path = newPath()
path.rect(10, 10, 10, 10) path.rect(10, 10, 10, 10)
doAssert path.strokeOverlaps(vec2(10, 10)) doAssert path.strokeOverlaps(vec2(10, 10))
@ -559,7 +559,7 @@ block:
doAssert not path.strokeOverlaps(vec2(5, 5)) doAssert not path.strokeOverlaps(vec2(5, 5))
block: block:
var path: Path let path = newPath()
path.ellipse(20, 20, 20, 10) path.ellipse(20, 20, 20, 10)
doAssert not path.strokeOverlaps(vec2(0, 0)) doAssert not path.strokeOverlaps(vec2(0, 0))
@ -570,7 +570,7 @@ block:
doAssert not path.strokeOverlaps(vec2(19.4, 30.6)) doAssert not path.strokeOverlaps(vec2(19.4, 30.6))
block: block:
var path: Path let path = newPath()
path.circle(50, 50, 30) path.circle(50, 50, 30)
var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255)) var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255))
@ -582,7 +582,7 @@ block:
image.writeFile("tests/images/paths/opacityFill.png") image.writeFile("tests/images/paths/opacityFill.png")
block: block:
var path: Path let path = newPath()
path.circle(50, 50, 30) path.circle(50, 50, 30)
var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255)) var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255))