1/*
2 * Lips3.cpp
3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4 */
5
6
7#include "Lips3.h"
8
9#include <vector>
10
11#include <Alert.h>
12#include <Bitmap.h>
13#include <File.h>
14
15#include "Compress3.h"
16#include "DbgMsg.h"
17#include "Halftone.h"
18#include "JobData.h"
19#include "Lips3Cap.h"
20#include "PrinterData.h"
21#include "UIDriver.h"
22#include "ValidRect.h"
23
24
25LIPS3Driver::LIPS3Driver(BMessage* message, PrinterData* printerData,
26	const PrinterCap* printerCap)
27	:
28	GraphicsDriver(message, printerData, printerCap),
29	fHalftone(NULL)
30{
31}
32
33
34bool
35LIPS3Driver::StartDocument()
36{
37	try {
38		_BeginTextMode();
39		_JobStart();
40		_SoftReset();
41		_SizeUnitMode();
42		_SelectSizeUnit();
43		_SelectPageFormat();
44		_PaperFeedMode();
45		_DisableAutoFF();
46		_SetNumberOfCopies();
47		fHalftone = new Halftone(GetJobData()->GetSurfaceType(),
48			GetJobData()->GetGamma(), GetJobData()->GetInkDensity(),
49			GetJobData()->GetDitherType());
50		return true;
51	}
52	catch (TransportException& err) {
53		return false;
54	}
55}
56
57
58bool
59LIPS3Driver::StartPage(int)
60{
61	try {
62		fCurrentX = 0;
63		fCurrentY = 0;
64		_MemorizedPosition();
65		return true;
66	}
67	catch (TransportException& err) {
68		return false;
69	}
70}
71
72
73bool
74LIPS3Driver::EndPage(int)
75{
76	try {
77		_FormFeed();
78		return true;
79	}
80	catch (TransportException& err) {
81		return false;
82	}
83}
84
85
86bool
87LIPS3Driver::EndDocument(bool)
88{
89	try {
90		if (fHalftone)
91			delete fHalftone;
92
93		_JobEnd();
94		return true;
95	}
96	catch (TransportException& err) {
97		return false;
98	}
99}
100
101
102bool
103LIPS3Driver::NextBand(BBitmap* bitmap, BPoint* offset)
104{
105	DBGMSG(("> nextBand\n"));
106
107	try {
108		BRect bounds = bitmap->Bounds();
109
110		RECT rc;
111		rc.left = (int)bounds.left;
112		rc.top = (int)bounds.top;
113		rc.right = (int)bounds.right;
114		rc.bottom = (int)bounds.bottom;
115
116		int height = rc.bottom - rc.top + 1;
117
118		int x = (int)offset->x;
119		int y = (int)offset->y;
120
121		int page_height = GetPageHeight();
122
123		if (y + height > page_height)
124			height = page_height - y;
125
126		rc.bottom = height - 1;
127
128		DBGMSG(("height = %d\n", height));
129		DBGMSG(("x = %d\n", x));
130		DBGMSG(("y = %d\n", y));
131
132		if (get_valid_rect(bitmap, &rc)) {
133
134			DBGMSG(("validate rect = %d, %d, %d, %d\n",
135				rc.left, rc.top, rc.right, rc.bottom));
136
137			x = rc.left;
138			y += rc.top;
139
140			int width = rc.right - rc.left + 1;
141			int widthByte = (width + 7) / 8;
142				// byte boundary
143			int height = rc.bottom - rc.top + 1;
144			int in_size = widthByte * height;
145			int out_size = (in_size * 6 + 4) / 5;
146			int delta = bitmap->BytesPerRow();
147
148			DBGMSG(("width = %d\n", width));
149			DBGMSG(("widthByte = %d\n", widthByte));
150			DBGMSG(("height = %d\n", height));
151			DBGMSG(("in_size = %d\n", in_size));
152			DBGMSG(("out_size = %d\n", out_size));
153			DBGMSG(("delta = %d\n", delta));
154			DBGMSG(("renderobj->Get_pixel_depth() = %d\n",
155				fHalftone->GetPixelDepth()));
156
157			uchar* ptr = static_cast<uchar*>(bitmap->Bits())
158						+ rc.top * delta
159						+ (rc.left * fHalftone->GetPixelDepth()) / 8;
160
161			int compressionMethod;
162			int compressedSize;
163			const uchar* buffer;
164
165			std::vector<uchar> in_buffer(in_size);
166			std::vector<uchar> out_buffer(out_size);
167
168			uchar* ptr2 = &in_buffer[0];
169
170			DBGMSG(("move\n"));
171
172			_Move(x, y);
173
174			for (int i = rc.top; i <= rc.bottom; i++) {
175				fHalftone->Dither(ptr2, ptr, x, y, width);
176				ptr  += delta;
177				ptr2 += widthByte;
178				y++;
179			}
180
181			compressedSize = compress3(&out_buffer[0], &in_buffer[0], in_size);
182
183			if (compressedSize < in_size) {
184				compressionMethod = 9;
185					// compress3
186				buffer = &out_buffer[0];
187			} else if (compressedSize > out_size) {
188				BAlert* alert = new BAlert("memory overrun!!!", "warning",
189					"OK");
190				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
191				alert->Go();
192				return false;
193			} else {
194				compressionMethod = 0;
195				buffer = &in_buffer[0];
196				compressedSize = in_size;
197			}
198
199			DBGMSG(("compressedSize = %d\n", compressedSize));
200			DBGMSG(("widthByte = %d\n", widthByte));
201			DBGMSG(("height = %d\n", height));
202			DBGMSG(("compression_method = %d\n", compressionMethod));
203
204			_RasterGraphics(
205				compressedSize,	// size,
206				widthByte,			// widthByte
207				height,				// height,
208				compressionMethod,
209				buffer);
210
211		} else
212			DBGMSG(("band bitmap is clean.\n"));
213
214		if (y >= page_height) {
215			offset->x = -1.0;
216			offset->y = -1.0;
217		} else
218			offset->y += height;
219
220		DBGMSG(("< nextBand\n"));
221		return true;
222	}
223	catch (TransportException& err) {
224		BAlert* alert = new BAlert("", err.What(), "OK");
225		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
226		alert->Go();
227		return false;
228	}
229}
230
231
232void
233LIPS3Driver::_BeginTextMode()
234{
235	WriteSpoolString("\033%%@");
236}
237
238
239void
240LIPS3Driver::_JobStart()
241{
242	WriteSpoolString("\033P31;300;1J\033\\");
243}
244
245
246void
247LIPS3Driver::_SoftReset()
248{
249	WriteSpoolString("\033<");
250}
251
252
253void
254LIPS3Driver::_SizeUnitMode()
255{
256	WriteSpoolString("\033[11h");
257}
258
259
260void
261LIPS3Driver::_SelectSizeUnit()
262{
263	WriteSpoolString("\033[7 I");
264}
265
266
267void
268LIPS3Driver::_SelectPageFormat()
269{
270	int i;
271	int width  = 0;
272	int height = 0;
273
274	switch (GetJobData()->GetPaper()) {
275	case JobData::kA3:
276		i = 12;
277		break;
278
279	case JobData::kA4:
280		i = 14;
281		break;
282
283	case JobData::kA5:
284		i = 16;
285		break;
286
287	case JobData::kJapanesePostcard:
288		i = 18;
289		break;
290
291	case JobData::kB4:
292		i = 24;
293		break;
294
295	case JobData::kB5:
296		i = 26;
297		break;
298
299	case JobData::kLetter:
300		i = 30;
301		break;
302
303	case JobData::kLegal:
304		i = 32;
305		break;
306
307//	case JobData::kExecutive:
308//		i = 40;
309//		break;
310//
311//	case JobData::kJEnvYou4:
312//		i = 50;
313//		break;
314//
315//	case JobData::kUser:
316//		i = 90;
317//		break;
318//
319	default:
320		i = 80;
321		width  = GetJobData()->GetPaperRect().IntegerWidth();
322		height = GetJobData()->GetPaperRect().IntegerHeight();
323		break;
324	}
325
326	if (JobData::kLandscape == GetJobData()->GetOrientation())
327		i++;
328
329	if (i < 80)
330		WriteSpoolString("\033[%d;;p", i);
331	else
332		WriteSpoolString("\033[%d;%d;%dp", i, height, width);
333}
334
335
336void
337LIPS3Driver::_PaperFeedMode()
338{
339	// 0 auto
340	// --------------
341	// 1 MP tray
342	// 2 lower
343	// 3 lupper
344	// --------------
345	// 10 MP tray
346	// 11 casette 1
347	// 12 casette 2
348	// 13 casette 3
349	// 14 casette 4
350	// 15 casette 5
351	// 16 casette 6
352	// 17 casette 7
353
354	int i;
355
356	switch (GetJobData()->GetPaperSource()) {
357		case JobData::kManual:
358			i = 1;
359			break;
360		case JobData::kLower:
361			i = 2;
362			break;
363		case JobData::kUpper:
364			i = 3;
365			break;
366		case JobData::kAuto:
367		default:
368			i = 0;
369			break;
370	}
371
372	WriteSpoolString("\033[%dq", i);
373}
374
375
376void
377LIPS3Driver::_DisableAutoFF()
378{
379	WriteSpoolString("\033[?2h");
380}
381
382
383void
384LIPS3Driver::_SetNumberOfCopies()
385{
386	WriteSpoolString("\033[%ldv", GetJobData()->GetCopies());
387}
388
389
390void
391LIPS3Driver::_MemorizedPosition()
392{
393	WriteSpoolString("\033[0;1;0x");
394}
395
396
397void
398LIPS3Driver::_MoveAbsoluteHorizontal(int x)
399{
400	WriteSpoolString("\033[%d`", x);
401}
402
403
404void
405LIPS3Driver::_CarriageReturn()
406{
407	WriteSpoolChar('\x0d');
408}
409
410
411void
412LIPS3Driver::_MoveDown(int dy)
413{
414	WriteSpoolString("\033[%de", dy);
415}
416
417
418void
419LIPS3Driver::_RasterGraphics( int compressionSize, int widthbyte, int height,
420	int compressionMethod,	const uchar* buffer)
421{
422//  0 RAW
423//  9 compress-3
424	WriteSpoolString("\033[%d;%d;%d;%d;%d.r", compressionSize, widthbyte,
425		GetJobData()->GetXres(), compressionMethod, height);
426
427	WriteSpoolData(buffer, compressionSize);
428}
429
430
431void
432LIPS3Driver::_FormFeed()
433{
434	WriteSpoolChar('\014');
435}
436
437
438void
439LIPS3Driver::_JobEnd()
440{
441	WriteSpoolString("\033P0J\033\\");
442}
443
444
445void
446LIPS3Driver::_Move(int x, int y)
447{
448	if (fCurrentX != x) {
449		if (x)
450			_MoveAbsoluteHorizontal(x);
451		else
452			_CarriageReturn();
453
454		fCurrentX = x;
455	}
456	if (fCurrentY != y) {
457		int dy = y - fCurrentY;
458		_MoveDown(dy);
459		fCurrentY = y;
460	}
461}
462