diff --git a/README.md b/README.md index 261bf71..9e61cb5 100644 --- a/README.md +++ b/README.md @@ -136,11 +136,11 @@ proc newFont(typeface: Typeface, size: float32, color: ColorRGBA): Font = let spans = @[ newSpan("verb [with object] ", - typeface.newFont(12, rgba(200, 200, 200, 255))), - newSpan("strallow\n", typeface.newFont(36, rgba(0, 0, 0, 255))), - newSpan("\nstral·low\n", typeface.newFont(13, rgba(0, 127, 244, 255))), + newFont(typeface, 12, rgba(200, 200, 200, 255))), + newSpan("strallow\n", newFont(typeface, 36, rgba(0, 0, 0, 255))), + newSpan("\nstral·low\n", newFont(typeface, 13, rgba(0, 127, 244, 255))), newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ", - typeface.newFont(14, rgba(80, 80, 80, 255))) + newFont(typeface, 14, rgba(80, 80, 80, 255))) ] image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10)) @@ -236,18 +236,16 @@ image.draw(lines) ### Gradient [examples/gradient.nim](examples/gradient.nim) ```nim -let paint = Paint( - kind: pkGradientRadial, - gradientHandlePositions: @[ - vec2(100, 100), - vec2(200, 100), - vec2(100, 200) - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), - ] -) +let paint = newPaint(pkGradientRadial) +paint.gradientHandlePositions = @[ + vec2(100, 100), + vec2(200, 100), + vec2(100, 200) +] +paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), +] image.fillPath( """ @@ -272,14 +270,12 @@ path.polygon( 70, sides = 8 ) -image.fillPath( - path, - Paint( - kind: pkImageTiled, - image: readImage("tests/images/png/baboon.png"), - imageMat: scale(vec2(0.08, 0.08)) - ) -) + +let paint = newPaint(pkImageTiled) +paint.image = readImage("tests/images/png/baboon.png") +paint.imageMat = scale(vec2(0.08, 0.08)) + +image.fillPath(path, paint) ``` ![example output](examples/image_tiled.png) diff --git a/examples/gradient.nim b/examples/gradient.nim index fae47f7..f86be4c 100644 --- a/examples/gradient.nim +++ b/examples/gradient.nim @@ -3,18 +3,16 @@ import pixie let image = newImage(200, 200) image.fill(rgba(255, 255, 255, 255)) -let paint = Paint( - kind: pkGradientRadial, - gradientHandlePositions: @[ - vec2(100, 100), - vec2(200, 100), - vec2(100, 200) - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), - ] -) +let paint = newPaint(pkGradientRadial) +paint.gradientHandlePositions = @[ + vec2(100, 100), + vec2(200, 100), + vec2(100, 200) +] +paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), +] image.fillPath( """ diff --git a/examples/image_tiled.nim b/examples/image_tiled.nim index 0860331..2f5d3ce 100644 --- a/examples/image_tiled.nim +++ b/examples/image_tiled.nim @@ -9,13 +9,10 @@ path.polygon( 70, sides = 8 ) -image.fillPath( - path, - Paint( - kind: pkImageTiled, - image: readImage("tests/images/png/baboon.png"), - imageMat: scale(vec2(0.08, 0.08)) - ) -) +let paint = newPaint(pkImageTiled) +paint.image = readImage("tests/images/png/baboon.png") +paint.imageMat = scale(vec2(0.08, 0.08)) + +image.fillPath(path, paint) image.writeFile("examples/image_tiled.png") diff --git a/examples/realtime_glfw.nim b/examples/realtime_glfw.nim index 4daf53a..55740da 100644 --- a/examples/realtime_glfw.nim +++ b/examples/realtime_glfw.nim @@ -16,7 +16,7 @@ proc display() = ## Called every frame by main while loop # draw shiny sphere on gradient background - var linerGradient = Paint(kind: pkGradientLinear) + let linerGradient = newPaint(pkGradientLinear) linerGradient.gradientHandlePositions.add(vec2(0, 0)) linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientStops.add( @@ -26,7 +26,7 @@ proc display() = ctx.fillStyle = linerGradient ctx.fillRect(0, 0, 256, 256) - var radialGradient = Paint(kind: pkGradientRadial) + let radialGradient = newPaint(pkGradientRadial) radialGradient.gradientHandlePositions.add(vec2(128, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(128, 256)) diff --git a/examples/realtime_glut.nim b/examples/realtime_glut.nim index acf49e8..5289094 100644 --- a/examples/realtime_glut.nim +++ b/examples/realtime_glut.nim @@ -15,7 +15,7 @@ proc display() {.cdecl.} = ## Called every frame by GLUT # draw shiny sphere on gradient background - var linerGradient = Paint(kind: pkGradientLinear) + let linerGradient = newPaint(pkGradientLinear) linerGradient.gradientHandlePositions.add(vec2(0, 0)) linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientStops.add( @@ -25,7 +25,7 @@ proc display() {.cdecl.} = ctx.fillStyle = linerGradient ctx.fillRect(0, 0, 256, 256) - var radialGradient = Paint(kind: pkGradientRadial) + let radialGradient = newPaint(pkGradientRadial) radialGradient.gradientHandlePositions.add(vec2(128, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(128, 256)) diff --git a/examples/realtime_sdl.nim b/examples/realtime_sdl.nim index c88a959..b604c11 100644 --- a/examples/realtime_sdl.nim +++ b/examples/realtime_sdl.nim @@ -26,7 +26,7 @@ proc display() = ## Called every frame by main while loop # draw shiny sphere on gradient background - var linerGradient = Paint(kind: pkGradientLinear) + let linerGradient = newPaint(pkGradientLinear) linerGradient.gradientHandlePositions.add(vec2(0, 0)) linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientStops.add( @@ -36,7 +36,7 @@ proc display() = ctx.fillStyle = linerGradient ctx.fillRect(0, 0, 256, 256) - var radialGradient = Paint(kind: pkGradientRadial) + let radialGradient = newPaint(pkGradientRadial) radialGradient.gradientHandlePositions.add(vec2(128, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(128, 256)) diff --git a/examples/realtime_win32.nim b/examples/realtime_win32.nim index 1148b22..68a147f 100644 --- a/examples/realtime_win32.nim +++ b/examples/realtime_win32.nim @@ -15,7 +15,7 @@ var proc draw() = # draw shiny sphere on gradient background - var linerGradient = Paint(kind: pkGradientLinear) + let linerGradient = newPaint(pkGradientLinear) linerGradient.gradientHandlePositions.add(vec2(0, 0)) linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientStops.add( @@ -25,7 +25,7 @@ proc draw() = ctx.fillStyle = linerGradient ctx.fillRect(0, 0, 256, 256) - var radialGradient = Paint(kind: pkGradientRadial) + let radialGradient = newPaint(pkGradientRadial) radialGradient.gradientHandlePositions.add(vec2(128, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(128, 256)) diff --git a/examples/realtime_wnim.nim b/examples/realtime_wnim.nim index e88bfaf..681500a 100644 --- a/examples/realtime_wnim.nim +++ b/examples/realtime_wnim.nim @@ -14,7 +14,7 @@ var proc draw() = # draw shiny sphere on gradient background - var linerGradient = Paint(kind: pkGradientLinear) + let linerGradient = newPaint(pkGradientLinear) linerGradient.gradientHandlePositions.add(vec2(0, 0)) linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientStops.add( @@ -24,7 +24,7 @@ proc draw() = ctx.fillStyle = linerGradient ctx.fillRect(0, 0, 256, 256) - var radialGradient = Paint(kind: pkGradientRadial) + let radialGradient = newPaint(pkGradientRadial) radialGradient.gradientHandlePositions.add(vec2(128, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(128, 256)) diff --git a/examples/text_spans.nim b/examples/text_spans.nim index efcaeef..e69d952 100644 --- a/examples/text_spans.nim +++ b/examples/text_spans.nim @@ -12,11 +12,11 @@ proc newFont(typeface: Typeface, size: float32, color: ColorRGBA): Font = let spans = @[ newSpan("verb [with object] ", - typeface.newFont(12, rgba(200, 200, 200, 255))), - newSpan("strallow\n", typeface.newFont(36, rgba(0, 0, 0, 255))), - newSpan("\nstral·low\n", typeface.newFont(13, rgba(0, 127, 244, 255))), + newFont(typeface, 12, rgba(200, 200, 200, 255))), + newSpan("strallow\n", newFont(typeface, 36, rgba(0, 0, 0, 255))), + newSpan("\nstral·low\n", newFont(typeface, 13, rgba(0, 127, 244, 255))), newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ", - typeface.newFont(14, rgba(80, 80, 80, 255))) + newFont(typeface, 14, rgba(80, 80, 80, 255))) ] image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10)) diff --git a/src/pixie/contexts.nim b/src/pixie/contexts.nim index 68d6804..7fad185 100644 --- a/src/pixie/contexts.nim +++ b/src/pixie/contexts.nim @@ -53,8 +53,8 @@ proc newContext*(image: Image): Context = result.globalAlpha = 1 result.lineWidth = 1 result.miterLimit = 10 - result.fillStyle = Paint(kind: pkSolid, color: rgbx(0, 0, 0, 255)) - result.strokeStyle = Paint(kind: pkSolid, color: rgbx(0, 0, 0, 255)) + result.fillStyle = rgbx(0, 0, 0, 255) + result.strokeStyle = rgbx(0, 0, 0, 255) result.fontSize = 12 proc newContext*(width, height: int): Context {.inline.} = @@ -81,6 +81,9 @@ proc save*(ctx: Context) {.inline.} = ## a stack. ctx.stateStack.add(ctx.state()) + ctx.fillStyle = newPaint(ctx.fillStyle) + ctx.strokeStyle = newPaint(ctx.strokeStyle) + proc saveLayer*(ctx: Context) = ## Saves the entire state of the context by pushing the current state onto ## a stack and allocates a new image layer for subsequent drawing. Calling @@ -356,20 +359,15 @@ proc stroke*(ctx: Context) {.inline.} = proc clearRect*(ctx: Context, rect: Rect) = ## Erases the pixels in a rectangular area. + let paint = newPaint(pkSolid) + paint.blendMode = bmOverwrite + let path = newPath() path.rect(rect) if ctx.layer != nil: - ctx.layer.fillPath( - path, - Paint(kind: pkSolid, color: rgbx(0, 0, 0, 0), blendMode: bmOverwrite), - ctx.mat - ) + ctx.layer.fillPath( path, paint, ctx.mat) else: - ctx.image.fillPath( - path, - Paint(kind: pkSolid, color: rgbx(0, 0, 0, 0), blendMode: bmOverwrite), - ctx.mat - ) + ctx.image.fillPath(path, paint, ctx.mat) proc clearRect*(ctx: Context, x, y, width, height: float32) {.inline.} = ## Erases the pixels in a rectangular area. @@ -604,17 +602,22 @@ proc strokePolygon*(ctx: Context, pos: Vec2, size: float32, sides: int) = proc drawImage*(ctx: Context, image: Image, dx, dy, dWidth, dHeight: float32) = ## Draws a source image onto the destination image. - var + let imageMat = ctx.mat * translate(vec2(dx, dy)) * scale(vec2( dWidth / image.width.float32, dHeight / image.height.float32 )) - savedStyle = ctx.fillStyle - ctx.fillStyle = Paint(kind: pkImage, image: image, imageMat: imageMat) + 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 = savedStyle + + ctx.fillStyle = savedFillStyle proc drawImage*(ctx: Context, image: Image, dx, dy: float32) = ## Draws a source image onto the destination image. @@ -635,7 +638,7 @@ proc drawImage*( dx, dy, dWidth, dHeight: float32 ) = ## Draws a source image onto the destination image. - var image = image.subImage(sx.int, sy.int, sWidth.int, sHeight.int) + 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) = diff --git a/src/pixie/fileformats/svg.nim b/src/pixie/fileformats/svg.nim index 02144df..7b00d88 100644 --- a/src/pixie/fileformats/svg.nim +++ b/src/pixie/fileformats/svg.nim @@ -172,14 +172,12 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx = let id = fill[5 .. ^2] if id in result.linearGradients: let linearGradient = result.linearGradients[id] - result.fill = Paint( - kind: pkGradientLinear, - gradientHandlePositions: @[ - result.transform * vec2(linearGradient.x1, linearGradient.y1), - result.transform * vec2(linearGradient.x2, linearGradient.y2) - ], - gradientStops: linearGradient.stops, - ) + result.fill = newPaint(pkGradientLinear) + result.fill.gradientHandlePositions = @[ + result.transform * vec2(linearGradient.x1, linearGradient.y1), + result.transform * vec2(linearGradient.x2, linearGradient.y2) + ] + result.fill.gradientStops = linearGradient.stops else: raise newException(PixieError, "Missing SVG resource " & id) else: diff --git a/src/pixie/paints.nim b/src/pixie/paints.nim index 6421c63..a6ee40f 100644 --- a/src/pixie/paints.nim +++ b/src/pixie/paints.nim @@ -1,4 +1,4 @@ -import blends, chroma, common, images, internal, options, vmath +import blends, chroma, common, images, internal, vmath type PaintKind* = enum @@ -9,19 +9,19 @@ type pkGradientRadial pkGradientAngular - Paint* = object + Paint* = ref object ## Paint used to fill paths. - case kind*: PaintKind - of pkSolid: - color*: ColorRGBX ## Color to fill with. - of pkImage, pkImageTiled: - image*: Image ## Image to fill with. - imageMat*: Mat3 ## Matrix of the filled image. - of pkGradientLinear, pkGradientRadial, pkGradientAngular: - gradientHandlePositions*: seq[Vec2] ## Gradient positions (image space). - gradientStops*: seq[ColorStop] ## Color stops (gradient space). - blendMode*: BlendMode ## Blend mode. - opacityOption: Option[float32] + kind*: PaintKind + blendMode*: BlendMode ## Blend mode. + opacity*: float32 + # pkSolid + color*: ColorRGBX ## Color to fill with. + # pkImage, pkImageTiled: + image*: Image ## Image to fill with. + imageMat*: Mat3 ## Matrix of the filled image. + # pkGradientLinear, pkGradientRadial, pkGradientAngular: + gradientHandlePositions*: seq[Vec2] ## Gradient positions (image space). + gradientStops*: seq[ColorStop] ## Color stops (gradient space). ColorStop* = object ## Color stop on a gradient curve. @@ -30,32 +30,35 @@ type SomePaint* = string | Paint | SomeColor +proc newPaint*(kind: PaintKind): Paint = + ## Create a new Paint. + result = Paint(kind: kind, opacity: 1, imageMat: mat3()) + +proc newPaint*(paint: Paint): Paint = + ## Create a new Paint with the same properties. + result = newPaint(paint.kind) + result.blendMode = paint.blendMode + result.opacity = paint.opacity + result.color = paint.color + result.image = paint.image + result.imageMat = paint.imageMat + result.gradientHandlePositions = paint.gradientHandlePositions + result.gradientStops = paint.gradientStops + converter parseSomePaint*(paint: SomePaint): Paint {.inline.} = ## Given SomePaint, parse it in different ways. when type(paint) is string: - Paint(kind: pkSolid, color: parseHtmlColor(paint).rgbx()) + result = newPaint(pkSolid) + result.color = parseHtmlColor(paint).rgbx() elif type(paint) is SomeColor: + result = newPaint(pkSolid) when type(paint) is ColorRGBX: - Paint(kind: pkSolid, color: paint) + result.color = paint else: - Paint(kind: pkSolid, color: paint.rgbx()) + result.color = paint.rgbx() elif type(paint) is Paint: paint -proc opacity*(paint: Paint): float32 = - ## Paint opacity (applies with color or image opacity). - if paint.opacityOption.isSome: - paint.opacityOption.get() - else: - 1 - -proc `opacity=`*(paint: var Paint, opacity: float32) = - ## Set the paint opacity (applies with color or image opacity). - if opacity >= 0 and opacity <= 1: - paint.opacityOption = some(opacity) - else: - raise newException(PixieError, "Invalid opacity: " & $opacity) - proc toLineSpace(at, to, point: Vec2): float32 {.inline.} = ## Convert position on to where it would fall on a line between at and to. let diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 49b47c4..53eb836 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -1803,23 +1803,24 @@ proc fillPath*( # Draw the image (maybe tiled) or gradients. Do this with opaque paint and # and then apply the paint's opacity to the mask. - - var paintOpaque = paint - paintOpaque.opacity = 1 + let savedOpacity = paint.opacity + paint.opacity = 1 case paint.kind: of pkSolid: discard # Handled above of pkImage: - fill.draw(paintOpaque.image, paintOpaque.imageMat) + fill.draw(paint.image, paint.imageMat) of pkImageTiled: - fill.drawTiled(paintOpaque.image, paintOpaque.imageMat) + fill.drawTiled(paint.image, paint.imageMat) of pkGradientLinear: - fill.fillGradientLinear(paintOpaque) + fill.fillGradientLinear(paint) of pkGradientRadial: - fill.fillGradientRadial(paintOpaque) + fill.fillGradientRadial(paint) of pkGradientAngular: - fill.fillGradientAngular(paintOpaque) + fill.fillGradientAngular(paint) + + paint.opacity = savedOpacity if paint.opacity != 1: mask.applyOpacity(paint.opacity) @@ -1898,23 +1899,24 @@ proc strokePath*( # Draw the image (maybe tiled) or gradients. Do this with opaque paint and # and then apply the paint's opacity to the mask. - - var paintOpaque = paint - paintOpaque.opacity = 1 + let savedOpacity = paint.opacity + paint.opacity = 1 case paint.kind: of pkSolid: discard # Handled above of pkImage: - fill.draw(paintOpaque.image, paintOpaque.imageMat) + fill.draw(paint.image, paint.imageMat) of pkImageTiled: - fill.drawTiled(paintOpaque.image, paintOpaque.imageMat) + fill.drawTiled(paint.image, paint.imageMat) of pkGradientLinear: - fill.fillGradientLinear(paintOpaque) + fill.fillGradientLinear(paint) of pkGradientRadial: - fill.fillGradientRadial(paintOpaque) + fill.fillGradientRadial(paint) of pkGradientAngular: - fill.fillGradientAngular(paintOpaque) + fill.fillGradientAngular(paint) + + paint.opacity = savedOpacity if paint.opacity != 1: mask.applyOpacity(paint.opacity) diff --git a/tests/images/context/paintSaveRestore.png b/tests/images/context/paintSaveRestore.png new file mode 100644 index 0000000..baa7f02 Binary files /dev/null and b/tests/images/context/paintSaveRestore.png differ diff --git a/tests/test_contexts.nim b/tests/test_contexts.nim index c89c940..2ccb18e 100644 --- a/tests/test_contexts.nim +++ b/tests/test_contexts.nim @@ -526,7 +526,8 @@ block: image.fill(rgba(255, 255, 255, 255)) - var paint = Paint(kind: pkSolid, color: rgba(0, 0, 255, 255)) + let paint = newPaint(pkSolid) + paint.color = rgba(0, 0, 255, 255) paint.blendMode = bmExclusion ctx.fillStyle = paint @@ -634,3 +635,12 @@ block: ctx.ellipse(150, 75, 40, 60) ctx.lineWidth = 25 doAssert ctx.isPointInStroke(110, 75) + +block: + let ctx = newContext(newImage(100, 100)) + ctx.fillStyle.color = rgba(255, 0, 0, 255) + ctx.save() + ctx.fillStyle.color = rgba(0, 0, 255, 255) + ctx.restore() + ctx.fillRect(0, 0, ctx.image.width.float32, ctx.image.height.float32) + ctx.image.writeFile("tests/images/context/paintSaveRestore.png") diff --git a/tests/test_fonts.nim b/tests/test_fonts.nim index 1a30e10..68f868c 100644 --- a/tests/test_fonts.nim +++ b/tests/test_fonts.nim @@ -634,17 +634,15 @@ block: block: var font = readFont("tests/fonts/IBMPlexSans-Regular_2.ttf") font.size = 48 - font.paint = Paint( - kind: pkGradientLinear, - gradientHandlePositions: @[ - vec2(0, 50), - vec2(100, 50), - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 127), position: 1.0), - ] - ) + font.paint = newPaint(pkGradientLinear) + font.paint.gradientHandlePositions = @[ + vec2(0, 50), + vec2(100, 50), + ] + font.paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 127), position: 1.0), + ] let image = newImage(100, 100) image.fill(rgba(255, 255, 255, 255)) diff --git a/tests/test_paints.nim b/tests/test_paints.nim index fac4748..eeb0267 100644 --- a/tests/test_paints.nim +++ b/tests/test_paints.nim @@ -12,144 +12,108 @@ block: let image = newImage(100, 100) image.fillPath( heartShape, - Paint( - kind: pkSolid, - color: rgba(255, 0, 0, 255) - ) + rgba(255, 0, 0, 255) ) image.writeFile("tests/images/paths/paintSolid.png") block: + let paint = newPaint(pkImage) + paint.image = decodePng(readFile("tests/images/png/baboon.png")) + paint.imageMat = scale(vec2(0.2, 0.2)) + let image = newImage(100, 100) - image.fillPath( - heartShape, - Paint( - kind: pkImage, - image: decodePng(readFile("tests/images/png/baboon.png")), - imageMat: scale(vec2(0.2, 0.2)) - ) - ) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/paintImage.png") block: - var paint = Paint( - kind: pkImage, - image: decodePng(readFile("tests/images/png/baboon.png")), - imageMat: scale(vec2(0.2, 0.2)) - ) + let paint = newPaint(pkImage) + paint.image = decodePng(readFile("tests/images/png/baboon.png")) + paint.imageMat = scale(vec2(0.2, 0.2)) paint.opacity = 0.5 let image = newImage(100, 100) - image.fillPath( - heartShape, - paint - ) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/paintImageOpacity.png") block: + let paint = newPaint(pkImageTiled) + paint.image = decodePng(readFile("tests/images/png/baboon.png")) + paint.imageMat = scale(vec2(0.02, 0.02)) + let image = newImage(100, 100) - image.fillPath( - heartShape, - Paint( - kind: pkImageTiled, - image: decodePng(readFile("tests/images/png/baboon.png")), - imageMat: scale(vec2(0.02, 0.02)) - ) - ) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/paintImageTiled.png") block: - var paint = Paint( - kind: pkImageTiled, - image: decodePng(readFile("tests/images/png/baboon.png")), - imageMat: scale(vec2(0.02, 0.02)) - ) + let paint = newPaint(pkImageTiled) + paint.image = decodePng(readFile("tests/images/png/baboon.png")) + paint.imageMat = scale(vec2(0.02, 0.02)) paint.opacity = 0.5 let image = newImage(100, 100) - image.fillPath( - heartShape, - paint - ) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/paintImageTiledOpacity.png") block: + let paint = newPaint(pkGradientLinear) + paint.gradientHandlePositions = @[ + vec2(0, 50), + vec2(100, 50), + ] + paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), + ] + let image = newImage(100, 100) - image.fillPath( - heartShape, - Paint( - kind: pkGradientLinear, - gradientHandlePositions: @[ - vec2(0, 50), - vec2(100, 50), - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), - ] - ) - ) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/gradientLinear.png") block: - let image = newImage(100, 100) - image.fillPath( - heartShape, - Paint( - kind: pkGradientRadial, - gradientHandlePositions: @[ - vec2(50, 50), - vec2(100, 50), - vec2(50, 100) - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), - ] - ) - ) + let paint = newPaint(pkGradientRadial) + paint.gradientHandlePositions = @[ + vec2(50, 50), + vec2(100, 50), + vec2(50, 100) + ] + paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), + ] + let image = newImage(100, 100) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/gradientRadial.png") block: - let image = newImage(100, 100) - image.fillPath( - heartShape, - Paint( - kind: pkGradientAngular, - gradientHandlePositions: @[ - vec2(50, 50), - vec2(100, 50), - vec2(50, 100) - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), - ] - ) - ) + let paint = newPaint(pkGradientAngular) + paint.gradientHandlePositions = @[ + vec2(50, 50), + vec2(100, 50), + vec2(50, 100) + ] + paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), + ] + let image = newImage(100, 100) + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/gradientAngular.png") block: - var paint = Paint( - kind: pkGradientAngular, - gradientHandlePositions: @[ - vec2(50, 50), - vec2(100, 50), - vec2(50, 100) - ], - gradientStops: @[ - ColorStop(color: rgba(255, 0, 0, 255), position: 0), - ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), - ] - ) + let paint = newPaint(pkGradientAngular) + paint.gradientHandlePositions = @[ + vec2(50, 50), + vec2(100, 50), + vec2(50, 100) + ] + paint.gradientStops = @[ + ColorStop(color: rgba(255, 0, 0, 255), position: 0), + ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), + ] paint.opacity = 0.5 let image = newImage(100, 100) - image.fillPath( - heartShape, - paint - ) - + image.fillPath(heartShape, paint) image.writeFile("tests/images/paths/gradientAngularOpacity.png") diff --git a/tests/test_paths.nim b/tests/test_paths.nim index 7880282..d1bf887 100644 --- a/tests/test_paths.nim +++ b/tests/test_paths.nim @@ -367,11 +367,16 @@ block: let image = newImage(100, 100) image.fillPath( "M 10 10 H 60 V 60 H 10 z", - Paint(kind: pkSolid, color: rgbx(255, 0, 0, 255), blendMode: bmNormal) + rgbx(255, 0, 0, 255) ) + + let paint = newPaint(pkSolid) + paint.color = rgbx(0, 255, 0, 255) + paint.blendMode = bmExcludeMask + image.fillPath( "M 30 30 H 80 V 80 H 30 z", - Paint(kind: pkSolid, color: rgbx(0, 255, 0, 255), blendMode: bmExcludeMask) + paint ) image.writeFile("tests/images/paths/rectExcludeMask.png") @@ -379,11 +384,16 @@ block: let image = newImage(100, 100) image.fillPath( "M 10.1 10.1 H 60.1 V 60.1 H 10.1 z", - Paint(kind: pkSolid, color: rgbx(255, 0, 0, 255), blendMode: bmNormal) + rgbx(255, 0, 0, 255) ) + + let paint = newPaint(pkSolid) + paint.color = rgbx(0, 255, 0, 255) + paint.blendMode = bmExcludeMask + image.fillPath( "M 30.1 30.1 H 80.1 V 80.1 H 30.1 z", - Paint(kind: pkSolid, color: rgbx(0, 255, 0, 255), blendMode: bmExcludeMask) + paint ) image.writeFile("tests/images/paths/rectExcludeMaskAA.png") @@ -391,11 +401,16 @@ block: let image = newImage(100, 100) image.fillPath( "M 10 10 H 60 V 60 H 10 z", - Paint(kind: pkSolid, color: rgbx(255, 0, 0, 255), blendMode: bmNormal) + rgbx(255, 0, 0, 255) ) + + let paint = newPaint(pkSolid) + paint.color = rgbx(0, 255, 0, 255) + paint.blendMode = bmMask + image.fillPath( "M 30 30 H 80 V 80 H 30 z", - Paint(kind: pkSolid, color: rgbx(0, 255, 0, 255), blendMode: bmMask) + paint ) image.writeFile("tests/images/paths/rectMask.png") @@ -403,11 +418,16 @@ block: let image = newImage(100, 100) image.fillPath( "M 10.1 10.1 H 60.1 V 60.1 H 10.1 z", - Paint(kind: pkSolid, color: rgbx(255, 0, 0, 255), blendMode: bmNormal) + rgbx(255, 0, 0, 255) ) + + let paint = newPaint(pkSolid) + paint.color = rgbx(0, 255, 0, 255) + paint.blendMode = bmMask + image.fillPath( "M 30.1 30.1 H 80.1 V 80.1 H 30.1 z", - Paint(kind: pkSolid, color: rgbx(0, 255, 0, 255), blendMode: bmMask) + paint ) image.writeFile("tests/images/paths/rectMaskAA.png") @@ -573,7 +593,8 @@ block: let path = newPath() path.circle(50, 50, 30) - var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255)) + let paint = newPaint(pkSolid) + paint.color = rgba(255, 0, 255, 255) paint.opacity = 0.5 let image = newImage(100, 100) @@ -585,7 +606,8 @@ block: let path = newPath() path.circle(50, 50, 30) - var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255)) + let paint = newPaint(pkSolid) + paint.color = rgba(255, 0, 255, 255) paint.opacity = 0.5 let image = newImage(100, 100)