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