Exporting Cairo Drawings to PDF: Simple Steps and Practical Trade‑offs
Learn how to render vector graphics directly to a PDF with Cairo, see a minimal C example, and evaluate memory and performance trade‑offs.
20 Aug 2026, 11:16 UTC

When you need a document that stays crisp at any zoom level, raster images fall short. Cairo’s PDFSurface lets you write vector commands directly into a PDF, preserving line quality without extra steps.
Why PDF matters for vector output
A PDF surface is a Cairo backend that records drawing instructions instead of raster pixels. Because the commands are stored as mathematical paths, the resulting PDF scales perfectly, unlike bitmap formats that pixelate when zoomed. This makes PDFs ideal for technical diagrams, architectural plans, or any content where line sharpness matters at any scale.
Simple steps to create a PDF with Cairo
Create the surface and context
Call cairo_pdf_surface_create with a filename, width, and height. Wrap the returned surface in a context using cairo_create. Ensure you have Cairo ≥ 1.10, which introduced this API and remains stable in later releases. The surface width and height are in pixels, which the PDF will map to points, so you can control printed size.
Draw with standard Cairo commands
Use the familiar cairo_move_to, cairo_line, cairo_set_source_rgb, and cairo_fill functions exactly as you would for an ImageSurface. You can also set line width with cairo_set_line_width and use cairo_stroke for outlines. The drawing code stays unchanged.
Finish and close the surface
After completing all drawing calls, destroy the context with cairo_destroy and finalize the surface using cairo_pdf_surface_finish. The surface must be finished before destroying; otherwise the PDF may be truncated or corrupted.
Worked example: generating a technical diagram
This program creates a 600 × 400 pixel page, draws a blue rectangle at (50,50) with size 200 × 100, and places the label near the bottom.
#include
#include
int main() {
// 1. Create the PDF surface (filename, width, height)
cairo_surface_t *surface = cairo_pdf_surface_create("output.pdf", 600, 400);
if (!surface) {
fprintf(stderr, "Failed to create PDF surface\\n");
return 1;
}
// 2. Create the drawing context
cairo_t *cr = cairo_create(surface);
// 3. Draw a simple vector rectangle
cairo_set_source_rgb(cr, 0.1, 0.1, 0.5); // Dark blue
cairo_rectangle(cr, 50, 50, 200, 100);
cairo_fill(cr);
// 4. Add high‑quality text
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); // White
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 20.0);
cairo_move_to(cr, 60, 100);
cairo_show_text(cr, "Vector Export");
// 5. Critical: Finalize and clean up
cairo_destroy(cr);
cairo_pdf_surface_finish(surface);
cairo_surface_destroy(surface);
printf("PDF generated successfully: output.pdf\\n");
return 0;
}
Trade‑offs and limitations
- Memory usage: Embedding raster images requires loading them into an
ImageSurfacefirst, which can raise memory consumption during rendering. - CPU overhead: PDF generation is more intensive than writing a PNG because the library builds PDF object tables; avoid using it for real‑time frame buffers.
- File size: Simple vector PDFs are small, but documents with many unique paths or embedded high‑resolution images may become larger than a compressed raster file. Large PDFs can exceed typical email attachment limits of 25 MB, so consider compression or splitting.
Verification and practical checks
Compile the example with a command such as gcc main.c --cflags --libs cairo-2. Run the resulting executable and open output.pdf in a viewer to confirm that the rectangle and text appear correctly. Verify that the PDF viewer can render the file on the target platform. If the viewer shows missing glyphs, ensure the font is installed on the system.
To test memory impact, run the program under a memory profiler while adding an ImageSurface with a high‑resolution photo and compare peak usage to a direct PNG export.
In summary, Cairo’s PDFSurface provides a straightforward way to produce resolution‑independent PDFs for documentation, presentations, or archival purposes. Use it when vector fidelity outweighs the extra CPU and memory cost, and always close the surface to avoid corrupted files.