cab CUPS Treiber  ---
rastertocab.c
Go to the documentation of this file.
1 /******************************************************************************
2  * cab Produkttechnik GmbH & Co KG
3  * Entwicklung Etikettendrucker
4  *
5  * cab CUPS Linux Driver, raster.h
6  * - Main implementation of the printer filter module
7  *
8  * Copyright (c) 2004-2020 cab Produkttechnik GmbH, Germany
9  *
10  * Licensed under Apache License v2.0. See the file "LICENSE" for more
11  * information.
12  *
13  */
14 
15 /*****************************************************************************/
16 
17 #include <cups/cups.h>
18 
19 
20 #include <cups/raster.h>
21 #include <cups/backend.h>
22 #include <stdlib.h>
23 #include <fcntl.h>
24 #include <signal.h>
25 
26 #include "cab_options.h"
27 #include "cab_model.h"
28 #include "image.h"
29 #include "rastertocab.h"
30 
31 
32 /* Globals */
33 static int modelnumber; /* cupsModelNumber attribute */
34 static double printwidth; /* Max. Printwidth */
35 static int cancelled; /* Flag for cancel print job */
36 
37 #ifndef VERSION
38 #define VERSION "<unknown>"
39 #endif
40 
41 
42 
43 void sigterm_callback(int sig)
44 {
45  fputs("DEBUG: cab - Job cancelled ... \n", stderr);
46 
47  (void) sig;
48  cancelled = 1;
49 }
50 
51 
52 static int setup_printer(int cups_opts, cups_option_t *cups_opt)
53 {
54  ppd_file_t *ppd;
55  const char* sFilename = (char*) getenv("PPD");
56  int conflicts;
57 
58  if(!sFilename)
59  return CUPS_BACKEND_FAILED;
60 
61  if(!(ppd = ppdOpenFile(sFilename)))
62  return CUPS_BACKEND_FAILED;
63 
64  modelnumber = ppd->model_number;
66 
67  ppdMarkDefaults(ppd);
68  conflicts = cupsMarkOptions(ppd, cups_opts, cups_opt);
69 
70  if (conflicts != 0)
71  {
72  fprintf(stderr, "ERROR: Driver conflicts occurred: %d conflicts ...\n", conflicts);
73  fprintf(stderr, "ERROR: Report this, please. Thank you!\n");
74 
75  ppdClose(ppd);
76  return CUPS_BACKEND_FAILED;
77  }
79 
80  ppdClose(ppd);
81 
82  return CUPS_BACKEND_OK;
83 }
84 
85 
86 /*****************************************************************************/
87 /* Veranlast die gesendete Bilddatei zum Drucken. Das Bild wird in */
88 /* ein Etikett integriert. Dabei wird der Druckjob intialisiert und */
89 /* bei Bedarf die Anzahl der Kopien des Etiketts eingestellt. */
90 /*---------------------------------------------------------------------------*/
91 static void print_page(cups_page_header2_t *header, int image_offset_pix, int page)
92 {
93  char cLine[40 + CUSTOM_JSCRIPT_PARAM_MAX];
94  int image_offset_mm;
95  int replace;
96 
97  replace = get_option_replace();
98 
99  /* pix -> mm ... dpi -> dpmm */
100  image_offset_mm = (int)(25.4 / (double)header->HWResolution[0] * (double)image_offset_pix);
101 
102  putchar(0x1b); /* ESC-Zeichen ... */
103  printf("end-of-data\r\n"); /* Bilddatenstrom abschliessen ... */
104 
105  if(page <= 1 || !replace)
106  {
107  /* Immediate Kommando Pause 'Start of Job' */
108  if (get_immediate_cmd(cLine, OPT_CAB_PAUSE_MODE, 'S') == TRUE)
109  printf("%s", cLine);
110 
111  /* Immediate Kommando Formfeed 'Start of Job' */
112  if (get_immediate_cmd(cLine, OPT_CAB_FORMFEED_MODE, 'S') == TRUE)
113  printf("%s", cLine);
114 
115  /* Setzen der Maßeinheit ... */
116  printf("m m\r\n");
117  /* Senden des Job-Start Befehls ... */
118  printf("J\r\n");
119 
120  if(get_custom_jscript1_cmd(cLine, page))
121  printf("%s", cLine);
122 
123  /* Setzen der Druck-Optionen ... */
124  if (get_o_option_cmd(cLine) == TRUE)
125  printf("%s", cLine);
126 
127  /* Setzen der Perforationstiefe, falls ein Perforationsmesser installiert ist
128  * oder Pre-Print Option auf 'Perforate' gesetzt ist
129  */
131  {
132  get_perfo_depth(cLine);
133  printf("%s", cLine);
134  }
135 
136  get_h_option_cmd(cLine);
137  printf("%s", cLine);
138 
139  if(get_custom_jscript3_cmd(cLine))
140  printf("%s", cLine);
141 
142  if (get_d_option_cmd(cLine))
143  printf("%s", cLine);
144 
145  /* Etikettengröße festlegen ... */
146  get_s_option_cmd(cLine, header, printwidth);
147  printf("%s", cLine);
148 
149  /* Bild-Element drucken lassen ... */
150  printf("I:Field1; 0,%d,0;cups\r\n", image_offset_mm);
151 
152  /* Perforation Offset */
153  if (isPerfoCutterInstalled() == TRUE)
154  {
155  get_perfo_offset(cLine);
156  printf("%s", cLine);
157  }
158 
159  /* Pre-Printing Option */
160  if (get_preprint_opt(cLine) == TRUE)
161  printf("%s", cLine);
162 
163  /* Schneidemesser Optionen senden ... */
164  if (get_c_option_cmd(cLine) == TRUE)
165  printf("%s", cLine);
166 
167  /* Peel-Off Optionen senden ... */
168  if (get_p_option_cmd(cLine) == TRUE)
169  printf("%s", cLine);
170  }
171  else
172  {
173  if(get_custom_jscript1_cmd(cLine, page))
174  printf("%s", cLine);
175 
176  printf("R Field1;cups\r\n");
177  }
178 
179  /* Einstellen der gewünschten Kopien ... */
180  if (header->NumCopies >= 1)
181  printf("A%u\r\n", header->NumCopies);
182  else
183  printf("A1\r\n");
184 
185  /* Immediate Kommando Formfeed 'End of Job' */
186  if (get_immediate_cmd(cLine, OPT_CAB_FORMFEED_MODE, 'E') == TRUE)
187  printf("%s", cLine);
188 }
189 
190 
191 static int line_is_empty(short *ptr, int size)
192 {
193  int i;
194 
195  for(i = 0; i < size; i++)
196  {
197  if(*(ptr + i) != 0)
198  return 0;
199  }
200  return 1;
201 }
202 
203 
204 static void print_raster_image(cups_raster_t *ras, cups_page_header2_t *header, int *image_offset_pix)
205 {
206  pictogram_t *image;
207  short *ptr;
208  short *img_buffer;
209  int wwidth, y, front, height;
210  int image_opimization;
211 
212  image_opimization = get_option_image_optimization();
213  /* Automatically enable image optimization when RibbonSave is active...*/
214  if (isRibbonSaveSelected())
215  {
216  image_opimization=TRUE;
217  }
218  *image_offset_pix = 0;
219  image = malloc(sizeof(pictogram_t));
220  image->breite = (short) header->cupsWidth;
221  image->hoehe = (short) header->cupsHeight;
222  wwidth = (int) ((header->cupsBytesPerLine + 1) >> 1);
223  img_buffer = malloc(header->cupsHeight * wwidth * 2);
224  ptr = image->inh = img_buffer;
225  front = height = -1;
226 
227  /* Loop for each line on the page... */
228  for (y = 0; y < header->cupsHeight && !cancelled; y++)
229  {
230  /* Read a line of graphics... */
231  if (cupsRasterReadPixels(ras, (unsigned char *) ptr, header->cupsBytesPerLine) < 1)
232  break;
233 
234  if(front < 0 && image_opimization)
235  {
236  if(!line_is_empty(ptr, wwidth))
237  {
238  front = y;
239  height = 1;
240  }
241  }
242  else
243  {
244  if(!line_is_empty(ptr, wwidth))
245  height = y - front + 1;
246  }
247  ptr += wwidth;
248  }
249 
250  if(!cancelled)
251  {
252  printf("e img;*\r"); /* Bildspeicher im Drucker löschen ... */
253  printf("d IMG;cups\r"); /* Zuerst mal Bild downloaden ... */
254  putchar(0x1b); /* ESC-Zeichen ... */
255  putchar(':');
256 
257  if(front >= 0)
258  {
259  image->hoehe = height;
260  image->inh += front * wwidth;
261  write_img_header(stdout, header->cupsBytesPerLine * 8, height);
262  write_img(image, stdout);
263  *image_offset_pix = front;
264  }
265  else
266  {
267  write_img_header(stdout, header->cupsBytesPerLine * 8, header->cupsHeight);
268  write_img(image, stdout);
269  }
270  }
271  free(img_buffer);
272  free(image);
273 }
274 
275 
276 /*****************************************************************************/
277 /* Main program of the cab CUPS driver. */
278 /*---------------------------------------------------------------------------*/
279 int main(int argc, char *argv[])
280 {
281  cups_raster_t *ras; /* Raster stream for printing */
282  cups_page_header2_t header; /* Page header from file */
283  cups_option_t *options;
284  int rv, fd, num_options, page;
285  int image_offset_pix;
286 
287  signal(SIGPIPE, SIG_IGN);
288  signal(SIGTERM, sigterm_callback);
289 
290  fd = 0;
291  page = 0;
292  cancelled = 0;
293  rv = CUPS_BACKEND_OK;
294 
295 #ifdef DEBUG_INFO
296  fputs("DEBUG: cab - Starting rastertocab ...\n", stderr);
297  //sleep(20);
298 #endif
299 
300  /* Make sure status messages are not buffered... */
301  setbuf(stderr, NULL);
302 
303  if(argc == 2 && (strcmp(argv[1], "--version") == 0 ))
304  {
305  fprintf(stderr, "%s - version %s\n", argv[0], VERSION);
306  return 0;
307  }
308  else if (argc == 7) /* Open the page stream... */
309  {
310  if ((fd = open(argv[6], O_RDONLY)) < 0)
311  {
312  perror("ERROR: rastertocab - Unable to open raster file - ");
313  return CUPS_BACKEND_FAILED;
314  }
315  }
316  else if (argc != 6)
317  {
318  fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", argv[0]);
319  return CUPS_BACKEND_FAILED;
320  }
321 
322  /* CUPS Optionen einlesen ... */
323  options = NULL;
324  num_options = cupsParseOptions(argv[5], 0, &options);
325 
326 #ifdef DEBUG_INFO
327  dump_cups_options(num_options, options);
328 #endif
329 
330  /* Raster-Datenstrom öffnen ... */
331  ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
332 
333  /* Initialize the print device... */
334  if((rv = setup_printer(num_options, options)) != CUPS_BACKEND_OK)
335  return rv;
336 
337  /* Process pages as needed ... */
338  while (cupsRasterReadHeader2(ras, &header))
339  {
340 #ifdef DEBUG_INFO
341  dump_pg_header(&header);
342 #endif
343  /* print image */
344  print_raster_image(ras, &header, &image_offset_pix);
345 
346  if(cancelled)
347  {
348  rv = CUPS_BACKEND_CANCEL;
349  break;
350  }
351  else
352  {
353  /* Write a status message with the page number and number of copies. */
354  fprintf(stderr, "INFO: rastertocab - PAGE: %d\n", ++page);
355 
356  /* print page ... */
357  print_page(&header, image_offset_pix, page);
358  }
359  }
360 
361  /* Close the raster stream ... */
362  cupsRasterClose(ras);
363 
364  if(fd)
365  close(fd);
366 
367  /* If no pages were printed, send an error message ... */
368  if (!page)
369  {
370  fputs("ERROR: rastertocab - No pages found!\n", stderr);
371  return CUPS_BACKEND_FAILED;
372  }
373  fputs("DEBUG: rastertocab - Ready to print.\n", stderr);
374  return rv;
375 }
static void print_raster_image(cups_raster_t *ras, cups_page_header2_t *header, int *image_offset_pix)
Definition: rastertocab.c:204
void sigterm_callback(int sig)
Definition: rastertocab.c:43
#define TRUE
Debug level.
Definition: rastertocab.h:30
int get_p_option_cmd(char *command)
Definition: cab_options.c:259
int get_preprint_opt(char *command)
Assembles the command for the per-print option (C-Command)
Definition: cab_options.c:491
void write_img_header(FILE *oFile, unsigned int xdim, unsigned int ydim)
Creates and writes the image header.
Definition: image.c:60
int get_o_option_cmd(char *command)
Definition: cab_options.c:401
int isPrePrintPerforate()
Return, wether the pre-print option is set to &#39;Perforate&#39;.
Definition: cab_options.c:364
static int cancelled
Definition: rastertocab.c:35
void get_s_option_cmd(char *command, cups_page_header2_t *header, double printwidth)
Definition: cab_options.c:154
double get_printing_width(int modelnumber)
Definition: cab_model.c:228
#define OPT_CAB_FORMFEED_MODE
Definition: cab_options.h:141
int get_option_replace()
Definition: cab_options.c:788
static int setup_printer(int cups_opts, cups_option_t *cups_opt)
Definition: rastertocab.c:52
void dump_pg_header(cups_page_header2_t *header)
Dumps the CUPS page header structure.
Definition: raster_int.c:39
void get_perfo_depth(char *command)
Assembles the command for the perforation depth (C-Command)
Definition: cab_options.c:468
static int line_is_empty(short *ptr, int size)
Definition: rastertocab.c:191
int isPerfoCutterInstalled()
Return, wether a perforation cutter is installed.
Definition: cab_options.c:347
int get_immediate_cmd(char *command, const char *type, const char value)
Definition: cab_options.c:517
int get_d_option_cmd(char *command)
Definition: cab_options.c:315
int isRibbonSaveSelected()
Return, wether the RibbonSave is active.
Definition: cab_options.c:381
#define CUSTOM_JSCRIPT_PARAM_MAX
Definition: cab_options.h:160
short * inh
pointer to bitmap
Definition: image.h:43
int get_option_image_optimization()
Definition: cab_options.c:777
#define VERSION
Definition: rastertocab.c:38
int get_custom_jscript1_cmd(char *command, int page)
Definition: cab_options.c:106
void handleMarkedPPDOptions(ppd_file_t *ppd)
Definition: cab_options.c:1254
int get_custom_jscript3_cmd(char *command)
Definition: cab_options.c:122
static int modelnumber
Definition: rastertocab.c:33
#define OPT_CAB_PAUSE_MODE
Definition: cab_options.h:143
short breite
width in pixels (16 pixel steps!)
Definition: image.h:41
Internal struct to store informations for images.
Definition: image.h:39
void get_perfo_offset(char *command)
Assembles the command for the perforation offset (C-Command)
Definition: cab_options.c:447
void write_img(pictogram_t *pp, FILE *fp)
Definition: image.c:94
int get_c_option_cmd(char *command)
Definition: cab_options.c:214
int main(int argc, char *argv[])
Definition: rastertocab.c:279
short hoehe
height in pixels
Definition: image.h:42
static void print_page(cups_page_header2_t *header, int image_offset_pix, int page)
Definition: rastertocab.c:91
void get_h_option_cmd(char *command)
Definition: cab_options.c:286
static double printwidth
Definition: rastertocab.c:34