vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / print / drivers / gutenprint / GPDriver.cpp
blobce1f04171953278617863e1593a9dd16f5dab8a6
1 /*
2 * GP.cpp
3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4 * Copyright 2010 Michael Pfeiffer.
5 */
8 #include "GPDriver.h"
10 #include <memory>
12 #include <Alert.h>
13 #include <Bitmap.h>
14 #include <Debug.h>
15 #include <File.h>
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"
28 using namespace std;
31 GPDriver::GPDriver(BMessage* message, PrinterData* printerData,
32 const PrinterCap* printerCap)
34 GraphicsDriver(message, printerData, printerCap)
38 void
39 GPDriver::Write(const void* buffer, size_t size)
40 throw (TransportException)
42 WriteSpoolData(buffer, size);
45 bool
46 GPDriver::StartDocument()
48 try {
49 const GPData* data = dynamic_cast<const GPData*>(GetPrinterData());
50 ASSERT(data != NULL);
51 fConfiguration.fDriver = data->fGutenprintDriverName;
53 SetParameter(fConfiguration.fPageSize, PrinterCap::kPaper,
54 GetJobData()->GetPaper());
56 SetParameter(fConfiguration.fResolution, PrinterCap::kResolution,
57 GetJobData()->GetResolutionID());
59 fConfiguration.fXDPI = GetJobData()->GetXres();
60 fConfiguration.fYDPI = GetJobData()->GetYres();
62 SetParameter(fConfiguration.fInputSlot, PrinterCap::kPaperSource,
63 GetJobData()->GetPaperSource());
65 SetParameter(fConfiguration.fPrintingMode, PrinterCap::kColor,
66 GetJobData()->GetColor());
68 if (GetPrinterCap()->Supports(PrinterCap::kDriverSpecificCapabilities))
69 SetDriverSpecificSettings();
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());
77 return fBinding.BeginJob(&fConfiguration, this) == B_OK;
79 catch (TransportException& err) {
80 return false;
85 void
86 GPDriver::SetParameter(BString& parameter, PrinterCap::CapID category,
87 int value)
89 const EnumCap* capability;
90 capability = GetPrinterCap()->FindCap(category, value);
91 if (capability != NULL && capability->fKey != "")
92 parameter = capability->Key();
96 void
97 GPDriver::SetDriverSpecificSettings()
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;
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;
134 void
135 GPDriver::AddDriverSpecificSetting(PrinterCap::CapID category, const char* key) {
136 const EnumCap* capability = NULL;
137 if (GetJobData()->Settings().HasString(key))
139 const string& value = GetJobData()->Settings().GetString(key);
140 capability = GetPrinterCap()->FindCapWithKey(category, value.c_str());
143 if (capability == NULL) {
144 // job data should contain a value;
145 // try to use the default value anyway
146 capability = GetPrinterCap()->GetDefaultCap(category);
149 if (capability == NULL) {
150 // should not reach here!
151 return;
154 fConfiguration.fStringSettings[key] = capability->fKey;
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);
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);
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);
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);
194 bool
195 GPDriver::StartPage(int)
197 fBinding.BeginPage();
198 return true;
202 bool
203 GPDriver::EndPage(int)
205 try {
206 fBinding.EndPage();
207 return true;
209 catch (TransportException& err) {
210 ShowError(err.What());
211 return false;
216 bool
217 GPDriver::EndDocument(bool)
219 try {
220 fBinding.EndJob();
221 return true;
223 catch (TransportException& err) {
224 ShowError(err.What());
225 return false;
230 bool
231 GPDriver::NextBand(BBitmap* bitmap, BPoint* offset)
233 DBGMSG(("> nextBand\n"));
234 try {
235 BRect bounds = bitmap->Bounds();
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;
243 int height = rc.bottom - rc.top + 1;
245 int x = (int)offset->x;
246 int y = (int)offset->y;
248 int pageHeight = GetPageHeight();
250 if (y + height > pageHeight)
251 height = pageHeight - y;
253 rc.bottom = height - 1;
255 DBGMSG(("height = %d\n", height));
256 DBGMSG(("x = %d\n", x));
257 DBGMSG(("y = %d\n", y));
259 if (get_valid_rect(bitmap, &rc)) {
261 DBGMSG(("validate rect = %d, %d, %d, %d\n",
262 rc.left, rc.top, rc.right, rc.bottom));
264 x = rc.left;
265 y += rc.top;
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;
283 } else {
284 DBGMSG(("band bitmap is empty.\n"));
287 if (y >= pageHeight) {
288 offset->x = -1.0;
289 offset->y = -1.0;
290 } else
291 offset->y += height;
293 DBGMSG(("< nextBand\n"));
294 return true;
296 catch (TransportException& err) {
297 ShowError(err.What());
298 return false;
303 void
304 GPDriver::ShowError(const char* message)
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();