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
This commit is contained in:
Michael Pfeiffer 2005-01-10 19:29:07 +00:00
parent 1ee14bea49
commit dcab43435a
3 changed files with 210 additions and 35 deletions

View File

@ -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,12 +181,17 @@ 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++) {
@ -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
@ -226,6 +306,7 @@ void PCL6Driver::jobStart()
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);
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)
@ -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;
}
}

View File

@ -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_UByte fMediaSide; // side if in duplex mode
};
#endif /* __PCL6_H */

View File

@ -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;