From dcab43435a6fd69b40eef4de8c2bf48152550ac2 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Mon, 10 Jan 2005 19:29:07 +0000 Subject: [PATCH] Implemented delta row compression. Added media sources. Enabled duplex mode. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10663 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/print/drivers/pcl6/PCL6.cpp | 201 ++++++++++++++++++--- src/add-ons/print/drivers/pcl6/PCL6.h | 17 +- src/add-ons/print/drivers/pcl6/PCL6Cap.cpp | 27 +++ 3 files changed, 210 insertions(+), 35 deletions(-) diff --git a/src/add-ons/print/drivers/pcl6/PCL6.cpp b/src/add-ons/print/drivers/pcl6/PCL6.cpp index 56256be07a..758af29cd8 100644 --- a/src/add-ons/print/drivers/pcl6/PCL6.cpp +++ b/src/add-ons/print/drivers/pcl6/PCL6.cpp @@ -17,6 +17,7 @@ #include "Halftone.h" #include "ValidRect.h" #include "DbgMsg.h" +#include "DeltaRowCompression.h" #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) using namespace std; @@ -24,6 +25,38 @@ using namespace std; #define std #endif +// Compression method configuration +// Set to 0 to disable compression and to 1 to enable compression +// Note compression takes place only if it takes less space than uncompressed data! + +// Run-Length-Encoding Compression +// DO NOT ENABLE HP_M2TIFF_Compress seems to be broken!!! +#define ENABLE_RLE_COMPRESSION 0 + +// Delta Row Compression +#define ENABLE_DELTA_ROW_COMPRESSION 1 + +// DeltaRowStreamCompressor writes the delta row directly to the +// in the contructor specified stream. +class DeltaRowStreamCompressor : public AbstractDeltaRowCompressor +{ +public: + DeltaRowStreamCompressor(int rowSize, uchar initialSeed, HP_StreamHandleType stream) + : AbstractDeltaRowCompressor(rowSize, initialSeed) + , fStream(stream) + { + // nothing to do + } + +protected: + void AppendByteToDeltaRow(uchar byte) { + HP_RawUByte(fStream, byte); + } + +private: + HP_StreamHandleType fStream; +}; + PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) : GraphicsDriver(msg, printer_data, printer_cap) { @@ -138,8 +171,6 @@ bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset) + rc.top * delta + (rc.left * fHalftone->getPixelDepth()) / 8; - int compression_method; - int compressed_size; const uchar *buffer; uchar *out_buffer = new uchar[out_size]; @@ -150,13 +181,18 @@ bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset) DBGMSG(("move\n")); - move(x, y); - startRasterGraphics(x, y, width, height); - - compression_method = 0; // uncompressed buffer = out_buffer; - compressed_size = out_size; + int xPage = x; + int yPage = y; + + DeltaRowCompressor deltaRowCompressor(out_row_length, 0); + if (deltaRowCompressor.InitCheck() != B_OK) { + return false; + } + + int deltaRowSize = 0; + // dither entire band into out_buffer for (int i = rc.top; i <= rc.bottom; i++) { uchar* out = out_ptr; @@ -180,17 +216,17 @@ bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset) *out = 0; } + { + int size = deltaRowCompressor.CalculateSize(out_ptr, true); + deltaRowSize += size + 2; // two bytes for the row byte count + } + ptr += delta; out_ptr += out_row_length; y++; } - rasterGraphics( - compression_method, - buffer, - compressed_size); - - endRasterGraphics(); + writeBitmap(buffer, out_size, out_row_length, xPage, yPage, width, height, deltaRowSize); } else { DBGMSG(("band bitmap is clean.\n")); @@ -213,6 +249,50 @@ bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset) } } +void PCL6Driver::writeBitmap(const uchar* buffer, int outSize, int rowSize, int x, int y, int width, int height, int deltaRowSize) +{ + // choose the best compression method + int compressionMethod = HP_eNoCompression; + int dataSize = outSize; + +#if ENABLE_DELTA_ROW_COMPRESSION + if (deltaRowSize < dataSize) { + compressionMethod = HP_eDeltaRowCompression; + dataSize = deltaRowSize; + } +#endif + +#if ENABLE_RLE_COMPRESSION + HP_UInt32 compressedSize = 0; + HP_M2TIFF_CalcCompression((HP_pCharHuge)buffer, outSize, &compressedSize); + if (compressedSize < (uint32)dataSize) { + compressionMethod = HP_eRLECompression; + dataSize = compressedSize; + } +#endif + + // write bitmap + move(x, y); + + startRasterGraphics(x, y, width, height, compressionMethod); + + rasterGraphics(buffer, outSize, dataSize, rowSize, height, compressionMethod); + + endRasterGraphics(); + +#if 1 + fprintf(stderr, "Out Size %d %2.2f\n", (int)outSize, 100.0); +#if ENABLE_RLE_COMPRESSION + fprintf(stderr, "RLE Size %d %2.2f\n", (int)compressedSize, 100.0 * compressedSize / outSize); +#endif +#if ENABLE_DELTA_ROW_COMPRESSION + fprintf(stderr, "Delta Row Size %d %2.2f\n", (int)deltaRowSize, 100.0 * deltaRowSize / outSize); +#endif + fprintf(stderr, "Data Size %d %2.2f\n", (int)dataSize, 100.0 * dataSize / outSize); +#endif +} + + void PCL6Driver::jobStart() { // PJL header @@ -225,7 +305,8 @@ void PCL6Driver::jobStart() // PCL6 begin fStream = HP_NewStream(16 * 1024, this); HP_BeginSession_2(fStream, getJobData()->getXres(), getJobData()->getYres(), HP_eInch, HP_eBackChAndErrPage); - HP_OpenDataSource_1(fStream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst); + HP_OpenDataSource_1(fStream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst); + fMediaSide = HP_eFrontMediaSide; } bool PCL6Driver::startPage(int) @@ -234,7 +315,22 @@ bool PCL6Driver::startPage(int) if (getJobData()->getOrientation() == JobData::kLandscape) { orientation = HP_eLandscapeOrientation; } - HP_BeginPage_3(fStream, orientation, mediaSize(getJobData()->getPaper()), HP_eAutoSelect); + + HP_UByte mediaSize = PCL6Driver::mediaSize(getJobData()->getPaper()); + if (getJobData()->getPrintStyle() == JobData::kSimplex) { + HP_BeginPage_3(fStream, orientation, mediaSize, PCL6Driver::mediaSource(getJobData()->getPaperSource())); + } else if (getJobData()->getPrintStyle() == JobData::kDuplex) { + HP_BeginPage_5(fStream, orientation, mediaSize, HP_DuplexPageMode, fMediaSide); + + if (fMediaSide == HP_eFrontMediaSide) { + fMediaSide = HP_eBackMediaSide; + } else { + fMediaSide = HP_eFrontMediaSide; + } + } else { + return false; + } + // PageOrigin from Windows NT printer driver int x = 142 * getJobData()->getXres() / 600; int y = 100 * getJobData()->getYres() / 600; @@ -247,12 +343,11 @@ bool PCL6Driver::startPage(int) return true; } -void PCL6Driver::startRasterGraphics(int x, int y, int width, int height) +void PCL6Driver::startRasterGraphics(int x, int y, int width, int height, int compressionMethod) { bool color = getJobData()->getColor() == JobData::kColor; - fCompressionMethod = -1; HP_BeginImage_1(fStream, HP_eDirectPixel, color ? HP_e8Bit : HP_e1Bit, width, height, width, height); - HP_ReadImage_1(fStream, 0, height, HP_eNoCompression); + HP_ReadImage_1(fStream, 0, height, compressionMethod); } void PCL6Driver::endRasterGraphics() @@ -261,15 +356,46 @@ void PCL6Driver::endRasterGraphics() } void PCL6Driver::rasterGraphics( - int compression_method, const uchar *buffer, - int size) + int bufferSize, + int dataSize, + int rowSize, + int height, + int compressionMethod +) { - if (fCompressionMethod != compression_method) { - fCompressionMethod = compression_method; + // write bitmap byte size + HP_EmbeddedDataPrefix32(fStream, dataSize); + + // write data + if (compressionMethod == HP_eRLECompression) { + // use RLE compression + HP_UInt32 compressedSize = 0; + HP_M2TIFF_Compress(fStream, 0, (HP_pCharHuge)buffer, bufferSize, &compressedSize); + } else if (compressionMethod == HP_eDeltaRowCompression) { + // use delta row compression + DeltaRowStreamCompressor compressor(rowSize, 0, fStream); + if (compressor.InitCheck() != B_OK) { + return; + } + + const uchar* row = buffer; + for (int i = 0; i < height; i ++) { + // write row byte count + int size = compressor.CalculateSize(row); + HP_RawUInt16(fStream, size); + + if (size > 0) { + // write delta row + compressor.Compress(row); + } + + row += rowSize; + } + } else { + // write raw data + HP_RawUByteArray(fStream, (uchar*)buffer, bufferSize); } - HP_EmbeddedDataPrefix32(fStream, size); - HP_RawUByteArray(fStream, (uchar*)buffer, size); } bool PCL6Driver::endPage(int) @@ -301,12 +427,12 @@ void PCL6Driver::move(int x, int y) HP_UByte PCL6Driver::mediaSize(JobData::Paper paper) { switch (paper) { - case JobData::kLetter: return HP_eLetterPaper; - case JobData::kLegal: return HP_eLegalPaper; - case JobData::kA4: return HP_eA4Paper; + case JobData::kLetter: return HP_eLetterPaper; + case JobData::kLegal: return HP_eLegalPaper; + case JobData::kA4: return HP_eA4Paper; case JobData::kExecutive: return HP_eExecPaper; - case JobData::kLedger: return HP_eLedgerPaper; - case JobData::kA3: return HP_eA3Paper; + case JobData::kLedger: return HP_eLedgerPaper; + case JobData::kA3: return HP_eA3Paper; /* case : return HP_eCOM10Envelope; case : return HP_eMonarchEnvelope; @@ -330,3 +456,20 @@ HP_UByte PCL6Driver::mediaSize(JobData::Paper paper) } } +HP_UByte PCL6Driver::mediaSource(JobData::PaperSource source) +{ + switch (source) { + case JobData::kAuto: return HP_eAutoSelect; + case JobData::kCassette1: return HP_eDefaultSource; + case JobData::kCassette2: return HP_eEnvelopeTray; + case JobData::kLower: return HP_eLowerCassette; + case JobData::kUpper: return HP_eUpperCassette; + case JobData::kMiddle: return HP_eThirdCassette; + case JobData::kManual: return HP_eManualFeed; + case JobData::kCassette3: return HP_eMultiPurposeTray; + + default: + return HP_eAutoSelect; + } +} + diff --git a/src/add-ons/print/drivers/pcl6/PCL6.h b/src/add-ons/print/drivers/pcl6/PCL6.h index 9811792ef3..6a1b14c4e3 100644 --- a/src/add-ons/print/drivers/pcl6/PCL6.h +++ b/src/add-ons/print/drivers/pcl6/PCL6.h @@ -30,19 +30,24 @@ protected: private: HP_UByte mediaSize(JobData::Paper paper); + HP_UByte mediaSource(JobData::PaperSource source); void move(int x, int y); void jobStart(); - void startRasterGraphics(int x, int y, int width, int height); + void writeBitmap(const uchar* buffer, int outSize, int rowSize, int x, int y, int width, int height, int deltaRowSize); + void startRasterGraphics(int x, int y, int width, int height, int compressionMethod); void endRasterGraphics(); void rasterGraphics( - int compression_method, const uchar *buffer, - int size); + int bufferSize, + int dataSize, + int rowSize, + int height, + int compression_method); void jobEnd(); - HP_StreamHandleType fStream; - int fCompressionMethod; - Halftone *fHalftone; + HP_StreamHandleType fStream; + Halftone *fHalftone; + HP_UByte fMediaSide; // side if in duplex mode }; #endif /* __PCL6_H */ diff --git a/src/add-ons/print/drivers/pcl6/PCL6Cap.cpp b/src/add-ons/print/drivers/pcl6/PCL6Cap.cpp index 43c1d332b1..3c7bd2779d 100644 --- a/src/add-ons/print/drivers/pcl6/PCL6Cap.cpp +++ b/src/add-ons/print/drivers/pcl6/PCL6Cap.cpp @@ -65,11 +65,21 @@ const PaperCap legal( BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4980.0f), TO72DPI(8280.0f))); const PaperSourceCap autobin("Auto", true, JobData::kAuto); +const PaperSourceCap defaultSource("Default", false, JobData::kCassette1); +const PaperSourceCap envelopeTray("Envelope Tray", false, JobData::kCassette2); +const PaperSourceCap lowerCassette("Lower Cassette", false, JobData::kLower); +const PaperSourceCap upperCassette("Upper Cassette", false, JobData::kUpper); +const PaperSourceCap thridCassette("Thrid Cassette", false, JobData::kMiddle); +const PaperSourceCap manualFeed("Manual Feed", false, JobData::kManual); +const PaperSourceCap multiPurposeTray("Multi Purpose Tray", false, JobData::kCassette3); const ResolutionCap dpi300("300dpi", true, 300, 300); const ResolutionCap dpi600("600dpi", false, 600, 600); const ResolutionCap dpi1200("1200dpi", false, 1200, 1200); +const PrintStyleCap simplex("Simplex", true, JobData::kSimplex); +const PrintStyleCap duplex("Duplex", false, JobData::kDuplex); + const PaperCap *papers[] = { &a4, &a3, @@ -82,6 +92,13 @@ const PaperCap *papers[] = { const PaperSourceCap *papersources[] = { &autobin, + &defaultSource, + &envelopeTray, + &lowerCassette, + &upperCassette, + &thridCassette, + &manualFeed, + &multiPurposeTray }; const ResolutionCap *resolutions[] = { @@ -90,6 +107,11 @@ const ResolutionCap *resolutions[] = { &dpi1200, }; +const PrintStyleCap *printStyles[] = { + &simplex, + &duplex +}; + const ColorCap color("Color", false, JobData::kColor); const ColorCap monochrome("Monochrome", true, JobData::kMonochrome); @@ -114,6 +136,8 @@ int PCL6Cap::countCap(CapID capid) const return sizeof(resolutions) / sizeof(resolutions[0]); case kColor: return sizeof(colors) / sizeof(colors[0]); + case kPrintStyle: + return sizeof(printStyles) / sizeof(printStyles[0]); default: return 0; } @@ -130,6 +154,8 @@ const BaseCap **PCL6Cap::enumCap(CapID capid) const return (const BaseCap **)resolutions; case kColor: return (const BaseCap **)colors; + case kPrintStyle: + return (const BaseCap **)printStyles; default: return NULL; } @@ -143,6 +169,7 @@ bool PCL6Cap::isSupport(CapID capid) const case kResolution: case kColor: case kCopyCommand: + case kPrintStyle: return true; default: return false;