Linux/CUPS printing example/tutorial?

Elmi picture Elmi · Jan 25, 2013 · Viewed 10.1k times · Source

I need to print some vector data (or to be more exact: some dots and polylines) using Linux. When I ask Google for that it shows me many tutorials and documentations - but all for end users, no programming examples.

So does anybody know a good programmers HOWTO/tutorial that shows printing under Linux?

Thanks!

Answer

Finlay McWalter picture Finlay McWalter · Feb 1, 2013

CUPS doesn't have its own document description API. It doesn't need one: formats like PostScript, PDF, and JPEG are first-class citizens of CUPS. You use whatever program or API you like to create a such a file, and you then send it to CUPS (with lpr or with the CUPS API) and CUPS will transform it to the appropriate internal format and send it to the printer.

So, for your case, you might use a vector graphics library like Cairo to author PostScript, and then you send that off to CUPS for printing. Here's a simple C example:

// compile with:
//   gcc -Wall -o cairo_print cairo_print.c `pkg-config --cflags --libs cairo` `cups-config --cflags --libs`

#include <stdio.h>
#include <cairo.h>
#include <cairo-ps.h>
#include <cups/cups.h>

// A4 width, height in points, from GhostView manual:
//   http://www.gnu.org/software/gv/manual/html_node/Paper-Keywords-and-paper-size-in-points.html
#define WIDTH  595  
#define HEIGHT 842  

int main(int argc, char** argv) {
  if (argc!= 2){
    fprintf (stderr, "usage: %s word\n", argv[0]);
    return 1;
  }

  // setup
  char* tmpfilename = tempnam(NULL,NULL);
  cairo_surface_t* surface = cairo_ps_surface_create(tmpfilename, 
                                                     WIDTH, 
                                                     HEIGHT);
  cairo_t *context = cairo_create(surface);

  // draw some text
  cairo_select_font_face(context, 
                         "Arial Black", 
                         CAIRO_FONT_SLANT_NORMAL, 
                         CAIRO_FONT_WEIGHT_NORMAL);
  cairo_set_font_size(context, 30);
  cairo_move_to(context, WIDTH/2, HEIGHT/2);
  cairo_show_text(context, argv[1]); // the text we got as a parameter

  // draw a dotted box
  const double pattern[] = {15.0, 10.0};
  cairo_set_dash(context, pattern, 2, 0);
  cairo_set_line_width(context, 5);
  cairo_rectangle(context, WIDTH*0.33, HEIGHT*0.33, WIDTH*0.5, WIDTH*0.5);
  cairo_stroke(context);

  // finish up
  cairo_show_page(context);
  cairo_destroy(context);
  cairo_surface_flush(surface);
  cairo_surface_destroy(surface);

  // print
  cupsPrintFile(cupsGetDefault(), tmpfilename, "cairo PS", 0, NULL);
  unlink(tmpfilename);

  return 0;
}

Strictly you don't need that temporary file: the CUPS API allows you to construct a stream and you can emit the page data into that (but a file is handy for debugging).