13bfe34e2SMichael Pfeiffer /* 23bfe34e2SMichael Pfeiffer * PCL6.cpp 33bfe34e2SMichael Pfeiffer * Copyright 1999-2000 Y.Takagi. All Rights Reserved. 43bfe34e2SMichael Pfeiffer * Copyright 2003 Michael Pfeiffer. 53bfe34e2SMichael Pfeiffer */ 63bfe34e2SMichael Pfeiffer 73bfe34e2SMichael Pfeiffer #include <Alert.h> 83bfe34e2SMichael Pfeiffer #include <Bitmap.h> 93bfe34e2SMichael Pfeiffer #include <File.h> 103bfe34e2SMichael Pfeiffer #include <memory> 113bfe34e2SMichael Pfeiffer #include "PCL6.h" 123bfe34e2SMichael Pfeiffer #include "UIDriver.h" 133bfe34e2SMichael Pfeiffer #include "JobData.h" 143bfe34e2SMichael Pfeiffer #include "PrinterData.h" 153bfe34e2SMichael Pfeiffer #include "PCL6Cap.h" 163bfe34e2SMichael Pfeiffer #include "PackBits.h" 173bfe34e2SMichael Pfeiffer #include "Halftone.h" 183bfe34e2SMichael Pfeiffer #include "ValidRect.h" 193bfe34e2SMichael Pfeiffer #include "DbgMsg.h" 203bfe34e2SMichael Pfeiffer 213bfe34e2SMichael Pfeiffer #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) 223bfe34e2SMichael Pfeiffer using namespace std; 233bfe34e2SMichael Pfeiffer #else 243bfe34e2SMichael Pfeiffer #define std 253bfe34e2SMichael Pfeiffer #endif 263bfe34e2SMichael Pfeiffer 273bfe34e2SMichael Pfeiffer PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) 283bfe34e2SMichael Pfeiffer : GraphicsDriver(msg, printer_data, printer_cap) 293bfe34e2SMichael Pfeiffer { 30d2c03b1bSMichael Pfeiffer fHalftone = NULL; 31d2c03b1bSMichael Pfeiffer fStream = NULL; 323bfe34e2SMichael Pfeiffer } 333bfe34e2SMichael Pfeiffer 343bfe34e2SMichael Pfeiffer void PCL6Driver::FlushOutBuffer(HP_StreamHandleType pStream, unsigned long cookie, HP_pUByte pOutBuffer, HP_SInt32 currentBufferLen) 353bfe34e2SMichael Pfeiffer { 363bfe34e2SMichael Pfeiffer writeSpoolData(pOutBuffer, currentBufferLen); 373bfe34e2SMichael Pfeiffer } 383bfe34e2SMichael Pfeiffer 393bfe34e2SMichael Pfeiffer 403bfe34e2SMichael Pfeiffer bool PCL6Driver::startDoc() 413bfe34e2SMichael Pfeiffer { 423bfe34e2SMichael Pfeiffer try { 433bfe34e2SMichael Pfeiffer jobStart(); 44*3b6882f1SMichael Pfeiffer fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); 453bfe34e2SMichael Pfeiffer return true; 463bfe34e2SMichael Pfeiffer } 473bfe34e2SMichael Pfeiffer catch (TransportException &err) { 483bfe34e2SMichael Pfeiffer return false; 493bfe34e2SMichael Pfeiffer } 503bfe34e2SMichael Pfeiffer } 513bfe34e2SMichael Pfeiffer 523bfe34e2SMichael Pfeiffer bool PCL6Driver::endDoc(bool) 533bfe34e2SMichael Pfeiffer { 543bfe34e2SMichael Pfeiffer try { 55d2c03b1bSMichael Pfeiffer if (fHalftone) { 56d2c03b1bSMichael Pfeiffer delete fHalftone; 573bfe34e2SMichael Pfeiffer } 583bfe34e2SMichael Pfeiffer jobEnd(); 593bfe34e2SMichael Pfeiffer return true; 603bfe34e2SMichael Pfeiffer } 613bfe34e2SMichael Pfeiffer catch (TransportException &err) { 623bfe34e2SMichael Pfeiffer return false; 633bfe34e2SMichael Pfeiffer } 643bfe34e2SMichael Pfeiffer } 653bfe34e2SMichael Pfeiffer 663bfe34e2SMichael Pfeiffer bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset) 673bfe34e2SMichael Pfeiffer { 683bfe34e2SMichael Pfeiffer DBGMSG(("> nextBand\n")); 693bfe34e2SMichael Pfeiffer 703bfe34e2SMichael Pfeiffer try { 713bfe34e2SMichael Pfeiffer BRect bounds = bitmap->Bounds(); 723bfe34e2SMichael Pfeiffer 733bfe34e2SMichael Pfeiffer RECT rc; 743bfe34e2SMichael Pfeiffer rc.left = (int)bounds.left; 753bfe34e2SMichael Pfeiffer rc.top = (int)bounds.top; 763bfe34e2SMichael Pfeiffer rc.right = (int)bounds.right; 773bfe34e2SMichael Pfeiffer rc.bottom = (int)bounds.bottom; 783bfe34e2SMichael Pfeiffer 793bfe34e2SMichael Pfeiffer int height = rc.bottom - rc.top + 1; 803bfe34e2SMichael Pfeiffer 813bfe34e2SMichael Pfeiffer int x = (int)offset->x; 823bfe34e2SMichael Pfeiffer int y = (int)offset->y; 833bfe34e2SMichael Pfeiffer 843bfe34e2SMichael Pfeiffer int page_height = getPageHeight(); 853bfe34e2SMichael Pfeiffer 863bfe34e2SMichael Pfeiffer if (y + height > page_height) { 873bfe34e2SMichael Pfeiffer height = page_height - y; 883bfe34e2SMichael Pfeiffer } 893bfe34e2SMichael Pfeiffer 903bfe34e2SMichael Pfeiffer rc.bottom = height - 1; 913bfe34e2SMichael Pfeiffer 923bfe34e2SMichael Pfeiffer DBGMSG(("height = %d\n", height)); 933bfe34e2SMichael Pfeiffer DBGMSG(("x = %d\n", x)); 943bfe34e2SMichael Pfeiffer DBGMSG(("y = %d\n", y)); 953bfe34e2SMichael Pfeiffer 96d2c03b1bSMichael Pfeiffer if (get_valid_rect(bitmap, &rc)) { 973bfe34e2SMichael Pfeiffer 983bfe34e2SMichael Pfeiffer DBGMSG(("validate rect = %d, %d, %d, %d\n", 993bfe34e2SMichael Pfeiffer rc.left, rc.top, rc.right, rc.bottom)); 1003bfe34e2SMichael Pfeiffer 1013bfe34e2SMichael Pfeiffer x = rc.left; 1023bfe34e2SMichael Pfeiffer y += rc.top; 1033bfe34e2SMichael Pfeiffer 10491c89ca3SMichael Pfeiffer bool color; 10591c89ca3SMichael Pfeiffer int width; 10691c89ca3SMichael Pfeiffer int widthByte; 10791c89ca3SMichael Pfeiffer int padBytes; 10891c89ca3SMichael Pfeiffer int out_row_length; 10991c89ca3SMichael Pfeiffer int height; 11091c89ca3SMichael Pfeiffer int out_size; 11191c89ca3SMichael Pfeiffer int delta; 11291c89ca3SMichael Pfeiffer 113d2c03b1bSMichael Pfeiffer color = getJobData()->getColor() == JobData::kColor; 11491c89ca3SMichael Pfeiffer 11591c89ca3SMichael Pfeiffer width = rc.right - rc.left + 1; 11691c89ca3SMichael Pfeiffer height = rc.bottom - rc.top + 1; 11791c89ca3SMichael Pfeiffer delta = bitmap->BytesPerRow(); 11891c89ca3SMichael Pfeiffer 11991c89ca3SMichael Pfeiffer if (color) { 12091c89ca3SMichael Pfeiffer widthByte = 3 * width; 12191c89ca3SMichael Pfeiffer } else { 12291c89ca3SMichael Pfeiffer widthByte = (width + 7) / 8; /* byte boundary */ 12391c89ca3SMichael Pfeiffer } 12491c89ca3SMichael Pfeiffer 12591c89ca3SMichael Pfeiffer out_row_length = 4*((widthByte+3)/4); 12691c89ca3SMichael Pfeiffer padBytes = out_row_length - widthByte; /* line length is a multiple of 4 bytes */ 12791c89ca3SMichael Pfeiffer out_size = out_row_length * height; 12891c89ca3SMichael Pfeiffer 1293bfe34e2SMichael Pfeiffer 1303bfe34e2SMichael Pfeiffer DBGMSG(("width = %d\n", width)); 1313bfe34e2SMichael Pfeiffer DBGMSG(("widthByte = %d\n", widthByte)); 1323bfe34e2SMichael Pfeiffer DBGMSG(("height = %d\n", height)); 1333bfe34e2SMichael Pfeiffer DBGMSG(("out_size = %d\n", out_size)); 1343bfe34e2SMichael Pfeiffer DBGMSG(("delta = %d\n", delta)); 135d2c03b1bSMichael Pfeiffer DBGMSG(("renderobj->get_pixel_depth() = %d\n", fHalftone->getPixelDepth())); 1363bfe34e2SMichael Pfeiffer 1373bfe34e2SMichael Pfeiffer uchar *ptr = (uchar *)bitmap->Bits() 1383bfe34e2SMichael Pfeiffer + rc.top * delta 139d2c03b1bSMichael Pfeiffer + (rc.left * fHalftone->getPixelDepth()) / 8; 1403bfe34e2SMichael Pfeiffer 1413bfe34e2SMichael Pfeiffer int compression_method; 1423bfe34e2SMichael Pfeiffer int compressed_size; 1433bfe34e2SMichael Pfeiffer const uchar *buffer; 1443bfe34e2SMichael Pfeiffer 1453bfe34e2SMichael Pfeiffer uchar *out_buffer = new uchar[out_size]; 1463bfe34e2SMichael Pfeiffer 1473bfe34e2SMichael Pfeiffer uchar *out_ptr = out_buffer; 1483bfe34e2SMichael Pfeiffer 1493bfe34e2SMichael Pfeiffer auto_ptr<uchar> _out_buffer(out_buffer); 1503bfe34e2SMichael Pfeiffer 1513bfe34e2SMichael Pfeiffer DBGMSG(("move\n")); 1523bfe34e2SMichael Pfeiffer 1533bfe34e2SMichael Pfeiffer move(x, y); 1543bfe34e2SMichael Pfeiffer startRasterGraphics(x, y, width, height); 1553bfe34e2SMichael Pfeiffer 1563bfe34e2SMichael Pfeiffer compression_method = 0; // uncompressed 1573bfe34e2SMichael Pfeiffer buffer = out_buffer; 1583bfe34e2SMichael Pfeiffer compressed_size = out_size; 1593bfe34e2SMichael Pfeiffer 1603bfe34e2SMichael Pfeiffer // dither entire band into out_buffer 1613bfe34e2SMichael Pfeiffer for (int i = rc.top; i <= rc.bottom; i++) { 16291c89ca3SMichael Pfeiffer uchar* out = out_ptr; 16391c89ca3SMichael Pfeiffer if (color) { 16491c89ca3SMichael Pfeiffer uchar* in = ptr; 16591c89ca3SMichael Pfeiffer for (int w = width; w > 0; w --) { 16691c89ca3SMichael Pfeiffer *out++ = in[2]; 16791c89ca3SMichael Pfeiffer *out++ = in[1]; 16891c89ca3SMichael Pfeiffer *out++ = in[0]; 16991c89ca3SMichael Pfeiffer in += 4; 17091c89ca3SMichael Pfeiffer } 17191c89ca3SMichael Pfeiffer } else { 172d2c03b1bSMichael Pfeiffer fHalftone->dither(out_ptr, ptr, x, y, width); 1733bfe34e2SMichael Pfeiffer // invert pixels 1743bfe34e2SMichael Pfeiffer for (int w = widthByte; w > 0; w --, out ++) { 1753bfe34e2SMichael Pfeiffer *out = ~*out; 1763bfe34e2SMichael Pfeiffer } 17791c89ca3SMichael Pfeiffer } 1783bfe34e2SMichael Pfeiffer // pad with 0s 1793bfe34e2SMichael Pfeiffer for (int w = padBytes; w > 0; w --, out ++) { 1803bfe34e2SMichael Pfeiffer *out = 0; 1813bfe34e2SMichael Pfeiffer } 1823bfe34e2SMichael Pfeiffer 1833bfe34e2SMichael Pfeiffer ptr += delta; 1843bfe34e2SMichael Pfeiffer out_ptr += out_row_length; 1853bfe34e2SMichael Pfeiffer y++; 1863bfe34e2SMichael Pfeiffer } 1873bfe34e2SMichael Pfeiffer 1883bfe34e2SMichael Pfeiffer rasterGraphics( 1893bfe34e2SMichael Pfeiffer compression_method, 1903bfe34e2SMichael Pfeiffer buffer, 1913bfe34e2SMichael Pfeiffer compressed_size); 1923bfe34e2SMichael Pfeiffer 1933bfe34e2SMichael Pfeiffer endRasterGraphics(); 1943bfe34e2SMichael Pfeiffer 1953bfe34e2SMichael Pfeiffer } else { 1963bfe34e2SMichael Pfeiffer DBGMSG(("band bitmap is clean.\n")); 1973bfe34e2SMichael Pfeiffer } 1983bfe34e2SMichael Pfeiffer 1993bfe34e2SMichael Pfeiffer if (y >= page_height) { 2003bfe34e2SMichael Pfeiffer offset->x = -1.0; 2013bfe34e2SMichael Pfeiffer offset->y = -1.0; 2023bfe34e2SMichael Pfeiffer } else { 2033bfe34e2SMichael Pfeiffer offset->y += height; 2043bfe34e2SMichael Pfeiffer } 2053bfe34e2SMichael Pfeiffer 2063bfe34e2SMichael Pfeiffer DBGMSG(("< nextBand\n")); 2073bfe34e2SMichael Pfeiffer return true; 2083bfe34e2SMichael Pfeiffer } 2093bfe34e2SMichael Pfeiffer catch (TransportException &err) { 2103bfe34e2SMichael Pfeiffer BAlert *alert = new BAlert("", err.what(), "OK"); 2113bfe34e2SMichael Pfeiffer alert->Go(); 2123bfe34e2SMichael Pfeiffer return false; 2133bfe34e2SMichael Pfeiffer } 2143bfe34e2SMichael Pfeiffer } 2153bfe34e2SMichael Pfeiffer 2163bfe34e2SMichael Pfeiffer void PCL6Driver::jobStart() 2173bfe34e2SMichael Pfeiffer { 2183bfe34e2SMichael Pfeiffer // PJL header 2193bfe34e2SMichael Pfeiffer writeSpoolString("\033%%-12345X@PJL JOB\n" 2208fb205f2SMichael Pfeiffer "@PJL SET RESOLUTION=%d\n" 221a0d17a8cSMichael Pfeiffer "@PJL ENTER LANGUAGE=PCLXL\n" 2223bfe34e2SMichael Pfeiffer ") HP-PCL XL;1;1;" 2238fb205f2SMichael Pfeiffer "Comment Copyright (c) 2003 OBOS\n", 2248fb205f2SMichael Pfeiffer getJobData()->getXres()); 2253bfe34e2SMichael Pfeiffer // PCL6 begin 226d2c03b1bSMichael Pfeiffer fStream = HP_NewStream(16 * 1024, this); 227d2c03b1bSMichael Pfeiffer HP_BeginSession_2(fStream, getJobData()->getXres(), getJobData()->getYres(), HP_eInch, HP_eBackChAndErrPage); 228d2c03b1bSMichael Pfeiffer HP_OpenDataSource_1(fStream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst); 2293bfe34e2SMichael Pfeiffer } 2303bfe34e2SMichael Pfeiffer 2318fb205f2SMichael Pfeiffer bool PCL6Driver::startPage(int) 2328fb205f2SMichael Pfeiffer { 2338fb205f2SMichael Pfeiffer // XXX orientation 234d2c03b1bSMichael Pfeiffer HP_BeginPage_3(fStream, HP_ePortraitOrientation, mediaSize(getJobData()->getPaper()), HP_eAutoSelect); 2358fb205f2SMichael Pfeiffer // PageOrigin from Windows NT printer driver 2368fb205f2SMichael Pfeiffer int x = 142 * getJobData()->getXres() / 600; 2378fb205f2SMichael Pfeiffer int y = 100 * getJobData()->getYres() / 600; 238d2c03b1bSMichael Pfeiffer bool color = getJobData()->getColor() == JobData::kColor; 239d2c03b1bSMichael Pfeiffer HP_SetPageOrigin_1(fStream, x, y); 240d2c03b1bSMichael Pfeiffer HP_SetColorSpace_1(fStream, color ? HP_eRGB : HP_eGray); 241d2c03b1bSMichael Pfeiffer HP_SetPaintTxMode_1(fStream, HP_eOpaque); 242d2c03b1bSMichael Pfeiffer HP_SetSourceTxMode_1(fStream, HP_eOpaque); 243d2c03b1bSMichael Pfeiffer HP_SetROP_1(fStream, 204); 2448fb205f2SMichael Pfeiffer return true; 2458fb205f2SMichael Pfeiffer } 2468fb205f2SMichael Pfeiffer 2473bfe34e2SMichael Pfeiffer void PCL6Driver::startRasterGraphics(int x, int y, int width, int height) 2483bfe34e2SMichael Pfeiffer { 249d2c03b1bSMichael Pfeiffer bool color = getJobData()->getColor() == JobData::kColor; 250d2c03b1bSMichael Pfeiffer fCompressionMethod = -1; 251d2c03b1bSMichael Pfeiffer HP_BeginImage_1(fStream, HP_eDirectPixel, color ? HP_e8Bit : HP_e1Bit, width, height, width, height); 252d2c03b1bSMichael Pfeiffer HP_ReadImage_1(fStream, 0, height, HP_eNoCompression); 2533bfe34e2SMichael Pfeiffer } 2543bfe34e2SMichael Pfeiffer 2553bfe34e2SMichael Pfeiffer void PCL6Driver::endRasterGraphics() 2563bfe34e2SMichael Pfeiffer { 257d2c03b1bSMichael Pfeiffer HP_EndImage_1(fStream); 2583bfe34e2SMichael Pfeiffer } 2593bfe34e2SMichael Pfeiffer 2603bfe34e2SMichael Pfeiffer void PCL6Driver::rasterGraphics( 2613bfe34e2SMichael Pfeiffer int compression_method, 2623bfe34e2SMichael Pfeiffer const uchar *buffer, 2633bfe34e2SMichael Pfeiffer int size) 2643bfe34e2SMichael Pfeiffer { 265d2c03b1bSMichael Pfeiffer if (fCompressionMethod != compression_method) { 266d2c03b1bSMichael Pfeiffer fCompressionMethod = compression_method; 2673bfe34e2SMichael Pfeiffer } 268d2c03b1bSMichael Pfeiffer HP_EmbeddedDataPrefix32(fStream, size); 269d2c03b1bSMichael Pfeiffer HP_RawUByteArray(fStream, (uchar*)buffer, size); 2703bfe34e2SMichael Pfeiffer } 2713bfe34e2SMichael Pfeiffer 2728fb205f2SMichael Pfeiffer bool PCL6Driver::endPage(int) 2738fb205f2SMichael Pfeiffer { 2748fb205f2SMichael Pfeiffer try { 275d2c03b1bSMichael Pfeiffer HP_EndPage_2(fStream, getJobData()->getCopies()); 2768fb205f2SMichael Pfeiffer return true; 2778fb205f2SMichael Pfeiffer } 2788fb205f2SMichael Pfeiffer catch (TransportException &err) { 2798fb205f2SMichael Pfeiffer return false; 2808fb205f2SMichael Pfeiffer } 2818fb205f2SMichael Pfeiffer } 2828fb205f2SMichael Pfeiffer 2833bfe34e2SMichael Pfeiffer void PCL6Driver::jobEnd() 2843bfe34e2SMichael Pfeiffer { 285d2c03b1bSMichael Pfeiffer HP_CloseDataSource_1(fStream); 286d2c03b1bSMichael Pfeiffer HP_EndSession_1(fStream); 287d2c03b1bSMichael Pfeiffer HP_FinishStream(fStream); 2883bfe34e2SMichael Pfeiffer // PJL footer 2893bfe34e2SMichael Pfeiffer writeSpoolString("\033%%-12345X@PJL EOJ\n" 2903bfe34e2SMichael Pfeiffer "\033%%-12345X"); 2913bfe34e2SMichael Pfeiffer } 2923bfe34e2SMichael Pfeiffer 2933bfe34e2SMichael Pfeiffer void PCL6Driver::move(int x, int y) 2943bfe34e2SMichael Pfeiffer { 295d2c03b1bSMichael Pfeiffer HP_SetCursor_1(fStream, x, y); 2963bfe34e2SMichael Pfeiffer } 2973bfe34e2SMichael Pfeiffer 298d2c03b1bSMichael Pfeiffer HP_UByte PCL6Driver::mediaSize(JobData::Paper paper) 2993bfe34e2SMichael Pfeiffer { 3003bfe34e2SMichael Pfeiffer switch (paper) { 301d2c03b1bSMichael Pfeiffer case JobData::kLetter: return HP_eLetterPaper; 302d2c03b1bSMichael Pfeiffer case JobData::kLegal: return HP_eLegalPaper; 303d2c03b1bSMichael Pfeiffer case JobData::kA4: return HP_eA4Paper; 304d2c03b1bSMichael Pfeiffer case JobData::kExecutive: return HP_eExecPaper; 305d2c03b1bSMichael Pfeiffer case JobData::kLedger: return HP_eLedgerPaper; 306d2c03b1bSMichael Pfeiffer case JobData::kA3: return HP_eA3Paper; 3073bfe34e2SMichael Pfeiffer /* 3083bfe34e2SMichael Pfeiffer case : return HP_eCOM10Envelope; 3093bfe34e2SMichael Pfeiffer case : return HP_eMonarchEnvelope; 3103bfe34e2SMichael Pfeiffer case : return HP_eC5Envelope; 3113bfe34e2SMichael Pfeiffer case : return HP_eDLEnvelope; 3123bfe34e2SMichael Pfeiffer case : return HP_eJB4Paper; 3133bfe34e2SMichael Pfeiffer case : return HP_eJB5Paper; 3143bfe34e2SMichael Pfeiffer case : return HP_eB5Envelope; 3153bfe34e2SMichael Pfeiffer case : return HP_eB5Paper; 3163bfe34e2SMichael Pfeiffer case : return HP_eJPostcard; 3173bfe34e2SMichael Pfeiffer case : return HP_eJDoublePostcard; 3183bfe34e2SMichael Pfeiffer case : return HP_eA5Paper; 3193bfe34e2SMichael Pfeiffer case : return HP_eA6Paper; 3203bfe34e2SMichael Pfeiffer case : return HP_eJB6Paper; 3213bfe34e2SMichael Pfeiffer case : return HP_eJIS8KPaper; 3223bfe34e2SMichael Pfeiffer case : return HP_eJIS16KPaper; 3233bfe34e2SMichael Pfeiffer case : return HP_eJISExecPaper; 3243bfe34e2SMichael Pfeiffer */ 325d2c03b1bSMichael Pfeiffer default: 326d2c03b1bSMichael Pfeiffer return HP_eLegalPaper; 3273bfe34e2SMichael Pfeiffer } 3283bfe34e2SMichael Pfeiffer } 3293bfe34e2SMichael Pfeiffer 330