1 /* 2 * PCL6.cpp 3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved. 4 * Copyright 2003 Michael Pfeiffer. 5 */ 6 7 #include <Alert.h> 8 #include <Bitmap.h> 9 #include <File.h> 10 #include <memory> 11 #include "PCL6.h" 12 #include "UIDriver.h" 13 #include "JobData.h" 14 #include "PrinterData.h" 15 #include "PCL6Cap.h" 16 #include "PackBits.h" 17 #include "Halftone.h" 18 #include "ValidRect.h" 19 #include "DbgMsg.h" 20 21 #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) 22 using namespace std; 23 #else 24 #define std 25 #endif 26 27 PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) 28 : GraphicsDriver(msg, printer_data, printer_cap) 29 { 30 __halftone = NULL; 31 __stream = NULL; 32 } 33 34 void PCL6Driver::FlushOutBuffer(HP_StreamHandleType pStream, unsigned long cookie, HP_pUByte pOutBuffer, HP_SInt32 currentBufferLen) 35 { 36 writeSpoolData(pOutBuffer, currentBufferLen); 37 } 38 39 40 bool PCL6Driver::startDoc() 41 { 42 try { 43 jobStart(); 44 __halftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma()); 45 return true; 46 } 47 catch (TransportException &err) { 48 return false; 49 } 50 } 51 52 bool PCL6Driver::endDoc(bool) 53 { 54 try { 55 if (__halftone) { 56 delete __halftone; 57 } 58 jobEnd(); 59 return true; 60 } 61 catch (TransportException &err) { 62 return false; 63 } 64 } 65 66 bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset) 67 { 68 DBGMSG(("> nextBand\n")); 69 70 try { 71 BRect bounds = bitmap->Bounds(); 72 73 RECT rc; 74 rc.left = (int)bounds.left; 75 rc.top = (int)bounds.top; 76 rc.right = (int)bounds.right; 77 rc.bottom = (int)bounds.bottom; 78 79 int height = rc.bottom - rc.top + 1; 80 81 int x = (int)offset->x; 82 int y = (int)offset->y; 83 84 int page_height = getPageHeight(); 85 86 if (y + height > page_height) { 87 height = page_height - y; 88 } 89 90 rc.bottom = height - 1; 91 92 DBGMSG(("height = %d\n", height)); 93 DBGMSG(("x = %d\n", x)); 94 DBGMSG(("y = %d\n", y)); 95 96 if (get_valid_rect(bitmap, __halftone->getPalette(), &rc)) { 97 98 DBGMSG(("validate rect = %d, %d, %d, %d\n", 99 rc.left, rc.top, rc.right, rc.bottom)); 100 101 x = rc.left; 102 y += rc.top; 103 104 int width = rc.right - rc.left + 1; 105 int widthByte = (width + 7) / 8; /* byte boundary */ 106 int padBytes = ((width + 31) / 32) * 4 - widthByte; /* line length is a multiple of 4 bytes */ 107 int out_row_length = widthByte + padBytes; 108 int height = rc.bottom - rc.top + 1; 109 int out_size = out_row_length * height; 110 int delta = bitmap->BytesPerRow(); 111 112 DBGMSG(("width = %d\n", width)); 113 DBGMSG(("widthByte = %d\n", widthByte)); 114 DBGMSG(("height = %d\n", height)); 115 DBGMSG(("out_size = %d\n", out_size)); 116 DBGMSG(("delta = %d\n", delta)); 117 DBGMSG(("renderobj->get_pixel_depth() = %d\n", __halftone->getPixelDepth())); 118 119 uchar *ptr = (uchar *)bitmap->Bits() 120 + rc.top * delta 121 + (rc.left * __halftone->getPixelDepth()) / 8; 122 123 int compression_method; 124 int compressed_size; 125 const uchar *buffer; 126 127 uchar *out_buffer = new uchar[out_size]; 128 129 uchar *out_ptr = out_buffer; 130 131 auto_ptr<uchar> _out_buffer(out_buffer); 132 133 DBGMSG(("move\n")); 134 135 move(x, y); 136 startRasterGraphics(x, y, width, height); 137 138 compression_method = 0; // uncompressed 139 buffer = out_buffer; 140 compressed_size = out_size; 141 142 // dither entire band into out_buffer 143 for (int i = rc.top; i <= rc.bottom; i++) { 144 __halftone->dither(out_ptr, ptr, x, y, width); 145 // invert pixels 146 uchar* out = out_ptr; 147 for (int w = widthByte; w > 0; w --, out ++) { 148 *out = ~*out; 149 } 150 // pad with 0s 151 for (int w = padBytes; w > 0; w --, out ++) { 152 *out = 0; 153 } 154 155 ptr += delta; 156 out_ptr += out_row_length; 157 y++; 158 } 159 160 rasterGraphics( 161 compression_method, 162 buffer, 163 compressed_size); 164 165 endRasterGraphics(); 166 167 } else { 168 DBGMSG(("band bitmap is clean.\n")); 169 } 170 171 if (y >= page_height) { 172 offset->x = -1.0; 173 offset->y = -1.0; 174 } else { 175 offset->y += height; 176 } 177 178 DBGMSG(("< nextBand\n")); 179 return true; 180 } 181 catch (TransportException &err) { 182 BAlert *alert = new BAlert("", err.what(), "OK"); 183 alert->Go(); 184 return false; 185 } 186 } 187 188 void PCL6Driver::jobStart() 189 { 190 // PJL header 191 writeSpoolString("\033%%-12345X@PJL JOB\n" 192 "@PJL SET RESOLUTION=%d\n" 193 "@PJL ENTER LANGUAGE=PCLXL\n" 194 ") HP-PCL XL;1;1;" 195 "Comment Copyright (c) 2003 OBOS\n", 196 getJobData()->getXres()); 197 // PCL6 begin 198 __stream = HP_NewStream(16 * 1024, this); 199 HP_BeginSession_2(__stream, getJobData()->getXres(), getJobData()->getYres(), HP_eInch, HP_eBackChAndErrPage); 200 HP_OpenDataSource_1(__stream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst); 201 } 202 203 bool PCL6Driver::startPage(int) 204 { 205 // XXX orientation 206 HP_BeginPage_3(__stream, HP_ePortraitOrientation, mediaSize(getJobData()->getPaper()), HP_eAutoSelect); 207 // PageOrigin from Windows NT printer driver 208 int x = 142 * getJobData()->getXres() / 600; 209 int y = 100 * getJobData()->getYres() / 600; 210 HP_SetPageOrigin_1(__stream, x, y); 211 HP_SetColorSpace_1(__stream, HP_eGray); 212 HP_SetPaintTxMode_1(__stream, HP_eOpaque); 213 HP_SetSourceTxMode_1(__stream, HP_eOpaque); 214 HP_SetROP_1(__stream, 204); 215 return true; 216 } 217 218 void PCL6Driver::startRasterGraphics(int x, int y, int width, int height) 219 { 220 __compression_method = -1; 221 HP_BeginImage_1(__stream, HP_eDirectPixel, HP_e1Bit, width, height, width, height); 222 HP_ReadImage_1(__stream, 0, height, HP_eNoCompression); 223 } 224 225 void PCL6Driver::endRasterGraphics() 226 { 227 HP_EndImage_1(__stream); 228 } 229 230 void PCL6Driver::rasterGraphics( 231 int compression_method, 232 const uchar *buffer, 233 int size) 234 { 235 if (__compression_method != compression_method) { 236 __compression_method = compression_method; 237 } 238 HP_EmbeddedDataPrefix32(__stream, size); 239 HP_RawUByteArray(__stream, (uchar*)buffer, size); 240 } 241 242 bool PCL6Driver::endPage(int) 243 { 244 try { 245 HP_EndPage_2(__stream, getJobData()->getCopies()); 246 return true; 247 } 248 catch (TransportException &err) { 249 return false; 250 } 251 } 252 253 void PCL6Driver::jobEnd() 254 { 255 HP_CloseDataSource_1(__stream); 256 HP_EndSession_1(__stream); 257 HP_FinishStream(__stream); 258 // PJL footer 259 writeSpoolString("\033%%-12345X@PJL EOJ\n" 260 "\033%%-12345X"); 261 } 262 263 void PCL6Driver::move(int x, int y) 264 { 265 HP_SetCursor_1(__stream, x, y); 266 } 267 268 HP_UByte PCL6Driver::mediaSize(JobData::PAPER paper) 269 { 270 switch (paper) { 271 case JobData::LETTER: return HP_eLetterPaper; 272 case JobData::LEGAL: return HP_eLegalPaper; 273 case JobData::A4: return HP_eA4Paper; 274 case JobData::EXECUTIVE: return HP_eExecPaper; 275 case JobData::LEDGER: return HP_eLedgerPaper; 276 case JobData::A3: return HP_eA3Paper; 277 /* 278 case : return HP_eCOM10Envelope; 279 case : return HP_eMonarchEnvelope; 280 case : return HP_eC5Envelope; 281 case : return HP_eDLEnvelope; 282 case : return HP_eJB4Paper; 283 case : return HP_eJB5Paper; 284 case : return HP_eB5Envelope; 285 case : return HP_eB5Paper; 286 case : return HP_eJPostcard; 287 case : return HP_eJDoublePostcard; 288 case : return HP_eA5Paper; 289 case : return HP_eA6Paper; 290 case : return HP_eJB6Paper; 291 case : return HP_eJIS8KPaper; 292 case : return HP_eJIS16KPaper; 293 case : return HP_eJISExecPaper; 294 */ 295 default: HP_eLegalPaper; 296 } 297 } 298 299