Merge pull request #255 from guzba/master

paint as ref object
This commit is contained in:
treeform 2021-08-06 17:11:01 -07:00 committed by GitHub
commit 390f9b95c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 243 additions and 252 deletions

View file

@ -136,11 +136,11 @@ proc newFont(typeface: Typeface, size: float32, color: ColorRGBA): Font =
let spans = @[ let spans = @[
newSpan("verb [with object] ", newSpan("verb [with object] ",
typeface.newFont(12, rgba(200, 200, 200, 255))), newFont(typeface, 12, rgba(200, 200, 200, 255))),
newSpan("strallow\n", typeface.newFont(36, rgba(0, 0, 0, 255))), newSpan("strallow\n", newFont(typeface, 36, rgba(0, 0, 0, 255))),
newSpan("\nstral·low\n", typeface.newFont(13, rgba(0, 127, 244, 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\" ", 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)) image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))
@ -236,18 +236,16 @@ image.draw(lines)
### Gradient ### Gradient
[examples/gradient.nim](examples/gradient.nim) [examples/gradient.nim](examples/gradient.nim)
```nim ```nim
let paint = Paint( let paint = newPaint(pkGradientRadial)
kind: pkGradientRadial, paint.gradientHandlePositions = @[
gradientHandlePositions: @[ vec2(100, 100),
vec2(100, 100), vec2(200, 100),
vec2(200, 100), vec2(100, 200)
vec2(100, 200) ]
], paint.gradientStops = @[
gradientStops: @[ ColorStop(color: rgba(255, 0, 0, 255), position: 0),
ColorStop(color: rgba(255, 0, 0, 255), position: 0), ColorStop(color: rgba(255, 0, 0, 40), position: 1.0),
ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), ]
]
)
image.fillPath( image.fillPath(
""" """
@ -272,14 +270,12 @@ path.polygon(
70, 70,
sides = 8 sides = 8
) )
image.fillPath(
path, let paint = newPaint(pkImageTiled)
Paint( paint.image = readImage("tests/images/png/baboon.png")
kind: pkImageTiled, paint.imageMat = scale(vec2(0.08, 0.08))
image: readImage("tests/images/png/baboon.png"),
imageMat: scale(vec2(0.08, 0.08)) image.fillPath(path, paint)
)
)
``` ```
![example output](examples/image_tiled.png) ![example output](examples/image_tiled.png)

View file

@ -3,18 +3,16 @@ 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 paint = Paint( let paint = newPaint(pkGradientRadial)
kind: pkGradientRadial, paint.gradientHandlePositions = @[
gradientHandlePositions: @[ vec2(100, 100),
vec2(100, 100), vec2(200, 100),
vec2(200, 100), vec2(100, 200)
vec2(100, 200) ]
], paint.gradientStops = @[
gradientStops: @[ ColorStop(color: rgba(255, 0, 0, 255), position: 0),
ColorStop(color: rgba(255, 0, 0, 255), position: 0), ColorStop(color: rgba(255, 0, 0, 40), position: 1.0),
ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), ]
]
)
image.fillPath( image.fillPath(
""" """

View file

@ -9,13 +9,10 @@ path.polygon(
70, 70,
sides = 8 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") image.writeFile("examples/image_tiled.png")

View file

@ -16,7 +16,7 @@ proc display() =
## Called every frame by main while loop ## Called every frame by main while loop
# draw shiny sphere on gradient background # 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, 0))
linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientHandlePositions.add(vec2(0, 256))
linerGradient.gradientStops.add( linerGradient.gradientStops.add(
@ -26,7 +26,7 @@ proc display() =
ctx.fillStyle = linerGradient ctx.fillStyle = linerGradient
ctx.fillRect(0, 0, 256, 256) 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(128, 128))
radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128))
radialGradient.gradientHandlePositions.add(vec2(128, 256)) radialGradient.gradientHandlePositions.add(vec2(128, 256))

View file

@ -15,7 +15,7 @@ proc display() {.cdecl.} =
## Called every frame by GLUT ## Called every frame by GLUT
# draw shiny sphere on gradient background # 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, 0))
linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientHandlePositions.add(vec2(0, 256))
linerGradient.gradientStops.add( linerGradient.gradientStops.add(
@ -25,7 +25,7 @@ proc display() {.cdecl.} =
ctx.fillStyle = linerGradient ctx.fillStyle = linerGradient
ctx.fillRect(0, 0, 256, 256) 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(128, 128))
radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128))
radialGradient.gradientHandlePositions.add(vec2(128, 256)) radialGradient.gradientHandlePositions.add(vec2(128, 256))

View file

@ -26,7 +26,7 @@ proc display() =
## Called every frame by main while loop ## Called every frame by main while loop
# draw shiny sphere on gradient background # 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, 0))
linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientHandlePositions.add(vec2(0, 256))
linerGradient.gradientStops.add( linerGradient.gradientStops.add(
@ -36,7 +36,7 @@ proc display() =
ctx.fillStyle = linerGradient ctx.fillStyle = linerGradient
ctx.fillRect(0, 0, 256, 256) 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(128, 128))
radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128))
radialGradient.gradientHandlePositions.add(vec2(128, 256)) radialGradient.gradientHandlePositions.add(vec2(128, 256))

View file

@ -15,7 +15,7 @@ var
proc draw() = proc draw() =
# draw shiny sphere on gradient background # 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, 0))
linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientHandlePositions.add(vec2(0, 256))
linerGradient.gradientStops.add( linerGradient.gradientStops.add(
@ -25,7 +25,7 @@ proc draw() =
ctx.fillStyle = linerGradient ctx.fillStyle = linerGradient
ctx.fillRect(0, 0, 256, 256) 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(128, 128))
radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128))
radialGradient.gradientHandlePositions.add(vec2(128, 256)) radialGradient.gradientHandlePositions.add(vec2(128, 256))

View file

@ -14,7 +14,7 @@ var
proc draw() = proc draw() =
# draw shiny sphere on gradient background # 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, 0))
linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientHandlePositions.add(vec2(0, 256))
linerGradient.gradientStops.add( linerGradient.gradientStops.add(
@ -24,7 +24,7 @@ proc draw() =
ctx.fillStyle = linerGradient ctx.fillStyle = linerGradient
ctx.fillRect(0, 0, 256, 256) 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(128, 128))
radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128))
radialGradient.gradientHandlePositions.add(vec2(128, 256)) radialGradient.gradientHandlePositions.add(vec2(128, 256))

View file

@ -12,11 +12,11 @@ proc newFont(typeface: Typeface, size: float32, color: ColorRGBA): Font =
let spans = @[ let spans = @[
newSpan("verb [with object] ", newSpan("verb [with object] ",
typeface.newFont(12, rgba(200, 200, 200, 255))), newFont(typeface, 12, rgba(200, 200, 200, 255))),
newSpan("strallow\n", typeface.newFont(36, rgba(0, 0, 0, 255))), newSpan("strallow\n", newFont(typeface, 36, rgba(0, 0, 0, 255))),
newSpan("\nstral·low\n", typeface.newFont(13, rgba(0, 127, 244, 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\" ", 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)) image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))

View file

@ -53,8 +53,8 @@ proc newContext*(image: Image): Context =
result.globalAlpha = 1 result.globalAlpha = 1
result.lineWidth = 1 result.lineWidth = 1
result.miterLimit = 10 result.miterLimit = 10
result.fillStyle = Paint(kind: pkSolid, color: rgbx(0, 0, 0, 255)) result.fillStyle = rgbx(0, 0, 0, 255)
result.strokeStyle = Paint(kind: pkSolid, color: rgbx(0, 0, 0, 255)) result.strokeStyle = rgbx(0, 0, 0, 255)
result.fontSize = 12 result.fontSize = 12
proc newContext*(width, height: int): Context {.inline.} = proc newContext*(width, height: int): Context {.inline.} =
@ -81,6 +81,9 @@ proc save*(ctx: Context) {.inline.} =
## a stack. ## a stack.
ctx.stateStack.add(ctx.state()) ctx.stateStack.add(ctx.state())
ctx.fillStyle = newPaint(ctx.fillStyle)
ctx.strokeStyle = newPaint(ctx.strokeStyle)
proc saveLayer*(ctx: Context) = proc saveLayer*(ctx: Context) =
## Saves the entire state of the context by pushing the current state onto ## 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 ## 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) = proc clearRect*(ctx: Context, rect: Rect) =
## Erases the pixels in a rectangular area. ## Erases the pixels in a rectangular area.
let paint = newPaint(pkSolid)
paint.blendMode = bmOverwrite
let path = newPath() let path = newPath()
path.rect(rect) path.rect(rect)
if ctx.layer != nil: if ctx.layer != nil:
ctx.layer.fillPath( ctx.layer.fillPath( path, paint, ctx.mat)
path,
Paint(kind: pkSolid, color: rgbx(0, 0, 0, 0), blendMode: bmOverwrite),
ctx.mat
)
else: else:
ctx.image.fillPath( ctx.image.fillPath(path, paint, ctx.mat)
path,
Paint(kind: pkSolid, color: rgbx(0, 0, 0, 0), blendMode: bmOverwrite),
ctx.mat
)
proc clearRect*(ctx: Context, x, y, width, height: float32) {.inline.} = proc clearRect*(ctx: Context, x, y, width, height: float32) {.inline.} =
## Erases the pixels in a rectangular area. ## 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) = proc drawImage*(ctx: Context, image: Image, dx, dy, dWidth, dHeight: float32) =
## Draws a source image onto the destination image. ## Draws a source image onto the destination image.
var let
imageMat = ctx.mat * translate(vec2(dx, dy)) * scale(vec2( imageMat = ctx.mat * translate(vec2(dx, dy)) * scale(vec2(
dWidth / image.width.float32, dWidth / image.width.float32,
dHeight / image.height.float32 dHeight / image.height.float32
)) ))
savedStyle = ctx.fillStyle savedFillStyle = ctx.fillStyle
ctx.fillStyle = Paint(kind: pkImage, image: image, imageMat: imageMat)
ctx.fillStyle = newPaint(pkImage)
ctx.fillStyle.image = image
ctx.fillStyle.imageMat = imageMat
let path = newPath() 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 = savedFillStyle
proc drawImage*(ctx: Context, image: Image, dx, dy: float32) = proc drawImage*(ctx: Context, image: Image, dx, dy: float32) =
## Draws a source image onto the destination image. ## Draws a source image onto the destination image.
@ -635,7 +638,7 @@ proc drawImage*(
dx, dy, dWidth, dHeight: float32 dx, dy, dWidth, dHeight: float32
) = ) =
## Draws a source image onto the destination image. ## 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) ctx.drawImage(image, dx, dx, image.width.float32, image.height.float32)
proc drawImage*(ctx: Context, image: Image, src, dest: Rect) = proc drawImage*(ctx: Context, image: Image, src, dest: Rect) =

View file

@ -172,14 +172,12 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
let id = fill[5 .. ^2] let id = fill[5 .. ^2]
if id in result.linearGradients: if id in result.linearGradients:
let linearGradient = result.linearGradients[id] let linearGradient = result.linearGradients[id]
result.fill = Paint( result.fill = newPaint(pkGradientLinear)
kind: pkGradientLinear, result.fill.gradientHandlePositions = @[
gradientHandlePositions: @[ result.transform * vec2(linearGradient.x1, linearGradient.y1),
result.transform * vec2(linearGradient.x1, linearGradient.y1), result.transform * vec2(linearGradient.x2, linearGradient.y2)
result.transform * vec2(linearGradient.x2, linearGradient.y2) ]
], result.fill.gradientStops = linearGradient.stops
gradientStops: linearGradient.stops,
)
else: else:
raise newException(PixieError, "Missing SVG resource " & id) raise newException(PixieError, "Missing SVG resource " & id)
else: else:

View file

@ -1,4 +1,4 @@
import blends, chroma, common, images, internal, options, vmath import blends, chroma, common, images, internal, vmath
type type
PaintKind* = enum PaintKind* = enum
@ -9,19 +9,19 @@ type
pkGradientRadial pkGradientRadial
pkGradientAngular pkGradientAngular
Paint* = object Paint* = ref object
## Paint used to fill paths. ## Paint used to fill paths.
case kind*: PaintKind kind*: PaintKind
of pkSolid: blendMode*: BlendMode ## Blend mode.
color*: ColorRGBX ## Color to fill with. opacity*: float32
of pkImage, pkImageTiled: # pkSolid
image*: Image ## Image to fill with. color*: ColorRGBX ## Color to fill with.
imageMat*: Mat3 ## Matrix of the filled image. # pkImage, pkImageTiled:
of pkGradientLinear, pkGradientRadial, pkGradientAngular: image*: Image ## Image to fill with.
gradientHandlePositions*: seq[Vec2] ## Gradient positions (image space). imageMat*: Mat3 ## Matrix of the filled image.
gradientStops*: seq[ColorStop] ## Color stops (gradient space). # pkGradientLinear, pkGradientRadial, pkGradientAngular:
blendMode*: BlendMode ## Blend mode. gradientHandlePositions*: seq[Vec2] ## Gradient positions (image space).
opacityOption: Option[float32] gradientStops*: seq[ColorStop] ## Color stops (gradient space).
ColorStop* = object ColorStop* = object
## Color stop on a gradient curve. ## Color stop on a gradient curve.
@ -30,32 +30,35 @@ type
SomePaint* = string | Paint | SomeColor 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.} = converter parseSomePaint*(paint: SomePaint): Paint {.inline.} =
## Given SomePaint, parse it in different ways. ## Given SomePaint, parse it in different ways.
when type(paint) is string: 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: elif type(paint) is SomeColor:
result = newPaint(pkSolid)
when type(paint) is ColorRGBX: when type(paint) is ColorRGBX:
Paint(kind: pkSolid, color: paint) result.color = paint
else: else:
Paint(kind: pkSolid, color: paint.rgbx()) result.color = paint.rgbx()
elif type(paint) is Paint: elif type(paint) is Paint:
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.} = proc toLineSpace(at, to, point: Vec2): float32 {.inline.} =
## Convert position on to where it would fall on a line between at and to. ## Convert position on to where it would fall on a line between at and to.
let let

View file

@ -1803,23 +1803,24 @@ proc fillPath*(
# Draw the image (maybe tiled) or gradients. Do this with opaque paint and # Draw the image (maybe tiled) or gradients. Do this with opaque paint and
# and then apply the paint's opacity to the mask. # and then apply the paint's opacity to the mask.
let savedOpacity = paint.opacity
var paintOpaque = paint paint.opacity = 1
paintOpaque.opacity = 1
case paint.kind: case paint.kind:
of pkSolid: of pkSolid:
discard # Handled above discard # Handled above
of pkImage: of pkImage:
fill.draw(paintOpaque.image, paintOpaque.imageMat) fill.draw(paint.image, paint.imageMat)
of pkImageTiled: of pkImageTiled:
fill.drawTiled(paintOpaque.image, paintOpaque.imageMat) fill.drawTiled(paint.image, paint.imageMat)
of pkGradientLinear: of pkGradientLinear:
fill.fillGradientLinear(paintOpaque) fill.fillGradientLinear(paint)
of pkGradientRadial: of pkGradientRadial:
fill.fillGradientRadial(paintOpaque) fill.fillGradientRadial(paint)
of pkGradientAngular: of pkGradientAngular:
fill.fillGradientAngular(paintOpaque) fill.fillGradientAngular(paint)
paint.opacity = savedOpacity
if paint.opacity != 1: if paint.opacity != 1:
mask.applyOpacity(paint.opacity) mask.applyOpacity(paint.opacity)
@ -1898,23 +1899,24 @@ proc strokePath*(
# Draw the image (maybe tiled) or gradients. Do this with opaque paint and # Draw the image (maybe tiled) or gradients. Do this with opaque paint and
# and then apply the paint's opacity to the mask. # and then apply the paint's opacity to the mask.
let savedOpacity = paint.opacity
var paintOpaque = paint paint.opacity = 1
paintOpaque.opacity = 1
case paint.kind: case paint.kind:
of pkSolid: of pkSolid:
discard # Handled above discard # Handled above
of pkImage: of pkImage:
fill.draw(paintOpaque.image, paintOpaque.imageMat) fill.draw(paint.image, paint.imageMat)
of pkImageTiled: of pkImageTiled:
fill.drawTiled(paintOpaque.image, paintOpaque.imageMat) fill.drawTiled(paint.image, paint.imageMat)
of pkGradientLinear: of pkGradientLinear:
fill.fillGradientLinear(paintOpaque) fill.fillGradientLinear(paint)
of pkGradientRadial: of pkGradientRadial:
fill.fillGradientRadial(paintOpaque) fill.fillGradientRadial(paint)
of pkGradientAngular: of pkGradientAngular:
fill.fillGradientAngular(paintOpaque) fill.fillGradientAngular(paint)
paint.opacity = savedOpacity
if paint.opacity != 1: if paint.opacity != 1:
mask.applyOpacity(paint.opacity) mask.applyOpacity(paint.opacity)

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

View file

@ -526,7 +526,8 @@ block:
image.fill(rgba(255, 255, 255, 255)) 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 paint.blendMode = bmExclusion
ctx.fillStyle = paint ctx.fillStyle = paint
@ -634,3 +635,12 @@ block:
ctx.ellipse(150, 75, 40, 60) ctx.ellipse(150, 75, 40, 60)
ctx.lineWidth = 25 ctx.lineWidth = 25
doAssert ctx.isPointInStroke(110, 75) 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")

View file

@ -634,17 +634,15 @@ block:
block: block:
var font = readFont("tests/fonts/IBMPlexSans-Regular_2.ttf") var font = readFont("tests/fonts/IBMPlexSans-Regular_2.ttf")
font.size = 48 font.size = 48
font.paint = Paint( font.paint = newPaint(pkGradientLinear)
kind: pkGradientLinear, font.paint.gradientHandlePositions = @[
gradientHandlePositions: @[ vec2(0, 50),
vec2(0, 50), vec2(100, 50),
vec2(100, 50), ]
], font.paint.gradientStops = @[
gradientStops: @[ ColorStop(color: rgba(255, 0, 0, 255), position: 0),
ColorStop(color: rgba(255, 0, 0, 255), position: 0), ColorStop(color: rgba(255, 0, 0, 127), position: 1.0),
ColorStop(color: rgba(255, 0, 0, 127), position: 1.0), ]
]
)
let image = newImage(100, 100) let image = newImage(100, 100)
image.fill(rgba(255, 255, 255, 255)) image.fill(rgba(255, 255, 255, 255))

View file

@ -12,144 +12,108 @@ block:
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(
heartShape, heartShape,
Paint( rgba(255, 0, 0, 255)
kind: pkSolid,
color: rgba(255, 0, 0, 255)
)
) )
image.writeFile("tests/images/paths/paintSolid.png") image.writeFile("tests/images/paths/paintSolid.png")
block: 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) let image = newImage(100, 100)
image.fillPath( image.fillPath(heartShape, paint)
heartShape,
Paint(
kind: pkImage,
image: decodePng(readFile("tests/images/png/baboon.png")),
imageMat: scale(vec2(0.2, 0.2))
)
)
image.writeFile("tests/images/paths/paintImage.png") image.writeFile("tests/images/paths/paintImage.png")
block: block:
var paint = Paint( let paint = newPaint(pkImage)
kind: pkImage, paint.image = decodePng(readFile("tests/images/png/baboon.png"))
image: decodePng(readFile("tests/images/png/baboon.png")), paint.imageMat = scale(vec2(0.2, 0.2))
imageMat: scale(vec2(0.2, 0.2))
)
paint.opacity = 0.5 paint.opacity = 0.5
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(heartShape, paint)
heartShape,
paint
)
image.writeFile("tests/images/paths/paintImageOpacity.png") image.writeFile("tests/images/paths/paintImageOpacity.png")
block: 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) let image = newImage(100, 100)
image.fillPath( image.fillPath(heartShape, paint)
heartShape,
Paint(
kind: pkImageTiled,
image: decodePng(readFile("tests/images/png/baboon.png")),
imageMat: scale(vec2(0.02, 0.02))
)
)
image.writeFile("tests/images/paths/paintImageTiled.png") image.writeFile("tests/images/paths/paintImageTiled.png")
block: block:
var paint = Paint( let paint = newPaint(pkImageTiled)
kind: pkImageTiled, paint.image = decodePng(readFile("tests/images/png/baboon.png"))
image: decodePng(readFile("tests/images/png/baboon.png")), paint.imageMat = scale(vec2(0.02, 0.02))
imageMat: scale(vec2(0.02, 0.02))
)
paint.opacity = 0.5 paint.opacity = 0.5
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(heartShape, paint)
heartShape,
paint
)
image.writeFile("tests/images/paths/paintImageTiledOpacity.png") image.writeFile("tests/images/paths/paintImageTiledOpacity.png")
block: 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) let image = newImage(100, 100)
image.fillPath( image.fillPath(heartShape, paint)
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.writeFile("tests/images/paths/gradientLinear.png") image.writeFile("tests/images/paths/gradientLinear.png")
block: block:
let image = newImage(100, 100) let paint = newPaint(pkGradientRadial)
image.fillPath( paint.gradientHandlePositions = @[
heartShape, vec2(50, 50),
Paint( vec2(100, 50),
kind: pkGradientRadial, vec2(50, 100)
gradientHandlePositions: @[ ]
vec2(50, 50), paint.gradientStops = @[
vec2(100, 50), ColorStop(color: rgba(255, 0, 0, 255), position: 0),
vec2(50, 100) ColorStop(color: rgba(255, 0, 0, 40), position: 1.0),
], ]
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") image.writeFile("tests/images/paths/gradientRadial.png")
block: block:
let image = newImage(100, 100) let paint = newPaint(pkGradientAngular)
image.fillPath( paint.gradientHandlePositions = @[
heartShape, vec2(50, 50),
Paint( vec2(100, 50),
kind: pkGradientAngular, vec2(50, 100)
gradientHandlePositions: @[ ]
vec2(50, 50), paint.gradientStops = @[
vec2(100, 50), ColorStop(color: rgba(255, 0, 0, 255), position: 0),
vec2(50, 100) ColorStop(color: rgba(255, 0, 0, 40), position: 1.0),
], ]
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") image.writeFile("tests/images/paths/gradientAngular.png")
block: block:
var paint = Paint( let paint = newPaint(pkGradientAngular)
kind: pkGradientAngular, paint.gradientHandlePositions = @[
gradientHandlePositions: @[ vec2(50, 50),
vec2(50, 50), vec2(100, 50),
vec2(100, 50), vec2(50, 100)
vec2(50, 100) ]
], paint.gradientStops = @[
gradientStops: @[ ColorStop(color: rgba(255, 0, 0, 255), position: 0),
ColorStop(color: rgba(255, 0, 0, 255), position: 0), ColorStop(color: rgba(255, 0, 0, 40), position: 1.0),
ColorStop(color: rgba(255, 0, 0, 40), position: 1.0), ]
]
)
paint.opacity = 0.5 paint.opacity = 0.5
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(heartShape, paint)
heartShape,
paint
)
image.writeFile("tests/images/paths/gradientAngularOpacity.png") image.writeFile("tests/images/paths/gradientAngularOpacity.png")

View file

@ -367,11 +367,16 @@ block:
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(
"M 10 10 H 60 V 60 H 10 z", "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( image.fillPath(
"M 30 30 H 80 V 80 H 30 z", "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") image.writeFile("tests/images/paths/rectExcludeMask.png")
@ -379,11 +384,16 @@ block:
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(
"M 10.1 10.1 H 60.1 V 60.1 H 10.1 z", "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( image.fillPath(
"M 30.1 30.1 H 80.1 V 80.1 H 30.1 z", "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") image.writeFile("tests/images/paths/rectExcludeMaskAA.png")
@ -391,11 +401,16 @@ block:
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(
"M 10 10 H 60 V 60 H 10 z", "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( image.fillPath(
"M 30 30 H 80 V 80 H 30 z", "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") image.writeFile("tests/images/paths/rectMask.png")
@ -403,11 +418,16 @@ block:
let image = newImage(100, 100) let image = newImage(100, 100)
image.fillPath( image.fillPath(
"M 10.1 10.1 H 60.1 V 60.1 H 10.1 z", "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( image.fillPath(
"M 30.1 30.1 H 80.1 V 80.1 H 30.1 z", "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") image.writeFile("tests/images/paths/rectMaskAA.png")
@ -573,7 +593,8 @@ block:
let path = newPath() let path = newPath()
path.circle(50, 50, 30) 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 paint.opacity = 0.5
let image = newImage(100, 100) let image = newImage(100, 100)
@ -585,7 +606,8 @@ block:
let path = newPath() let path = newPath()
path.circle(50, 50, 30) 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 paint.opacity = 0.5
let image = newImage(100, 100) let image = newImage(100, 100)