xref: /haiku/src/add-ons/print/drivers/gutenprint/GPDriver.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2  * GP.cpp
3  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4  * Copyright 2010 Michael Pfeiffer.
5  */
6 
7 
8 #include "GPDriver.h"
9 
10 #include <memory>
11 
12 #include <Alert.h>
13 #include <Bitmap.h>
14 #include <Debug.h>
15 #include <File.h>
16 
17 #include "DbgMsg.h"
18 #include "Halftone.h"
19 #include "JobData.h"
20 #include "PackBits.h"
21 #include "GPCapabilities.h"
22 #include "GPData.h"
23 #include "PrinterData.h"
24 #include "UIDriver.h"
25 #include "ValidRect.h"
26 
27 
28 using namespace std;
29 
30 
31 GPDriver::GPDriver(BMessage* message, PrinterData* printerData,
32 	const PrinterCap* printerCap)
33 	:
34 	GraphicsDriver(message, printerData, printerCap)
35 {
36 }
37 
38 void
39 GPDriver::Write(const void* buffer, size_t size)
40 	throw (TransportException)
41 {
42 	WriteSpoolData(buffer, size);
43 }
44 
45 bool
46 GPDriver::StartDocument()
47 {
48 	try {
49 		const GPData* data = dynamic_cast<const GPData*>(GetPrinterData());
50 		ASSERT(data != NULL);
51 		fConfiguration.fDriver = data->fGutenprintDriverName;
52 
53 		SetParameter(fConfiguration.fPageSize, PrinterCap::kPaper,
54 			GetJobData()->GetPaper());
55 
56 		SetParameter(fConfiguration.fResolution, PrinterCap::kResolution,
57 			GetJobData()->GetResolutionID());
58 
59 		fConfiguration.fXDPI = GetJobData()->GetXres();
60 		fConfiguration.fYDPI = GetJobData()->GetYres();
61 
62 		SetParameter(fConfiguration.fInputSlot, PrinterCap::kPaperSource,
63 			GetJobData()->GetPaperSource());
64 
65 		SetParameter(fConfiguration.fPrintingMode, PrinterCap::kColor,
66 			GetJobData()->GetColor());
67 
68 		if (GetPrinterCap()->Supports(PrinterCap::kDriverSpecificCapabilities))
69 			SetDriverSpecificSettings();
70 
71 		fprintf(stderr, "Driver: %s\n", fConfiguration.fDriver.String());
72 		fprintf(stderr, "PageSize %s\n", fConfiguration.fPageSize.String());
73 		fprintf(stderr, "Resolution %s\n", fConfiguration.fResolution.String());
74 		fprintf(stderr, "InputSlot %s\n", fConfiguration.fInputSlot.String());
75 		fprintf(stderr, "PrintingMode %s\n", fConfiguration.fPrintingMode.String());
76 
77 		return fBinding.BeginJob(&fConfiguration, this) == B_OK;
78 	}
79 	catch (TransportException& err) {
80 		return false;
81 	}
82 }
83 
84 
85 void
86 GPDriver::SetParameter(BString& parameter, PrinterCap::CapID category,
87 	int value)
88 {
89 	const EnumCap* capability;
90 	capability = GetPrinterCap()->FindCap(category, value);
91 	if (capability != NULL && capability->fKey != "")
92 		parameter = capability->Key();
93 }
94 
95 
96 void
97 GPDriver::SetDriverSpecificSettings()
98 {
99 	PrinterCap::CapID category = PrinterCap::kDriverSpecificCapabilities;
100 	int count = GetPrinterCap()->CountCap(category);
101 	const BaseCap** capabilities = GetPrinterCap()->GetCaps(category);
102 	for (int i = 0; i < count; i++) {
103 		const DriverSpecificCap* capability =
104 			dynamic_cast<const DriverSpecificCap*>(capabilities[i]);
105 		if (capability == NULL) {
106 			fprintf(stderr, "Internal error: DriverSpecificCap name='%s' "
107 				"has wrong type!\n", capabilities[i]->Label());
108 			continue;
109 		}
110 
111 		PrinterCap::CapID id = static_cast<PrinterCap::CapID>(capability->ID());
112 		const char* key = capability->fKey.c_str();
113 		switch (capability->fType) {
114 			case DriverSpecificCap::kList:
115 				AddDriverSpecificSetting(id, key);
116 				break;
117 			case DriverSpecificCap::kBoolean:
118 				AddDriverSpecificBooleanSetting(id, key);
119 				break;
120 			case DriverSpecificCap::kIntRange:
121 				AddDriverSpecificIntSetting(id, key);
122 				break;
123 			case DriverSpecificCap::kIntDimension:
124 				AddDriverSpecificDimensionSetting(id, key);
125 				break;
126 			case DriverSpecificCap::kDoubleRange:
127 				AddDriverSpecificDoubleSetting(id, key);
128 				break;
129 		}
130 	}
131 }
132 
133 
134 void
135 GPDriver::AddDriverSpecificSetting(PrinterCap::CapID category, const char* key) {
136 	const EnumCap* capability = NULL;
137 	if (GetJobData()->Settings().HasString(key))
138 	{
139 		const string& value = GetJobData()->Settings().GetString(key);
140 		capability = GetPrinterCap()->FindCapWithKey(category, value.c_str());
141 	}
142 
143 	if (capability == NULL) {
144 		// job data should contain a value;
145 		// try to use the default value anyway
146 		capability = GetPrinterCap()->GetDefaultCap(category);
147 	}
148 
149 	if (capability == NULL) {
150 		// should not reach here!
151 		return;
152 	}
153 
154 	fConfiguration.fStringSettings[key] = capability->fKey;
155 }
156 
157 
158 void
159 GPDriver::AddDriverSpecificBooleanSetting(PrinterCap::CapID category,
160 	const char* key) {
161 	if (GetJobData()->Settings().HasBoolean(key))
162 		fConfiguration.fBooleanSettings[key] =
163 			GetJobData()->Settings().GetBoolean(key);
164 }
165 
166 
167 void
168 GPDriver::AddDriverSpecificIntSetting(PrinterCap::CapID category,
169 	const char* key) {
170 	if (GetJobData()->Settings().HasInt(key))
171 		fConfiguration.fIntSettings[key] =
172 			GetJobData()->Settings().GetInt(key);
173 }
174 
175 
176 void
177 GPDriver::AddDriverSpecificDimensionSetting(PrinterCap::CapID category,
178 	const char* key) {
179 	if (GetJobData()->Settings().HasInt(key))
180 		fConfiguration.fDimensionSettings[key] =
181 			GetJobData()->Settings().GetInt(key);
182 }
183 
184 
185 void
186 GPDriver::AddDriverSpecificDoubleSetting(PrinterCap::CapID category,
187 	const char* key) {
188 	if (GetJobData()->Settings().HasDouble(key))
189 		fConfiguration.fDoubleSettings[key] =
190 			GetJobData()->Settings().GetDouble(key);
191 }
192 
193 
194 bool
195 GPDriver::StartPage(int)
196 {
197 	fBinding.BeginPage();
198 	return true;
199 }
200 
201 
202 bool
203 GPDriver::EndPage(int)
204 {
205 	try {
206 		fBinding.EndPage();
207 		return true;
208 	}
209 	catch (TransportException& err) {
210 		ShowError(err.What());
211 		return false;
212 	}
213 }
214 
215 
216 bool
217 GPDriver::EndDocument(bool)
218 {
219 	try {
220 		fBinding.EndJob();
221 		return true;
222 	}
223 	catch (TransportException& err) {
224 		ShowError(err.What());
225 		return false;
226 	}
227 }
228 
229 
230 bool
231 GPDriver::NextBand(BBitmap* bitmap, BPoint* offset)
232 {
233 	DBGMSG(("> nextBand\n"));
234 	try {
235 		BRect bounds = bitmap->Bounds();
236 
237 		RECT rc;
238 		rc.left = (int)bounds.left;
239 		rc.top = (int)bounds.top;
240 		rc.right = (int)bounds.right;
241 		rc.bottom = (int)bounds.bottom;
242 
243 		int height = rc.bottom - rc.top + 1;
244 
245 		int x = (int)offset->x;
246 		int y = (int)offset->y;
247 
248 		int pageHeight = GetPageHeight();
249 
250 		if (y + height > pageHeight)
251 			height = pageHeight - y;
252 
253 		rc.bottom = height - 1;
254 
255 		DBGMSG(("height = %d\n", height));
256 		DBGMSG(("x = %d\n", x));
257 		DBGMSG(("y = %d\n", y));
258 
259 		if (get_valid_rect(bitmap, &rc)) {
260 
261 			DBGMSG(("validate rect = %d, %d, %d, %d\n",
262 				rc.left, rc.top, rc.right, rc.bottom));
263 
264 			x = rc.left;
265 			y += rc.top;
266 
267 			int width = rc.right - rc.left + 1;
268 			int height = rc.bottom - rc.top + 1;
269 			fprintf(stderr, "GPDriver nextBand x %d, y %d, width %d,"
270 				" height %d\n",
271 				x, y, width, height);
272 			BRect imageRect(rc.left, rc.top, rc.right, rc.bottom);
273 			status_t status;
274 			status = fBinding.AddBitmapToPage(bitmap, imageRect, BPoint(x, y));
275 			if (status == B_NO_MEMORY) {
276 				ShowError("Out of memory");
277 				return false;
278 			} else if (status != B_OK) {
279 				ShowError("Unknown error");
280 				return false;
281 			}
282 
283 		} else {
284 			DBGMSG(("band bitmap is empty.\n"));
285 		}
286 
287 		if (y >= pageHeight) {
288 			offset->x = -1.0;
289 			offset->y = -1.0;
290 		} else
291 			offset->y += height;
292 
293 		DBGMSG(("< nextBand\n"));
294 		return true;
295 	}
296 	catch (TransportException& err) {
297 		ShowError(err.What());
298 		return false;
299 	}
300 }
301 
302 
303 void
304 GPDriver::ShowError(const char* message)
305 {
306 	BString text;
307 	text << "An error occurred attempting to print with Gutenprint:";
308 	text << "\n";
309 	text << message;
310 	BAlert* alert = new BAlert("", text.String(), "OK");
311 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
312 	alert->Go();
313 }
314