xref: /haiku/src/add-ons/print/drivers/pcl6/PCL6.cpp (revision dcab43435a6fd69b40eef4de8c2bf48152550ac2)
13bfe34e2SMichael Pfeiffer /*
23bfe34e2SMichael Pfeiffer  * PCL6.cpp
33bfe34e2SMichael Pfeiffer  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
43bfe34e2SMichael Pfeiffer  * Copyright 2003 Michael Pfeiffer.
53bfe34e2SMichael Pfeiffer  */
63bfe34e2SMichael Pfeiffer 
73bfe34e2SMichael Pfeiffer #include <Alert.h>
83bfe34e2SMichael Pfeiffer #include <Bitmap.h>
93bfe34e2SMichael Pfeiffer #include <File.h>
103bfe34e2SMichael Pfeiffer #include <memory>
113bfe34e2SMichael Pfeiffer #include "PCL6.h"
123bfe34e2SMichael Pfeiffer #include "UIDriver.h"
133bfe34e2SMichael Pfeiffer #include "JobData.h"
143bfe34e2SMichael Pfeiffer #include "PrinterData.h"
153bfe34e2SMichael Pfeiffer #include "PCL6Cap.h"
163bfe34e2SMichael Pfeiffer #include "PackBits.h"
173bfe34e2SMichael Pfeiffer #include "Halftone.h"
183bfe34e2SMichael Pfeiffer #include "ValidRect.h"
193bfe34e2SMichael Pfeiffer #include "DbgMsg.h"
20*dcab4343SMichael Pfeiffer #include "DeltaRowCompression.h"
213bfe34e2SMichael Pfeiffer 
223bfe34e2SMichael Pfeiffer #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
233bfe34e2SMichael Pfeiffer using namespace std;
243bfe34e2SMichael Pfeiffer #else
253bfe34e2SMichael Pfeiffer #define std
263bfe34e2SMichael Pfeiffer #endif
273bfe34e2SMichael Pfeiffer 
28*dcab4343SMichael Pfeiffer // Compression method configuration
29*dcab4343SMichael Pfeiffer // Set to 0 to disable compression and to 1 to enable compression
30*dcab4343SMichael Pfeiffer // Note compression takes place only if it takes less space than uncompressed data!
31*dcab4343SMichael Pfeiffer 
32*dcab4343SMichael Pfeiffer // Run-Length-Encoding Compression
33*dcab4343SMichael Pfeiffer // DO NOT ENABLE HP_M2TIFF_Compress seems to be broken!!!
34*dcab4343SMichael Pfeiffer #define ENABLE_RLE_COMPRESSION       0
35*dcab4343SMichael Pfeiffer 
36*dcab4343SMichael Pfeiffer // Delta Row Compression
37*dcab4343SMichael Pfeiffer #define ENABLE_DELTA_ROW_COMPRESSION 1
38*dcab4343SMichael Pfeiffer 
39*dcab4343SMichael Pfeiffer // DeltaRowStreamCompressor writes the delta row directly to the
40*dcab4343SMichael Pfeiffer // in the contructor specified stream.
41*dcab4343SMichael Pfeiffer class DeltaRowStreamCompressor : public AbstractDeltaRowCompressor
42*dcab4343SMichael Pfeiffer {
43*dcab4343SMichael Pfeiffer public:
44*dcab4343SMichael Pfeiffer 	DeltaRowStreamCompressor(int rowSize, uchar initialSeed, HP_StreamHandleType stream)
45*dcab4343SMichael Pfeiffer 		: AbstractDeltaRowCompressor(rowSize, initialSeed)
46*dcab4343SMichael Pfeiffer 		, fStream(stream)
47*dcab4343SMichael Pfeiffer 	{
48*dcab4343SMichael Pfeiffer 		// nothing to do
49*dcab4343SMichael Pfeiffer 	}
50*dcab4343SMichael Pfeiffer 
51*dcab4343SMichael Pfeiffer protected:
52*dcab4343SMichael Pfeiffer 	void AppendByteToDeltaRow(uchar byte) {
53*dcab4343SMichael Pfeiffer 		HP_RawUByte(fStream, byte);
54*dcab4343SMichael Pfeiffer 	}
55*dcab4343SMichael Pfeiffer 
56*dcab4343SMichael Pfeiffer private:
57*dcab4343SMichael Pfeiffer 	HP_StreamHandleType fStream;
58*dcab4343SMichael Pfeiffer };
59*dcab4343SMichael Pfeiffer 
603bfe34e2SMichael Pfeiffer PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
613bfe34e2SMichael Pfeiffer 	: GraphicsDriver(msg, printer_data, printer_cap)
623bfe34e2SMichael Pfeiffer {
63d2c03b1bSMichael Pfeiffer 	fHalftone = NULL;
64d2c03b1bSMichael Pfeiffer 	fStream = NULL;
653bfe34e2SMichael Pfeiffer }
663bfe34e2SMichael Pfeiffer 
673bfe34e2SMichael Pfeiffer void PCL6Driver::FlushOutBuffer(HP_StreamHandleType pStream, unsigned long cookie, HP_pUByte pOutBuffer, HP_SInt32 currentBufferLen)
683bfe34e2SMichael Pfeiffer {
693bfe34e2SMichael Pfeiffer 	writeSpoolData(pOutBuffer, currentBufferLen);
703bfe34e2SMichael Pfeiffer }
713bfe34e2SMichael Pfeiffer 
723bfe34e2SMichael Pfeiffer 
733bfe34e2SMichael Pfeiffer bool PCL6Driver::startDoc()
743bfe34e2SMichael Pfeiffer {
753bfe34e2SMichael Pfeiffer 	try {
763bfe34e2SMichael Pfeiffer 		jobStart();
773b6882f1SMichael Pfeiffer 		fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType());
783bfe34e2SMichael Pfeiffer 		return true;
793bfe34e2SMichael Pfeiffer 	}
803bfe34e2SMichael Pfeiffer 	catch (TransportException &err) {
813bfe34e2SMichael Pfeiffer 		return false;
823bfe34e2SMichael Pfeiffer 	}
833bfe34e2SMichael Pfeiffer }
843bfe34e2SMichael Pfeiffer 
853bfe34e2SMichael Pfeiffer bool PCL6Driver::endDoc(bool)
863bfe34e2SMichael Pfeiffer {
873bfe34e2SMichael Pfeiffer 	try {
88d2c03b1bSMichael Pfeiffer 		if (fHalftone) {
89d2c03b1bSMichael Pfeiffer 			delete fHalftone;
903bfe34e2SMichael Pfeiffer 		}
913bfe34e2SMichael Pfeiffer 		jobEnd();
923bfe34e2SMichael Pfeiffer 		return true;
933bfe34e2SMichael Pfeiffer 	}
943bfe34e2SMichael Pfeiffer 	catch (TransportException &err) {
953bfe34e2SMichael Pfeiffer 		return false;
963bfe34e2SMichael Pfeiffer 	}
973bfe34e2SMichael Pfeiffer }
983bfe34e2SMichael Pfeiffer 
993bfe34e2SMichael Pfeiffer bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset)
1003bfe34e2SMichael Pfeiffer {
1013bfe34e2SMichael Pfeiffer 	DBGMSG(("> nextBand\n"));
1023bfe34e2SMichael Pfeiffer 
1033bfe34e2SMichael Pfeiffer 	try {
1043bfe34e2SMichael Pfeiffer 		BRect bounds = bitmap->Bounds();
1053bfe34e2SMichael Pfeiffer 
1063bfe34e2SMichael Pfeiffer 		RECT rc;
1073bfe34e2SMichael Pfeiffer 		rc.left   = (int)bounds.left;
1083bfe34e2SMichael Pfeiffer 		rc.top    = (int)bounds.top;
1093bfe34e2SMichael Pfeiffer 		rc.right  = (int)bounds.right;
1103bfe34e2SMichael Pfeiffer 		rc.bottom = (int)bounds.bottom;
1113bfe34e2SMichael Pfeiffer 
1123bfe34e2SMichael Pfeiffer 		int height = rc.bottom - rc.top + 1;
1133bfe34e2SMichael Pfeiffer 
1143bfe34e2SMichael Pfeiffer 		int x = (int)offset->x;
1153bfe34e2SMichael Pfeiffer 		int y = (int)offset->y;
1163bfe34e2SMichael Pfeiffer 
1173bfe34e2SMichael Pfeiffer 		int page_height = getPageHeight();
1183bfe34e2SMichael Pfeiffer 
1193bfe34e2SMichael Pfeiffer 		if (y + height > page_height) {
1203bfe34e2SMichael Pfeiffer 			height = page_height - y;
1213bfe34e2SMichael Pfeiffer 		}
1223bfe34e2SMichael Pfeiffer 
1233bfe34e2SMichael Pfeiffer 		rc.bottom = height - 1;
1243bfe34e2SMichael Pfeiffer 
1253bfe34e2SMichael Pfeiffer 		DBGMSG(("height = %d\n", height));
1263bfe34e2SMichael Pfeiffer 		DBGMSG(("x = %d\n", x));
1273bfe34e2SMichael Pfeiffer 		DBGMSG(("y = %d\n", y));
1283bfe34e2SMichael Pfeiffer 
129d2c03b1bSMichael Pfeiffer 		if (get_valid_rect(bitmap, &rc)) {
1303bfe34e2SMichael Pfeiffer 
1313bfe34e2SMichael Pfeiffer 			DBGMSG(("validate rect = %d, %d, %d, %d\n",
1323bfe34e2SMichael Pfeiffer 				rc.left, rc.top, rc.right, rc.bottom));
1333bfe34e2SMichael Pfeiffer 
1343bfe34e2SMichael Pfeiffer 			x = rc.left;
1353bfe34e2SMichael Pfeiffer 			y += rc.top;
1363bfe34e2SMichael Pfeiffer 
13791c89ca3SMichael Pfeiffer 			bool color;
13891c89ca3SMichael Pfeiffer 			int width;
13991c89ca3SMichael Pfeiffer 			int widthByte;
14091c89ca3SMichael Pfeiffer 			int padBytes;
14191c89ca3SMichael Pfeiffer 			int out_row_length;
14291c89ca3SMichael Pfeiffer 			int height;
14391c89ca3SMichael Pfeiffer 			int out_size;
14491c89ca3SMichael Pfeiffer 			int delta;
14591c89ca3SMichael Pfeiffer 
146d2c03b1bSMichael Pfeiffer 			color = getJobData()->getColor() == JobData::kColor;
14791c89ca3SMichael Pfeiffer 
14891c89ca3SMichael Pfeiffer 			width = rc.right - rc.left + 1;
14991c89ca3SMichael Pfeiffer 			height = rc.bottom - rc.top + 1;
15091c89ca3SMichael Pfeiffer 			delta = bitmap->BytesPerRow();
15191c89ca3SMichael Pfeiffer 
15291c89ca3SMichael Pfeiffer 			if (color) {
15391c89ca3SMichael Pfeiffer 				widthByte = 3 * width;
15491c89ca3SMichael Pfeiffer 			} else {
15591c89ca3SMichael Pfeiffer 				widthByte = (width + 7) / 8;	/* byte boundary */
15691c89ca3SMichael Pfeiffer 			}
15791c89ca3SMichael Pfeiffer 
15891c89ca3SMichael Pfeiffer 			out_row_length = 4*((widthByte+3)/4);
15991c89ca3SMichael Pfeiffer 			padBytes = out_row_length - widthByte; /* line length is a multiple of 4 bytes */
16091c89ca3SMichael Pfeiffer 			out_size  = out_row_length * height;
16191c89ca3SMichael Pfeiffer 
1623bfe34e2SMichael Pfeiffer 
1633bfe34e2SMichael Pfeiffer 			DBGMSG(("width = %d\n", width));
1643bfe34e2SMichael Pfeiffer 			DBGMSG(("widthByte = %d\n", widthByte));
1653bfe34e2SMichael Pfeiffer 			DBGMSG(("height = %d\n", height));
1663bfe34e2SMichael Pfeiffer 			DBGMSG(("out_size = %d\n", out_size));
1673bfe34e2SMichael Pfeiffer 			DBGMSG(("delta = %d\n", delta));
168d2c03b1bSMichael Pfeiffer 			DBGMSG(("renderobj->get_pixel_depth() = %d\n", fHalftone->getPixelDepth()));
1693bfe34e2SMichael Pfeiffer 
1703bfe34e2SMichael Pfeiffer 			uchar *ptr = (uchar *)bitmap->Bits()
1713bfe34e2SMichael Pfeiffer 						+ rc.top * delta
172d2c03b1bSMichael Pfeiffer 						+ (rc.left * fHalftone->getPixelDepth()) / 8;
1733bfe34e2SMichael Pfeiffer 
1743bfe34e2SMichael Pfeiffer 			const uchar *buffer;
1753bfe34e2SMichael Pfeiffer 
1763bfe34e2SMichael Pfeiffer 			uchar *out_buffer = new uchar[out_size];
1773bfe34e2SMichael Pfeiffer 
1783bfe34e2SMichael Pfeiffer 			uchar *out_ptr = out_buffer;
1793bfe34e2SMichael Pfeiffer 
1803bfe34e2SMichael Pfeiffer 			auto_ptr<uchar> _out_buffer(out_buffer);
1813bfe34e2SMichael Pfeiffer 
1823bfe34e2SMichael Pfeiffer 			DBGMSG(("move\n"));
1833bfe34e2SMichael Pfeiffer 
1843bfe34e2SMichael Pfeiffer 			buffer = out_buffer;
185*dcab4343SMichael Pfeiffer 
186*dcab4343SMichael Pfeiffer 			int xPage = x;
187*dcab4343SMichael Pfeiffer 			int yPage = y;
188*dcab4343SMichael Pfeiffer 
189*dcab4343SMichael Pfeiffer 			DeltaRowCompressor deltaRowCompressor(out_row_length, 0);
190*dcab4343SMichael Pfeiffer 			if (deltaRowCompressor.InitCheck() != B_OK) {
191*dcab4343SMichael Pfeiffer 				return false;
192*dcab4343SMichael Pfeiffer 			}
193*dcab4343SMichael Pfeiffer 
194*dcab4343SMichael Pfeiffer 			int deltaRowSize = 0;
1953bfe34e2SMichael Pfeiffer 
1963bfe34e2SMichael Pfeiffer 			// dither entire band into out_buffer
1973bfe34e2SMichael Pfeiffer 			for (int i = rc.top; i <= rc.bottom; i++) {
19891c89ca3SMichael Pfeiffer 				uchar* out = out_ptr;
19991c89ca3SMichael Pfeiffer 				if (color) {
20091c89ca3SMichael Pfeiffer 					uchar* in = ptr;
20191c89ca3SMichael Pfeiffer 					for (int w = width; w > 0; w --) {
20291c89ca3SMichael Pfeiffer 						*out++ = in[2];
20391c89ca3SMichael Pfeiffer 						*out++ = in[1];
20491c89ca3SMichael Pfeiffer 						*out++ = in[0];
20591c89ca3SMichael Pfeiffer 						in += 4;
20691c89ca3SMichael Pfeiffer 					}
20791c89ca3SMichael Pfeiffer 				} else {
208d2c03b1bSMichael Pfeiffer 					fHalftone->dither(out_ptr, ptr, x, y, width);
2093bfe34e2SMichael Pfeiffer 					// invert pixels
2103bfe34e2SMichael Pfeiffer 					for (int w = widthByte; w > 0; w --, out ++) {
2113bfe34e2SMichael Pfeiffer 						*out = ~*out;
2123bfe34e2SMichael Pfeiffer 					}
21391c89ca3SMichael Pfeiffer 				}
2143bfe34e2SMichael Pfeiffer 				// pad with 0s
2153bfe34e2SMichael Pfeiffer 				for (int w = padBytes; w > 0; w --, out ++) {
2163bfe34e2SMichael Pfeiffer 					*out = 0;
2173bfe34e2SMichael Pfeiffer 				}
2183bfe34e2SMichael Pfeiffer 
219*dcab4343SMichael Pfeiffer 				{
220*dcab4343SMichael Pfeiffer 					int size = deltaRowCompressor.CalculateSize(out_ptr, true);
221*dcab4343SMichael Pfeiffer 					deltaRowSize += size + 2; // two bytes for the row byte count
222*dcab4343SMichael Pfeiffer 				}
223*dcab4343SMichael Pfeiffer 
2243bfe34e2SMichael Pfeiffer 				ptr  += delta;
2253bfe34e2SMichael Pfeiffer 				out_ptr += out_row_length;
2263bfe34e2SMichael Pfeiffer 				y++;
2273bfe34e2SMichael Pfeiffer 			}
2283bfe34e2SMichael Pfeiffer 
229*dcab4343SMichael Pfeiffer 			writeBitmap(buffer, out_size, out_row_length, xPage, yPage, width, height, deltaRowSize);
2303bfe34e2SMichael Pfeiffer 
2313bfe34e2SMichael Pfeiffer 		} else {
2323bfe34e2SMichael Pfeiffer 			DBGMSG(("band bitmap is clean.\n"));
2333bfe34e2SMichael Pfeiffer 		}
2343bfe34e2SMichael Pfeiffer 
2353bfe34e2SMichael Pfeiffer 		if (y >= page_height) {
2363bfe34e2SMichael Pfeiffer 			offset->x = -1.0;
2373bfe34e2SMichael Pfeiffer 			offset->y = -1.0;
2383bfe34e2SMichael Pfeiffer 		} else {
2393bfe34e2SMichael Pfeiffer 			offset->y += height;
2403bfe34e2SMichael Pfeiffer 		}
2413bfe34e2SMichael Pfeiffer 
2423bfe34e2SMichael Pfeiffer 		DBGMSG(("< nextBand\n"));
2433bfe34e2SMichael Pfeiffer 		return true;
2443bfe34e2SMichael Pfeiffer 	}
2453bfe34e2SMichael Pfeiffer 	catch (TransportException &err) {
2463bfe34e2SMichael Pfeiffer 		BAlert *alert = new BAlert("", err.what(), "OK");
2473bfe34e2SMichael Pfeiffer 		alert->Go();
2483bfe34e2SMichael Pfeiffer 		return false;
2493bfe34e2SMichael Pfeiffer 	}
2503bfe34e2SMichael Pfeiffer }
2513bfe34e2SMichael Pfeiffer 
252*dcab4343SMichael Pfeiffer void PCL6Driver::writeBitmap(const uchar* buffer, int outSize, int rowSize, int x, int y, int width, int height, int deltaRowSize)
253*dcab4343SMichael Pfeiffer {
254*dcab4343SMichael Pfeiffer 	// choose the best compression method
255*dcab4343SMichael Pfeiffer 	int compressionMethod = HP_eNoCompression;
256*dcab4343SMichael Pfeiffer 	int dataSize = outSize;
257*dcab4343SMichael Pfeiffer 
258*dcab4343SMichael Pfeiffer #if ENABLE_DELTA_ROW_COMPRESSION
259*dcab4343SMichael Pfeiffer 	if (deltaRowSize < dataSize) {
260*dcab4343SMichael Pfeiffer 		compressionMethod = HP_eDeltaRowCompression;
261*dcab4343SMichael Pfeiffer 		dataSize = deltaRowSize;
262*dcab4343SMichael Pfeiffer 	}
263*dcab4343SMichael Pfeiffer #endif
264*dcab4343SMichael Pfeiffer 
265*dcab4343SMichael Pfeiffer #if ENABLE_RLE_COMPRESSION
266*dcab4343SMichael Pfeiffer 	HP_UInt32 compressedSize = 0;
267*dcab4343SMichael Pfeiffer 	HP_M2TIFF_CalcCompression((HP_pCharHuge)buffer, outSize, &compressedSize);
268*dcab4343SMichael Pfeiffer 	if (compressedSize < (uint32)dataSize) {
269*dcab4343SMichael Pfeiffer 		compressionMethod = HP_eRLECompression;
270*dcab4343SMichael Pfeiffer 		dataSize = compressedSize;
271*dcab4343SMichael Pfeiffer 	}
272*dcab4343SMichael Pfeiffer #endif
273*dcab4343SMichael Pfeiffer 
274*dcab4343SMichael Pfeiffer 	// write bitmap
275*dcab4343SMichael Pfeiffer 	move(x, y);
276*dcab4343SMichael Pfeiffer 
277*dcab4343SMichael Pfeiffer 	startRasterGraphics(x, y, width, height, compressionMethod);
278*dcab4343SMichael Pfeiffer 
279*dcab4343SMichael Pfeiffer 	rasterGraphics(buffer, outSize, dataSize, rowSize, height, compressionMethod);
280*dcab4343SMichael Pfeiffer 
281*dcab4343SMichael Pfeiffer 	endRasterGraphics();
282*dcab4343SMichael Pfeiffer 
283*dcab4343SMichael Pfeiffer #if 1
284*dcab4343SMichael Pfeiffer 	fprintf(stderr, "Out Size       %d %2.2f\n", (int)outSize, 100.0);
285*dcab4343SMichael Pfeiffer #if ENABLE_RLE_COMPRESSION
286*dcab4343SMichael Pfeiffer 	fprintf(stderr, "RLE Size       %d %2.2f\n", (int)compressedSize, 100.0 * compressedSize / outSize);
287*dcab4343SMichael Pfeiffer #endif
288*dcab4343SMichael Pfeiffer #if ENABLE_DELTA_ROW_COMPRESSION
289*dcab4343SMichael Pfeiffer 	fprintf(stderr, "Delta Row Size %d %2.2f\n", (int)deltaRowSize, 100.0 * deltaRowSize / outSize);
290*dcab4343SMichael Pfeiffer #endif
291*dcab4343SMichael Pfeiffer 	fprintf(stderr, "Data Size      %d %2.2f\n", (int)dataSize, 100.0 * dataSize / outSize);
292*dcab4343SMichael Pfeiffer #endif
293*dcab4343SMichael Pfeiffer }
294*dcab4343SMichael Pfeiffer 
295*dcab4343SMichael Pfeiffer 
2963bfe34e2SMichael Pfeiffer void PCL6Driver::jobStart()
2973bfe34e2SMichael Pfeiffer {
2983bfe34e2SMichael Pfeiffer 	// PJL header
2993bfe34e2SMichael Pfeiffer 	writeSpoolString("\033%%-12345X@PJL JOB\n"
3008fb205f2SMichael Pfeiffer 					 "@PJL SET RESOLUTION=%d\n"
301a0d17a8cSMichael Pfeiffer 	                 "@PJL ENTER LANGUAGE=PCLXL\n"
3023bfe34e2SMichael Pfeiffer 	                 ") HP-PCL XL;1;1;"
30382f24520SMichael Pfeiffer 	                 "Comment Copyright (c) 2003, 2004 Haiku\n",
3048fb205f2SMichael Pfeiffer 	                 getJobData()->getXres());
3053bfe34e2SMichael Pfeiffer 	// PCL6 begin
306d2c03b1bSMichael Pfeiffer 	fStream = HP_NewStream(16 * 1024, this);
307d2c03b1bSMichael Pfeiffer 	HP_BeginSession_2(fStream, getJobData()->getXres(), getJobData()->getYres(), HP_eInch, HP_eBackChAndErrPage);
308d2c03b1bSMichael Pfeiffer 	HP_OpenDataSource_1(fStream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst);
309*dcab4343SMichael Pfeiffer 	fMediaSide = HP_eFrontMediaSide;
3103bfe34e2SMichael Pfeiffer }
3113bfe34e2SMichael Pfeiffer 
3128fb205f2SMichael Pfeiffer bool PCL6Driver::startPage(int)
3138fb205f2SMichael Pfeiffer {
31482f24520SMichael Pfeiffer 	HP_UByte orientation = HP_ePortraitOrientation;
31582f24520SMichael Pfeiffer 	if (getJobData()->getOrientation() == JobData::kLandscape) {
31682f24520SMichael Pfeiffer 		orientation = HP_eLandscapeOrientation;
31782f24520SMichael Pfeiffer 	}
318*dcab4343SMichael Pfeiffer 
319*dcab4343SMichael Pfeiffer 	HP_UByte mediaSize = PCL6Driver::mediaSize(getJobData()->getPaper());
320*dcab4343SMichael Pfeiffer 	if (getJobData()->getPrintStyle() == JobData::kSimplex) {
321*dcab4343SMichael Pfeiffer 		HP_BeginPage_3(fStream, orientation, mediaSize, PCL6Driver::mediaSource(getJobData()->getPaperSource()));
322*dcab4343SMichael Pfeiffer 	} else if (getJobData()->getPrintStyle() == JobData::kDuplex) {
323*dcab4343SMichael Pfeiffer 		HP_BeginPage_5(fStream, orientation, mediaSize, HP_DuplexPageMode, fMediaSide);
324*dcab4343SMichael Pfeiffer 
325*dcab4343SMichael Pfeiffer 		if (fMediaSide == HP_eFrontMediaSide) {
326*dcab4343SMichael Pfeiffer 			fMediaSide = HP_eBackMediaSide;
327*dcab4343SMichael Pfeiffer 		} else {
328*dcab4343SMichael Pfeiffer 			fMediaSide = HP_eFrontMediaSide;
329*dcab4343SMichael Pfeiffer 		}
330*dcab4343SMichael Pfeiffer 	} else {
331*dcab4343SMichael Pfeiffer 		return false;
332*dcab4343SMichael Pfeiffer 	}
333*dcab4343SMichael Pfeiffer 
3348fb205f2SMichael Pfeiffer 	// PageOrigin from Windows NT printer driver
3358fb205f2SMichael Pfeiffer 	int x = 142 * getJobData()->getXres() / 600;
3368fb205f2SMichael Pfeiffer 	int y = 100 * getJobData()->getYres() / 600;
337d2c03b1bSMichael Pfeiffer 	bool color = getJobData()->getColor() == JobData::kColor;
338d2c03b1bSMichael Pfeiffer 	HP_SetPageOrigin_1(fStream, x, y);
339d2c03b1bSMichael Pfeiffer 	HP_SetColorSpace_1(fStream, color ? HP_eRGB : HP_eGray);
340d2c03b1bSMichael Pfeiffer 	HP_SetPaintTxMode_1(fStream, HP_eOpaque);
341d2c03b1bSMichael Pfeiffer 	HP_SetSourceTxMode_1(fStream, HP_eOpaque);
342d2c03b1bSMichael Pfeiffer 	HP_SetROP_1(fStream, 204);
3438fb205f2SMichael Pfeiffer 	return true;
3448fb205f2SMichael Pfeiffer }
3458fb205f2SMichael Pfeiffer 
346*dcab4343SMichael Pfeiffer void PCL6Driver::startRasterGraphics(int x, int y, int width, int height, int compressionMethod)
3473bfe34e2SMichael Pfeiffer {
348d2c03b1bSMichael Pfeiffer 	bool color = getJobData()->getColor() == JobData::kColor;
349d2c03b1bSMichael Pfeiffer 	HP_BeginImage_1(fStream, HP_eDirectPixel, color ? HP_e8Bit : HP_e1Bit, width, height, width, height);
350*dcab4343SMichael Pfeiffer 	HP_ReadImage_1(fStream, 0, height, compressionMethod);
3513bfe34e2SMichael Pfeiffer }
3523bfe34e2SMichael Pfeiffer 
3533bfe34e2SMichael Pfeiffer void PCL6Driver::endRasterGraphics()
3543bfe34e2SMichael Pfeiffer {
355d2c03b1bSMichael Pfeiffer 	HP_EndImage_1(fStream);
3563bfe34e2SMichael Pfeiffer }
3573bfe34e2SMichael Pfeiffer 
3583bfe34e2SMichael Pfeiffer void PCL6Driver::rasterGraphics(
3593bfe34e2SMichael Pfeiffer 	const uchar *buffer,
360*dcab4343SMichael Pfeiffer 	int bufferSize,
361*dcab4343SMichael Pfeiffer 	int dataSize,
362*dcab4343SMichael Pfeiffer 	int rowSize,
363*dcab4343SMichael Pfeiffer 	int height,
364*dcab4343SMichael Pfeiffer 	int compressionMethod
365*dcab4343SMichael Pfeiffer )
3663bfe34e2SMichael Pfeiffer {
367*dcab4343SMichael Pfeiffer 	// write bitmap byte size
368*dcab4343SMichael Pfeiffer 	HP_EmbeddedDataPrefix32(fStream, dataSize);
369*dcab4343SMichael Pfeiffer 
370*dcab4343SMichael Pfeiffer 	// write data
371*dcab4343SMichael Pfeiffer 	if (compressionMethod == HP_eRLECompression) {
372*dcab4343SMichael Pfeiffer 		// use RLE compression
373*dcab4343SMichael Pfeiffer 		HP_UInt32 compressedSize = 0;
374*dcab4343SMichael Pfeiffer 		HP_M2TIFF_Compress(fStream, 0, (HP_pCharHuge)buffer, bufferSize, &compressedSize);
375*dcab4343SMichael Pfeiffer 	} else if (compressionMethod == HP_eDeltaRowCompression) {
376*dcab4343SMichael Pfeiffer 		// use delta row compression
377*dcab4343SMichael Pfeiffer 		DeltaRowStreamCompressor compressor(rowSize, 0, fStream);
378*dcab4343SMichael Pfeiffer 		if (compressor.InitCheck() != B_OK) {
379*dcab4343SMichael Pfeiffer 			return;
3803bfe34e2SMichael Pfeiffer 		}
381*dcab4343SMichael Pfeiffer 
382*dcab4343SMichael Pfeiffer 		const uchar* row = buffer;
383*dcab4343SMichael Pfeiffer 		for (int i = 0; i < height; i ++) {
384*dcab4343SMichael Pfeiffer 			// write row byte count
385*dcab4343SMichael Pfeiffer 			int size = compressor.CalculateSize(row);
386*dcab4343SMichael Pfeiffer 			HP_RawUInt16(fStream, size);
387*dcab4343SMichael Pfeiffer 
388*dcab4343SMichael Pfeiffer 			if (size > 0) {
389*dcab4343SMichael Pfeiffer 				// write delta row
390*dcab4343SMichael Pfeiffer 				compressor.Compress(row);
391*dcab4343SMichael Pfeiffer 			}
392*dcab4343SMichael Pfeiffer 
393*dcab4343SMichael Pfeiffer 			row += rowSize;
394*dcab4343SMichael Pfeiffer 		}
395*dcab4343SMichael Pfeiffer 	} else {
396*dcab4343SMichael Pfeiffer 		// write raw data
397*dcab4343SMichael Pfeiffer 		HP_RawUByteArray(fStream, (uchar*)buffer, bufferSize);
398*dcab4343SMichael Pfeiffer 	}
3993bfe34e2SMichael Pfeiffer }
4003bfe34e2SMichael Pfeiffer 
4018fb205f2SMichael Pfeiffer bool PCL6Driver::endPage(int)
4028fb205f2SMichael Pfeiffer {
4038fb205f2SMichael Pfeiffer 	try {
404d2c03b1bSMichael Pfeiffer 		HP_EndPage_2(fStream, getJobData()->getCopies());
4058fb205f2SMichael Pfeiffer 		return true;
4068fb205f2SMichael Pfeiffer 	}
4078fb205f2SMichael Pfeiffer 	catch (TransportException &err) {
4088fb205f2SMichael Pfeiffer 		return false;
4098fb205f2SMichael Pfeiffer 	}
4108fb205f2SMichael Pfeiffer }
4118fb205f2SMichael Pfeiffer 
4123bfe34e2SMichael Pfeiffer void PCL6Driver::jobEnd()
4133bfe34e2SMichael Pfeiffer {
414d2c03b1bSMichael Pfeiffer 	HP_CloseDataSource_1(fStream);
415d2c03b1bSMichael Pfeiffer 	HP_EndSession_1(fStream);
416d2c03b1bSMichael Pfeiffer 	HP_FinishStream(fStream);
4173bfe34e2SMichael Pfeiffer 	// PJL footer
4183bfe34e2SMichael Pfeiffer 	writeSpoolString("\033%%-12345X@PJL EOJ\n"
4193bfe34e2SMichael Pfeiffer 	                 "\033%%-12345X");
4203bfe34e2SMichael Pfeiffer }
4213bfe34e2SMichael Pfeiffer 
4223bfe34e2SMichael Pfeiffer void PCL6Driver::move(int x, int y)
4233bfe34e2SMichael Pfeiffer {
424d2c03b1bSMichael Pfeiffer 	HP_SetCursor_1(fStream, x, y);
4253bfe34e2SMichael Pfeiffer }
4263bfe34e2SMichael Pfeiffer 
427d2c03b1bSMichael Pfeiffer HP_UByte PCL6Driver::mediaSize(JobData::Paper paper)
4283bfe34e2SMichael Pfeiffer {
4293bfe34e2SMichael Pfeiffer 	switch (paper) {
430d2c03b1bSMichael Pfeiffer 		case JobData::kLetter:    return HP_eLetterPaper;
431d2c03b1bSMichael Pfeiffer 		case JobData::kLegal:     return HP_eLegalPaper;
432d2c03b1bSMichael Pfeiffer 		case JobData::kA4:        return HP_eA4Paper;
433d2c03b1bSMichael Pfeiffer 		case JobData::kExecutive: return HP_eExecPaper;
434d2c03b1bSMichael Pfeiffer 		case JobData::kLedger:    return HP_eLedgerPaper;
435d2c03b1bSMichael Pfeiffer 		case JobData::kA3:        return HP_eA3Paper;
4363bfe34e2SMichael Pfeiffer /*
4373bfe34e2SMichael Pfeiffer 		case : return HP_eCOM10Envelope;
4383bfe34e2SMichael Pfeiffer 		case : return HP_eMonarchEnvelope;
4393bfe34e2SMichael Pfeiffer 		case : return HP_eC5Envelope;
4403bfe34e2SMichael Pfeiffer 		case : return HP_eDLEnvelope;
4413bfe34e2SMichael Pfeiffer 		case : return HP_eJB4Paper;
4423bfe34e2SMichael Pfeiffer 		case : return HP_eJB5Paper;
4433bfe34e2SMichael Pfeiffer 		case : return HP_eB5Envelope;
4443bfe34e2SMichael Pfeiffer 		case : return HP_eB5Paper;
4453bfe34e2SMichael Pfeiffer 		case : return HP_eJPostcard;
4463bfe34e2SMichael Pfeiffer 		case : return HP_eJDoublePostcard;
4473bfe34e2SMichael Pfeiffer 		case : return HP_eA5Paper;
4483bfe34e2SMichael Pfeiffer 		case : return HP_eA6Paper;
4493bfe34e2SMichael Pfeiffer 		case : return HP_eJB6Paper;
4503bfe34e2SMichael Pfeiffer 		case : return HP_eJIS8KPaper;
4513bfe34e2SMichael Pfeiffer 		case : return HP_eJIS16KPaper;
4523bfe34e2SMichael Pfeiffer 		case : return HP_eJISExecPaper;
4533bfe34e2SMichael Pfeiffer */
454d2c03b1bSMichael Pfeiffer 		default:
455d2c03b1bSMichael Pfeiffer 			return HP_eLegalPaper;
4563bfe34e2SMichael Pfeiffer 	}
4573bfe34e2SMichael Pfeiffer }
4583bfe34e2SMichael Pfeiffer 
459*dcab4343SMichael Pfeiffer HP_UByte PCL6Driver::mediaSource(JobData::PaperSource source)
460*dcab4343SMichael Pfeiffer {
461*dcab4343SMichael Pfeiffer 	switch (source) {
462*dcab4343SMichael Pfeiffer 		case JobData::kAuto:       return HP_eAutoSelect;
463*dcab4343SMichael Pfeiffer 		case JobData::kCassette1:  return HP_eDefaultSource;
464*dcab4343SMichael Pfeiffer 		case JobData::kCassette2:  return HP_eEnvelopeTray;
465*dcab4343SMichael Pfeiffer 		case JobData::kLower:      return HP_eLowerCassette;
466*dcab4343SMichael Pfeiffer 		case JobData::kUpper:      return HP_eUpperCassette;
467*dcab4343SMichael Pfeiffer 		case JobData::kMiddle:     return HP_eThirdCassette;
468*dcab4343SMichael Pfeiffer 		case JobData::kManual:     return HP_eManualFeed;
469*dcab4343SMichael Pfeiffer 		case JobData::kCassette3:  return HP_eMultiPurposeTray;
470*dcab4343SMichael Pfeiffer 
471*dcab4343SMichael Pfeiffer 		default:
472*dcab4343SMichael Pfeiffer 			return HP_eAutoSelect;
473*dcab4343SMichael Pfeiffer 	}
474*dcab4343SMichael Pfeiffer }
475*dcab4343SMichael Pfeiffer 
476