diff --git a/README.md b/README.md index 9a3de71..53be7ab 100644 --- a/README.md +++ b/README.md @@ -50,16 +50,11 @@ image.drawSegment(segment(start, stop), color, strokeWidth = 10) [examples/rounded_rectangle.nim](examples/rounded_rectangle.nim) ```nim let - x = 50.0 - y = 50.0 - w = 100.0 - h = 100.0 + pos = vec2(50, 50) + wh = vec2(100, 100) r = 25.0 -var path: Path -path.roundedRect(vec2(x, y), vec2(w, h), r, r, r, r) - -image.fillPath(path, rgba(0, 255, 0, 255)) +image.drawRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255)) ``` ![example output](examples/rounded_rectangle.png) @@ -83,32 +78,29 @@ image.fillPath( ### Shadow [examples/shadow.nim](examples/shadow.nim) ```nim -var p: Path -p.polygon(100, 100, 70, sides = 8) -p.closePath() +let polygonImage = newImage(200, 200) +polygonImage.drawPolygon( + vec2(100, 100), + 70, + sides = 8, + rgba(255, 255, 255, 255) +) -var polyImage = newImage(200, 200) -polyImage.fillPath(p, rgba(255, 255, 255, 255)) - -image.draw(polyImage.shadow( +image.draw(polygonImage.shadow( offset = vec2(2, 2), spread = 2, blur = 10, color = rgba(0, 0, 0, 200) )) -image.draw(polyImage) +image.draw(polygonImage) ``` ![example output](examples/shadow.png) ### Blur [examples/blur.nim](examples/blur.nim) ```nim -var p: Path -p.polygon(100, 100, 70, sides = 6) -p.closePath() - let mask = newMask(200, 200) -mask.fillPath(p) +mask.drawPolygon(vec2(100, 100), 70, sides = 6) blur.blur(20) blur.draw(mask, blendMode = bmMask) diff --git a/examples/blur.nim b/examples/blur.nim index 53d48a1..e9889fd 100644 --- a/examples/blur.nim +++ b/examples/blur.nim @@ -7,12 +7,8 @@ let image.fill(rgba(255, 255, 255, 255)) -var p: Path -p.polygon(100, 100, 70, sides = 6) -p.closePath() - let mask = newMask(200, 200) -mask.fillPath(p) +mask.drawPolygon(vec2(100, 100), 70, sides = 6) blur.blur(20) blur.draw(mask, blendMode = bmMask) diff --git a/examples/rounded_rectangle.nim b/examples/rounded_rectangle.nim index 67f41f2..776fb6d 100644 --- a/examples/rounded_rectangle.nim +++ b/examples/rounded_rectangle.nim @@ -4,15 +4,10 @@ let image = newImage(200, 200) image.fill(rgba(255, 255, 255, 255)) let - x = 50.0 - y = 50.0 - w = 100.0 - h = 100.0 + pos = vec2(50, 50) + wh = vec2(100, 100) r = 25.0 -var path: Path -path.roundedRect(vec2(x, y), vec2(w, h), r, r, r, r) - -image.fillPath(path, rgba(0, 255, 0, 255)) +image.drawRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255)) image.writeFile("examples/rounded_rectangle.png") diff --git a/examples/shadow.nim b/examples/shadow.nim index a85c0f1..52c0d33 100644 --- a/examples/shadow.nim +++ b/examples/shadow.nim @@ -1,24 +1,22 @@ import pixie -let - trees = readImage("examples/data/trees.png") - image = newImage(200, 200) - +let image = newImage(200, 200) image.fill(rgba(255, 255, 255, 255)) -var p: Path -p.polygon(100, 100, 70, sides = 8) -p.closePath() +let polygonImage = newImage(200, 200) +polygonImage.drawPolygon( + vec2(100, 100), + 70, + sides = 8, + rgba(255, 255, 255, 255) +) -var polyImage = newImage(200, 200) -polyImage.fillPath(p, rgba(255, 255, 255, 255)) - -image.draw(polyImage.shadow( +image.draw(polygonImage.shadow( offset = vec2(2, 2), spread = 2, blur = 10, color = rgba(0, 0, 0, 200) )) -image.draw(polyImage) +image.draw(polygonImage) image.writeFile("examples/shadow.png") diff --git a/src/pixie.nim b/src/pixie.nim index 5305e4b..f8b4caf 100644 --- a/src/pixie.nim +++ b/src/pixie.nim @@ -62,6 +62,38 @@ proc drawRect*(mask: Mask, rect: Rect) = path.rect(rect) mask.fillPath(path) +proc drawRoundedRect*( + image: Image, + rect: Rect, + nw, ne, se, sw: float32, + color: ColorRGBA, + blendMode = bmNormal +) = + var path: Path + path.roundedRect(rect, nw, ne, se, sw) + image.fillPath(path, color, wrNonZero, blendMode) + +proc drawRoundedRect*( + image: Image, + rect: Rect, + radius: float32, + color: ColorRGBA, + blendMode = bmNormal +) = + var path: Path + path.roundedRect(rect, radius, radius, radius, radius) + image.fillPath(path, color, wrNonZero, blendMode) + +proc drawRoundedRect*(mask: Mask, rect: Rect, nw, ne, se, sw: float32) = + var path: Path + path.roundedRect(rect, nw, ne, se, sw) + mask.fillPath(path) + +proc drawRoundedRect*(mask: Mask, rect: Rect, radius: float32) = + var path: Path + path.roundedRect(rect, radius, radius, radius, radius) + mask.fillPath(path) + proc drawSegment*( image: Image, segment: Segment, @@ -79,3 +111,65 @@ proc drawSegment*(mask: Mask, segment: Segment, strokeWidth: float32) = path.moveTo(segment.at) path.lineTo(segment.to) mask.strokePath(path, strokeWidth) + +proc drawEllipse*( + image: Image, + center: Vec2, + rx, ry: float32, + color: ColorRGBA, + blendMode = bmNormal +) = + var path: Path + path.ellipse(center, rx, ry) + image.fillPath(path, color, wrNonZero, blendMode) + +proc drawEllipse*( + mask: Mask, + center: Vec2, + rx, ry: float32 +) = + var path: Path + path.ellipse(center, rx, ry) + mask.fillPath(path) + +proc drawCircle*( + image: Image, + center: Vec2, + radius: float32, + color: ColorRGBA, + blendMode = bmNormal +) = + var path: Path + path.ellipse(center, radius, radius) + image.fillPath(path, color, wrNonZero, blendMode) + +proc drawCircle*( + mask: Mask, + center: Vec2, + radius: float32 +) = + var path: Path + path.ellipse(center, radius, radius) + mask.fillPath(path) + +proc drawPolygon*( + image: Image, + pos: Vec2, + size: float32, + sides: int, + color: ColorRGBA, + blendMode = bmNormal +) = + var path: Path + path.polygon(pos, size, sides) + image.fillPath(path, color, wrNonZero, blendMode) + +proc drawPolygon*( + mask: Mask, + pos: Vec2, + size: float32, + sides: int +) = + var path: Path + path.polygon(pos, size, sides) + mask.fillPath(path) diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index acd5308..e5ae49f 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -376,13 +376,9 @@ proc rect*(path: var Path, rect: Rect, clockwise = true) {.inline.} = const splineCircleK = 4.0 * (-1.0 + sqrt(2.0)) / 3 proc roundedRect*( - path: var Path, pos, wh: Vec2, nw, ne, se, sw: float32, clockwise = true + path: var Path, x, y, w, h, nw, ne, se, sw: float32, clockwise = true ) = let - x = pos.x - y = pos.y - w = wh.x - h = wh.y s = splineCircleK maxRadius = min(w / 2, h / 2) @@ -432,6 +428,16 @@ proc roundedRect*( path.closePath() +proc roundedRect*( + path: var Path, pos, wh: Vec2, nw, ne, se, sw: float32, clockwise = true +) {.inline.} = + path.roundedRect(pos.x, pos.y, wh.x, wh.y, nw, ne, se, sw, clockwise) + +proc roundedRect*( + path: var Path, rect: Rect, nw, ne, se, sw: float32, clockwise = true +) {.inline.} = + path.roundedRect(rect.x, rect.y, rect.w, rect.h, nw, ne, se, sw, clockwise) + proc ellipse*(path: var Path, cx, cy, rx, ry: float32) = let magicX = splineCircleK * rx @@ -444,6 +450,9 @@ proc ellipse*(path: var Path, cx, cy, rx, ry: float32) = path.bezierCurveTo(cx + magicX, cy - ry, cx + rx, cy - magicY, cx + rx, cy) path.closePath() +proc ellipse*(path: var Path, center: Vec2, rx, ry: float32) {.inline.} = + path.ellipse(center.x, center.y, rx, ry) + proc polygon*(path: var Path, x, y, size: float32, sides: int) = ## Draws a n sided regular polygon at (x, y) with size. path.moveTo(x + size * cos(0.0), y + size * sin(0.0)) @@ -453,6 +462,9 @@ proc polygon*(path: var Path, x, y, size: float32, sides: int) = y + size * sin(side.float32 * 2.0 * PI / sides.float32) ) +proc polygon*(path: var Path, pos: Vec2, size: float32, sides: int) {.inline.} = + path.polygon(pos.x, pos.y, size, sides) + proc commandsToShapes*(path: Path): seq[seq[Vec2]] = ## Converts SVG-like commands to line segments. diff --git a/tests/images/drawEllipse.png b/tests/images/drawEllipse.png new file mode 100644 index 0000000..a816ac3 Binary files /dev/null and b/tests/images/drawEllipse.png differ diff --git a/tests/images/drawPolygon.png b/tests/images/drawPolygon.png new file mode 100644 index 0000000..7f2ba6c Binary files /dev/null and b/tests/images/drawPolygon.png differ diff --git a/tests/images/drawRoundedRect.png b/tests/images/drawRoundedRect.png new file mode 100644 index 0000000..c3050ad Binary files /dev/null and b/tests/images/drawRoundedRect.png differ diff --git a/tests/images/masks/drawEllipse.png b/tests/images/masks/drawEllipse.png new file mode 100644 index 0000000..1bd4af3 Binary files /dev/null and b/tests/images/masks/drawEllipse.png differ diff --git a/tests/images/masks/drawPolygon.png b/tests/images/masks/drawPolygon.png new file mode 100644 index 0000000..089d0d3 Binary files /dev/null and b/tests/images/masks/drawPolygon.png differ diff --git a/tests/images/masks/drawRoundedRect.png b/tests/images/masks/drawRoundedRect.png new file mode 100644 index 0000000..13bb852 Binary files /dev/null and b/tests/images/masks/drawRoundedRect.png differ diff --git a/tests/test_images_draw.nim b/tests/test_images_draw.nim index 274c369..a553d84 100644 --- a/tests/test_images_draw.nim +++ b/tests/test_images_draw.nim @@ -56,6 +56,16 @@ block: image.drawRect(rect(vec2(10, 10), vec2(30, 30)), rgba(255, 255, 0, 255)) image.writeFile("tests/images/drawRect.png") +block: + let image = newImage(100, 100) + image.fill(rgba(0, 255, 255, 255)) + image.drawRoundedRect( + rect(vec2(10, 10), vec2(30, 30)), + 10, + rgba(255, 255, 0, 255) + ) + image.writeFile("tests/images/drawRoundedRect.png") + block: let image = newImage(100, 100) image.fill(rgba(0, 255, 255, 255)) @@ -65,3 +75,25 @@ block: strokeWidth = 10 ) image.writeFile("tests/images/drawSegment.png") + +block: + let image = newImage(100, 100) + image.fill(rgba(0, 255, 255, 255)) + image.drawEllipse( + vec2(50, 50), + 25, + 25, + rgba(255, 255, 0, 255) + ) + image.writeFile("tests/images/drawEllipse.png") + +block: + let image = newImage(100, 100) + image.fill(rgba(0, 255, 255, 255)) + image.drawPolygon( + vec2(50, 50), + 30, + 6, + rgba(255, 255, 0, 255) + ) + image.writeFile("tests/images/drawPolygon.png") diff --git a/tests/test_masks.nim b/tests/test_masks.nim index 48d163f..5818291 100644 --- a/tests/test_masks.nim +++ b/tests/test_masks.nim @@ -108,6 +108,11 @@ block: mask.drawRect(rect(vec2(10, 10), vec2(30, 30))) writeFile("tests/images/masks/drawRect.png", mask.encodePng()) +block: + let mask = newMask(100, 100) + mask.drawRoundedRect(rect(vec2(10, 10), vec2(30, 30)), 10) + writeFile("tests/images/masks/drawRoundedRect.png", mask.encodePng()) + block: let mask = newMask(100, 100) mask.drawSegment( @@ -115,3 +120,13 @@ block: strokeWidth = 10 ) writeFile("tests/images/masks/drawSegment.png", mask.encodePng()) + +block: + let mask = newMask(100, 100) + mask.drawEllipse(vec2(50, 50), 20, 10) + writeFile("tests/images/masks/drawEllipse.png", mask.encodePng()) + +block: + let mask = newMask(100, 100) + mask.drawPolygon(vec2(50, 50), 30, 6) + writeFile("tests/images/masks/drawPolygon.png", mask.encodePng())