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