1 /* 2 * Lips4.cpp 3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved. 4 */ 5 6 #include <Alert.h> 7 #include <Bitmap.h> 8 #include <File.h> 9 #include <memory> 10 #include "Lips4.h" 11 #include "PackBits.h" 12 #include "JobData.h" 13 #include "PrinterData.h" 14 #include "Lips4Cap.h" 15 #include "Halftone.h" 16 #include "ValidRect.h" 17 #include "DbgMsg.h" 18 19 #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) 20 using namespace std; 21 #else 22 #define std 23 #endif 24 25 LIPS4Driver::LIPS4Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) 26 : GraphicsDriver(msg, printer_data, printer_cap) 27 { 28 fHalftone = NULL; 29 } 30 31 bool LIPS4Driver::startDoc() 32 { 33 try { 34 beginTextMode(); 35 jobStart(); 36 colorModeDeclaration(); 37 softReset(); 38 sizeUnitMode(); 39 selectSizeUnit(); 40 paperFeedMode(); 41 selectPageFormat(); 42 disableAutoFF(); 43 setNumberOfCopies(); 44 sidePrintingControl(); 45 setBindingMargin(); 46 fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); 47 return true; 48 } 49 catch (TransportException &err) { 50 return false; 51 } 52 } 53 54 bool LIPS4Driver::startPage(int) 55 { 56 try { 57 fCurrentX = 0; 58 fCurrentY = 0; 59 memorizedPosition(); 60 return true; 61 } 62 catch (TransportException &err) { 63 return false; 64 } 65 } 66 67 bool LIPS4Driver::endPage(int) 68 { 69 try { 70 formFeed(); 71 return true; 72 } 73 catch (TransportException &err) { 74 return false; 75 } 76 } 77 78 bool LIPS4Driver::endDoc(bool) 79 { 80 try { 81 if (fHalftone) { 82 delete fHalftone; 83 } 84 jobEnd(); 85 return true; 86 } 87 catch (TransportException &err) { 88 return false; 89 } 90 } 91 92 bool LIPS4Driver::nextBand(BBitmap *bitmap, BPoint *offset) 93 { 94 DBGMSG(("> nextBand\n")); 95 96 try { 97 98 if (bitmap == NULL) { 99 uchar dummy[1]; 100 dummy[0] = '\0'; 101 rasterGraphics(1, 1, 1, 0, dummy); 102 DBGMSG(("< next_band\n")); 103 return true; 104 } 105 106 BRect bounds = bitmap->Bounds(); 107 108 RECT rc; 109 rc.left = (int)bounds.left; 110 rc.top = (int)bounds.top; 111 rc.right = (int)bounds.right; 112 rc.bottom = (int)bounds.bottom; 113 114 int height = rc.bottom - rc.top + 1; 115 116 int x = (int)offset->x; 117 int y = (int)offset->y; 118 119 int page_height = getPageHeight(); 120 121 if (y + height > page_height) { 122 height = page_height - y; 123 } 124 125 rc.bottom = height - 1; 126 127 DBGMSG(("height = %d\n", height)); 128 DBGMSG(("x = %d\n", x)); 129 DBGMSG(("y = %d\n", y)); 130 131 if (get_valid_rect(bitmap, &rc)) { 132 133 DBGMSG(("validate rect = %d, %d, %d, %d\n", 134 rc.left, rc.top, rc.right, rc.bottom)); 135 136 x = rc.left; 137 y += rc.top; 138 139 int width = rc.right - rc.left + 1; 140 int widthByte = (width + 7) / 8; 141 int height = rc.bottom - rc.top + 1; 142 int in_size = widthByte * height; 143 int out_size = (in_size * 6 + 4) / 5; 144 int delta = bitmap->BytesPerRow(); 145 146 DBGMSG(("width = %d\n", width)); 147 DBGMSG(("widthByte = %d\n", widthByte)); 148 DBGMSG(("height = %d\n", height)); 149 DBGMSG(("in_size = %d\n", in_size)); 150 DBGMSG(("out_size = %d\n", out_size)); 151 DBGMSG(("delta = %d\n", delta)); 152 DBGMSG(("fHalftone_engine->get_pixel_depth() = %d\n", fHalftone->getPixelDepth())); 153 154 uchar *ptr = (uchar *)bitmap->Bits() 155 + rc.top * delta 156 + (rc.left * fHalftone->getPixelDepth()) / 8; 157 158 int compression_method; 159 int compressed_size; 160 const uchar *buffer; 161 162 uchar *in_buffer = new uchar[in_size]; 163 uchar *out_buffer = new uchar[out_size]; 164 165 auto_ptr<uchar> _in_buffer (in_buffer); 166 auto_ptr<uchar> _out_buffer(out_buffer); 167 168 uchar *ptr2 = (uchar *)in_buffer; 169 170 DBGMSG(("move\n")); 171 172 move(x, y); 173 174 for (int i = rc.top; i <= rc.bottom; i++) { 175 fHalftone->dither(ptr2, ptr, x, y, width); 176 ptr += delta; 177 ptr2 += widthByte; 178 y++; 179 } 180 181 DBGMSG(("PackBits\n")); 182 183 compressed_size = pack_bits(out_buffer, in_buffer, in_size); 184 185 if (compressed_size < in_size) { 186 compression_method = 11; 187 buffer = out_buffer; 188 } else if (compressed_size > out_size) { 189 BAlert *alert = new BAlert("memory overrun!!!", "warning", "OK"); 190 alert->Go(); 191 return false; 192 } else { 193 compression_method = 0; 194 buffer = in_buffer; 195 compressed_size = in_size; 196 } 197 198 DBGMSG(("compressed_size = %d\n", compressed_size)); 199 DBGMSG(("widthByte = %d\n", widthByte)); 200 DBGMSG(("height = %d\n", height)); 201 DBGMSG(("compression_method = %d\n", compression_method)); 202 203 rasterGraphics( 204 compressed_size, // size, 205 widthByte, // widthByte 206 height, // height, 207 compression_method, 208 buffer); 209 210 } else { 211 DBGMSG(("band bitmap is clean.\n")); 212 } 213 214 if (y >= page_height) { 215 offset->x = -1.0; 216 offset->y = -1.0; 217 } else { 218 offset->y += height; 219 } 220 221 DBGMSG(("< nextBand\n")); 222 return true; 223 } 224 catch (TransportException &err) { 225 BAlert *alert = new BAlert("", err.what(), "OK"); 226 alert->Go(); 227 return false; 228 } 229 } 230 231 void LIPS4Driver::beginTextMode() 232 { 233 writeSpoolString("\033%%@"); 234 } 235 236 void LIPS4Driver::jobStart() 237 { 238 writeSpoolString("\033P41;%d;1J\033\\", getJobData()->getXres()); 239 } 240 241 void LIPS4Driver::colorModeDeclaration() 242 { 243 // if (color) 244 // writeSpoolString("\033[1\"p"); 245 // else 246 writeSpoolString("\033[0\"p"); 247 } 248 249 void LIPS4Driver::softReset() 250 { 251 writeSpoolString("\033<"); 252 } 253 254 void LIPS4Driver::sizeUnitMode() 255 { 256 writeSpoolString("\033[11h"); 257 } 258 259 void LIPS4Driver::selectSizeUnit() 260 { 261 writeSpoolString("\033[?7;%d I", getJobData()->getXres()); 262 } 263 264 void LIPS4Driver::paperFeedMode() 265 { 266 // 0 auto 267 // -------------- 268 // 1 MP tray 269 // 2 lower 270 // 3 lupper 271 // -------------- 272 // 10 MP tray 273 // 11 casette 1 274 // 12 casette 2 275 // 13 casette 3 276 // 14 casette 4 277 // 15 casette 5 278 // 16 casette 6 279 // 17 casette 7 280 281 int i; 282 283 switch (getJobData()->getPaperSource()) { 284 case JobData::kManual: 285 i = 10; 286 break; 287 case JobData::kUpper: 288 i = 11; 289 break; 290 case JobData::kMiddle: 291 i = 12; 292 break; 293 case JobData::kLower: 294 i = 13; 295 break; 296 case JobData::kAuto: 297 default: 298 i = 0; 299 break; 300 } 301 302 writeSpoolString("\033[%dq", i); 303 } 304 305 void LIPS4Driver::selectPageFormat() 306 { 307 int i; 308 309 switch (getJobData()->getPaper()) { 310 case JobData::kA3: 311 i = 12; 312 break; 313 314 case JobData::kA4: 315 i = 14; 316 break; 317 318 case JobData::kA5: 319 i = 16; 320 break; 321 322 case JobData::kJapanesePostcard: 323 i = 18; 324 break; 325 326 case JobData::kB4: 327 i = 24; 328 break; 329 330 case JobData::kB5: 331 i = 26; 332 break; 333 334 case JobData::kLetter: 335 i = 30; 336 break; 337 338 case JobData::kLegal: 339 i = 32; 340 break; 341 342 case JobData::kExecutive: 343 i = 40; 344 break; 345 346 case JobData::kJEnvYou4: 347 i = 50; 348 break; 349 350 case JobData::kUser: 351 i = 90; 352 break; 353 354 default: 355 i = 0; 356 break; 357 } 358 359 if (JobData::kLandscape == getJobData()->getOrientation()) 360 i++; 361 362 writeSpoolString("\033[%d;;p", i); 363 } 364 365 void LIPS4Driver::disableAutoFF() 366 { 367 writeSpoolString("\033[?2h"); 368 } 369 370 void LIPS4Driver::setNumberOfCopies() 371 { 372 writeSpoolString("\033[%ldv", getJobData()->getCopies()); 373 } 374 375 void LIPS4Driver::sidePrintingControl() 376 { 377 if (getJobData()->getPrintStyle() == JobData::kSimplex) 378 writeSpoolString("\033[0#x"); 379 else 380 writeSpoolString("\033[2;0#x"); 381 } 382 383 void LIPS4Driver::setBindingMargin() 384 { 385 if (getJobData()->getPrintStyle() == JobData::kDuplex) { 386 int i; 387 // switch (job_data()->binding_location()) { 388 // case kLongEdgeLeft: 389 i = 0; 390 // break; 391 // case kLongEdgeRight: 392 // i = 1; 393 // break; 394 // case kShortEdgeTop: 395 // i = 2; 396 // break; 397 // case kShortEdgeBottom: 398 // i = 3; 399 // break; 400 // } 401 writeSpoolString("\033[%d;0#w", i); 402 } 403 } 404 405 void LIPS4Driver::memorizedPosition() 406 { 407 writeSpoolString("\033[0;1;0x"); 408 } 409 410 void LIPS4Driver::moveAbsoluteHorizontal(int x) 411 { 412 writeSpoolString("\033[%ld`", x); 413 } 414 415 void LIPS4Driver::carriageReturn() 416 { 417 writeSpoolChar('\x0d'); 418 } 419 420 void LIPS4Driver::moveDown(int dy) 421 { 422 writeSpoolString("\033[%lde", dy); 423 } 424 425 void LIPS4Driver::rasterGraphics( 426 int compression_size, 427 int widthbyte, 428 int height, 429 int compression_method, 430 const uchar *buffer) 431 { 432 // 0 RAW 433 // 10 RLE 434 // 11 packbits 435 436 writeSpoolString( 437 "\033[%ld;%ld;%d;%ld;%ld.r", 438 compression_size, 439 widthbyte, 440 getJobData()->getXres(), 441 compression_method, 442 height); 443 444 writeSpoolData(buffer, compression_size); 445 } 446 447 void LIPS4Driver::formFeed() 448 { 449 writeSpoolChar('\014'); 450 } 451 452 void LIPS4Driver::jobEnd() 453 { 454 writeSpoolString("\033P0J\033\\"); 455 } 456 457 void LIPS4Driver::move(int x, int y) 458 { 459 if (fCurrentX != x) { 460 if (x) { 461 moveAbsoluteHorizontal(x); 462 } else { 463 carriageReturn(); 464 } 465 fCurrentX = x; 466 } 467 if (fCurrentY != y) { 468 int dy = y - fCurrentY; 469 moveDown(dy); 470 fCurrentY = y; 471 } 472 } 473