/** * Path - PDF path construction and vector graphics * * This module provides comprehensive support for creating and manipulating vector paths * used in PDF graphics. Paths are fundamental building blocks for drawing lines, curves, * shapes, and complex vector graphics in PDF documents. * * This module provides 100% API compatibility with MicroPDF's path operations. * * @module path * @example * ```typescript * import { Path, StrokeState, LineCap, LineJoin, Matrix } from 'micropdf'; * * // Create a simple path * const path = Path.create(); * path.moveTo(10, 10); * path.lineTo(100, 10); * path.lineTo(100, 100); * path.close(); * * // Create a rectangle * const rect = Path.create(); * rect.rect(0, 0, 200, 100); * * // Create a curve * const curve = Path.create(); * curve.moveTo(0, 0); * curve.curveTo(50, 100, 100, 100, 150, 0); * * // Configure stroke * const stroke = StrokeState.create(); * stroke.setLineWidth(2); * stroke.setLineCap(LineCap.Round); * stroke.setLineJoin(LineJoin.Round); * stroke.setDash([5, 3], 0); // 5 on, 3 off * * // Transform path * const matrix = Matrix.scale(2, 2); * path.transform(matrix); * ``` */ import { Point, Rect, type PointLike, type MatrixLike } from './geometry.js'; /** * Line cap styles determine how the ends of stroked paths are rendered. * * @enum {number} * @example * ```typescript * const stroke = StrokeState.create(); * stroke.setLineCap(LineCap.Round); // Rounded end caps * stroke.setStartCap(LineCap.Square); // Square start cap * stroke.setEndCap(LineCap.Butt); // Flat end cap * ``` */ export declare enum LineCap { /** * Butt cap - Line ends exactly at the endpoint (no extension). * This is the most common and default cap style. */ Butt = 0, /** * Round cap - Line extends with a semicircular cap at the endpoint. * The diameter equals the line width. */ Round = 1, /** * Square cap - Line extends with a square cap at the endpoint. * The extension equals half the line width. */ Square = 2, /** * Triangle cap - Line extends with a triangular cap at the endpoint. * Less common, used for special effects. */ Triangle = 3 } /** * Line join styles determine how path segments connect at corners. * * @enum {number} * @example * ```typescript * const stroke = StrokeState.create(); * stroke.setLineJoin(LineJoin.Round); // Smooth rounded corners * stroke.setLineJoin(LineJoin.Miter); // Sharp pointed corners * stroke.setMiterLimit(10); // Limit miter length * ``` */ export declare enum LineJoin { /** * Miter join - Extends the outer edges until they meet at a point. * Creates sharp corners but can become very long at acute angles. * Use miterLimit to prevent excessive extension. */ Miter = 0, /** * Round join - Joins segments with a circular arc. * Creates smooth, rounded corners with radius equal to half the line width. */ Round = 1, /** * Bevel join - Joins segments with a straight line across the corner. * Creates a flat, beveled corner. Safe for all angles. */ Bevel = 2, /** * Miter XPS join - Miter join variant used in XPS documents. * Similar to standard miter but with slightly different behavior. */ MiterXPS = 3 } /** * Type alias for line cap styles (backwards compatibility). * @deprecated Use {@link LineCap} instead * @type {typeof LineCap} */ export declare const LineCapStyle: typeof LineCap; /** * Type alias for line join styles (backwards compatibility). * @deprecated Use {@link LineJoin} instead * @type {typeof LineJoin} */ export declare const LineJoinStyle: typeof LineJoin; /** * Stroke state configuration for path rendering. * * StrokeState encapsulates all the properties that control how paths are stroked * (drawn with lines). This includes line width, cap styles, join styles, miter limits, * and dash patterns. * * **Reference Counting**: StrokeState uses manual reference counting. Call `keep()` to * increment the reference count and `drop()` to decrement it. * * @class StrokeState * @example * ```typescript * // Create default stroke state * const stroke = StrokeState.create(); * * // Configure stroke properties * stroke.setLineWidth(2.5); * stroke.setStartCap(LineCap.Round); * stroke.setLineJoin(LineJoin.Round); * stroke.setMiterLimit(10); * * // Set dash pattern: 5 units on, 3 units off * stroke.setDash([5, 3], 0); * * // Clone for variations * const thickStroke = stroke.clone(); * thickStroke.setLineWidth(5); * * // Clean up * stroke.drop(); * thickStroke.drop(); * ``` * * @example * ```typescript * // Create dotted line * const dotted = StrokeState.create(); * dotted.setLineWidth(1); * dotted.setLineCap(LineCap.Round); * dotted.setDash([2, 2], 0); // 2 on, 2 off * * // Create dashed line * const dashed = StrokeState.create(); * dashed.setLineWidth(2); * dashed.setDash([10, 5], 0); // 10 on, 5 off * * // Create solid line with rounded corners * const rounded = StrokeState.create(); * rounded.setLineWidth(3); * rounded.setLineCap(LineCap.Round); * rounded.setLineJoin(LineJoin.Round); * ``` */ export declare class StrokeState { private _lineWidth; private _startCap; private _dashCap; private _endCap; private _lineJoin; private _miterLimit; private _dashPhase; private _dashPattern; private _refCount; constructor(); /** * Create a new stroke state */ static create(): StrokeState; /** * Create stroke state with specific dash pattern length */ static createWithDashLen(dashLen: number): StrokeState; /** * Clone this stroke state */ clone(): StrokeState; /** * Keep (increment ref count) */ keep(): this; /** * Drop (decrement ref count) */ drop(): void; /** * Unshare (make a unique copy if shared) */ unshare(): StrokeState; get lineWidth(): number; set lineWidth(width: number); get startCap(): LineCap; set startCap(cap: LineCap); get dashCap(): LineCap; set dashCap(cap: LineCap); get endCap(): LineCap; set endCap(cap: LineCap); get lineJoin(): LineJoin; set lineJoin(join: LineJoin); get miterLimit(): number; set miterLimit(limit: number); get dashPhase(): number; get dashLength(): number; getDashPattern(): number[]; setDash(pattern: number[], phase?: number): this; setLineWidth(width: number): this; setLineCap(cap: LineCap): this; setStartCap(cap: LineCap): this; setDashCap(cap: LineCap): this; setEndCap(cap: LineCap): this; setLineJoin(join: LineJoin): this; setMiterLimit(limit: number): this; get lineCap(): LineCap; get dashLen(): number; get dashPattern(): number[]; /** * Check if stroke state is valid */ isValid(): boolean; } /** * Path walker interface for traversing path commands */ export interface PathWalker { moveTo?(x: number, y: number): void; lineTo?(x: number, y: number): void; curveTo?(cx1: number, cy1: number, cx2: number, cy2: number, x: number, y: number): void; closePath?(): void; quadTo?(cx: number, cy: number, x: number, y: number): void; rectTo?(x: number, y: number, w: number, h: number): void; } /** * Path command types */ declare enum PathCmd { MoveTo = 0, LineTo = 1, CurveTo = 2, Close = 3, QuadTo = 4, RectTo = 5 } /** * A single path command with its parameters */ interface PathCommand { cmd: PathCmd; params: number[]; } /** * A graphics path for constructing vector shapes and drawings. * * Path represents a sequence of drawing commands that define vector graphics. * Paths can contain lines, curves, rectangles, and other geometric primitives. * They can be stroked (outlined) or filled to create visible graphics in PDFs. * * **Path Construction**: Paths are built using a sequence of commands: * - `moveTo()` - Start a new subpath at a point * - `lineTo()` - Draw a straight line to a point * - `curveTo()` - Draw a cubic Bézier curve * - `quadTo()` - Draw a quadratic Bézier curve * - `rect()` - Add a rectangle * - `closePath()` / `close()` - Close the current subpath * * **Reference Counting**: Paths use manual reference counting. Call `keep()` to * increment the reference count and `drop()` to decrement it. * * @class Path * @example * ```typescript * // Draw a triangle * const triangle = Path.create(); * triangle.moveTo(50, 0); * triangle.lineTo(100, 100); * triangle.lineTo(0, 100); * triangle.close(); * * // Draw a rectangle * const rect = Path.create(); * rect.rect(10, 10, 200, 100); * * // Draw a rounded rectangle * const roundedRect = Path.create(); * const x = 10, y = 10, w = 200, h = 100, r = 10; * roundedRect.moveTo(x + r, y); * roundedRect.lineTo(x + w - r, y); * roundedRect.curveTo(x + w, y, x + w, y, x + w, y + r); * roundedRect.lineTo(x + w, y + h - r); * roundedRect.curveTo(x + w, y + h, x + w, y + h, x + w - r, y + h); * roundedRect.lineTo(x + r, y + h); * roundedRect.curveTo(x, y + h, x, y + h, x, y + h - r); * roundedRect.lineTo(x, y + r); * roundedRect.curveTo(x, y, x, y, x + r, y); * roundedRect.close(); * ``` * * @example * ```typescript * // Draw a sine wave * const wave = Path.create(); * wave.moveTo(0, 50); * for (let x = 0; x <= 200; x += 5) { * const y = 50 + Math.sin(x * 0.1) * 20; * wave.lineTo(x, y); * } * * // Transform the path * const matrix = Matrix.scale(2, 2); * wave.transform(matrix); * * // Check if empty * if (!wave.isEmpty()) { * console.log('Path has commands'); * } * * // Clean up * wave.drop(); * ``` * * @example * ```typescript * // Draw a circle approximation with cubic Bézier curves * const circle = Path.create(); * const cx = 100, cy = 100, r = 50; * const k = 0.5522847498; // 4/3 * (sqrt(2) - 1) * const kr = r * k; * * circle.moveTo(cx, cy - r); * circle.curveTo(cx + kr, cy - r, cx + r, cy - kr, cx + r, cy); * circle.curveTo(cx + r, cy + kr, cx + kr, cy + r, cx, cy + r); * circle.curveTo(cx - kr, cy + r, cx - r, cy + kr, cx - r, cy); * circle.curveTo(cx - r, cy - kr, cx - kr, cy - r, cx, cy - r); * circle.close(); * ``` */ export declare class Path { private _commands; private _currentPoint; private _refCount; constructor(); /** * Create a new empty path */ static create(): Path; /** * Keep (increment ref count) */ keep(): this; /** * Drop (decrement ref count) */ drop(): void; /** * Clone this path */ clone(): Path; /** * Get the current point */ get currentPoint(): Point; /** * Check if the path is empty */ isEmpty(): boolean; /** * Move to a point (start a new subpath) */ moveTo(x: number, y: number): this; moveTo(point: PointLike): this; /** * Draw a line to a point */ lineTo(x: number, y: number): this; lineTo(point: PointLike): this; /** * Draw a cubic Bézier curve */ curveTo(cx1: number, cy1: number, cx2: number, cy2: number, x: number, y: number): this; /** * Draw a quadratic Bézier curve */ quadTo(cx: number, cy: number, x: number, y: number): this; /** * Close the current subpath */ closePath(): this; /** * Close the current subpath (alias for closePath) */ close(): this; /** * Add a rectangle to the path */ rectTo(x: number, y: number, w: number, h: number): this; /** * Add a rectangle from corners */ rect(x1: number, y1: number, x2: number, y2: number): this; /** * Get the bounding box of the path */ getBounds(): Rect; /** * Transform the path by a matrix */ transform(matrix: MatrixLike): this; /** * Walk the path commands */ walk(walker: PathWalker): void; /** * Check if path is valid */ isValid(): boolean; /** * Get the number of commands in the path */ get length(): number; /** * Clear all commands from the path */ clear(): this; /** * Get bounding box (alias for getBounds) */ bbox(): Rect; /** * Get path commands as an array */ getCommands(): PathCommand[]; } export {}; //# sourceMappingURL=path.d.ts.map