From 40dfcfcde109b36481d3c5b90cc7a9246905928b Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sat, 23 Jan 2021 21:15:39 -0600 Subject: [PATCH] 0.0.16 quadraticCurveTo, transform --- pixie.nimble | 2 +- src/pixie/paths.nim | 70 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/pixie.nimble b/pixie.nimble index 6f0215f..ed00d2d 100644 --- a/pixie.nimble +++ b/pixie.nimble @@ -1,4 +1,4 @@ -version = "0.0.15" +version = "0.0.16" author = "Andre von Houck and Ryan Oldenburg" description = "Full-featured 2d graphics library for Nim." license = "MIT" diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 9925ca8..89a7572 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -188,6 +188,60 @@ proc `$`*(path: Path): string = if i != path.commands.len - 1 or j != command.numbers.len - 1: result.add " " +proc transform*(path: Path, mat: Mat3) = + for command in path.commands.mitems: + case command.kind: + of Close: + discard + of Move, Line, RMove, RLine, TQuad, RTQuad: + var pos = vec2(command.numbers[0], command.numbers[1]) + pos = mat * pos + command.numbers[0] = pos.x + command.numbers[1] = pos.y + of HLine, RHLine: + var pos = vec2(command.numbers[0], 0) + pos = mat * pos + command.numbers[0] = pos.x + of VLine, RVLine: + var pos = vec2(0, command.numbers[0]) + pos = mat * pos + command.numbers[0] = pos.y + of Cubic, RCubic: + var + ctrl1 = vec2(command.numbers[0], command.numbers[1]) + ctrl2 = vec2(command.numbers[2], command.numbers[3]) + to = vec2(command.numbers[4], command.numbers[5]) + ctrl1 = mat * ctrl1 + ctrl2 = mat * ctrl2 + to = mat * to + command.numbers[0] = ctrl1.x + command.numbers[1] = ctrl1.y + command.numbers[2] = ctrl2.x + command.numbers[3] = ctrl2.y + command.numbers[4] = to.x + command.numbers[5] = to.y + of SCubic, RSCubic, Quad, RQuad: + var + ctrl = vec2(command.numbers[0], command.numbers[1]) + to = vec2(command.numbers[2], command.numbers[3]) + ctrl = mat * ctrl + to = mat * to + command.numbers[0] = ctrl.x + command.numbers[1] = ctrl.y + command.numbers[2] = to.x + command.numbers[3] = to.y + of Arc, RArc: + var + radii = vec2(command.numbers[0], command.numbers[1]) + to = vec2(command.numbers[5], command.numbers[6]) + # Extract the scale from the matrix and only apply that to the radii + radii = scale(vec2(mat[0, 0], mat[1, 1])) * radii + to = mat * to + command.numbers[0] = radii.x + command.numbers[1] = radii.y + command.numbers[5] = to.x + command.numbers[6] = to.y + proc commandsToPolygons*(commands: seq[PathCommand]): seq[seq[Vec2]] = ## Converts SVG-like commands to simpler polygon @@ -855,9 +909,19 @@ proc bezierCurveTo*(path: Path, x1, y1, x2, y2, x3, y3: float32) = x1, y1, x2, y2, x3, y3 ])) -proc quadraticCurveTo*(path: Path) = - ## Adds a quadratic Bézier curve to the current path. - raise newException(ValueError, "not implemented") +proc quadraticCurveTo*(path: var Path, x1, y1, x2, y2: float32) = + ## Adds a quadratic Bézier curve to the path. This requires 2 points. + ## The first point is the control point and the second is the end point. + ## The starting point is the last point in the current path, which can be + ## changed using moveTo() before creating the curve. + path.commands.add(PathCommand( + kind: Quad, + numbers: @[x1, y1, x2, y2] + )) + path.at = vec2(x2, y2) + +proc quadraticCurveTo*(path: var Path, ctrl, to: Vec2) {.inline.} = + path.quadraticCurveTo(ctrl.x, ctrl.y, to.x, to.y) proc arc*(path: Path) = ## Adds an arc to the path which is centered at (x, y) position with radius r starting at startAngle and ending at endAngle going in the given direction by anticlockwise (defaulting to clockwise).