import { type Point } from "./point.ts"; /** * A 2D path builder used by both the WebGL and Canvas renderers to build and * interpolate paths from SVG command strings or direct method calls. Its method * semantics follow the standard * [Path2D](https://developer.mozilla.org/en-US/docs/Web/API/Path2D) API. * * Each renderer exposes a reusable instance as `renderer.path2D`; you can also * create your own with `new Path2D()`. Build a path (via {@link parseSVGPath} or * the imperative {@link moveTo}/{@link lineTo}/curve methods), then draw it with * the renderer's `stroke()` (outline) and `fill()` (solid) methods. Curves and * arcs are flattened into line segments; {@link arcResolution} controls how fine * that approximation is. * * **Sub-paths & holes:** a new sub-path begins on every {@link moveTo} (and on * each `M` in an SVG string). When filled, the first sub-path is the outer * contour and each subsequent sub-path is treated as a hole — so shapes with * holes or disconnected regions (a donut, a ring, the letter "O", text outlines) * fill correctly. The Canvas renderer fills via the native non-zero winding rule * (so holes should be wound opposite to the outer contour); the WebGL renderer * triangulates with holes via earcut, which matches that result for the usual * case of oppositely-wound holes. Sub-path boundaries are tracked in * {@link subPaths}. * * Supported SVG commands: `M`, `L`, `H`, `V`, `Q`, `C`, `A`, `Z` (uppercase / * absolute only; `H` and `V` take a relative offset). * @example * // build a path with the imperative API, then fill and outline it * const path = renderer.path2D; * path.beginPath(); * path.moveTo(50, 0); * path.lineTo(100, 100); * path.lineTo(0, 100); * path.closePath(); * renderer.setColor("#4CAF50"); * renderer.fill(); // fill the current path * renderer.setColor("#1B5E20"); * renderer.stroke(); // outline the current path * @example * // the same triangle from an SVG path string * renderer.path2D.parseSVGPath("M 50 0 L 100 100 L 0 100 Z"); * renderer.fill(); * @category Geometry */ declare class Path2D { /** * the points defining the current path */ points: Point[]; /** * start index (into {@link points}) of each sub-path after the first; used * as the hole indices when triangulating, and as the `moveTo` boundaries * when the Canvas renderer replays the path. */ subPaths: number[]; /** * space between interpolated points for quadratic and bezier curve approx. in pixels. * @default 2 */ arcResolution: number; vertices: Point[]; startPoint: Point; isDirty: boolean; constructor(svgPath?: string); /** * Parses an SVG path string and generates interpolated points for rendering. * Clears any existing path data before parsing (calls {@link beginPath} internally). * * Supported commands: * - **M** x y — move to (starts a new sub-path) * - **L** x y — line to * - **H** dx — horizontal line (relative offset from current x) * - **V** dy — vertical line (relative offset from current y) * - **Q** cx cy x y — quadratic Bézier curve * - **C** cx1 cy1 cx2 cy2 x y — cubic Bézier curve * - **A** rx ry xRot largeArc sweep x y — elliptical arc * - **Z** — close the current sub-path (line back to its starting point) * * Multiple `M` commands define separate sub-paths; when filled the first is * the outer contour and the rest are holes. After parsing, the generated * points are available in {@link points} and can be rendered using the * renderer's `stroke()` and `fill()` methods. * @example * // draw a heart shape * renderer.path2D.parseSVGPath( * "M 10 30 A 20 20 0 0 1 50 30 A 20 20 0 0 1 90 30 Q 90 60 50 90 Q 10 60 10 30 Z" * ); * renderer.setColor("#EF5350"); * renderer.fill(); * @example * // a donut: an outer ring with an inner hole (two `M` sub-paths) * renderer.path2D.parseSVGPath( * "M 0 40 A 40 40 0 1 0 80 40 A 40 40 0 1 0 0 40 Z " + * "M 20 40 A 20 20 0 1 0 60 40 A 20 20 0 1 0 20 40 Z" * ); * renderer.fill(); * @param svgPath - An SVG path data string (e.g. "M 0 0 L 100 0 L 50 100 Z"). * Only uppercase (absolute) commands are supported. */ parseSVGPath(svgPath: string): void; /** * begin a new (empty) path, discarding all previously recorded points and * sub-paths. Called automatically by {@link parseSVGPath}. * @example * path.beginPath(); * path.rect(0, 0, 100, 60); * renderer.fill(); */ beginPath(): void; /** * causes the point of the pen to move back to the start of the current sub-path. * It tries to draw a straight line from the current point to the start. * If the shape has already been closed or has only one point, this function does nothing. * @example * path.beginPath(); * path.moveTo(0, 0); * path.lineTo(50, 0); * path.lineTo(25, 40); * path.closePath(); // draw the final edge back to (0, 0) */ closePath(): void; /** * triangulate the shape defined by this path into a flat list of triangle * vertices (every three consecutive points form one triangle). Sub-paths * after the first are treated as holes. Used by the WebGL renderer to fill, * and cached until the path changes. * @returns the triangulated vertices, three per triangle * @example * path.parseSVGPath("M 0 0 L 100 0 L 50 100 Z"); * const verts = path.triangulatePath(); // 3 vertices = 1 triangle */ triangulatePath(): Point[]; /** * moves the starting point of a new sub-path to the (x, y) coordinates. * @param x - the x-axis (horizontal) coordinate of the point. * @param y - the y-axis (vertical) coordinate of the point. * @example * path.beginPath(); * path.moveTo(20, 20); // lift the pen to (20, 20): starts a new sub-path * path.lineTo(80, 20); */ moveTo(x: number, y: number): void; /** * connects the last point in the current sub-path to the (x, y) coordinates with a straight line. * @param x - the x-axis coordinate of the line's end point. * @param y - the y-axis coordinate of the line's end point. * @example * path.beginPath(); * path.moveTo(0, 0); * path.lineTo(50, 0); // horizontal segment * path.lineTo(50, 50); // vertical segment (an "L" shape) */ lineTo(x: number, y: number): void; /** * adds an arc to the current path which is centered at (x, y) position with the given radius, * starting at startAngle and ending at endAngle going in the given direction by counterclockwise (defaulting to clockwise). * @param x - the horizontal coordinate of the arc's center. * @param y - the vertical coordinate of the arc's center. * @param radius - the arc's radius. Must be positive. * @param startAngle - the angle at which the arc starts in radians, measured from the positive x-axis. * @param endAngle - the angle at which the arc ends in radians, measured from the positive x-axis. * @param [anticlockwise=false] - an optional boolean value. If true, draws the arc counter-clockwise between the start and end angles. * @example * // a full circle of radius 40 centred at (50, 50) * path.beginPath(); * path.arc(50, 50, 40, 0, Math.PI * 2); * renderer.stroke(); */ arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; /** * adds a circular arc to the path with the given control points and radius, connected to the previous point by a straight line. * @param x1 - the x-axis coordinate of the first control point. * @param y1 - the y-axis coordinate of the first control point. * @param x2 - the x-axis coordinate of the second control point. * @param y2 - the y-axis coordinate of the second control point. * @param radius - the arc's radius. Must be positive. * @example * // round the corner where two segments meet at (50, 0) * path.beginPath(); * path.moveTo(0, 0); * path.arcTo(50, 0, 50, 50, 20); * path.lineTo(50, 50); */ arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void; /** * adds an elliptical arc to the path which is centered at (x, y) position with the radii radiusX and radiusY * starting at startAngle and ending at endAngle going in the given direction by counterclockwise. * @param x - the x-axis (horizontal) coordinate of the ellipse's center. * @param y - the y-axis (vertical) coordinate of the ellipse's center. * @param radiusX - the ellipse's major-axis radius. Must be non-negative. * @param radiusY - the ellipse's minor-axis radius. Must be non-negative. * @param rotation - the rotation of the ellipse, expressed in radians. * @param startAngle - the angle at which the ellipse starts, measured clockwise from the positive x-axis and expressed in radians. * @param endAngle - the angle at which the ellipse ends, measured clockwise from the positive x-axis and expressed in radians. * @param [anticlockwise=false] - an optional boolean value which, if true, draws the ellipse counterclockwise (anticlockwise). * @example * // a 45°-rotated ellipse, filled * path.beginPath(); * path.ellipse(50, 50, 60, 30, Math.PI / 4, 0, Math.PI * 2); * renderer.fill(); */ ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; /** * Adds a quadratic Bézier curve to the path. * @param cpX - The x-coordinate of the control point. * @param cpY - The y-coordinate of the control point. * @param x - The x-coordinate of the end point of the curve. * @param y - The y-coordinate of the end point of the curve. * @example * path.beginPath(); * path.moveTo(0, 50); * path.quadraticCurveTo(50, 0, 100, 50); // one control point at (50, 0) */ quadraticCurveTo(cpX: number, cpY: number, x: number, y: number): void; /** * Adds a cubic Bézier curve to the path. * @param cp1X - The x-coordinate of the first control point. * @param cp1Y - The y-coordinate of the first control point. * @param cp2X - The x-coordinate of the second control point. * @param cp2Y - The y-coordinate of the second control point. * @param x - The x-coordinate of the end point of the curve. * @param y - The y-coordinate of the end point of the curve. * @example * path.beginPath(); * path.moveTo(0, 50); * path.bezierCurveTo(25, 0, 75, 100, 100, 50); // two control points */ bezierCurveTo(cp1X: number, cp1Y: number, cp2X: number, cp2Y: number, x: number, y: number): void; /** * creates a path for a rectangle at position (x, y) with a size that is determined by width and height. * @param x - the x-axis coordinate of the rectangle's starting point. * @param y - the y-axis coordinate of the rectangle's starting point. * @param width - the rectangle's width. Positive values are to the right, and negative to the left. * @param height - the rectangle's height. Positive values are down, and negative are up. * @example * path.beginPath(); * path.rect(10, 10, 80, 50); * renderer.fill(); */ rect(x: number, y: number, width: number, height: number): void; /** * adds an rounded rectangle to the current path. * @param x - the x-axis coordinate of the rectangle's starting point. * @param y - the y-axis coordinate of the rectangle's starting point. * @param width - the rectangle's width. Positive values are to the right, and negative to the left. * @param height - the rectangle's height. Positive values are down, and negative are up. * @param radius - the arc's radius to draw the borders. Must be positive. * @example * path.beginPath(); * path.roundRect(10, 10, 80, 50, 12); // 12px corner radius * renderer.fill(); */ roundRect(x: number, y: number, width: number, height: number, radius: number): void; } export default Path2D; //# sourceMappingURL=path2d.d.ts.map