computeBounds, bindings changes
This commit is contained in:
parent
400f66c3f4
commit
fe6fb8c90e
4 changed files with 154 additions and 153 deletions
|
@ -1,4 +1,4 @@
|
||||||
import chroma, vmath
|
import bumpy, chroma, vmath
|
||||||
|
|
||||||
type
|
type
|
||||||
PixieError* = object of ValueError ## Raised if an operation fails.
|
PixieError* = object of ValueError ## Raised if an operation fails.
|
||||||
|
@ -16,9 +16,20 @@ proc lerp*(a, b: ColorRGBX, t: float32): ColorRGBX {.inline.} =
|
||||||
result.b = ((a.b.uint32 * (255 - x) + b.b.uint32 * x) div 255).uint8
|
result.b = ((a.b.uint32 * (255 - x) + b.b.uint32 * x) div 255).uint8
|
||||||
result.a = ((a.a.uint32 * (255 - x) + b.a.uint32 * x) div 255).uint8
|
result.a = ((a.a.uint32 * (255 - x) + b.a.uint32 * x) div 255).uint8
|
||||||
|
|
||||||
func lerp*(a, b: Color, v: float32): Color {.inline.} =
|
proc lerp*(a, b: Color, v: float32): Color {.inline.} =
|
||||||
## Linearly interpolate between a and b using t.
|
## Linearly interpolate between a and b using t.
|
||||||
result.r = lerp(a.r, b.r, v)
|
result.r = lerp(a.r, b.r, v)
|
||||||
result.g = lerp(a.g, b.g, v)
|
result.g = lerp(a.g, b.g, v)
|
||||||
result.b = lerp(a.b, b.b, v)
|
result.b = lerp(a.b, b.b, v)
|
||||||
result.a = lerp(a.a, b.a, v)
|
result.a = lerp(a.a, b.a, v)
|
||||||
|
|
||||||
|
proc snapToPixels*(rect: Rect): Rect =
|
||||||
|
let
|
||||||
|
xMin = rect.x
|
||||||
|
xMax = rect.x + rect.w
|
||||||
|
yMin = rect.y
|
||||||
|
yMax = rect.y + rect.h
|
||||||
|
result.x = floor(xMin)
|
||||||
|
result.w = ceil(xMax) - result.x
|
||||||
|
result.y = floor(yMin)
|
||||||
|
result.h = ceil(yMax) - result.y
|
||||||
|
|
|
@ -17,9 +17,9 @@ type
|
||||||
lineJoin*: LineJoin
|
lineJoin*: LineJoin
|
||||||
font*: string ## File path to a .ttf or .otf file.
|
font*: string ## File path to a .ttf or .otf file.
|
||||||
fontSize*: float32
|
fontSize*: float32
|
||||||
textAlign*: HAlignMode
|
textAlign*: HorizontalAlignment
|
||||||
|
lineDash*: seq[float32]
|
||||||
path: Path
|
path: Path
|
||||||
lineDash: seq[float32]
|
|
||||||
mat: Mat3
|
mat: Mat3
|
||||||
mask: Mask
|
mask: Mask
|
||||||
layer: Image
|
layer: Image
|
||||||
|
@ -35,7 +35,7 @@ type
|
||||||
lineJoin: LineJoin
|
lineJoin: LineJoin
|
||||||
font: string
|
font: string
|
||||||
fontSize*: float32
|
fontSize*: float32
|
||||||
textAlign: HAlignMode
|
textAlign: HorizontalAlignment
|
||||||
lineDash: seq[float32]
|
lineDash: seq[float32]
|
||||||
mat: Mat3
|
mat: Mat3
|
||||||
mask: Mask
|
mask: Mask
|
||||||
|
@ -289,6 +289,22 @@ proc quadraticCurveTo*(ctx: Context, ctrl, to: Vec2) {.inline.} =
|
||||||
## Bézier curve.
|
## Bézier curve.
|
||||||
ctx.path.quadraticCurveTo(ctrl, to)
|
ctx.path.quadraticCurveTo(ctrl, to)
|
||||||
|
|
||||||
|
proc arc*(ctx: Context, x, y, r, a0, a1: float32, ccw: bool = false) =
|
||||||
|
## Draws a circular arc.
|
||||||
|
ctx.path.arc(x, y, r, a0, a1, ccw)
|
||||||
|
|
||||||
|
proc arc*(ctx: Context, pos: Vec2, r: float32, a: Vec2, ccw: bool = false) =
|
||||||
|
## Adds a circular arc to the current sub-path.
|
||||||
|
ctx.path.arc(pos, r, a, ccw)
|
||||||
|
|
||||||
|
proc arcTo*(ctx: Context, x1, y1, x2, y2, radius: float32) =
|
||||||
|
## Draws a circular arc using the given control points and radius.
|
||||||
|
ctx.path.arcTo(x1, y1, x2, y2, radius)
|
||||||
|
|
||||||
|
proc arcTo*(ctx: Context, a, b: Vec2, r: float32) =
|
||||||
|
## Adds a circular arc using the given control points and radius.
|
||||||
|
ctx.path.arcTo(a, b, r)
|
||||||
|
|
||||||
proc closePath*(ctx: Context) {.inline.} =
|
proc closePath*(ctx: Context) {.inline.} =
|
||||||
## 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
|
||||||
|
@ -326,6 +342,8 @@ proc fill*(ctx: Context, windingRule = wrNonZero) {.inline.} =
|
||||||
## Fills the current path with the current fillStyle.
|
## Fills the current path with the current fillStyle.
|
||||||
ctx.fill(ctx.path, windingRule)
|
ctx.fill(ctx.path, windingRule)
|
||||||
|
|
||||||
|
proc clip*(ctx: Context, windingRule = wrNonZero) {.inline.}
|
||||||
|
|
||||||
proc clip*(ctx: Context, path: Path, windingRule = wrNonZero) =
|
proc clip*(ctx: Context, path: Path, windingRule = wrNonZero) =
|
||||||
## Turns the path into the current clipping region. The previous clipping
|
## Turns the path into the current clipping region. The previous clipping
|
||||||
## region, if any, is intersected with the current or given path to create
|
## region, if any, is intersected with the current or given path to create
|
||||||
|
@ -342,6 +360,8 @@ proc clip*(ctx: Context, windingRule = wrNonZero) {.inline.} =
|
||||||
## to create the new clipping region.
|
## to create the new clipping region.
|
||||||
ctx.clip(ctx.path, windingRule)
|
ctx.clip(ctx.path, windingRule)
|
||||||
|
|
||||||
|
proc stroke*(ctx: Context) {.inline.}
|
||||||
|
|
||||||
proc stroke*(ctx: Context, path: Path) =
|
proc stroke*(ctx: Context, path: Path) =
|
||||||
## Strokes (outlines) the current or given path with the current strokeStyle.
|
## Strokes (outlines) the current or given path with the current strokeStyle.
|
||||||
if ctx.mask != nil and ctx.layer == nil:
|
if ctx.mask != nil and ctx.layer == nil:
|
||||||
|
@ -491,7 +511,110 @@ proc resetTransform*(ctx: Context) {.inline.} =
|
||||||
## Resets the current transform to the identity matrix.
|
## Resets the current transform to the identity matrix.
|
||||||
ctx.mat = mat3()
|
ctx.mat = mat3()
|
||||||
|
|
||||||
|
proc drawImage*(ctx: Context, image: Image, dx, dy, dWidth, dHeight: float32) =
|
||||||
|
## Draws a source image onto the destination image.
|
||||||
|
let
|
||||||
|
imageMat = ctx.mat * translate(vec2(dx, dy)) * scale(vec2(
|
||||||
|
dWidth / image.width.float32,
|
||||||
|
dHeight / image.height.float32
|
||||||
|
))
|
||||||
|
savedFillStyle = ctx.fillStyle
|
||||||
|
|
||||||
|
ctx.fillStyle = newPaint(pkImage)
|
||||||
|
ctx.fillStyle.image = image
|
||||||
|
ctx.fillStyle.imageMat = imageMat
|
||||||
|
|
||||||
|
let path = newPath()
|
||||||
|
path.rect(rect(dx, dy, dWidth, dHeight))
|
||||||
|
ctx.fill(path)
|
||||||
|
|
||||||
|
ctx.fillStyle = savedFillStyle
|
||||||
|
|
||||||
|
proc drawImage*(ctx: Context, image: Image, dx, dy: float32) =
|
||||||
|
## Draws a source image onto the destination image.
|
||||||
|
ctx.drawImage(image, dx, dx, image.width.float32, image.height.float32)
|
||||||
|
|
||||||
|
proc drawImage*(ctx: Context, image: Image, pos: Vec2) =
|
||||||
|
## Draws a source image onto the destination image.
|
||||||
|
ctx.drawImage(image, pos.x, pos.y)
|
||||||
|
|
||||||
|
proc drawImage*(ctx: Context, image: Image, rect: Rect) =
|
||||||
|
## Draws a source image onto the destination image.
|
||||||
|
ctx.drawImage(image, rect.x, rect.y, rect.w, rect.h)
|
||||||
|
|
||||||
|
proc drawImage*(
|
||||||
|
ctx: Context,
|
||||||
|
image: Image,
|
||||||
|
sx, sy, sWidth, sHeight,
|
||||||
|
dx, dy, dWidth, dHeight: float32
|
||||||
|
) =
|
||||||
|
## Draws a source image onto the destination image.
|
||||||
|
let image = image.subImage(sx.int, sy.int, sWidth.int, sHeight.int)
|
||||||
|
ctx.drawImage(image, dx, dx, image.width.float32, image.height.float32)
|
||||||
|
|
||||||
|
proc drawImage*(ctx: Context, image: Image, src, dest: Rect) =
|
||||||
|
## Draws a source image onto the destination image.
|
||||||
|
ctx.drawImage(
|
||||||
|
image,
|
||||||
|
src.x, src.y, src.w, src.h,
|
||||||
|
dest.x, dest.y, dest.w, dest.h
|
||||||
|
)
|
||||||
|
|
||||||
|
proc isPointInPath*(
|
||||||
|
ctx: Context, path: Path, pos: Vec2, windingRule = wrNonZero
|
||||||
|
): bool =
|
||||||
|
## Returns whether or not the specified point is contained in the current path.
|
||||||
|
path.fillOverlaps(pos, ctx.mat, windingRule)
|
||||||
|
|
||||||
|
proc isPointInPath*(
|
||||||
|
ctx: Context, path: Path, x, y: float32, windingRule = wrNonZero
|
||||||
|
): bool {.inline.} =
|
||||||
|
## Returns whether or not the specified point is contained in the current path.
|
||||||
|
ctx.isPointInPath(path, vec2(x, y), windingRule)
|
||||||
|
|
||||||
|
proc isPointInPath*(
|
||||||
|
ctx: Context, pos: Vec2, windingRule = wrNonZero
|
||||||
|
): bool {.inline.} =
|
||||||
|
## Returns whether or not the specified point is contained in the current path.
|
||||||
|
ctx.isPointInPath(ctx.path, pos, windingRule)
|
||||||
|
|
||||||
|
proc isPointInPath*(
|
||||||
|
ctx: Context, x, y: float32, windingRule = wrNonZero
|
||||||
|
): bool {.inline.} =
|
||||||
|
## Returns whether or not the specified point is contained in the current path.
|
||||||
|
ctx.isPointInPath(ctx.path, vec2(x, y), windingRule)
|
||||||
|
|
||||||
|
proc isPointInStroke*(ctx: Context, path: Path, pos: Vec2): bool =
|
||||||
|
## Returns whether or not the specified point is inside the area contained
|
||||||
|
## by the stroking of a path.
|
||||||
|
path.strokeOverlaps(
|
||||||
|
pos,
|
||||||
|
ctx.mat,
|
||||||
|
ctx.lineWidth,
|
||||||
|
ctx.lineCap,
|
||||||
|
ctx.lineJoin,
|
||||||
|
ctx.miterLimit,
|
||||||
|
ctx.lineDash
|
||||||
|
)
|
||||||
|
|
||||||
|
proc isPointInStroke*(ctx: Context, path: Path, x, y: float32): bool {.inline.} =
|
||||||
|
## Returns whether or not the specified point is inside the area contained
|
||||||
|
## by the stroking of a path.
|
||||||
|
ctx.isPointInStroke(path, vec2(x, y))
|
||||||
|
|
||||||
|
proc isPointInStroke*(ctx: Context, pos: Vec2): bool {.inline.} =
|
||||||
|
## Returns whether or not the specified point is inside the area contained
|
||||||
|
## by the stroking of a path.
|
||||||
|
ctx.isPointInStroke(ctx.path, pos)
|
||||||
|
|
||||||
|
proc isPointInStroke*(ctx: Context, x, y: float32): bool {.inline.} =
|
||||||
|
## Returns whether or not the specified point is inside the area contained
|
||||||
|
## by the stroking of a path.
|
||||||
|
ctx.isPointInStroke(ctx.path, vec2(x, y))
|
||||||
|
|
||||||
|
#
|
||||||
# Additional procs that are not part of the JS API
|
# Additional procs that are not part of the JS API
|
||||||
|
#
|
||||||
|
|
||||||
proc roundedRect*(ctx: Context, x, y, w, h, nw, ne, se, sw: float32) {.inline.} =
|
proc roundedRect*(ctx: Context, x, y, w, h, nw, ne, se, sw: float32) {.inline.} =
|
||||||
## Adds a rounded rectangle to the current path.
|
## Adds a rounded rectangle to the current path.
|
||||||
|
@ -566,12 +689,6 @@ proc fillCircle*(ctx: Context, circle: Circle) =
|
||||||
path.circle(circle)
|
path.circle(circle)
|
||||||
ctx.fill(path)
|
ctx.fill(path)
|
||||||
|
|
||||||
proc fillCircle*(ctx: Context, center: Vec2, radius: float32) =
|
|
||||||
## Draws a circle that is filled according to the current fillStyle.
|
|
||||||
let path = newPath()
|
|
||||||
path.ellipse(center, radius, radius)
|
|
||||||
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.
|
||||||
|
@ -579,13 +696,6 @@ proc strokeCircle*(ctx: Context, circle: Circle) =
|
||||||
path.circle(circle)
|
path.circle(circle)
|
||||||
ctx.stroke(path)
|
ctx.stroke(path)
|
||||||
|
|
||||||
proc strokeCircle*(ctx: Context, center: Vec2, radius: float32) =
|
|
||||||
## Draws a circle that is stroked (outlined) according to the current
|
|
||||||
## strokeStyle and other context settings.
|
|
||||||
let path = newPath()
|
|
||||||
path.ellipse(center, radius, radius)
|
|
||||||
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.
|
||||||
|
@ -599,120 +709,3 @@ proc strokePolygon*(ctx: Context, pos: Vec2, size: float32, sides: int) =
|
||||||
let path = newPath()
|
let path = newPath()
|
||||||
path.polygon(pos, size, sides)
|
path.polygon(pos, size, sides)
|
||||||
ctx.stroke(path)
|
ctx.stroke(path)
|
||||||
|
|
||||||
proc drawImage*(ctx: Context, image: Image, dx, dy, dWidth, dHeight: float32) =
|
|
||||||
## Draws a source image onto the destination image.
|
|
||||||
let
|
|
||||||
imageMat = ctx.mat * translate(vec2(dx, dy)) * scale(vec2(
|
|
||||||
dWidth / image.width.float32,
|
|
||||||
dHeight / image.height.float32
|
|
||||||
))
|
|
||||||
savedFillStyle = ctx.fillStyle
|
|
||||||
|
|
||||||
ctx.fillStyle = newPaint(pkImage)
|
|
||||||
ctx.fillStyle.image = image
|
|
||||||
ctx.fillStyle.imageMat = imageMat
|
|
||||||
|
|
||||||
let path = newPath()
|
|
||||||
path.rect(rect(dx, dy, dWidth, dHeight))
|
|
||||||
ctx.fill(path)
|
|
||||||
|
|
||||||
ctx.fillStyle = savedFillStyle
|
|
||||||
|
|
||||||
proc drawImage*(ctx: Context, image: Image, dx, dy: float32) =
|
|
||||||
## Draws a source image onto the destination image.
|
|
||||||
ctx.drawImage(image, dx, dx, image.width.float32, image.height.float32)
|
|
||||||
|
|
||||||
proc drawImage*(ctx: Context, image: Image, pos: Vec2) =
|
|
||||||
## Draws a source image onto the destination image.
|
|
||||||
ctx.drawImage(image, pos.x, pos.y)
|
|
||||||
|
|
||||||
proc drawImage*(ctx: Context, image: Image, rect: Rect) =
|
|
||||||
## Draws a source image onto the destination image.
|
|
||||||
ctx.drawImage(image, rect.x, rect.y, rect.w, rect.h)
|
|
||||||
|
|
||||||
proc drawImage*(
|
|
||||||
ctx: Context,
|
|
||||||
image: Image,
|
|
||||||
sx, sy, sWidth, sHeight,
|
|
||||||
dx, dy, dWidth, dHeight: float32
|
|
||||||
) =
|
|
||||||
## Draws a source image onto the destination image.
|
|
||||||
let image = image.subImage(sx.int, sy.int, sWidth.int, sHeight.int)
|
|
||||||
ctx.drawImage(image, dx, dx, image.width.float32, image.height.float32)
|
|
||||||
|
|
||||||
proc drawImage*(ctx: Context, image: Image, src, dest: Rect) =
|
|
||||||
## Draws a source image onto the destination image.
|
|
||||||
ctx.drawImage(
|
|
||||||
image,
|
|
||||||
src.x, src.y, src.w, src.h,
|
|
||||||
dest.x, dest.y, dest.w, dest.h
|
|
||||||
)
|
|
||||||
|
|
||||||
proc arc*(ctx: Context, x, y, r, a0, a1: float32, ccw: bool = false) =
|
|
||||||
## Draws a circular arc.
|
|
||||||
ctx.path.arc(x, y, r, a0, a1, ccw)
|
|
||||||
|
|
||||||
proc arc*(ctx: Context, pos: Vec2, r: float32, a: Vec2, ccw: bool = false) =
|
|
||||||
## Adds a circular arc to the current sub-path.
|
|
||||||
ctx.path.arc(pos, r, a, ccw)
|
|
||||||
|
|
||||||
proc arcTo*(ctx: Context, x1, y1, x2, y2, radius: float32) =
|
|
||||||
## Draws a circular arc using the given control points and radius.
|
|
||||||
ctx.path.arcTo(x1, y1, x2, y2, radius)
|
|
||||||
|
|
||||||
proc arcTo*(ctx: Context, a, b: Vec2, r: float32) =
|
|
||||||
## Adds a circular arc using the given control points and radius.
|
|
||||||
ctx.path.arcTo(a, b, r)
|
|
||||||
|
|
||||||
proc isPointInPath*(
|
|
||||||
ctx: Context, path: Path, pos: Vec2, windingRule = wrNonZero
|
|
||||||
): bool =
|
|
||||||
## Returns whether or not the specified point is contained in the current path.
|
|
||||||
path.fillOverlaps(pos, ctx.mat, windingRule)
|
|
||||||
|
|
||||||
proc isPointInPath*(
|
|
||||||
ctx: Context, path: Path, x, y: float32, windingRule = wrNonZero
|
|
||||||
): bool {.inline.} =
|
|
||||||
## Returns whether or not the specified point is contained in the current path.
|
|
||||||
ctx.isPointInPath(path, vec2(x, y), windingRule)
|
|
||||||
|
|
||||||
proc isPointInPath*(
|
|
||||||
ctx: Context, pos: Vec2, windingRule = wrNonZero
|
|
||||||
): bool {.inline.} =
|
|
||||||
## Returns whether or not the specified point is contained in the current path.
|
|
||||||
ctx.isPointInPath(ctx.path, pos, windingRule)
|
|
||||||
|
|
||||||
proc isPointInPath*(
|
|
||||||
ctx: Context, x, y: float32, windingRule = wrNonZero
|
|
||||||
): bool {.inline.} =
|
|
||||||
## Returns whether or not the specified point is contained in the current path.
|
|
||||||
ctx.isPointInPath(ctx.path, vec2(x, y), windingRule)
|
|
||||||
|
|
||||||
proc isPointInStroke*(ctx: Context, path: Path, pos: Vec2): bool =
|
|
||||||
## Returns whether or not the specified point is inside the area contained
|
|
||||||
## by the stroking of a path.
|
|
||||||
path.strokeOverlaps(
|
|
||||||
pos,
|
|
||||||
ctx.mat,
|
|
||||||
ctx.lineWidth,
|
|
||||||
ctx.lineCap,
|
|
||||||
ctx.lineJoin,
|
|
||||||
ctx.miterLimit,
|
|
||||||
ctx.lineDash
|
|
||||||
)
|
|
||||||
|
|
||||||
proc isPointInStroke*(ctx: Context, path: Path, x, y: float32): bool {.inline.} =
|
|
||||||
## Returns whether or not the specified point is inside the area contained
|
|
||||||
## by the stroking of a path.
|
|
||||||
ctx.isPointInStroke(path, vec2(x, y))
|
|
||||||
|
|
||||||
proc isPointInStroke*(ctx: Context, pos: Vec2): bool {.inline.} =
|
|
||||||
## Returns whether or not the specified point is inside the area contained
|
|
||||||
## by the stroking of a path.
|
|
||||||
ctx.isPointInStroke(ctx.path, pos)
|
|
||||||
|
|
||||||
proc isPointInStroke*(ctx: Context, x, y: float32): bool {.inline.} =
|
|
||||||
## Returns whether or not the specified point is inside the area contained
|
|
||||||
## by the stroking of a path.
|
|
||||||
ctx.isPointInStroke(ctx.path, vec2(x, y))
|
|
||||||
|
|
|
@ -35,12 +35,12 @@ type
|
||||||
positions*: seq[Vec2] ## The positions of the glyphs for each rune.
|
positions*: seq[Vec2] ## The positions of the glyphs for each rune.
|
||||||
selectionRects*: seq[Rect] ## The selection rects for each glyph.
|
selectionRects*: seq[Rect] ## The selection rects for each glyph.
|
||||||
|
|
||||||
HAlignMode* = enum
|
HorizontalAlignment* = enum
|
||||||
haLeft
|
haLeft
|
||||||
haCenter
|
haCenter
|
||||||
haRight
|
haRight
|
||||||
|
|
||||||
VAlignMode* = enum
|
VerticalAlignment* = enum
|
||||||
vaTop
|
vaTop
|
||||||
vaMiddle
|
vaMiddle
|
||||||
vaBottom
|
vaBottom
|
||||||
|
|
|
@ -1021,7 +1021,13 @@ proc requiresAntiAliasing(segments: seq[(Segment, int16)]): bool =
|
||||||
# AA is required if all segments are not vertical or have fractional > 0
|
# AA is required if all segments are not vertical or have fractional > 0
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc computePixelBounds(segments: seq[(Segment, int16)]): Rect =
|
proc transform(shapes: var seq[seq[Vec2]], transform: Mat3) =
|
||||||
|
if transform != mat3():
|
||||||
|
for shape in shapes.mitems:
|
||||||
|
for vec in shape.mitems:
|
||||||
|
vec = transform * vec
|
||||||
|
|
||||||
|
proc computeBounds(segments: seq[(Segment, int16)]): Rect =
|
||||||
## Compute the bounds of the segments.
|
## Compute the bounds of the segments.
|
||||||
var
|
var
|
||||||
xMin = float32.high
|
xMin = float32.high
|
||||||
|
@ -1035,11 +1041,6 @@ proc computePixelBounds(segments: seq[(Segment, int16)]): Rect =
|
||||||
yMin = min(yMin, segment.at.y)
|
yMin = min(yMin, segment.at.y)
|
||||||
yMax = max(yMax, segment.to.y)
|
yMax = max(yMax, segment.to.y)
|
||||||
|
|
||||||
xMin = floor(xMin)
|
|
||||||
xMax = ceil(xMax)
|
|
||||||
yMin = floor(yMin)
|
|
||||||
yMax = ceil(yMax)
|
|
||||||
|
|
||||||
if xMin.isNaN() or xMax.isNaN() or yMin.isNaN() or yMax.isNaN():
|
if xMin.isNaN() or xMax.isNaN() or yMin.isNaN() or yMax.isNaN():
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
|
@ -1048,9 +1049,11 @@ proc computePixelBounds(segments: seq[(Segment, int16)]): Rect =
|
||||||
result.w = xMax - xMin
|
result.w = xMax - xMin
|
||||||
result.h = yMax - yMin
|
result.h = yMax - yMin
|
||||||
|
|
||||||
proc computePixelBounds*(path: Path): Rect =
|
proc computeBounds*(path: Path, transform = mat3()): Rect =
|
||||||
## Compute the bounds of the path.
|
## Compute the bounds of the path.
|
||||||
path.commandsToShapes().shapesToSegments().computePixelBounds()
|
var shapes = path.commandsToShapes()
|
||||||
|
shapes.transform(transform)
|
||||||
|
computeBounds(shapes.shapesToSegments())
|
||||||
|
|
||||||
proc partitionSegments(
|
proc partitionSegments(
|
||||||
segments: seq[(Segment, int16)], top, height: int
|
segments: seq[(Segment, int16)], top, height: int
|
||||||
|
@ -1482,7 +1485,7 @@ proc fillShapes(
|
||||||
rgbx = color.asRgbx()
|
rgbx = color.asRgbx()
|
||||||
segments = shapes.shapesToSegments()
|
segments = shapes.shapesToSegments()
|
||||||
aa = segments.requiresAntiAliasing()
|
aa = segments.requiresAntiAliasing()
|
||||||
bounds = computePixelBounds(segments)
|
bounds = computeBounds(segments).snapToPixels()
|
||||||
startX = max(0, bounds.x.int)
|
startX = max(0, bounds.x.int)
|
||||||
startY = max(0, bounds.y.int)
|
startY = max(0, bounds.y.int)
|
||||||
pathHeight = min(image.height, (bounds.y + bounds.h).int)
|
pathHeight = min(image.height, (bounds.y + bounds.h).int)
|
||||||
|
@ -1539,7 +1542,7 @@ proc fillShapes(
|
||||||
let
|
let
|
||||||
segments = shapes.shapesToSegments()
|
segments = shapes.shapesToSegments()
|
||||||
aa = segments.requiresAntiAliasing()
|
aa = segments.requiresAntiAliasing()
|
||||||
bounds = computePixelBounds(segments)
|
bounds = computeBounds(segments).snapToPixels()
|
||||||
startX = max(0, bounds.x.int)
|
startX = max(0, bounds.x.int)
|
||||||
startY = max(0, bounds.y.int)
|
startY = max(0, bounds.y.int)
|
||||||
pathHeight = min(mask.height, (bounds.y + bounds.h).int)
|
pathHeight = min(mask.height, (bounds.y + bounds.h).int)
|
||||||
|
@ -1729,12 +1732,6 @@ proc parseSomePath(
|
||||||
elif type(path) is Path:
|
elif type(path) is Path:
|
||||||
path.commandsToShapes(closeSubpaths, pixelScale)
|
path.commandsToShapes(closeSubpaths, pixelScale)
|
||||||
|
|
||||||
proc transform(shapes: var seq[seq[Vec2]], transform: Mat3) =
|
|
||||||
if transform != mat3():
|
|
||||||
for shape in shapes.mitems:
|
|
||||||
for segment in shape.mitems:
|
|
||||||
segment = transform * segment
|
|
||||||
|
|
||||||
proc fillPath*(
|
proc fillPath*(
|
||||||
mask: Mask,
|
mask: Mask,
|
||||||
path: SomePath,
|
path: SomePath,
|
||||||
|
|
Loading…
Reference in a new issue