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 fHalftone = NULL; 31 fStream = 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 fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); 45 return true; 46 } 47 catch (TransportException &err) { 48 return false; 49 } 50 } 51 52 bool PCL6Driver::endDoc(bool) 53 { 54 try { 55 if (fHalftone) { 56 delete fHalftone; 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, &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 bool color; 105 int width; 106 int widthByte; 107 int padBytes; 108 int out_row_length; 109 int height; 110 int out_size; 111 int delta; 112 113 color = getJobData()->getColor() == JobData::kColor; 114 115 width = rc.right - rc.left + 1; 116 height = rc.bottom - rc.top + 1; 117 delta = bitmap->BytesPerRow(); 118 119 if (color) { 120 widthByte = 3 * width; 121 } else { 122 widthByte = (width + 7) / 8; /* byte boundary */ 123 } 124 125 out_row_length = 4*((widthByte+3)/4); 126 padBytes = out_row_length - widthByte; /* line length is a multiple of 4 bytes */ 127 out_size = out_row_length * height; 128 129 130 DBGMSG(("width = %d\n", width)); 131 DBGMSG(("widthByte = %d\n", widthByte)); 132 DBGMSG(("height = %d\n", height)); 133 DBGMSG(("out_size = %d\n", out_size)); 134 DBGMSG(("delta = %d\n", delta)); 135 DBGMSG(("renderobj->get_pixel_depth() = %d\n", fHalftone->getPixelDepth())); 136 137 uchar *ptr = (uchar *)bitmap->Bits() 138 + rc.top * delta 139 + (rc.left * fHalftone->getPixelDepth()) / 8; 140 141 int compression_method; 142 int compressed_size; 143 const uchar *buffer; 144 145 uchar *out_buffer = new uchar[out_size]; 146 147 uchar *out_ptr = out_buffer; 148 149 auto_ptr<uchar> _out_buffer(out_buffer); 150 151 DBGMSG(("move\n")); 152 153 move(x, y); 154 startRasterGraphics(x, y, width, height); 155 156 compression_method = 0; // uncompressed 157 buffer = out_buffer; 158 compressed_size = out_size; 159 160 // dither entire band into out_buffer 161 for (int i = rc.top; i <= rc.bottom; i++) { 162 uchar* out = out_ptr; 163 if (color) { 164 uchar* in = ptr; 165 for (int w = width; w > 0; w --) { 166 *out++ = in[2]; 167 *out++ = in[1]; 168 *out++ = in[0]; 169 in += 4; 170 } 171 } else { 172 fHalftone->dither(out_ptr, ptr, x, y, width); 173 // invert pixels 174 for (int w = widthByte; w > 0; w --, out ++) { 175 *out = ~*out; 176 } 177 } 178 // pad with 0s 179 for (int w = padBytes; w > 0; w --, out ++) { 180 *out = 0; 181 } 182 183 ptr += delta; 184 out_ptr += out_row_length; 185 y++; 186 } 187 188 rasterGraphics( 189 compression_method, 190 buffer, 191 compressed_size); 192 193 endRasterGraphics(); 194 195 } else { 196 DBGMSG(("band bitmap is clean.\n")); 197 } 198 199 if (y >= page_height) { 200 offset->x = -1.0; 201 offset->y = -1.0; 202 } else { 203 offset->y += height; 204 } 205 206 DBGMSG(("< nextBand\n")); 207 return true; 208 } 209 catch (TransportException &err) { 210 BAlert *alert = new BAlert("", err.what(), "OK"); 211 alert->Go(); 212 return false; 213 } 214 } 215 216 void PCL6Driver::jobStart() 217 { 218 // PJL header 219 writeSpoolString("\033%%-12345X@PJL JOB\n" 220 "@PJL SET RESOLUTION=%d\n" 221 "@PJL ENTER LANGUAGE=PCLXL\n" 222 ") HP-PCL XL;1;1;" 223 "Comment Copyright (c) 2003 OBOS\n", 224 getJobData()->getXres()); 225 // PCL6 begin 226 fStream = HP_NewStream(16 * 1024, this); 227 HP_BeginSession_2(fStream, getJobData()->getXres(), getJobData()->getYres(), HP_eInch, HP_eBackChAndErrPage); 228 HP_OpenDataSource_1(fStream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst); 229 } 230 231 bool PCL6Driver::startPage(int) 232 { 233 // XXX orientation 234 HP_BeginPage_3(fStream, HP_ePortraitOrientation, mediaSize(getJobData()->getPaper()), HP_eAutoSelect); 235 // PageOrigin from Windows NT printer driver 236 int x = 142 * getJobData()->getXres() / 600; 237 int y = 100 * getJobData()->getYres() / 600; 238 bool color = getJobData()->getColor() == JobData::kColor; 239 HP_SetPageOrigin_1(fStream, x, y); 240 HP_SetColorSpace_1(fStream, color ? HP_eRGB : HP_eGray); 241 HP_SetPaintTxMode_1(fStream, HP_eOpaque); 242 HP_SetSourceTxMode_1(fStream, HP_eOpaque); 243 HP_SetROP_1(fStream, 204); 244 return true; 245 } 246 247 void PCL6Driver::startRasterGraphics(int x, int y, int width, int height) 248 { 249 bool color = getJobData()->getColor() == JobData::kColor; 250 fCompressionMethod = -1; 251 HP_BeginImage_1(fStream, HP_eDirectPixel, color ? HP_e8Bit : HP_e1Bit, width, height, width, height); 252 HP_ReadImage_1(fStream, 0, height, HP_eNoCompression); 253 } 254 255 void PCL6Driver::endRasterGraphics() 256 { 257 HP_EndImage_1(fStream); 258 } 259 260 void PCL6Driver::rasterGraphics( 261 int compression_method, 262 const uchar *buffer, 263 int size) 264 { 265 if (fCompressionMethod != compression_method) { 266 fCompressionMethod = compression_method; 267 } 268 HP_EmbeddedDataPrefix32(fStream, size); 269 HP_RawUByteArray(fStream, (uchar*)buffer, size); 270 } 271 272 bool PCL6Driver::endPage(int) 273 { 274 try { 275 HP_EndPage_2(fStream, getJobData()->getCopies()); 276 return true; 277 } 278 catch (TransportException &err) { 279 return false; 280 } 281 } 282 283 void PCL6Driver::jobEnd() 284 { 285 HP_CloseDataSource_1(fStream); 286 HP_EndSession_1(fStream); 287 HP_FinishStream(fStream); 288 // PJL footer 289 writeSpoolString("\033%%-12345X@PJL EOJ\n" 290 "\033%%-12345X"); 291 } 292 293 void PCL6Driver::move(int x, int y) 294 { 295 HP_SetCursor_1(fStream, x, y); 296 } 297 298 HP_UByte PCL6Driver::mediaSize(JobData::Paper paper) 299 { 300 switch (paper) { 301 case JobData::kLetter: return HP_eLetterPaper; 302 case JobData::kLegal: return HP_eLegalPaper; 303 case JobData::kA4: return HP_eA4Paper; 304 case JobData::kExecutive: return HP_eExecPaper; 305 case JobData::kLedger: return HP_eLedgerPaper; 306 case JobData::kA3: return HP_eA3Paper; 307 /* 308 case : return HP_eCOM10Envelope; 309 case : return HP_eMonarchEnvelope; 310 case : return HP_eC5Envelope; 311 case : return HP_eDLEnvelope; 312 case : return HP_eJB4Paper; 313 case : return HP_eJB5Paper; 314 case : return HP_eB5Envelope; 315 case : return HP_eB5Paper; 316 case : return HP_eJPostcard; 317 case : return HP_eJDoublePostcard; 318 case : return HP_eA5Paper; 319 case : return HP_eA6Paper; 320 case : return HP_eJB6Paper; 321 case : return HP_eJIS8KPaper; 322 case : return HP_eJIS16KPaper; 323 case : return HP_eJISExecPaper; 324 */ 325 default: 326 return HP_eLegalPaper; 327 } 328 } 329 330