Skip to main content

Working with Vector Graphics

PDFDancer allows you to work with vector graphics elements (paths) in PDFs. You can both select existing paths and create new ones - draw lines, shapes, bezier curves, and complex vector graphics.


Selecting Paths

Paths are vector graphics elements in PDFs (lines, shapes, drawings).

from pdfdancer import PDFDancer

with PDFDancer.open("document.pdf") as pdf:
# Get all paths on a specific page
paths = pdf.page(3).select_paths()

# Get paths at specific coordinates
paths_at_point = pdf.page(3).select_paths_at(x=150, y=320)

for path in paths:
print(f"Path ID: {path.internal_id}")

Understanding Vector Paths

Vector paths in PDFs can represent:

  • Lines and curves
  • Shapes (rectangles, circles, polygons)
  • Complex drawings and diagrams
  • Borders and decorative elements

Working with Paths

from pdfdancer import PDFDancer

with PDFDancer.open("document.pdf") as pdf:
# Select paths on a page
paths = pdf.page(1).select_paths()

print(f"Found {len(paths)} paths on page 0")

# You can iterate through paths
for i, path in enumerate(paths):
print(f"Path {i}: {path.internal_id}")

Drawing Lines

Create straight lines on a page:

from pdfdancer import PDFDancer, Color

with PDFDancer.open("document.pdf") as pdf:
page = pdf.page(1)

# Draw a simple line
page.new_line() \
.from_point(100, 100) \
.to_point(400, 100) \
.stroke_color(Color(0, 0, 0)) \
.stroke_width(2) \
.add()

# Draw a dashed line
page.new_line() \
.from_point(100, 150) \
.to_point(400, 150) \
.stroke_color(Color(255, 0, 0)) \
.stroke_width(1) \
.dash_pattern([5, 3]) \
.add()

pdf.save("output.pdf")

Drawing Rectangles

Create rectangles with stroke and fill:

from pdfdancer import PDFDancer, Color

with PDFDancer.open("document.pdf") as pdf:
page = pdf.page(1)

# Draw a stroked rectangle
page.new_rectangle() \
.at_coordinates(100, 200) \
.with_size(200, 100) \
.stroke_color(Color(0, 0, 255)) \
.stroke_width(3) \
.add()

# Draw a filled rectangle
page.new_rectangle() \
.at_coordinates(350, 200) \
.with_size(200, 100) \
.fill_color(Color(255, 200, 0)) \
.add()

# Draw a rectangle with both stroke and fill
page.new_rectangle() \
.at_coordinates(100, 350) \
.with_size(200, 100) \
.stroke_color(Color(0, 0, 0)) \
.stroke_width(2) \
.fill_color(Color(200, 200, 255)) \
.add()

pdf.save("output.pdf")

Drawing Bezier Curves

Create smooth curves using cubic Bezier curves:

from pdfdancer import PDFDancer, Color

with PDFDancer.open("document.pdf") as pdf:
page = pdf.page(1)

# Draw a bezier curve
page.new_bezier() \
.from_point(100, 100) \
.control_point_1(200, 200) \
.control_point_2(300, 200) \
.to_point(400, 100) \
.stroke_color(Color(0, 128, 0)) \
.stroke_width(2) \
.add()

pdf.save("output.pdf")

PathBuilder: Programmatic Path Creation

The newPath() method returns a builder that lets you create complex vector paths programmatically. This builder pattern allows you to chain commands to construct shapes, curves, and complex drawings.

TypeScript PathBuilder Class

In TypeScript SDK v1.0.22+, newPath() returns a PathBuilder instance that provides a fluent API for constructing vector paths. You can also import and use the PathBuilder class directly:

import { PathBuilder } from 'pdfdancer-client-typescript';

Builder Pattern Basics

from pdfdancer import PDFDancer, Color

with PDFDancer.open("document.pdf") as pdf:
# new_path() returns a builder - chain commands and call add()
pdf.page(1).new_path() \
.add_line(Point(100, 100), Point(200, 200)) \
.stroke_color(Color(0, 0, 0)) \
.stroke_width(2) \
.add() # Finalizes and adds the path to the page

Advanced Fill Rules

For complex shapes with overlapping regions, you can control the fill behavior:

// Even-odd fill rule for complex shapes
await pdf.page(1).newPath()
.moveTo(100, 100)
.lineTo(200, 100)
.lineTo(200, 200)
.lineTo(100, 200)
.closePath()
.fillColor(new Color(255, 0, 0))
.evenOddFill(true) // Use even-odd winding rule
.apply();
Even-Odd Fill Rule

The even-odd rule determines whether a point is inside a path by drawing a line from that point to infinity and counting how many times it crosses the path. If the count is odd, the point is inside; if even, it's outside. This is useful for creating shapes with holes or complex overlapping regions.

PathBuilder API Reference

Complete list of PathBuilder methods:

Drawing Commands:

  • moveTo(x, y) - Move to a point without drawing (sets the current point)
  • lineTo(x, y) - Draw a line from current point to (x, y)
  • bezierTo(cp1x, cp1y, cp2x, cp2y, x, y) - Draw a cubic Bezier curve
  • closePath() - Draw a line back to the starting point

Styling:

  • strokeColor(Color) - Set the outline color
  • fillColor(Color) - Set the fill color
  • strokeWidth(number) - Set outline width in points
  • dashPattern([on, off, ...]) - Set dash pattern for strokes

Advanced:

  • dashPhase(number) - Set the offset for dash patterns
  • evenOddFill(boolean) - Use even-odd fill rule (TypeScript)

Finalize:

  • at(pageNumber, x, y) / at(x, y) - Set position and optionally page index
  • add() / apply() - Add the path to the document
Python Method Names

Python uses snake_case: move_to(), line_to(), stroke_color(), etc.


Drawing Complex Paths

Create complex vector graphics using path commands:

from pdfdancer import PDFDancer, Color, Point

with PDFDancer.open("document.pdf") as pdf:
page = pdf.page(1)

# Draw a complex path (triangle)
page.new_path() \
.add_line(Point(250, 100), Point(350, 250)) \
.add_line(Point(350, 250), Point(150, 250)) \
.add_line(Point(150, 250), Point(250, 100)) \
.stroke_color(Color(128, 0, 128)) \
.stroke_width(3) \
.fill_color(Color(255, 200, 255)) \
.add()

# Draw a path with curves
page.new_path() \
.add_line(Point(100, 400), Point(200, 400)) \
.add_bezier(Point(200, 400), Point(250, 450), Point(300, 450), Point(350, 400)) \
.add_line(Point(350, 400), Point(450, 400)) \
.stroke_color(Color(255, 100, 0)) \
.stroke_width(2) \
.add()

pdf.save("output.pdf")

Path Commands

Available path commands:

  • move_to(x, y) / moveTo(x, y) - Move to a point without drawing
  • line_to(x, y) / lineTo(x, y) - Draw a straight line to a point
  • add_bezier(...) / bezierTo(cp1x, cp1y, cp2x, cp2y, x, y) / curveTo(...) - Draw a cubic Bezier curve
  • close_path() / closePath() - Close the current path by drawing a line to the start point

Styling Options

All vector graphics support these styling options:

Stroke (Outline)

  • stroke_color(Color) / strokeColor(Color) - Set the outline color
  • stroke_width(number) / strokeWidth(number) - Set the outline width in points
  • dash_pattern([on, off, ...]) / dashPattern([on, off, ...]) - Create dashed lines

Fill

  • fill_color(Color) / fillColor(Color) - Set the fill color for closed shapes
Stroke vs Fill
  • Use stroke for outlines and lines
  • Use fill for solid shapes
  • Use both for outlined shapes with a fill color
  • Omit both to create invisible paths (useful for clipping regions)

Next Steps