Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 14 KiB |
|
@ -2,7 +2,6 @@
|
|||
|
||||
import math, pixie, sdl2, sdl2/gfx
|
||||
|
||||
|
||||
const
|
||||
rmask = uint32 0x000000ff
|
||||
gmask = uint32 0x0000ff00
|
||||
|
@ -23,7 +22,6 @@ var
|
|||
mainTexture: TexturePtr
|
||||
evt = sdl2.defaultEvent
|
||||
|
||||
|
||||
proc display() =
|
||||
## Called every frame by main while loop
|
||||
|
||||
|
@ -52,7 +50,8 @@ proc display() =
|
|||
inc frameCount
|
||||
|
||||
var dataPtr = ctx.image.data[0].addr
|
||||
mainSurface = createRGBSurfaceFrom(dataPtr, cint w, cint h, cint 32, cint 4*w, rmask, gmask, bmask, amask)
|
||||
mainSurface = createRGBSurfaceFrom(dataPtr, cint w, cint h, cint 32, cint 4*w,
|
||||
rmask, gmask, bmask, amask)
|
||||
mainTexture = render.createTextureFromSurface(mainSurface)
|
||||
destroy(mainSurface)
|
||||
|
||||
|
@ -62,7 +61,6 @@ proc display() =
|
|||
|
||||
render.present()
|
||||
|
||||
|
||||
discard sdl2.init(INIT_EVERYTHING)
|
||||
window = createWindow("SDL/Pixie", 100, 100, cint w, cint h, SDL_WINDOW_SHOWN)
|
||||
render = createRenderer(window, -1, 0)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
## Load and Save SVG files.
|
||||
|
||||
import cairo, chroma, pixie/common, pixie/images, strutils, vmath,
|
||||
xmlparser, xmltree
|
||||
import cairo, chroma, pixie/common, pixie/images, strutils, vmath, xmlparser, xmltree
|
||||
|
||||
include pixie/paths
|
||||
|
||||
|
|
|
@ -23,6 +23,18 @@ proc gaussianKernel*(radius: int): seq[uint32] =
|
|||
for i, f in floats:
|
||||
result[i] = round(f * 255 * 1024).uint32
|
||||
|
||||
proc applyOpacity*(color: ColorRGBX, opacity: float32): ColorRGBX =
|
||||
if opacity == 0:
|
||||
rgbx(0, 0, 0, 0)
|
||||
else:
|
||||
let
|
||||
x = round(opacity * 255).uint32
|
||||
r = ((color.r * x) div 255).uint8
|
||||
g = ((color.g * x) div 255).uint8
|
||||
b = ((color.b * x) div 255).uint8
|
||||
a = ((color.a * x) div 255).uint8
|
||||
rgbx(r, g, b, a)
|
||||
|
||||
proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
|
||||
## Converts an image from premultiplied alpha to straight alpha.
|
||||
## This is expensive for large images.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import blends, chroma, common, images, vmath
|
||||
import blends, chroma, common, images, internal, options, vmath
|
||||
|
||||
type
|
||||
PaintKind* = enum
|
||||
|
@ -21,6 +21,7 @@ type
|
|||
gradientHandlePositions*: seq[Vec2] ## Gradient positions (image space).
|
||||
gradientStops*: seq[ColorStop] ## Color stops (gradient space).
|
||||
blendMode*: BlendMode ## Blend mode.
|
||||
opacityOption: Option[float32]
|
||||
|
||||
ColorStop* = object
|
||||
## Color stop on a gradient curve.
|
||||
|
@ -41,37 +42,55 @@ converter parseSomePaint*(paint: SomePaint): Paint {.inline.} =
|
|||
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
|
||||
d = to - at
|
||||
det = d.x * d.x + d.y * d.y
|
||||
return (d.y * (point.y - at.y) + d.x * (point.x - at.x)) / det
|
||||
(d.y * (point.y - at.y) + d.x * (point.x - at.x)) / det
|
||||
|
||||
proc gradientPut(image: Image, x, y: int, a: float32, stops: seq[ColorStop]) =
|
||||
## Put an gradient color based on the "a" - were are we related to a line.
|
||||
proc gradientPut(
|
||||
image: Image, paint: Paint, x, y: int, t: float32, stops: seq[ColorStop]
|
||||
) =
|
||||
## Put an gradient color based on `t` - where are we related to a line.
|
||||
var index = -1
|
||||
for i, stop in stops:
|
||||
if stop.position < a:
|
||||
if stop.position < t:
|
||||
index = i
|
||||
if stop.position > a:
|
||||
if stop.position > t:
|
||||
break
|
||||
var color: Color
|
||||
var color: ColorRGBX
|
||||
if index == -1:
|
||||
# first stop solid
|
||||
color = stops[0].color.color
|
||||
color = stops[0].color
|
||||
elif index + 1 >= stops.len:
|
||||
# last stop solid
|
||||
color = stops[index].color.color
|
||||
color = stops[index].color
|
||||
else:
|
||||
let
|
||||
gs1 = stops[index]
|
||||
gs2 = stops[index+1]
|
||||
color = mix(
|
||||
gs1.color.color,
|
||||
gs2.color.color,
|
||||
(a - gs1.position) / (gs2.position - gs1.position)
|
||||
gs2 = stops[index + 1]
|
||||
color = lerp(
|
||||
gs1.color,
|
||||
gs2.color,
|
||||
(t - gs1.position) / (gs2.position - gs1.position)
|
||||
)
|
||||
if paint.opacity != 1:
|
||||
color = color.applyOpacity(paint.opacity)
|
||||
image.setRgbaUnsafe(x, y, color.rgba.rgbx())
|
||||
|
||||
proc fillGradientLinear*(image: Image, paint: Paint) =
|
||||
|
@ -86,6 +105,9 @@ proc fillGradientLinear*(image: Image, paint: Paint) =
|
|||
if paint.gradientStops.len == 0:
|
||||
raise newException(PixieError, "Gradient must have at least 1 color stop")
|
||||
|
||||
if paint.opacity == 0:
|
||||
return
|
||||
|
||||
let
|
||||
at = paint.gradientHandlePositions[0]
|
||||
to = paint.gradientHandlePositions[1]
|
||||
|
@ -93,8 +115,8 @@ proc fillGradientLinear*(image: Image, paint: Paint) =
|
|||
for x in 0 ..< image.width:
|
||||
let
|
||||
xy = vec2(x.float32, y.float32)
|
||||
a = toLineSpace(at, to, xy)
|
||||
image.gradientPut(x, y, a, paint.gradientStops)
|
||||
t = toLineSpace(at, to, xy)
|
||||
image.gradientPut(paint, x, y, t, paint.gradientStops)
|
||||
|
||||
proc fillGradientRadial*(image: Image, paint: Paint) =
|
||||
## Fills a radial gradient.
|
||||
|
@ -108,6 +130,9 @@ proc fillGradientRadial*(image: Image, paint: Paint) =
|
|||
if paint.gradientStops.len == 0:
|
||||
raise newException(PixieError, "Gradient must have at least 1 color stop")
|
||||
|
||||
if paint.opacity == 0:
|
||||
return
|
||||
|
||||
let
|
||||
center = paint.gradientHandlePositions[0]
|
||||
edge = paint.gradientHandlePositions[1]
|
||||
|
@ -124,8 +149,8 @@ proc fillGradientRadial*(image: Image, paint: Paint) =
|
|||
for x in 0 ..< image.width:
|
||||
let
|
||||
xy = vec2(x.float32, y.float32)
|
||||
b = (mat * xy).length()
|
||||
image.gradientPut(x, y, b, paint.gradientStops)
|
||||
t = (mat * xy).length()
|
||||
image.gradientPut(paint, x, y, t, paint.gradientStops)
|
||||
|
||||
proc fillGradientAngular*(image: Image, paint: Paint) =
|
||||
## Fills an angular gradient.
|
||||
|
@ -139,6 +164,9 @@ proc fillGradientAngular*(image: Image, paint: Paint) =
|
|||
if paint.gradientStops.len == 0:
|
||||
raise newException(PixieError, "Gradient must have at least 1 color stop")
|
||||
|
||||
if paint.opacity == 0:
|
||||
return
|
||||
|
||||
let
|
||||
center = paint.gradientHandlePositions[0]
|
||||
edge = paint.gradientHandlePositions[1]
|
||||
|
@ -149,5 +177,5 @@ proc fillGradientAngular*(image: Image, paint: Paint) =
|
|||
let
|
||||
xy = vec2(x.float32, y.float32)
|
||||
angle = normalize(xy - center).angle()
|
||||
a = (angle + gradientAngle + PI/2).fixAngle() / 2 / PI + 0.5
|
||||
image.gradientPut(x, y, a, paint.gradientStops)
|
||||
t = (angle + gradientAngle + PI / 2).fixAngle() / 2 / PI + 0.5
|
||||
image.gradientPut(paint, x, y, t, paint.gradientStops)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import blends, bumpy, chroma, common, images, masks, paints, pixie/internal,
|
||||
strutils, vmath
|
||||
import blends, bumpy, chroma, common, images, internal, masks, paints, strutils, vmath
|
||||
|
||||
when defined(amd64) and not defined(pixieNoSimd):
|
||||
import nimsimd/sse2
|
||||
|
@ -1780,11 +1779,17 @@ proc fillPath*(
|
|||
windingRule = wrNonZero
|
||||
) =
|
||||
## Fills a path.
|
||||
if paint.opacity == 0:
|
||||
return
|
||||
|
||||
if paint.kind == pkSolid:
|
||||
if paint.color.a > 0 or paint.blendMode == bmOverwrite:
|
||||
var shapes = parseSomePath(path, true, transform.pixelScale())
|
||||
shapes.transform(transform)
|
||||
image.fillShapes(shapes, paint.color, windingRule, paint.blendMode)
|
||||
var color = paint.color
|
||||
if paint.opacity != 1:
|
||||
color = color.applyOpacity(paint.opacity)
|
||||
image.fillShapes(shapes, color, windingRule, paint.blendMode)
|
||||
return
|
||||
|
||||
let
|
||||
|
@ -1793,19 +1798,28 @@ proc fillPath*(
|
|||
|
||||
mask.fillPath(path, transform, windingRule)
|
||||
|
||||
# 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
|
||||
|
||||
case paint.kind:
|
||||
of pkSolid:
|
||||
discard # Handled above
|
||||
of pkImage:
|
||||
fill.draw(paint.image, paint.imageMat)
|
||||
fill.draw(paintOpaque.image, paintOpaque.imageMat)
|
||||
of pkImageTiled:
|
||||
fill.drawTiled(paint.image, paint.imageMat)
|
||||
fill.drawTiled(paintOpaque.image, paintOpaque.imageMat)
|
||||
of pkGradientLinear:
|
||||
fill.fillGradientLinear(paint)
|
||||
fill.fillGradientLinear(paintOpaque)
|
||||
of pkGradientRadial:
|
||||
fill.fillGradientRadial(paint)
|
||||
fill.fillGradientRadial(paintOpaque)
|
||||
of pkGradientAngular:
|
||||
fill.fillGradientAngular(paint)
|
||||
fill.fillGradientAngular(paintOpaque)
|
||||
|
||||
if paint.opacity != 1:
|
||||
mask.applyOpacity(paint.opacity)
|
||||
|
||||
fill.draw(mask)
|
||||
image.draw(fill, blendMode = paint.blendMode)
|
||||
|
@ -1845,6 +1859,9 @@ proc strokePath*(
|
|||
dashes: seq[float32] = @[]
|
||||
) =
|
||||
## Strokes a path.
|
||||
if paint.opacity == 0:
|
||||
return
|
||||
|
||||
if paint.kind == pkSolid:
|
||||
if paint.color.a > 0 or paint.blendMode == bmOverwrite:
|
||||
var strokeShapes = strokeShapes(
|
||||
|
@ -1856,7 +1873,10 @@ proc strokePath*(
|
|||
dashes
|
||||
)
|
||||
strokeShapes.transform(transform)
|
||||
image.fillShapes(strokeShapes, paint.color, wrNonZero, paint.blendMode)
|
||||
var color = paint.color
|
||||
if paint.opacity != 1:
|
||||
color = color.applyOpacity(paint.opacity)
|
||||
image.fillShapes(strokeShapes, color, wrNonZero, paint.blendMode)
|
||||
return
|
||||
|
||||
let
|
||||
|
@ -1873,19 +1893,28 @@ proc strokePath*(
|
|||
dashes
|
||||
)
|
||||
|
||||
# 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
|
||||
|
||||
case paint.kind:
|
||||
of pkSolid:
|
||||
discard # Handled above
|
||||
of pkImage:
|
||||
fill.draw(paint.image, paint.imageMat)
|
||||
fill.draw(paintOpaque.image, paintOpaque.imageMat)
|
||||
of pkImageTiled:
|
||||
fill.drawTiled(paint.image, paint.imageMat)
|
||||
fill.drawTiled(paintOpaque.image, paintOpaque.imageMat)
|
||||
of pkGradientLinear:
|
||||
fill.fillGradientLinear(paint)
|
||||
fill.fillGradientLinear(paintOpaque)
|
||||
of pkGradientRadial:
|
||||
fill.fillGradientRadial(paint)
|
||||
fill.fillGradientRadial(paintOpaque)
|
||||
of pkGradientAngular:
|
||||
fill.fillGradientAngular(paint)
|
||||
fill.fillGradientAngular(paintOpaque)
|
||||
|
||||
if paint.opacity != 1:
|
||||
mask.applyOpacity(paint.opacity)
|
||||
|
||||
fill.draw(mask)
|
||||
image.draw(fill, blendMode = paint.blendMode)
|
||||
|
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 5.3 KiB |
BIN
tests/images/paths/gradientAngularOpacity.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.9 KiB |
BIN
tests/images/paths/opacityFill.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
tests/images/paths/opacityStroke.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
tests/images/paths/paintImageOpacity.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
tests/images/paths/paintImageTiledOpacity.png
Normal file
After Width: | Height: | Size: 15 KiB |
|
@ -592,7 +592,7 @@ block:
|
|||
image = newImage(300, 227)
|
||||
ctx = newContext(image)
|
||||
rhino = readImage("tests/images/rhino.png")
|
||||
ctx.drawImage(rhino, 33, 71, 104, 124, 21, 20, 87, 104);
|
||||
ctx.drawImage(rhino, 33, 71, 104, 124, 21, 20, 87, 104)
|
||||
image.writeFile("tests/images/context/draw_image_rhino.png")
|
||||
|
||||
block:
|
||||
|
@ -600,7 +600,7 @@ block:
|
|||
image = newImage(300, 227)
|
||||
ctx = newContext(image)
|
||||
rhino = readImage("tests/images/rhino.png")
|
||||
ctx.drawImage(rhino, rect(33, 71, 104, 124), rect(21, 20, 87, 104));
|
||||
ctx.drawImage(rhino, rect(33, 71, 104, 124), rect(21, 20, 87, 104))
|
||||
image.writeFile("tests/images/context/draw_image_rhino2.png")
|
||||
|
||||
block:
|
||||
|
|
|
@ -31,6 +31,21 @@ block:
|
|||
)
|
||||
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))
|
||||
)
|
||||
paint.opacity = 0.5
|
||||
|
||||
let image = newImage(100, 100)
|
||||
image.fillPath(
|
||||
heartShape,
|
||||
paint
|
||||
)
|
||||
image.writeFile("tests/images/paths/paintImageOpacity.png")
|
||||
|
||||
block:
|
||||
let image = newImage(100, 100)
|
||||
image.fillPath(
|
||||
|
@ -43,6 +58,21 @@ block:
|
|||
)
|
||||
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))
|
||||
)
|
||||
paint.opacity = 0.5
|
||||
|
||||
let image = newImage(100, 100)
|
||||
image.fillPath(
|
||||
heartShape,
|
||||
paint
|
||||
)
|
||||
image.writeFile("tests/images/paths/paintImageTiledOpacity.png")
|
||||
|
||||
block:
|
||||
let image = newImage(100, 100)
|
||||
image.fillPath(
|
||||
|
@ -100,3 +130,26 @@ block:
|
|||
)
|
||||
|
||||
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),
|
||||
]
|
||||
)
|
||||
paint.opacity = 0.5
|
||||
|
||||
let image = newImage(100, 100)
|
||||
image.fillPath(
|
||||
heartShape,
|
||||
paint
|
||||
)
|
||||
|
||||
image.writeFile("tests/images/paths/gradientAngularOpacity.png")
|
||||
|
|
|
@ -445,20 +445,20 @@ block:
|
|||
# Draw shapes
|
||||
for i in 0 .. 3:
|
||||
for j in 0 .. 2:
|
||||
ctx.beginPath();
|
||||
let x = 25f + j.float32 * 50f; # x coordinate
|
||||
let y = 25f + i.float32 * 50f; # y coordinate
|
||||
let radius = 20f; # Arc radius
|
||||
let startAngle = 0f; # Starting point on circle
|
||||
let endAngle = PI + (PI * j.float32) / 2; # End point on circle
|
||||
let counterclockwise = i mod 2 == 1; # Draw counterclockwise
|
||||
ctx.beginPath()
|
||||
let x = 25f + j.float32 * 50f # x coordinate
|
||||
let y = 25f + i.float32 * 50f # y coordinate
|
||||
let radius = 20f # Arc radius
|
||||
let startAngle = 0f # Starting point on circle
|
||||
let endAngle = PI + (PI * j.float32) / 2 # End point on circle
|
||||
let counterclockwise = i mod 2 == 1 # Draw counterclockwise
|
||||
|
||||
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise);
|
||||
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise)
|
||||
|
||||
if i > 1:
|
||||
ctx.fill();
|
||||
ctx.fill()
|
||||
else:
|
||||
ctx.stroke();
|
||||
ctx.stroke()
|
||||
|
||||
surface.writeFile("tests/images/paths/arc.png")
|
||||
|
||||
|
@ -469,14 +469,14 @@ block:
|
|||
surface.fill(rgba(255, 255, 255, 255))
|
||||
|
||||
let
|
||||
p0 = vec2(230, 20 )
|
||||
p1 = vec2(90, 130)
|
||||
p2 = vec2(20, 20 )
|
||||
p0 = vec2(230, 20)
|
||||
p1 = vec2(90, 130)
|
||||
p2 = vec2(20, 20)
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(p0.x, p0.y);
|
||||
ctx.arcTo(p1.x, p1.y, p2.x, p2.y, 50);
|
||||
ctx.lineTo(p2.x, p2.y);
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(p0.x, p0.y)
|
||||
ctx.arcTo(p1.x, p1.y, p2.x, p2.y, 50)
|
||||
ctx.lineTo(p2.x, p2.y)
|
||||
ctx.stroke()
|
||||
|
||||
surface.writeFile("tests/images/paths/arcTo1.png")
|
||||
|
@ -487,33 +487,33 @@ block:
|
|||
ctx = newContext(surface)
|
||||
surface.fill(rgba(255, 255, 255, 255))
|
||||
# Tangential lines
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = "gray";
|
||||
ctx.moveTo(200, 20);
|
||||
ctx.lineTo(200, 130);
|
||||
ctx.lineTo(50, 20);
|
||||
ctx.stroke();
|
||||
ctx.beginPath()
|
||||
ctx.strokeStyle = "gray"
|
||||
ctx.moveTo(200, 20)
|
||||
ctx.lineTo(200, 130)
|
||||
ctx.lineTo(50, 20)
|
||||
ctx.stroke()
|
||||
|
||||
# Arc
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.lineWidth = 5;
|
||||
ctx.moveTo(200, 20);
|
||||
ctx.arcTo(200,130, 50,20, 40);
|
||||
ctx.stroke();
|
||||
ctx.beginPath()
|
||||
ctx.strokeStyle = "black"
|
||||
ctx.lineWidth = 5
|
||||
ctx.moveTo(200, 20)
|
||||
ctx.arcTo(200, 130, 50, 20, 40)
|
||||
ctx.stroke()
|
||||
|
||||
# Start point
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "blue";
|
||||
ctx.arc(200, 20, 5, 0, 2 * PI);
|
||||
ctx.fill();
|
||||
ctx.beginPath()
|
||||
ctx.fillStyle = "blue"
|
||||
ctx.arc(200, 20, 5, 0, 2 * PI)
|
||||
ctx.fill()
|
||||
|
||||
# Control points
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "red";
|
||||
ctx.arc(200, 130, 5, 0, 2 * PI); # Control point one
|
||||
ctx.arc(50, 20, 5, 0, 2 * PI); # Control point two
|
||||
ctx.fill();
|
||||
ctx.beginPath()
|
||||
ctx.fillStyle = "red"
|
||||
ctx.arc(200, 130, 5, 0, 2 * PI) # Control point one
|
||||
ctx.arc(50, 20, 5, 0, 2 * PI) # Control point two
|
||||
ctx.fill()
|
||||
|
||||
surface.writeFile("tests/images/paths/arcTo2.png")
|
||||
|
||||
|
@ -523,11 +523,11 @@ block:
|
|||
ctx = newContext(surface)
|
||||
surface.fill(rgba(255, 255, 255, 255))
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(180, 90);
|
||||
ctx.arcTo(180,130, 110,130, 130);
|
||||
ctx.lineTo(110, 130);
|
||||
ctx.stroke();
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(180, 90)
|
||||
ctx.arcTo(180, 130, 110, 130, 130)
|
||||
ctx.lineTo(110, 130)
|
||||
ctx.stroke()
|
||||
|
||||
surface.writeFile("tests/images/paths/arcTo3.png")
|
||||
|
||||
|
@ -568,3 +568,27 @@ block:
|
|||
doAssert path.strokeOverlaps(vec2(40, 20))
|
||||
doAssert path.strokeOverlaps(vec2(19.8, 30.2))
|
||||
doAssert not path.strokeOverlaps(vec2(19.4, 30.6))
|
||||
|
||||
block:
|
||||
var path: Path
|
||||
path.circle(50, 50, 30)
|
||||
|
||||
var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255))
|
||||
paint.opacity = 0.5
|
||||
|
||||
let image = newImage(100, 100)
|
||||
image.fillPath(path, paint)
|
||||
|
||||
image.writeFile("tests/images/paths/opacityFill.png")
|
||||
|
||||
block:
|
||||
var path: Path
|
||||
path.circle(50, 50, 30)
|
||||
|
||||
var paint = Paint(kind: pkSolid, color: rgba(255, 0, 255, 255))
|
||||
paint.opacity = 0.5
|
||||
|
||||
let image = newImage(100, 100)
|
||||
image.strokePath(path, paint, strokeWidth = 10)
|
||||
|
||||
image.writeFile("tests/images/paths/opacityStroke.png")
|
||||
|
|