11

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!

Elmi
  • 5,899
  • 15
  • 72
  • 143

1 Answers1

16

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).

Finlay McWalter
  • 1,222
  • 1
  • 10
  • 12
  • I have been trying to printing surface data directly to cups rather temp file with proper DPI. Could you suggest which api? Thanks – Dinesh Kumar Govinda Oct 15 '21 at 20:20
  • Dinesh Kumar Govinda: that would require using the CUPS API to find a printer, open a job on it, and then stream the data into the corresponding job. That's quite a different topic to this question. I'd recommend that you create a new question (tagged [cups] and [c]) to ask it, as you'll attract more attention than asking there. If I remember how (it's been a few year) I'll answer there, but maybe someone more experienced with CUPS with help you there. – Finlay McWalter Oct 17 '21 at 22:00