CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pycairo

Python interface for cairo graphics library providing 2D vector graphics, drawing operations, and rendering to multiple output formats

Pending
Overview
Eval results
Files

surfaces.mddocs/

Surfaces

Surface classes provide the rendering targets for Cairo drawing operations. Each surface type represents a different output format or backend, from in-memory image buffers to vector formats like PDF and SVG. Surfaces manage the destination for all drawing operations performed through a Context.

Capabilities

Base Surface Class

class Surface:
    def finish(self) -> None:
        """Do any pending drawing and free resources used by surface."""
        
    def flush(self) -> None:
        """Do any pending drawing for the surface."""
        
    def get_content(self) -> Content:
        """Get content type of surface (COLOR, ALPHA, or COLOR_ALPHA)."""
        
    def get_device(self) -> Device:
        """Get device associated with surface."""
        
    def get_font_options(self, options: FontOptions) -> None:
        """Retrieve default font rendering options for surface."""
        
    def mark_dirty(self) -> None:
        """Tell cairo that drawing has been done to surface."""
        
    def mark_dirty_rectangle(self, x: int, y: int, width: int, height: int) -> None:
        """Mark a rectangular region as dirty."""
        
    def set_device_scale(self, x_scale: float, y_scale: float) -> None:
        """Set device scale factors."""
        
    def get_device_scale(self) -> tuple[float, float]:
        """Get device scale factors."""
        
    def set_device_offset(self, x_offset: float, y_offset: float) -> None:
        """Set device offset."""
        
    def get_device_offset(self) -> tuple[float, float]:  
        """Get device offset."""
        
    def get_fallback_resolution(self) -> tuple[float, float]:
        """Get fallback resolution in pixels per inch."""
        
    def set_fallback_resolution(self, x_pixels_per_inch: float, y_pixels_per_inch: float) -> None:
        """Set fallback resolution."""
        
    def copy_page(self) -> None:
        """Emit current page for backends that support multiple pages."""
        
    def show_page(self) -> None:
        """Emit and clear current page for backends that support multiple pages."""
        
    def has_show_text_glyphs(self) -> bool:
        """Check if surface can render text and glyphs simultaneously."""
        
    def set_mime_data(self, mime_type: str, data: bytes) -> None:
        """Attach MIME data to surface."""
        
    def get_mime_data(self, mime_type: str) -> bytes:
        """Get MIME data previously attached to surface."""
        
    def supports_mime_type(self, mime_type: str) -> bool:
        """Check if surface supports given MIME type."""
        
    def create_for_rectangle(self, x: float, y: float, width: float, height: float) -> Surface:
        """Create sub-surface from rectangular region of this surface."""
        
    def create_similar_image(self, format: Format, width: int, height: int) -> ImageSurface:
        """Create similar image surface with specified format and dimensions."""
        
    def map_to_image(self, extents: Rectangle | None = None) -> ImageSurface:
        """Map surface or region to image surface for direct pixel access."""
        
    def unmap_image(self, image: ImageSurface) -> None:
        """Unmap previously mapped image surface."""
        
    def __enter__(self) -> Surface:
        """Enter context manager."""
        
    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        """Exit context manager and finish surface."""

Image Surface

class ImageSurface(Surface):
    def __init__(self, format: Format, width: int, height: int) -> None:
        """Create image surface with specified format and dimensions.
        
        Args:
            format: Pixel format (FORMAT_ARGB32, FORMAT_RGB24, etc.)
            width: Width in pixels
            height: Height in pixels
        """
        
    @classmethod
    def create_from_png(cls, filename: str) -> ImageSurface:
        """Create image surface from PNG file."""
        
    @classmethod
    def create_from_png_stream(cls, file: BinaryIO) -> ImageSurface:
        """Create image surface from PNG data stream."""
        
    @classmethod
    def create_for_data(cls, data: memoryview, format: Format, width: int, height: int, stride: int) -> ImageSurface:
        """Create image surface using provided data buffer."""
        
    def write_to_png(self, filename: str) -> None:
        """Write surface contents to PNG file."""
        
    def write_to_png_stream(self, file: BinaryIO) -> None:
        """Write surface contents to PNG data stream."""
        
    def get_data(self) -> memoryview:
        """Get raw pixel data as memory view."""
        
    def get_format(self) -> Format:
        """Get pixel format of surface."""
        
    def get_width(self) -> int:
        """Get width in pixels."""
        
    def get_height(self) -> int:
        """Get height in pixels."""
        
    def get_stride(self) -> int:
        """Get stride (bytes per row) of surface."""
        
    @staticmethod
    def format_stride_for_width(format: Format, width: int) -> int:
        """Calculate stride for given format and width."""

PDF Surface

class PDFSurface(Surface):
    def __init__(self, filename: str, width_in_points: float, height_in_points: float) -> None:
        """Create PDF surface writing to file.
        
        Args:
            filename: Output PDF filename
            width_in_points: Page width in points (1/72 inch)
            height_in_points: Page height in points (1/72 inch)
        """
        
    @classmethod
    def create_for_stream(cls, file: BinaryIO, width_in_points: float, height_in_points: float) -> PDFSurface:
        """Create PDF surface writing to stream."""
        
    def restrict_to_version(self, version: PDFVersion) -> None:
        """Restrict output to specific PDF version."""
        
    @staticmethod
    def get_versions() -> list[PDFVersion]:
        """Get list of supported PDF versions."""
        
    @staticmethod  
    def version_to_string(version: PDFVersion) -> str:
        """Get string representation of PDF version."""
        
    def set_size(self, width_in_points: float, height_in_points: float) -> None:
        """Change size of PDF surface for subsequent pages."""
        
    def add_outline(self, parent_id: int, text: str, link_attribs: str, flags: PDFOutlineFlags) -> int:
        """Add item to PDF outline (bookmarks).
        
        Args:
            parent_id: Parent outline item ID (use PDF_OUTLINE_ROOT for root)
            text: Display text for outline item
            link_attribs: Link attributes string
            flags: Outline item flags
            
        Returns:
            ID of created outline item
        """
        
    def set_metadata(self, metadata: PDFMetadata, value: str) -> None:
        """Set PDF metadata."""
        
    def set_page_label(self, label: str) -> None:
        """Set label for current page."""
        
    def set_thumbnail_size(self, width: int, height: int) -> None:
        """Set thumbnail image size for pages."""
        
    def set_custom_metadata(self, name: str, value: str) -> None:
        """Set custom metadata field."""

PostScript Surface

class PSSurface(Surface):
    def __init__(self, filename: str, width_in_points: float, height_in_points: float) -> None:
        """Create PostScript surface writing to file.
        
        Args:
            filename: Output PostScript filename  
            width_in_points: Page width in points
            height_in_points: Page height in points
        """
        
    @classmethod
    def create_for_stream(cls, file: BinaryIO, width_in_points: float, height_in_points: float) -> PSSurface:
        """Create PostScript surface writing to stream."""
        
    def restrict_to_level(self, level: PSLevel) -> None:
        """Restrict output to specific PostScript level."""
        
    @staticmethod
    def get_levels() -> list[PSLevel]:
        """Get list of supported PostScript levels."""
        
    @staticmethod
    def level_to_string(level: PSLevel) -> str:
        """Get string representation of PostScript level."""
        
    def set_eps(self, eps: bool) -> None:
        """Enable/disable Encapsulated PostScript mode."""
        
    def get_eps(self) -> bool:
        """Check if EPS mode is enabled."""
        
    def set_size(self, width_in_points: float, height_in_points: float) -> None:
        """Change size for subsequent pages."""
        
    def dsc_comment(self, comment: str) -> None:
        """Emit DSC comment to PostScript output."""
        
    def dsc_begin_setup(self) -> None:
        """Begin setup section in DSC-compliant PostScript."""
        
    def dsc_begin_page_setup(self) -> None:
        """Begin page setup section."""

SVG Surface

class SVGSurface(Surface):
    def __init__(self, filename: str, width_in_points: float, height_in_points: float) -> None:
        """Create SVG surface writing to file.
        
        Args:
            filename: Output SVG filename
            width_in_points: Surface width in points
            height_in_points: Surface height in points
        """
        
    @classmethod
    def create_for_stream(cls, file: BinaryIO, width_in_points: float, height_in_points: float) -> SVGSurface:
        """Create SVG surface writing to stream."""
        
    def restrict_to_version(self, version: SVGVersion) -> None:
        """Restrict output to specific SVG version."""
        
    @staticmethod
    def get_versions() -> list[SVGVersion]:
        """Get list of supported SVG versions."""
        
    @staticmethod
    def version_to_string(version: SVGVersion) -> str:
        """Get string representation of SVG version."""
        
    def set_document_unit(self, unit: SVGUnit) -> None:
        """Set unit used for SVG surface."""
        
    def get_document_unit(self) -> SVGUnit:
        """Get unit used for SVG surface."""

Recording Surface

class RecordingSurface(Surface):
    def __init__(self, content: Content, extents: Rectangle | None = None) -> None:
        """Create recording surface for caching drawing operations.
        
        Args:
            content: Content type (COLOR, ALPHA, or COLOR_ALPHA)
            extents: Recording extents or None for unbounded
        """
        
    def ink_extents(self) -> tuple[float, float, float, float]:
        """Get bounding box of recorded operations."""
        
    def get_extents(self) -> tuple[bool, float, float, float, float]:
        """Get recording extents."""

Other Surface Types

class Win32Surface(Surface):
    def __init__(self, hdc: int) -> None:
        """Create surface targeting Windows HDC."""

class Win32PrintingSurface(Surface):  
    def __init__(self, hdc: int) -> None:
        """Create surface for Windows printing."""

class XCBSurface(Surface):
    pass  # Platform-specific initialization

class XlibSurface(Surface):
    pass  # Platform-specific initialization

class TeeSurface(Surface):
    def __init__(self, primary: Surface) -> None:
        """Create tee surface directing to primary surface."""
        
    def add(self, target: Surface) -> None:
        """Add additional target surface."""
        
    def remove(self, target: Surface) -> None:
        """Remove target surface."""
        
    def index(self, index: int) -> Surface:
        """Get surface at given index."""

class ScriptSurface(Surface):
    def __init__(self, device: ScriptDevice, content: Content, width: float, height: float) -> None:
        """Create surface for Cairo script recording."""

Device Classes

class Device:
    def __init__(self) -> None:
        """Base device class (typically not instantiated directly)."""
        
    def finish(self) -> None:
        """Finish device and free associated resources."""
        
    def flush(self) -> None:
        """Flush pending operations on device."""
        
    def get_type(self) -> DeviceType:
        """Get device type."""

class ScriptDevice(Device):
    def __init__(self, filename: str) -> None:
        """Create script recording device writing to file.
        
        Args:
            filename: Output script filename
        """
        
    @classmethod
    def create_for_stream(cls, file: BinaryIO) -> ScriptDevice:
        """Create script device writing to stream."""
        
    def set_mode(self, mode: ScriptMode) -> None:
        """Set script recording mode (ASCII or BINARY)."""
        
    def get_mode(self) -> ScriptMode:
        """Get current script recording mode."""
        
    def write_comment(self, comment: str) -> None:
        """Write comment to script output."""
        
    def from_recording_surface(self, recording_surface: RecordingSurface) -> None:
        """Replay recording surface to script device."""

Usage Examples

Creating Different Surface Types

import cairo

# Image surface (in-memory bitmap)
image_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 800, 600)

# PDF surface  
pdf_surface = cairo.PDFSurface("output.pdf", 612, 792)  # US Letter size

# SVG surface
svg_surface = cairo.SVGSurface("output.svg", 400, 300)

# PostScript surface
ps_surface = cairo.PSSurface("output.ps", 612, 792)

# Recording surface (unbounded)
recording_surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, None)

Working with Image Surfaces

import cairo

# Create image surface
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
ctx = cairo.Context(surface)

# Draw something
ctx.set_source_rgb(0.8, 0.2, 0.2)
ctx.rectangle(50, 50, 100, 80)
ctx.fill()

# Save to PNG
surface.write_to_png("output.png")

# Access raw pixel data
data = surface.get_data()
width = surface.get_width()
height = surface.get_height()
stride = surface.get_stride()
format = surface.get_format()

print(f"Surface: {width}x{height}, format: {format}, stride: {stride}")

Multi-page PDF Document

import cairo

# Create PDF surface
surface = cairo.PDFSurface("document.pdf", 612, 792)  # US Letter
ctx = cairo.Context(surface)

# Configure PDF metadata
surface.set_metadata(cairo.PDF_METADATA_TITLE, "My Document")
surface.set_metadata(cairo.PDF_METADATA_AUTHOR, "Author Name")

# Page 1
ctx.set_source_rgb(0, 0, 0)
ctx.select_font_face("Arial", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
ctx.set_font_size(24)
ctx.move_to(50, 100)
ctx.show_text("Page 1")

# Add outline entry
outline_id = surface.add_outline(cairo.PDF_OUTLINE_ROOT, "Chapter 1", "page=1", 0)

surface.show_page()

# Page 2  
ctx.move_to(50, 100)
ctx.show_text("Page 2")
surface.show_page()

surface.finish()

Recording and Playback

import cairo

# Create recording surface
recording = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, None)
ctx = cairo.Context(recording)

# Record some operations
ctx.set_source_rgb(0.2, 0.4, 0.8)
ctx.rectangle(10, 10, 80, 60)
ctx.fill()

ctx.set_source_rgb(0.8, 0.4, 0.2)  
ctx.arc(50, 40, 20, 0, 2 * 3.14159)
ctx.fill()

# Get recorded extents
x, y, width, height = recording.ink_extents()
print(f"Recorded operations cover: {x}, {y}, {width}, {height}")

# Play back to image surface
image = cairo.ImageSurface(cairo.FORMAT_ARGB32, 200, 150)
ctx2 = cairo.Context(image)
ctx2.set_source_surface(recording)
ctx2.paint()

image.write_to_png("playback.png")

Stream-based Output

import cairo
import io

# Create PDF in memory
pdf_buffer = io.BytesIO()
surface = cairo.PDFSurface.create_for_stream(pdf_buffer, 400, 300)
ctx = cairo.Context(surface)

# Draw content
ctx.set_source_rgb(0.8, 0.2, 0.2)
ctx.rectangle(50, 50, 100, 80)
ctx.fill()

surface.finish()

# Get PDF data
pdf_data = pdf_buffer.getvalue()
print(f"Generated PDF size: {len(pdf_data)} bytes")

# Write to file
with open("output_from_stream.pdf", "wb") as f:
    f.write(pdf_data)

Install with Tessl CLI

npx tessl i tessl/pypi-pycairo

docs

constants-enums.md

drawing-context.md

geometry.md

index.md

patterns.md

surfaces.md

text-fonts.md

tile.json