cairo
| Language | C (C++ bindings: cairomm) |
|---|---|
| License | LGPL-2.1 or MPL-1.1 |
| Repository | gitlab.freedesktop.org/cairo/cairo |
| Documentation | PostScript surfaces |
| Depends on | pixman, FreeType, fontconfig, zlib |
| Read / write | no / 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#
- Without
set_epsthe same code writes a regular PostScript page; see cairo for PostScript. - To produce EPS, PDF and SVG from the same drawing, put the drawing in a function that takes a
cairo_t *and call it with each surface type.