xref: /haiku/src/add-ons/print/drivers/canon_lips/lips3/Lips3.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2  * Lips3.cpp
3  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4  */
5 
6 #include <Alert.h>
7 #include <Bitmap.h>
8 #include <File.h>
9 #include <memory>
10 #include "Lips3.h"
11 #include "UIDriver.h"
12 #include "Compress3.h"
13 #include "JobData.h"
14 #include "PrinterData.h"
15 #include "Lips3Cap.h"
16 #include "Halftone.h"
17 #include "ValidRect.h"
18 #include "DbgMsg.h"
19 
20 #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
21 using namespace std;
22 #else
23 #define std
24 #endif
25 
26 LIPS3Driver::LIPS3Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
27 	: GraphicsDriver(msg, printer_data, printer_cap)
28 {
29 	fHalftone = NULL;
30 }
31 
32 bool LIPS3Driver::startDoc()
33 {
34 	try {
35 		beginTextMode();
36 		jobStart();
37 		softReset();
38 		sizeUnitMode();
39 		selectSizeUnit();
40 		selectPageFormat();
41 		paperFeedMode();
42 		disableAutoFF();
43 		setNumberOfCopies();
44 		fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType());
45 		return true;
46 	}
47 	catch (TransportException &err) {
48 		return false;
49 	}
50 }
51 
52 bool LIPS3Driver::startPage(int)
53 {
54 	try {
55 		fCurrentX = 0;
56 		fCurrentY = 0;
57 		memorizedPosition();
58 		return true;
59 	}
60 	catch (TransportException &err) {
61 		return false;
62 	}
63 }
64 
65 bool LIPS3Driver::endPage(int)
66 {
67 	try {
68 		formFeed();
69 		return true;
70 	}
71 	catch (TransportException &err) {
72 		return false;
73 	}
74 }
75 
76 bool LIPS3Driver::endDoc(bool)
77 {
78 	try {
79 		if (fHalftone) {
80 			delete fHalftone;
81 		}
82 		jobEnd();
83 		return true;
84 	}
85 	catch (TransportException &err) {
86 		return false;
87 	}
88 }
89 
90 bool LIPS3Driver::nextBand(BBitmap *bitmap, BPoint *offset)
91 {
92 	DBGMSG(("> nextBand\n"));
93 
94 	try {
95 		BRect bounds = bitmap->Bounds();
96 
97 		RECT rc;
98 		rc.left   = (int)bounds.left;
99 		rc.top    = (int)bounds.top;
100 		rc.right  = (int)bounds.right;
101 		rc.bottom = (int)bounds.bottom;
102 
103 		int height = rc.bottom - rc.top + 1;
104 
105 		int x = (int)offset->x;
106 		int y = (int)offset->y;
107 
108 		int page_height = getPageHeight();
109 
110 		if (y + height > page_height) {
111 			height = page_height - y;
112 		}
113 
114 		rc.bottom = height - 1;
115 
116 		DBGMSG(("height = %d\n", height));
117 		DBGMSG(("x = %d\n", x));
118 		DBGMSG(("y = %d\n", y));
119 
120 		if (get_valid_rect(bitmap, &rc)) {
121 
122 			DBGMSG(("validate rect = %d, %d, %d, %d\n",
123 				rc.left, rc.top, rc.right, rc.bottom));
124 
125 			x = rc.left;
126 			y += rc.top;
127 
128 			int width = rc.right - rc.left + 1;
129 			int widthByte = (width + 7) / 8;	/* byte boundary */
130 			int height    = rc.bottom - rc.top + 1;
131 			int in_size   = widthByte * height;
132 			int out_size  = (in_size * 6 + 4) / 5;
133 			int delta     = bitmap->BytesPerRow();
134 
135 			DBGMSG(("width = %d\n", width));
136 			DBGMSG(("widthByte = %d\n", widthByte));
137 			DBGMSG(("height = %d\n", height));
138 			DBGMSG(("in_size = %d\n", in_size));
139 			DBGMSG(("out_size = %d\n", out_size));
140 			DBGMSG(("delta = %d\n", delta));
141 			DBGMSG(("renderobj->get_pixel_depth() = %d\n", fHalftone->getPixelDepth()));
142 
143 			uchar *ptr = (uchar *)bitmap->Bits()
144 						+ rc.top * delta
145 						+ (rc.left * fHalftone->getPixelDepth()) / 8;
146 
147 			int compression_method;
148 			int compressed_size;
149 			const uchar *buffer;
150 
151 			uchar *in_buffer  = new uchar[in_size];
152 			uchar *out_buffer = new uchar[out_size];
153 
154 			auto_ptr<uchar> _in_buffer (in_buffer);
155 			auto_ptr<uchar> _out_buffer(out_buffer);
156 
157 			uchar *ptr2 = (uchar *)in_buffer;
158 
159 			DBGMSG(("move\n"));
160 
161 			move(x, y);
162 
163 			for (int i = rc.top; i <= rc.bottom; i++) {
164 				fHalftone->dither(ptr2, ptr, x, y, width);
165 				ptr  += delta;
166 				ptr2 += widthByte;
167 				y++;
168 			}
169 
170 			compressed_size = compress3(out_buffer, in_buffer, in_size);
171 
172 			if (compressed_size < in_size) {
173 				compression_method = 9;		/* compress3 */
174 				buffer = out_buffer;
175 			} else if (compressed_size > out_size) {
176 				BAlert *alert = new BAlert("memory overrun!!!", "warning", "OK");
177 				alert->Go();
178 				return false;
179 			} else {
180 				compression_method = 0;
181 				buffer = in_buffer;
182 				compressed_size = in_size;
183 			}
184 
185 			DBGMSG(("compressed_size = %d\n", compressed_size));
186 			DBGMSG(("widthByte = %d\n", widthByte));
187 			DBGMSG(("height = %d\n", height));
188 			DBGMSG(("compression_method = %d\n", compression_method));
189 
190 			rasterGraphics(
191 				compressed_size,	// size,
192 				widthByte,			// widthByte
193 				height,				// height,
194 				compression_method,
195 				buffer);
196 
197 		} else {
198 			DBGMSG(("band bitmap is clean.\n"));
199 		}
200 
201 		if (y >= page_height) {
202 			offset->x = -1.0;
203 			offset->y = -1.0;
204 		} else {
205 			offset->y += height;
206 		}
207 
208 		DBGMSG(("< nextBand\n"));
209 		return true;
210 	}
211 	catch (TransportException &err) {
212 		BAlert *alert = new BAlert("", err.what(), "OK");
213 		alert->Go();
214 		return false;
215 	}
216 }
217 
218 void LIPS3Driver::beginTextMode()
219 {
220 	writeSpoolString("\033%%@");
221 }
222 
223 void LIPS3Driver::jobStart()
224 {
225 	writeSpoolString("\033P31;300;1J\033\\");
226 }
227 
228 void LIPS3Driver::softReset()
229 {
230 	writeSpoolString("\033<");
231 }
232 
233 void LIPS3Driver::sizeUnitMode()
234 {
235 	writeSpoolString("\033[11h");
236 }
237 
238 void LIPS3Driver::selectSizeUnit()
239 {
240 	writeSpoolString("\033[7 I");
241 }
242 
243 void LIPS3Driver::selectPageFormat()
244 {
245 	int i;
246 	int width  = 0;
247 	int height = 0;
248 
249 	switch (getJobData()->getPaper()) {
250 	case JobData::kA3:
251 		i = 12;
252 		break;
253 
254 	case JobData::kA4:
255 		i = 14;
256 		break;
257 
258 	case JobData::kA5:
259 		i = 16;
260 		break;
261 
262 	case JobData::kJapanesePostcard:
263 		i = 18;
264 		break;
265 
266 	case JobData::kB4:
267 		i = 24;
268 		break;
269 
270 	case JobData::kB5:
271 		i = 26;
272 		break;
273 
274 	case JobData::kLetter:
275 		i = 30;
276 		break;
277 
278 	case JobData::kLegal:
279 		i = 32;
280 		break;
281 
282 //	case JobData::kExecutive:
283 //		i = 40;
284 //		break;
285 //
286 //	case JobData::kJEnvYou4:
287 //		i = 50;
288 //		break;
289 //
290 //	case JobData::kUser:
291 //		i = 90;
292 //		break;
293 //
294 	default:
295 		i = 80;
296 		width  = getJobData()->getPaperRect().IntegerWidth();
297 		height = getJobData()->getPaperRect().IntegerHeight();
298 		break;
299 	}
300 
301 	if (JobData::kLandscape == getJobData()->getOrientation())
302 		i++;
303 
304 	if (i < 80) {
305 		writeSpoolString("\033[%d;;p", i);
306 	} else {
307 		writeSpoolString("\033[%d;%d;%dp", i, height, width);
308 	}
309 }
310 
311 void LIPS3Driver::paperFeedMode()
312 {
313 	// 0 auto
314 	// --------------
315 	// 1 MP tray
316 	// 2 lower
317 	// 3 lupper
318 	// --------------
319 	// 10 MP tray
320 	// 11 casette 1
321 	// 12 casette 2
322 	// 13 casette 3
323 	// 14 casette 4
324 	// 15 casette 5
325 	// 16 casette 6
326 	// 17 casette 7
327 
328 	int i;
329 
330 	switch (getJobData()->getPaperSource()) {
331 	case JobData::kManual:
332 		i = 1;
333 		break;
334 	case JobData::kLower:
335 		i = 2;
336 		break;
337 	case JobData::kUpper:
338 		i = 3;
339 		break;
340 	case JobData::kAuto:
341 	default:
342 		i = 0;
343 		break;
344 	}
345 
346 	writeSpoolString("\033[%dq", i);
347 }
348 
349 void LIPS3Driver::disableAutoFF()
350 {
351 	writeSpoolString("\033[?2h");
352 }
353 
354 void LIPS3Driver::setNumberOfCopies()
355 {
356 	writeSpoolString("\033[%ldv", getJobData()->getCopies());
357 }
358 
359 void LIPS3Driver::memorizedPosition()
360 {
361 	writeSpoolString("\033[0;1;0x");
362 }
363 
364 void LIPS3Driver::moveAbsoluteHorizontal(int x)
365 {
366 	writeSpoolString("\033[%d`", x);
367 }
368 
369 void LIPS3Driver::carriageReturn()
370 {
371 	writeSpoolChar('\x0d');
372 }
373 
374 void LIPS3Driver::moveDown(int dy)
375 {
376 	writeSpoolString("\033[%de", dy);
377 }
378 
379 void LIPS3Driver::rasterGraphics(
380 	int compression_size,
381 	int widthbyte,
382 	int height,
383 	int compression_method,
384 	const uchar *buffer)
385 {
386 //  0 RAW
387 //  9 compress-3
388 	writeSpoolString(
389 		"\033[%d;%d;%d;%d;%d.r",
390 		compression_size,
391 		widthbyte,
392 		getJobData()->getXres(),
393 		compression_method,
394 		height);
395 
396 	writeSpoolData(buffer, compression_size);
397 }
398 
399 void LIPS3Driver::formFeed()
400 {
401 	writeSpoolChar('\014');
402 }
403 
404 void LIPS3Driver::jobEnd()
405 {
406 	writeSpoolString("\033P0J\033\\");
407 }
408 
409 void LIPS3Driver::move(int x, int y)
410 {
411 	if (fCurrentX != x) {
412 		if (x) {
413 			moveAbsoluteHorizontal(x);
414 		} else {
415 			carriageReturn();
416 		}
417 		fCurrentX = x;
418 	}
419 	if (fCurrentY != y) {
420 		int dy = y - fCurrentY;
421 		moveDown(dy);
422 		fCurrentY = y;
423 	}
424 }
425