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