xref: /haiku/src/add-ons/print/drivers/pcl6/PCL6.cpp (revision e79e4e7c9e432c90415f79809b7160e864f79001)
1 /*
2  * PCL6.cpp
3  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4  * Copyright 2003 Michael Pfeiffer.
5  */
6 
7 #include <Alert.h>
8 #include <Bitmap.h>
9 #include <File.h>
10 #include <memory>
11 #include "PCL6.h"
12 #include "UIDriver.h"
13 #include "JobData.h"
14 #include "PrinterData.h"
15 #include "PCL6Cap.h"
16 #include "PackBits.h"
17 #include "Halftone.h"
18 #include "ValidRect.h"
19 #include "DbgMsg.h"
20 
21 #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
22 using namespace std;
23 #else
24 #define std
25 #endif
26 
27 PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
28 	: GraphicsDriver(msg, printer_data, printer_cap)
29 {
30 	__halftone = NULL;
31 	__stream = NULL;
32 }
33 
34 void PCL6Driver::FlushOutBuffer(HP_StreamHandleType pStream, unsigned long cookie, HP_pUByte pOutBuffer, HP_SInt32 currentBufferLen)
35 {
36 	writeSpoolData(pOutBuffer, currentBufferLen);
37 }
38 
39 
40 bool PCL6Driver::startDoc()
41 {
42 	try {
43 		jobStart();
44 		__halftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma());
45 		return true;
46 	}
47 	catch (TransportException &err) {
48 		return false;
49 	}
50 }
51 
52 bool PCL6Driver::endDoc(bool)
53 {
54 	try {
55 		if (__halftone) {
56 			delete __halftone;
57 		}
58 		jobEnd();
59 		return true;
60 	}
61 	catch (TransportException &err) {
62 		return false;
63 	}
64 }
65 
66 bool PCL6Driver::nextBand(BBitmap *bitmap, BPoint *offset)
67 {
68 	DBGMSG(("> nextBand\n"));
69 
70 	try {
71 		BRect bounds = bitmap->Bounds();
72 
73 		RECT rc;
74 		rc.left   = (int)bounds.left;
75 		rc.top    = (int)bounds.top;
76 		rc.right  = (int)bounds.right;
77 		rc.bottom = (int)bounds.bottom;
78 
79 		int height = rc.bottom - rc.top + 1;
80 
81 		int x = (int)offset->x;
82 		int y = (int)offset->y;
83 
84 		int page_height = getPageHeight();
85 
86 		if (y + height > page_height) {
87 			height = page_height - y;
88 		}
89 
90 		rc.bottom = height - 1;
91 
92 		DBGMSG(("height = %d\n", height));
93 		DBGMSG(("x = %d\n", x));
94 		DBGMSG(("y = %d\n", y));
95 
96 		if (get_valid_rect(bitmap, __halftone->getPalette(), &rc)) {
97 
98 			DBGMSG(("validate rect = %d, %d, %d, %d\n",
99 				rc.left, rc.top, rc.right, rc.bottom));
100 
101 			x = rc.left;
102 			y += rc.top;
103 
104 			int width = rc.right - rc.left + 1;
105 			int widthByte = (width + 7) / 8;	/* byte boundary */
106 			int padBytes = ((width + 31) / 32) * 4 - widthByte; /* line length is a multiple of 4 bytes */
107 			int out_row_length = widthByte + padBytes;
108 			int height    = rc.bottom - rc.top + 1;
109 			int out_size  = out_row_length * height;
110 			int delta     = bitmap->BytesPerRow();
111 
112 			DBGMSG(("width = %d\n", width));
113 			DBGMSG(("widthByte = %d\n", widthByte));
114 			DBGMSG(("height = %d\n", height));
115 			DBGMSG(("out_size = %d\n", out_size));
116 			DBGMSG(("delta = %d\n", delta));
117 			DBGMSG(("renderobj->get_pixel_depth() = %d\n", __halftone->getPixelDepth()));
118 
119 			uchar *ptr = (uchar *)bitmap->Bits()
120 						+ rc.top * delta
121 						+ (rc.left * __halftone->getPixelDepth()) / 8;
122 
123 			int compression_method;
124 			int compressed_size;
125 			const uchar *buffer;
126 
127 			uchar *out_buffer = new uchar[out_size];
128 
129 			uchar *out_ptr = out_buffer;
130 
131 			auto_ptr<uchar> _out_buffer(out_buffer);
132 
133 			DBGMSG(("move\n"));
134 
135 			move(x, y);
136 			startRasterGraphics(x, y, width, height);
137 
138 			compression_method = 0; // uncompressed
139 			buffer = out_buffer;
140 			compressed_size = out_size;
141 
142 			// dither entire band into out_buffer
143 			for (int i = rc.top; i <= rc.bottom; i++) {
144 				__halftone->dither(out_ptr, ptr, x, y, width);
145 				// invert pixels
146 				uchar* out = out_ptr;
147 				for (int w = widthByte; w > 0; w --, out ++) {
148 					*out = ~*out;
149 				}
150 				// pad with 0s
151 				for (int w = padBytes; w > 0; w --, out ++) {
152 					*out = 0;
153 				}
154 
155 				ptr  += delta;
156 				out_ptr += out_row_length;
157 				y++;
158 			}
159 
160 			rasterGraphics(
161 				compression_method,
162 				buffer,
163 				compressed_size);
164 
165 			endRasterGraphics();
166 
167 		} else {
168 			DBGMSG(("band bitmap is clean.\n"));
169 		}
170 
171 		if (y >= page_height) {
172 			offset->x = -1.0;
173 			offset->y = -1.0;
174 		} else {
175 			offset->y += height;
176 		}
177 
178 		DBGMSG(("< nextBand\n"));
179 		return true;
180 	}
181 	catch (TransportException &err) {
182 		BAlert *alert = new BAlert("", err.what(), "OK");
183 		alert->Go();
184 		return false;
185 	}
186 }
187 
188 void PCL6Driver::jobStart()
189 {
190 	// PJL header
191 	writeSpoolString("\033%%-12345X@PJL JOB\n"
192 					 "@PJL SET RESOLUTION=%d\n"
193 	                 "@PJL ENTER LANGUAGE=PCLXL\n"
194 	                 ") HP-PCL XL;1;1;"
195 	                 "Comment Copyright (c) 2003 OBOS\n",
196 	                 getJobData()->getXres());
197 	// PCL6 begin
198 	__stream = HP_NewStream(16 * 1024, this);
199 	HP_BeginSession_2(__stream, getJobData()->getXres(), getJobData()->getYres(), HP_eInch, HP_eBackChAndErrPage);
200 	HP_OpenDataSource_1(__stream, HP_eDefaultDataSource, HP_eBinaryLowByteFirst);
201 }
202 
203 bool PCL6Driver::startPage(int)
204 {
205 	// XXX orientation
206 	HP_BeginPage_3(__stream, HP_ePortraitOrientation, mediaSize(getJobData()->getPaper()), HP_eAutoSelect);
207 	// PageOrigin from Windows NT printer driver
208 	int x = 142 * getJobData()->getXres() / 600;
209 	int y = 100 * getJobData()->getYres() / 600;
210 	HP_SetPageOrigin_1(__stream, x, y);
211 	HP_SetColorSpace_1(__stream, HP_eGray);
212 	HP_SetPaintTxMode_1(__stream, HP_eOpaque);
213 	HP_SetSourceTxMode_1(__stream, HP_eOpaque);
214 	HP_SetROP_1(__stream, 204);
215 	return true;
216 }
217 
218 void PCL6Driver::startRasterGraphics(int x, int y, int width, int height)
219 {
220 	__compression_method = -1;
221 	HP_BeginImage_1(__stream, HP_eDirectPixel, HP_e1Bit, width, height, width, height);
222 	HP_ReadImage_1(__stream, 0, height, HP_eNoCompression);
223 }
224 
225 void PCL6Driver::endRasterGraphics()
226 {
227 	HP_EndImage_1(__stream);
228 }
229 
230 void PCL6Driver::rasterGraphics(
231 	int compression_method,
232 	const uchar *buffer,
233 	int size)
234 {
235 	if (__compression_method != compression_method) {
236 		__compression_method = compression_method;
237 	}
238 	HP_EmbeddedDataPrefix32(__stream, size);
239 	HP_RawUByteArray(__stream, (uchar*)buffer, size);
240 }
241 
242 bool PCL6Driver::endPage(int)
243 {
244 	try {
245 		HP_EndPage_2(__stream, getJobData()->getCopies());
246 		return true;
247 	}
248 	catch (TransportException &err) {
249 		return false;
250 	}
251 }
252 
253 void PCL6Driver::jobEnd()
254 {
255 	HP_CloseDataSource_1(__stream);
256 	HP_EndSession_1(__stream);
257 	HP_FinishStream(__stream);
258 	// PJL footer
259 	writeSpoolString("\033%%-12345X@PJL EOJ\n"
260 	                 "\033%%-12345X");
261 }
262 
263 void PCL6Driver::move(int x, int y)
264 {
265 	HP_SetCursor_1(__stream, x, y);
266 }
267 
268 HP_UByte PCL6Driver::mediaSize(JobData::PAPER paper)
269 {
270 	switch (paper) {
271 		case JobData::LETTER: return HP_eLetterPaper;
272 		case JobData::LEGAL: return HP_eLegalPaper;
273 		case JobData::A4: return HP_eA4Paper;
274 		case JobData::EXECUTIVE: return HP_eExecPaper;
275 		case JobData::LEDGER: return HP_eLedgerPaper;
276 		case JobData::A3: return HP_eA3Paper;
277 /*
278 		case : return HP_eCOM10Envelope;
279 		case : return HP_eMonarchEnvelope;
280 		case : return HP_eC5Envelope;
281 		case : return HP_eDLEnvelope;
282 		case : return HP_eJB4Paper;
283 		case : return HP_eJB5Paper;
284 		case : return HP_eB5Envelope;
285 		case : return HP_eB5Paper;
286 		case : return HP_eJPostcard;
287 		case : return HP_eJDoublePostcard;
288 		case : return HP_eA5Paper;
289 		case : return HP_eA6Paper;
290 		case : return HP_eJB6Paper;
291 		case : return HP_eJIS8KPaper;
292 		case : return HP_eJIS16KPaper;
293 		case : return HP_eJISExecPaper;
294 */
295 		default: HP_eLegalPaper;
296 	}
297 }
298 
299