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