All formats

cairo

LanguageC (C++ bindings: cairomm)
LicenseLGPL-2.1 or MPL-1.1
Repositorygitlab.freedesktop.org/cairo/cairo
DocumentationPostScript surfaces
Depends onpixman, FreeType, fontconfig, zlib
Read / writeno / yes (EPS Level 2 or 3)

cairo’s PostScript surface writes EPS when you call cairo_ps_surface_set_eps(surface, 1) before drawing. The %%BoundingBox is computed from the marks you actually draw, not from the surface size, so the graphic is cropped tightly. Fonts are embedded as subsets.

EPS can’t hold transparency: cairo replaces transparent areas with embedded bitmaps. Keep alpha at 1 for pure vector output. cairo writes EPS but can’t read it.

Installation#

Shell
sudo apt install libcairo2-dev   # Debian / Ubuntu
brew install cairo               # macOS
vcpkg install cairo              # Windows
Shell
cc logo.c $(pkg-config --cflags --libs cairo) -o logo

Basic usage: write an EPS file#

C
#include <cairo.h>
#include <cairo-ps.h>
#include <stdio.h>

int main(void) {
    cairo_surface_t *surface = cairo_ps_surface_create("logo.eps", 200, 100);
    cairo_ps_surface_set_eps(surface, 1);  // before any drawing
    cairo_ps_surface_dsc_comment(surface, "%%Title: Logo");

    cairo_t *cr = cairo_create(surface);
    cairo_set_source_rgb(cr, 0.2, 0.4, 0.8);
    cairo_rectangle(cr, 10, 10, 180, 80);
    cairo_fill(cr);

    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
    cairo_set_font_size(cr, 36);
    cairo_move_to(cr, 40, 64);  // origin is top-left
    cairo_show_text(cr, "LOGO");

    cairo_show_page(cr);  // EPS has exactly one page
    cairo_destroy(cr);
    cairo_surface_finish(surface);
    cairo_status_t status = cairo_surface_status(surface);
    cairo_surface_destroy(surface);
    if (status != CAIRO_STATUS_SUCCESS) {
        fprintf(stderr, "cairo: %s\n", cairo_status_to_string(status));
        return 1;
    }
    return 0;
}

The resulting file starts with %!PS-Adobe-3.0 EPSF-3.0 and its %%BoundingBox covers only the drawn rectangle, not the whole 200 x 100 surface.

How to write EPS for old PostScript Level 2 devices#

C
cairo_ps_surface_restrict_to_level(surface, CAIRO_PS_LEVEL_2);

How to embed a PNG image in an EPS file#

C
cairo_surface_t *img = cairo_image_surface_create_from_png("photo.png");
cairo_set_source_surface(cr, img, 0, 0);
cairo_paint(cr);
cairo_surface_destroy(img);

PNG files with transparency become a flattened bitmap in the EPS.

How to check whether a surface writes EPS#

C
if (cairo_ps_surface_get_eps(surface))
    printf("writing EPS\n");

Tips#