Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpcups / HPCupsFilter.cpp
1 /*****************************************************************************\
2   HPCupsFilter.cpp : Interface for HPCupsFilter class
3
4   Copyright (c) 1996 - 2009, Hewlett-Packard Co.
5   All rights reserved.
6
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
10   1. Redistributions of source code must retain the above copyright
11      notice, this list of conditions and the following disclaimer.
12   2. Redistributions in binary form must reproduce the above copyright
13      notice, this list of conditions and the following disclaimer in the
14      documentation and/or other materials provided with the distribution.
15   3. Neither the name of Hewlett-Packard nor the names of its
16      contributors may be used to endorse or promote products derived
17      from this software without specific prior written permission.
18
19   THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
22   NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24   TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30   Author: Naga Samrat Chowdary Narla, Sanjay Kumar, Amarnath Chitumalla
31 \*****************************************************************************/
32
33 #include "HPCupsFilter.h"
34 #include <signal.h>
35 #include <sys/wait.h>
36 #include <sys/utsname.h>
37 #include <time.h>
38 #include <sys/timeb.h>
39
40 #define HP_FILE_VERSION_STR    "03.09.08.0"
41
42 static HPCupsFilter    filter;
43 int main (int  argc, char *argv[])
44 {
45     openlog("hpcups", LOG_PID,  LOG_DAEMON);
46
47     if (argc < 6 || argc > 7) {
48         dbglog("ERROR: %s job-id user title copies options [file]\n", *argv);
49         return JOB_CANCELED;
50     }
51
52     return filter.StartPrintJob(argc, argv);
53 }
54
55 void HPCancelJob(int sig)
56 {
57     filter.CancelJob();
58     exit(0);
59 }
60
61 void HPCupsFilter::CreateBMPHeader (int width, int height, int planes, int bpp)
62 {
63     memset (&this->bmfh, 0, 14);
64     memset (&this->bmih, 0, 40);
65     bmfh.bfOffBits = 54;
66     bmfh.bfType = 0x4d42;
67     bmfh.bfReserved1 = 0;
68     bmfh.bfReserved2 = 0;
69     bmih.biSize = DBITMAPINFOHEADER;
70     bmih.biWidth = width;
71     bmih.biHeight = -height;
72     bmih.biPlanes = 1;
73     bmih.biBitCount = planes * bpp;
74     bmih.biCompression = 0;
75     bmih.biSizeImage = width * height * planes * bpp / 8;
76     bmih.biClrImportant = 0;
77     bmih.biClrUsed = (planes == 3) ? 0 : 2;
78     bmih.biXPelsPerMeter = 0;
79     bmih.biYPelsPerMeter = 0;
80
81     bmfh.bfOffBits += bmih.biClrUsed * 4;
82     bmfh.bfSize = bmih.biSizeImage + bmfh.bfOffBits;
83 }
84
85 void HPCupsFilter::WriteBMPHeader (FILE *fp, int width, int height, eRasterType raster_type)
86 {
87     if (fp == NULL)
88     {
89         return;
90     }
91     if (raster_type == BLACK_RASTER)
92     {
93         WriteKBMPHeader (fp, width, height);
94     }
95     else
96     {
97         WriteCBMPHeader (fp, width, height);
98     }
99 }
100
101 void HPCupsFilter::WriteCBMPHeader (FILE *fp, int width, int height)
102 {
103     if (fp == NULL)
104         return;
105     adj_c_width = width;
106     if (width % 4)
107     {
108         adj_c_width = (width / 4 + 1) * 4;
109     }
110     color_raster = new BYTE[adj_c_width * 3];
111     memset (color_raster, 0xFF, adj_c_width * 3);
112     CreateBMPHeader(adj_c_width, height, 3, 8);
113     fwrite (&this->bmfh.bfType, 1, sizeof (short), fp);
114     fwrite (&this->bmfh.bfSize, 1, sizeof (int), fp);
115     fwrite (&this->bmfh.bfReserved1, 1, sizeof (short), fp);
116     fwrite (&this->bmfh.bfReserved2, 1, sizeof (short), fp);
117     fwrite (&this->bmfh.bfOffBits, 1, sizeof (int), fp);
118     fwrite (&this->bmih, 1, DBITMAPINFOHEADER, fp);
119 }
120
121 void HPCupsFilter::WriteKBMPHeader(FILE *fp, int width, int height)
122 {
123     BYTE    cmap[8];
124     if (fp == NULL)
125         return;
126     adj_k_width = width;
127     if (width % 32)
128     {
129         adj_k_width = (width / 32 + 1) * 32;
130     }
131     CreateBMPHeader(adj_k_width, height, 1, 1);
132     adj_k_width /= 8;
133     black_raster = new BYTE[adj_k_width];
134     memset (black_raster, 0, adj_k_width);
135
136     fwrite (&this->bmfh.bfType, 1, sizeof (short), fp);
137     fwrite (&this->bmfh.bfSize, 1, sizeof (int), fp);
138     fwrite (&this->bmfh.bfReserved1, 1, sizeof (short), fp);
139     fwrite (&this->bmfh.bfReserved2, 1, sizeof (short), fp);
140     fwrite (&this->bmfh.bfOffBits, 1, sizeof (int), fp);
141     fwrite (&this->bmih, 1, DBITMAPINFOHEADER, fp);
142     memset(cmap, 0, sizeof(cmap));
143     cmap[0] = cmap[1] = cmap[2] = cmap[3] = 255;
144     fwrite(cmap, 1, sizeof(cmap), fp);
145 }
146
147 void HPCupsFilter::WriteBMPRaster (FILE *fp, BYTE *raster, int width, eRasterType raster_type)
148 {
149     if (raster_type == BLACK_RASTER)
150         return WriteKBMPRaster (fp, raster, width);
151     else
152         return WriteCBMPRaster (fp, raster, width);
153 }
154
155 void HPCupsFilter::WriteCBMPRaster (FILE *fp, BYTE *pbyrgb, int width)
156 {
157     if (fp == NULL)
158         return;
159     //BYTE    c[3];
160     int     i;
161     BYTE    *p = pbyrgb;
162     BYTE    *q = color_raster;
163     if (pbyrgb == NULL)
164     {
165         memset (color_raster, 0xFF, adj_c_width * 3);
166     }
167     else
168     {
169         for (i = 0; i < width; i++) {
170             q[0] = p[2];
171             q[1] = p[1];
172             q[2] = p[0];
173             p += 3;
174             q += 3;
175         }
176     }
177     fwrite (color_raster, 1, adj_c_width * 3, fp);
178 }
179
180 void HPCupsFilter::WriteKBMPRaster (FILE *fp, BYTE *pbyk, int width)
181 {
182     if (fp == NULL)
183         return;
184     if (pbyk == NULL)
185     {
186         memset (black_raster, 0, adj_k_width);
187     }
188     else
189     {
190         memcpy (black_raster, pbyk, width);
191     }
192     fwrite (black_raster, 1, adj_k_width, fp);
193 }
194
195 HPCupsFilter::HPCupsFilter() : m_pPrinterBuffer(NULL)
196 {
197     setbuf (stderr, NULL);
198
199     adj_c_width = 0;
200     adj_k_width = 0;
201     black_raster = NULL;
202     color_raster = NULL;
203 }
204
205 HPCupsFilter::~HPCupsFilter()
206 {
207
208 }
209
210 void HPCupsFilter::closeFilter ()
211 {
212     //! If we printed any pages, end the current job instance.
213     m_Job.Cleanup();
214     cleanup();
215 }
216
217 void HPCupsFilter::cleanup()
218 {
219     if (m_pPrinterBuffer) {
220         delete [] m_pPrinterBuffer;
221     }
222
223     if(m_ppd){
224        ppdClose(m_ppd);
225        m_ppd = NULL;
226     }
227 }
228
229 void HPCupsFilter::CancelJob()
230 {
231         m_Job.CancelJob();
232     cleanup();
233 }
234
235 DRIVER_ERROR HPCupsFilter::startPage (cups_page_header2_t *cups_header)
236 {
237     DRIVER_ERROR        err = NO_ERROR;
238     ppd_attr_t          *attr;
239     int                 xoverspray = 120;
240     int                 yoverspray = 60;
241
242 /*
243  *  Check for invalid data
244  */
245     if (cups_header->HWResolution[0] == 100 && cups_header->HWResolution[1] == 100)
246     {
247
248 /*
249  *      Something went wrong, cups is defaulting to 100 dpi.
250  *      Some inkjet printers do not support 100 dpi. Return error.
251  */
252
253         dbglog("ERROR: Unsupported resolution\n");
254         return JOB_CANCELED;
255     }
256
257 //  XOverSpray and YOverSpray are entered as fractional value * 1000
258
259     if (((attr = ppdFindAttr(m_ppd, "HPXOverSpray", NULL)) != NULL) &&
260         (attr && attr->value != NULL)) {
261            xoverspray = atoi(attr->value);
262     }
263     if (((attr = ppdFindAttr(m_ppd, "HPYOverSpray", NULL)) != NULL) &&
264         (attr && attr->value != NULL)) {
265            yoverspray = atoi(attr->value);
266     }
267
268     if (m_iLogLevel & BASIC_LOG) {
269         printCupsHeaderInfo(cups_header);
270     }
271
272     m_JA.quality_attributes.media_type = cups_header->cupsMediaType;
273     m_JA.quality_attributes.print_quality = atoi(cups_header->OutputType);
274     m_JA.quality_attributes.horizontal_resolution = cups_header->HWResolution[0];
275     m_JA.quality_attributes.vertical_resolution   = cups_header->HWResolution[1];
276     m_JA.quality_attributes.actual_vertical_resolution   = cups_header->HWResolution[1];
277
278 //  Get the printer's actual resolution, may be different than what is reported
279     char   *p;
280     if ((p = strstr (cups_header->OutputType, "_"))) {
281         int    x = 0, y = 0;
282         p++;
283         x = atoi(p);
284         while (*p && *p != 'x')
285             p++;
286         if (*p && *p == 'x') {
287             p++;
288             y = atoi(p);
289         }
290 //      Currently, there is one printer with one printmode that supports lower y-resolution
291         if (y != 0) {
292             m_JA.quality_attributes.actual_vertical_resolution = y;
293         }
294     }
295     m_JA.color_mode = cups_header->cupsRowStep;
296     m_JA.media_source = cups_header->MediaPosition;
297
298     m_JA.print_borderless = (cups_header->ImagingBoundingBox[0] == 0) ? true : false;
299     if (cups_header->Duplex) {
300         m_JA.e_duplex_mode  = (cups_header->Tumble == 0) ? DUPLEXMODE_BOOK : DUPLEXMODE_TABLET;
301     }
302     else {
303         m_JA.e_duplex_mode = DUPLEXMODE_NONE;
304     }
305     m_JA.krgb_mode = (cups_header->cupsColorSpace == CUPS_CSPACE_RGBW) ? true : false;
306
307     /*
308      *  Cups PageSize dimensions are in PostScript units, which are 72 units to an inch
309      *  and is stored as <width, height>
310      *  The ImagingBoundingBox is in PostScript units and are stored as <lower_left> <upper_right>
311      *  and <0, 0> is at the bottom left
312      *      lower_left_x = ImagingBoundingBox[0]
313      *      lower_left_y = ImagingBoundingBox[1]
314      *      upper_right_x = ImagingBoundingBox[2]
315      *      upper_right_y = ImagingBoundingBox[3]
316      *  We require <top_left> <bottom_right> values and <0, 0> is top left
317      *  So,
318      *      PrintableStartX = lower_left_x
319      *      PrintableStartY = PhysicalPageHeight - upper_right_y
320      */
321
322     int    horz_res = cups_header->HWResolution[0];
323     int    vert_res = cups_header->HWResolution[1];
324     m_JA.media_attributes.pcl_id = cups_header->cupsInteger[0];
325     m_JA.media_attributes.physical_width   = (cups_header->PageSize[0] * horz_res) / 72;
326     m_JA.media_attributes.physical_height  = (cups_header->PageSize[1] * vert_res) / 72;
327     m_JA.media_attributes.printable_width  = cups_header->cupsWidth;
328     m_JA.media_attributes.printable_height = cups_header->cupsHeight;
329
330     m_JA.media_attributes.printable_start_x = (cups_header->Margins[0] * horz_res) / 72;
331     m_JA.media_attributes.printable_start_y = ((cups_header->PageSize[1] - cups_header->ImagingBoundingBox[3]) * vert_res) / 72;
332
333     m_JA.media_attributes.horizontal_overspray = (xoverspray * horz_res) / 1000;
334     m_JA.media_attributes.vertical_overspray   = (yoverspray * vert_res) / 1000;
335
336     /*
337      * Left and top overspray in dots. We haven't defined ovespray for all classes in the drv.
338      * Hence using default values in the case of older classes.
339      */
340     m_JA.media_attributes.left_overspray = cups_header->cupsReal[0] ? (cups_header->cupsReal[0] * horz_res) : m_JA.media_attributes.horizontal_overspray / 2;
341     m_JA.media_attributes.top_overspray  = cups_header->cupsReal[1] ? (cups_header->cupsReal[1] * vert_res) : m_JA.media_attributes.vertical_overspray / 2;
342
343     if (((attr = ppdFindAttr(m_ppd, "HPMechOffset", NULL)) != NULL) &&
344         (attr && attr->value != NULL)) {
345         m_JA.mech_offset = atoi(attr->value);
346     }
347
348 //  Get printer platform name
349     if (((attr = ppdFindAttr(m_ppd, "hpPrinterPlatform", NULL)) != NULL) && (attr->value != NULL)) {
350
351                 strncpy(m_JA.printer_platform, attr->value, sizeof(m_JA.printer_platform)-1);
352
353                 if (m_iLogLevel & BASIC_LOG) {
354                         dbglog("HPCUPS: found Printer Platform, it is - %s\n", attr->value);
355                 }
356
357                 if(strcmp(m_JA.printer_platform, "ljzjscolor") == 0){
358                         if(((attr = ppdFindAttr(m_ppd, "hpLJZjsColorVersion", NULL)) != NULL) && (attr->value != NULL)){
359                                 m_JA.printer_platform_version = atoi(attr->value);
360                         }
361                 }
362     }
363
364 //Get Raster Preprocessing status
365         if(((attr = ppdFindAttr(m_ppd, "hpReverseRasterPages", NULL)) != NULL) && (attr->value != NULL)){                               
366                 m_JA.pre_process_raster = atoi(attr->value);
367         }
368
369
370 // Get the encapsulation technology from ppd
371
372     if (((attr = ppdFindAttr(m_ppd, "hpPrinterLanguage", NULL)) == NULL) ||
373         (attr && attr->value == NULL)) {
374             dbglog("DEBUG: Bad PPD - hpPrinterLanguage not found\n");
375             ppdClose(m_ppd);
376             m_ppd = NULL;
377             return SYSTEM_ERROR;
378     }
379     strncpy(m_JA.printer_language, attr->value, sizeof(m_JA.printer_language)-1);
380     if (m_iLogLevel & BASIC_LOG) {
381         dbglog("HPCUPS: found Printer Language, it is - %s\n", attr->value);
382     }
383
384 //  Fill in the other PCL header info
385
386     struct utsname  uts_name;
387     uname(&uts_name);
388     strncpy(m_JA.job_title, m_argv[3], sizeof(m_JA.job_title)-1);
389     strncpy(m_JA.user_name, m_argv[2], sizeof(m_JA.user_name)-1);
390     strncpy(m_JA.host_name, uts_name.nodename, sizeof(m_JA.host_name)-1);
391     strncpy(m_JA.os_name, uts_name.sysname, sizeof(m_JA.os_name)-1);
392     getdomainname(m_JA.domain_name, sizeof(m_JA.domain_name) - 1);
393     int i = strlen(m_argv[0]) - 1;
394     while (i >= 0 && m_argv[0][i] != '/') {
395         i--;
396     }
397     snprintf(m_JA.driver_name, sizeof(m_JA.driver_name), "%s; %s", &m_argv[0][i+1], HP_FILE_VERSION_STR);
398     char    *ptr = getenv("DEVICE_URI");
399     i = 0;
400     if (ptr) {
401         while (*ptr) {
402             if (*ptr == '%') {
403                 ptr += 3;
404                 m_JA.printer_name[i++] = ' ';
405             }
406             m_JA.printer_name[i++] = *ptr++;
407         }
408     }
409
410         string strPrinterURI="" ,strPrinterName= "";
411         m_DBusComm.initDBusComm(DBUS_PATH,DBUS_INTERFACE, getenv("DEVICE_URI"), m_JA.printer_name);
412
413     ptr = strstr(m_argv[5], "job-uuid");
414     if (ptr) {
415         strncpy(m_JA.uuid, ptr + strlen("job-uuid=urn:uuid:"), sizeof(m_JA.uuid)-1);
416     }
417
418     for (i = 0; i < 16; i++)
419         m_JA.integer_values[i] = cups_header->cupsInteger[i];
420
421     if (cups_header->cupsString[0]) {
422         strncpy(m_JA.quality_attributes.print_mode_name, &cups_header->cupsString[0][0],
423                 sizeof(m_JA.quality_attributes.print_mode_name)-1);
424     }
425     Encapsulator *encap_interface = EncapsulatorFactory::GetEncapsulator(attr->value);
426     if ((err = m_Job.Init(m_pSys, &m_JA, encap_interface)) != NO_ERROR)
427     {
428         if (err == PLUGIN_LIBRARY_MISSING)
429         {
430             fputs ("STATE: +hplip.plugin-error\n", stderr);
431
432                         m_DBusComm.sendEvent(EVENT_PRINT_FAILED_MISSING_PLUGIN, "Plugin missing", m_JA.job_id, m_JA.user_name);
433
434         }
435         dbglog ("m_Job initialization failed with error = %d", err);
436         ppdClose(m_ppd);
437         m_ppd = NULL;
438         return err;
439     }
440
441     if (m_iLogLevel & BASIC_LOG) {
442         dbglog("HPCUPS: returning NO_ERROR from startPage\n");
443     }
444
445     m_pPrinterBuffer = new BYTE[cups_header->cupsWidth * 4 + 32];
446
447
448     return NO_ERROR;
449 }
450
451 int HPCupsFilter::StartPrintJob(int  argc, char *argv[])
452 {
453     int              fd = 0;
454     cups_raster_t    *cups_raster;
455     int              err = 0;
456
457     memset(&m_JA, 0, sizeof(JobAttributes));
458     struct    tm       *t;
459     struct    timeb    tb;
460     time_t             long_time;
461     time(&long_time);
462     t = localtime(&long_time);
463     ftime(&tb);
464     strncpy(m_JA.job_start_time, asctime(t), sizeof(m_JA.job_start_time)-1);    // returns Fri Jun  5 08:12:16 2009
465     snprintf(m_JA.job_start_time+19, sizeof(m_JA.job_start_time) - 20, ":%d %d", tb.millitm, t->tm_year + 1900); // add milliseconds
466
467     getLogLevel();
468     m_JA.job_id = atoi(argv[1]);
469     FILE    *fp;
470     char    dFileName[32];
471     memset(dFileName, 0, sizeof(dFileName));
472     m_JA.job_id = atoi(argv[1]);
473     snprintf (dFileName, sizeof(dFileName), "/var/spool/cups/d%05d-001", m_JA.job_id);
474     if ((fp = fopen (dFileName, "r")))
475     {
476         char    line[258];
477         for (int i = 0; i < 10; i++)
478         {
479             fgets (line, 256, fp);
480             if (!strncmp (line, "%%Pages:", 8))
481             {
482                 sscanf (line+9, "%d", &m_JA.total_pages);
483                 break;
484             }
485         }
486         fclose (fp);
487     }
488
489     m_ppd = ppdOpenFile(getenv("PPD"));
490     if (m_ppd == NULL) {
491         dbglog("DEBUG: ppdOpenFile failed for %s\n", getenv("PPD"));
492         return SYSTEM_ERROR;
493     }
494
495     m_argv = argv;
496     if (m_iLogLevel & BASIC_LOG) {
497         for (int i = 0; i < argc; i++) {
498             dbglog("argv[%d] = %s\n", i, argv[i]);
499         }
500     }
501
502     if (argc == 7)
503     {
504         if (m_iLogLevel & BASIC_LOG)
505         {
506             dbglog("Page Stream Data Name: %s\n", argv[6] );
507         }
508         if ((fd = open (argv[6], O_RDONLY)) == -1)
509         {
510             perror("ERROR: Unable to open raster file - ");
511             return 1;
512         }
513     }
514
515     m_pSys = new SystemServices(m_iLogLevel, m_JA.job_id);
516
517 /*
518  *  When user cancels a print job, the spooler sends SIGTERM signal
519  *  to the filter. Must catch this signal to send end job sequence
520  *  to the printer.
521  */
522
523     signal(SIGTERM, HPCancelJob);
524
525
526     cups_raster = cupsRasterOpen(fd, CUPS_RASTER_READ);
527
528     if (cups_raster == NULL) {
529         dbglog("cupsRasterOpen failed, fd = %d\n", fd);
530         if (fd != 0) {
531             close(fd);
532         }
533         closeFilter();
534         return 1;
535     }
536
537     if ((err = processRasterData(cups_raster))) {
538         if (fd != 0) {
539             close(fd);
540         }
541         if (m_iLogLevel & BASIC_LOG)
542             dbglog("HPCUPS: processRasterData returned %d, calling closeFilter()", err);
543         closeFilter();
544         cupsRasterClose(cups_raster);
545         return 1;
546     }
547
548     if (fd != 0) {
549         close(fd);
550     }
551     if (m_iLogLevel & BASIC_LOG)
552         dbglog("HPCUPS: StartPrintJob end of job, calling closeFilter()");
553     closeFilter();
554     cupsRasterClose(cups_raster);
555     return 0;
556 }
557
558 bool HPCupsFilter::isBlankRaster(BYTE *input_raster, cups_page_header2_t *header)
559 {
560     int length_in_bytes = (int)header->cupsBytesPerLine;
561     if (input_raster == NULL) {
562         return true;
563     }
564
565     if(header->cupsColorSpace == CUPS_CSPACE_K){
566         if (*input_raster == 0x00 &&
567             !(memcmp(input_raster + 1, input_raster, length_in_bytes - 1))) {
568         return true;
569         }
570     }
571     else{
572         if (*input_raster == 0xFF &&
573               !(memcmp(input_raster + 1, input_raster, length_in_bytes - 1))) {
574         return true;
575         }
576     }
577     return false;
578 }
579
580
581 int HPCupsFilter::processRasterData(cups_raster_t *cups_raster)
582 {
583     FILE                   *kfp = NULL;
584     FILE                   *cfp = NULL;
585     BYTE                   *kRaster = NULL;
586     BYTE                   *rgbRaster = NULL;
587     int                    current_page_number = 0;
588     cups_page_header2_t    cups_header;
589     DRIVER_ERROR           err;
590     int                    ret_status = 0;
591     char hpPreProcessedRasterFile[] = "/tmp/hplipSwapedPagesXXXXXX"; //temp file needed to store raster data with swaped pages.
592
593     while (cupsRasterReadHeader2(cups_raster, &cups_header))
594     {
595         current_page_number++;
596
597         if (current_page_number == 1) {
598
599             if (startPage(&cups_header) != NO_ERROR) {
600                 return JOB_CANCELED;
601             }
602
603             if(m_JA.pre_process_raster) {
604                         err = m_Job.preProcessRasterData(&cups_raster, &cups_header, hpPreProcessedRasterFile);
605                                 if (err != NO_ERROR) {
606                                         if (m_iLogLevel & BASIC_LOG) {
607                                                 dbglog ("DEBUG: Job::StartPage failed with err = %d\n", err);
608                                         }
609                                         ret_status = JOB_CANCELED;
610                                         break;
611                                 }
612                         }
613
614             if (cups_header.cupsColorSpace == CUPS_CSPACE_RGBW) {
615                 rgbRaster = new BYTE[cups_header.cupsWidth * 3];
616                 if (rgbRaster == NULL) {
617                     return ALLOCMEM_ERROR;
618                 }
619                 kRaster = new BYTE[cups_header.cupsWidth];
620                 if (kRaster == NULL) {
621                     delete [] rgbRaster;
622                     return ALLOCMEM_ERROR;
623                 }
624                 memset (kRaster, 0, cups_header.cupsWidth);
625                 memset (rgbRaster, 0xFF, cups_header.cupsWidth * 3);
626             }
627         } // current_page_number == 1
628
629         if (cups_header.cupsColorSpace == CUPS_CSPACE_K) {
630             kRaster = m_pPrinterBuffer;
631             rgbRaster = NULL;
632         }
633         else if (cups_header.cupsColorSpace != CUPS_CSPACE_RGBW) {
634             rgbRaster = m_pPrinterBuffer;
635             kRaster = NULL;
636         }
637
638         BYTE    *color_raster = NULL;
639         BYTE    *black_raster = NULL;
640
641         err = m_Job.StartPage(&m_JA);
642         if (err != NO_ERROR) {
643             if (m_iLogLevel & BASIC_LOG) {
644                 dbglog ("DEBUG: Job::StartPage failed with err = %d\n", err);
645             }
646             ret_status = JOB_CANCELED;
647             break;
648         }
649
650         if (m_iLogLevel & SAVE_INPUT_RASTERS)
651         {
652             char    szFileName[32];
653             memset(szFileName, 0, sizeof(szFileName));
654             snprintf (szFileName, sizeof(szFileName), "/tmp/hpcupsfilterc_%d.bmp", current_page_number);
655             if (cups_header.cupsColorSpace == CUPS_CSPACE_RGBW ||
656                 cups_header.cupsColorSpace == CUPS_CSPACE_RGB)
657             {
658                 cfp = fopen (szFileName, "w");
659                 chmod (szFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
660             }
661             if (cups_header.cupsColorSpace == CUPS_CSPACE_RGBW ||
662                 cups_header.cupsColorSpace == CUPS_CSPACE_K)
663             {
664                 szFileName[17] = 'k';
665                 kfp = fopen (szFileName, "w");
666                 chmod (szFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
667             }
668
669             WriteBMPHeader (cfp, cups_header.cupsWidth, cups_header.cupsHeight, COLOR_RASTER);
670             WriteBMPHeader (kfp, cups_header.cupsWidth, cups_header.cupsHeight, BLACK_RASTER);
671         }
672
673         fprintf(stderr, "PAGE: %d %s\r\n", current_page_number, m_argv[4]);
674         // Iterating through the raster per page
675         for (int y = 0; y < (int) cups_header.cupsHeight; y++) {
676             cupsRasterReadPixels (cups_raster, m_pPrinterBuffer, cups_header.cupsBytesPerLine);
677             color_raster = rgbRaster;
678             black_raster = kRaster;
679
680             if(y == 0 && (0 == strcmp(m_JA.printer_language, "ljmono")) )
681                         {
682                                 //For ljmono, make sure that first line is not a blankRaster line.Otherwise printer
683                                 //may not skip blank lines before actual data
684                                 //Need to revisit to crosscheck if it is a firmware issue.
685
686                                 *m_pPrinterBuffer = 0x01;
687                                 dbglog("First raster data plane.." );
688                         }
689
690             if (this->isBlankRaster((BYTE *) m_pPrinterBuffer, &cups_header)) {
691
692                 color_raster = NULL;
693                 black_raster = NULL;
694             }
695             extractBlackPixels(&cups_header, black_raster, color_raster);
696             //! Sending Raster bits off to encapsulation
697             err = m_Job.SendRasters (black_raster, color_raster);
698             if (err != NO_ERROR) {
699                 break;
700             }
701             WriteBMPRaster (cfp, color_raster, cups_header.cupsWidth, COLOR_RASTER);
702             WriteBMPRaster (kfp, black_raster, cups_header.cupsWidth/8, BLACK_RASTER);
703         }
704         m_Job.NewPage();
705         if (err != NO_ERROR) {
706             break;
707         }
708     }
709
710     //! Remove the old processing band data...
711     if (cups_header.cupsColorSpace == CUPS_CSPACE_RGBW) {
712         delete [] kRaster;
713         delete [] rgbRaster;
714     }
715
716     unlink(hpPreProcessedRasterFile);
717     return ret_status;
718 }
719
720 void HPCupsFilter::extractBlackPixels(cups_page_header2_t *cups_header, BYTE *kRaster, BYTE *rgbRaster)
721 {
722 /*
723  *  DON'T DO BITPACKING HERE, DO IT IN HALFTONER FOR CMYK PRINTES
724  *  AND IN MODE9 FOR RGB PRINTERS
725  */
726
727 static BYTE pixel_value[8] = {
728             0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
729             };
730
731     if (rgbRaster == NULL) {
732         return;
733     }
734
735     if (cups_header->cupsColorSpace == CUPS_CSPACE_RGBW) {
736         int    k = 0;
737         BYTE   *pIn = m_pPrinterBuffer;
738         BYTE   kVal = 0;
739         BYTE   white=0;
740         BYTE   *rgb = rgbRaster;
741         BYTE   *black   = kRaster;
742         memset (kRaster, 0, cups_header->cupsWidth);
743
744
745         for (unsigned int i = 0; i < cups_header->cupsWidth; i++) {
746             rgb[0] = *pIn++;
747             rgb[1] = *pIn++;
748             rgb[2] = *pIn++;
749             white = *pIn++;
750
751             if(white == 0)
752             {
753                 //If W component is 0 (means black is 1) then no need of having RGB for that pixel.
754                 //ghostscript >= 8.71 sends both W and RGB for black pixel(i.e RGBW=(0,0,0,0)).
755                                 kVal |= pixel_value[k];
756                                 rgb[0] = 0xFF;
757                                 rgb[1] = 0xFF;
758                                 rgb[2] = 0xFF;
759             }
760             else if(white == 0xFF)
761             {
762                 kVal |= 0;
763             }
764             else
765             {
766               int cr,cg,cb;
767               cr = rgb[0] - (int)(255 - white);
768               rgb[0] = cr >= 0 ? cr : 0;
769
770               cg = rgb[1] - (int)(255 - white);
771               rgb[1] = cg >= 0 ? cg : 0;
772
773               cb = rgb[2] - (int)(255 - white);
774               rgb[2] = cb >= 0 ? cb : 0;
775             }
776
777             rgb += 3;
778             if (k == 7) {
779                 *black++ = kVal;
780                 kVal = 0;
781                 k = 0;
782             }
783             else {
784                 k++;
785             }
786         }  // end of for loop
787     *black = kVal;
788
789     } // end of if condition
790 }
791
792 void HPCupsFilter::printCupsHeaderInfo(cups_page_header2_t *header)
793 {
794
795     dbglog ("DEBUG: startPage...\n");
796     dbglog ("DEBUG: MediaClass = \"%s\"\n", header->MediaClass);
797     dbglog ("DEBUG: MediaColor = \"%s\"\n", header->MediaColor);
798     dbglog ("DEBUG: MediaType = \"%s\"\n", header->MediaType);
799     dbglog ("DEBUG: OutputType = \"%s\"\n", header->OutputType);
800     dbglog ("DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance);
801     dbglog ("DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia);
802     dbglog ("DEBUG: Collate = %d\n", header->Collate);
803     dbglog ("DEBUG: CutMedia = %d\n", header->CutMedia);
804     dbglog ("DEBUG: Duplex = %d\n", header->Duplex);
805     dbglog ("DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0], header->HWResolution[1]);
806     dbglog ("DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n",
807                header->ImagingBoundingBox[0], header->ImagingBoundingBox[1],
808                header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
809     dbglog ("DEBUG: InsertSheet = %d\n", header->InsertSheet);
810     dbglog ("DEBUG: Jog = %d\n", header->Jog);
811     dbglog ("DEBUG: LeadingEdge = %d\n", header->LeadingEdge);
812     dbglog ("DEBUG: Margins = [ %d %d ]\n", header->Margins[0], header->Margins[1]);
813     dbglog ("DEBUG: ManualFeed = %d\n", header->ManualFeed);
814     dbglog ("DEBUG: MediaPosition = %d\n", header->MediaPosition);
815     dbglog ("DEBUG: MediaWeight = %d\n", header->MediaWeight);
816     dbglog ("DEBUG: MirrorPrint = %d\n", header->MirrorPrint);
817     dbglog ("DEBUG: NegativePrint = %d\n", header->NegativePrint);
818     dbglog ("DEBUG: NumCopies = %d\n", header->NumCopies);
819     dbglog ("DEBUG: Orientation = %d\n", header->Orientation);
820     dbglog ("DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp);
821     dbglog ("DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0], header->PageSize[1]);
822     dbglog ("DEBUG: Separations = %d\n", header->Separations);
823     dbglog ("DEBUG: TraySwitch = %d\n", header->TraySwitch);
824     dbglog ("DEBUG: Tumble = %d\n", header->Tumble);
825     dbglog ("DEBUG: cupsWidth = %d\n", header->cupsWidth);
826     dbglog ("DEBUG: cupsHeight = %d\n", header->cupsHeight);
827     dbglog ("DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
828     dbglog ("DEBUG: cupsRowStep = %d\n", header->cupsRowStep);
829     dbglog ("DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
830     dbglog ("DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
831     dbglog ("DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
832     dbglog ("DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
833     dbglog ("DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
834     dbglog ("DEBUG: cupsCompression = %d\n", header->cupsCompression);
835     dbglog ("DEBUG: cupsPageSizeName = %s\n", header->cupsPageSizeName);
836     dbglog ("DEBUG: cupsInteger0 = %d\n", header->cupsInteger[0]); // max jpeg filesize
837     dbglog ("DEBUG: cupsInteger1 = %d\n", header->cupsInteger[1]); // Red eye removal
838     dbglog ("DEBUG: cupsInteger2 = %d\n", header->cupsInteger[2]); // Photo fix (RLT)
839     dbglog ("DEBUG: cupsString0 = %s\n", header->cupsString[0]);   // print_mode_name
840     dbglog ("DEBUG: cupsReal0 = %f\n", header->cupsReal[0]); // Left overspray
841     dbglog ("DEBUG: cupsReal1 = %f\n", header->cupsReal[1]); // Top overspray
842 }
843
844 void HPCupsFilter::getLogLevel ()
845 {
846     FILE    *fp;
847     char    str[258];
848     char    *p;
849     fp = fopen ("/etc/cups/cupsd.conf", "r");
850     if (fp == NULL)
851         return;
852     while (!feof (fp))
853     {
854         if (!fgets (str, 256, fp))
855         {
856             break;
857         }
858         if ((p = strstr (str, "hpLogLevel")))
859         {
860             p += strlen ("hpLogLevel") + 1;
861             m_iLogLevel = atoi (p);
862             break;
863         }
864     }
865     fclose (fp);
866 }
867