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 { 41 WriteSpoolData(buffer, size); 42 } 43 44 bool 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 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 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 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 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 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 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 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 194 GPDriver::StartPage(int) 195 { 196 fBinding.BeginPage(); 197 return true; 198 } 199 200 201 bool 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 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 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 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