/* * Lips4.cpp * Copyright 1999-2000 Y.Takagi. All Rights Reserved. */ #include #include #include #include #include "Lips4.h" #include "PackBits.h" #include "JobData.h" #include "PrinterData.h" #include "Lips4Cap.h" #include "Halftone.h" #include "ValidRect.h" #include "DbgMsg.h" #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) using namespace std; #else #define std #endif LIPS4Driver::LIPS4Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) : GraphicsDriver(msg, printer_data, printer_cap) { fHalftone = NULL; } bool LIPS4Driver::startDoc() { try { beginTextMode(); jobStart(); colorModeDeclaration(); softReset(); sizeUnitMode(); selectSizeUnit(); paperFeedMode(); selectPageFormat(); disableAutoFF(); setNumberOfCopies(); sidePrintingControl(); setBindingMargin(); fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); return true; } catch (TransportException &err) { return false; } } bool LIPS4Driver::startPage(int) { try { fCurrentX = 0; fCurrentY = 0; memorizedPosition(); return true; } catch (TransportException &err) { return false; } } bool LIPS4Driver::endPage(int) { try { formFeed(); return true; } catch (TransportException &err) { return false; } } bool LIPS4Driver::endDoc(bool) { try { if (fHalftone) { delete fHalftone; } jobEnd(); return true; } catch (TransportException &err) { return false; } } bool LIPS4Driver::nextBand(BBitmap *bitmap, BPoint *offset) { DBGMSG(("> nextBand\n")); try { if (bitmap == NULL) { uchar dummy[1]; dummy[0] = '\0'; rasterGraphics(1, 1, 1, 0, dummy); DBGMSG(("< next_band\n")); return true; } BRect bounds = bitmap->Bounds(); RECT rc; rc.left = (int)bounds.left; rc.top = (int)bounds.top; rc.right = (int)bounds.right; rc.bottom = (int)bounds.bottom; int height = rc.bottom - rc.top + 1; int x = (int)offset->x; int y = (int)offset->y; int page_height = getPageHeight(); if (y + height > page_height) { height = page_height - y; } rc.bottom = height - 1; DBGMSG(("height = %d\n", height)); DBGMSG(("x = %d\n", x)); DBGMSG(("y = %d\n", y)); if (get_valid_rect(bitmap, &rc)) { DBGMSG(("validate rect = %d, %d, %d, %d\n", rc.left, rc.top, rc.right, rc.bottom)); x = rc.left; y += rc.top; int width = rc.right - rc.left + 1; int widthByte = (width + 7) / 8; int height = rc.bottom - rc.top + 1; int in_size = widthByte * height; int out_size = (in_size * 6 + 4) / 5; int delta = bitmap->BytesPerRow(); DBGMSG(("width = %d\n", width)); DBGMSG(("widthByte = %d\n", widthByte)); DBGMSG(("height = %d\n", height)); DBGMSG(("in_size = %d\n", in_size)); DBGMSG(("out_size = %d\n", out_size)); DBGMSG(("delta = %d\n", delta)); DBGMSG(("fHalftone_engine->get_pixel_depth() = %d\n", fHalftone->getPixelDepth())); uchar *ptr = (uchar *)bitmap->Bits() + rc.top * delta + (rc.left * fHalftone->getPixelDepth()) / 8; int compression_method; int compressed_size; const uchar *buffer; uchar *in_buffer = new uchar[in_size]; uchar *out_buffer = new uchar[out_size]; auto_ptr _in_buffer (in_buffer); auto_ptr _out_buffer(out_buffer); uchar *ptr2 = (uchar *)in_buffer; DBGMSG(("move\n")); move(x, y); for (int i = rc.top; i <= rc.bottom; i++) { fHalftone->dither(ptr2, ptr, x, y, width); ptr += delta; ptr2 += widthByte; y++; } DBGMSG(("PackBits\n")); compressed_size = pack_bits(out_buffer, in_buffer, in_size); if (compressed_size < in_size) { compression_method = 11; buffer = out_buffer; } else if (compressed_size > out_size) { BAlert *alert = new BAlert("memory overrun!!!", "warning", "OK"); alert->Go(); return false; } else { compression_method = 0; buffer = in_buffer; compressed_size = in_size; } DBGMSG(("compressed_size = %d\n", compressed_size)); DBGMSG(("widthByte = %d\n", widthByte)); DBGMSG(("height = %d\n", height)); DBGMSG(("compression_method = %d\n", compression_method)); rasterGraphics( compressed_size, // size, widthByte, // widthByte height, // height, compression_method, buffer); } else { DBGMSG(("band bitmap is clean.\n")); } if (y >= page_height) { offset->x = -1.0; offset->y = -1.0; } else { offset->y += height; } DBGMSG(("< nextBand\n")); return true; } catch (TransportException &err) { BAlert *alert = new BAlert("", err.what(), "OK"); alert->Go(); return false; } } void LIPS4Driver::beginTextMode() { writeSpoolString("\033%%@"); } void LIPS4Driver::jobStart() { writeSpoolString("\033P41;%d;1J\033\\", getJobData()->getXres()); } void LIPS4Driver::colorModeDeclaration() { // if (color) // writeSpoolString("\033[1\"p"); // else writeSpoolString("\033[0\"p"); } void LIPS4Driver::softReset() { writeSpoolString("\033<"); } void LIPS4Driver::sizeUnitMode() { writeSpoolString("\033[11h"); } void LIPS4Driver::selectSizeUnit() { writeSpoolString("\033[?7;%d I", getJobData()->getXres()); } void LIPS4Driver::paperFeedMode() { // 0 auto // -------------- // 1 MP tray // 2 lower // 3 lupper // -------------- // 10 MP tray // 11 casette 1 // 12 casette 2 // 13 casette 3 // 14 casette 4 // 15 casette 5 // 16 casette 6 // 17 casette 7 int i; switch (getJobData()->getPaperSource()) { case JobData::kManual: i = 10; break; case JobData::kUpper: i = 11; break; case JobData::kMiddle: i = 12; break; case JobData::kLower: i = 13; break; case JobData::kAuto: default: i = 0; break; } writeSpoolString("\033[%dq", i); } void LIPS4Driver::selectPageFormat() { int i; switch (getJobData()->getPaper()) { case JobData::kA3: i = 12; break; case JobData::kA4: i = 14; break; case JobData::kA5: i = 16; break; case JobData::kJapanesePostcard: i = 18; break; case JobData::kB4: i = 24; break; case JobData::kB5: i = 26; break; case JobData::kLetter: i = 30; break; case JobData::kLegal: i = 32; break; case JobData::kExecutive: i = 40; break; case JobData::kJEnvYou4: i = 50; break; case JobData::kUser: i = 90; break; default: i = 0; break; } if (JobData::kLandscape == getJobData()->getOrientation()) i++; writeSpoolString("\033[%d;;p", i); } void LIPS4Driver::disableAutoFF() { writeSpoolString("\033[?2h"); } void LIPS4Driver::setNumberOfCopies() { writeSpoolString("\033[%ldv", getJobData()->getCopies()); } void LIPS4Driver::sidePrintingControl() { if (getJobData()->getPrintStyle() == JobData::kSimplex) writeSpoolString("\033[0#x"); else writeSpoolString("\033[2;0#x"); } void LIPS4Driver::setBindingMargin() { if (getJobData()->getPrintStyle() == JobData::kDuplex) { int i; // switch (job_data()->binding_location()) { // case kLongEdgeLeft: i = 0; // break; // case kLongEdgeRight: // i = 1; // break; // case kShortEdgeTop: // i = 2; // break; // case kShortEdgeBottom: // i = 3; // break; // } writeSpoolString("\033[%d;0#w", i); } } void LIPS4Driver::memorizedPosition() { writeSpoolString("\033[0;1;0x"); } void LIPS4Driver::moveAbsoluteHorizontal(int x) { writeSpoolString("\033[%ld`", x); } void LIPS4Driver::carriageReturn() { writeSpoolChar('\x0d'); } void LIPS4Driver::moveDown(int dy) { writeSpoolString("\033[%lde", dy); } void LIPS4Driver::rasterGraphics( int compression_size, int widthbyte, int height, int compression_method, const uchar *buffer) { // 0 RAW // 10 RLE // 11 packbits writeSpoolString( "\033[%ld;%ld;%d;%ld;%ld.r", compression_size, widthbyte, getJobData()->getXres(), compression_method, height); writeSpoolData(buffer, compression_size); } void LIPS4Driver::formFeed() { writeSpoolChar('\014'); } void LIPS4Driver::jobEnd() { writeSpoolString("\033P0J\033\\"); } void LIPS4Driver::move(int x, int y) { if (fCurrentX != x) { if (x) { moveAbsoluteHorizontal(x); } else { carriageReturn(); } fCurrentX = x; } if (fCurrentY != y) { int dy = y - fCurrentY; moveDown(dy); fCurrentY = y; } }