/* * GP.cpp * Copyright 1999-2000 Y.Takagi. All Rights Reserved. * Copyright 2010 Michael Pfeiffer. */ #include "GPDriver.h" #include #include #include #include #include #include "DbgMsg.h" #include "Halftone.h" #include "JobData.h" #include "PackBits.h" #include "GPCapabilities.h" #include "GPData.h" #include "PrinterData.h" #include "UIDriver.h" #include "ValidRect.h" using namespace std; GPDriver::GPDriver(BMessage* message, PrinterData* printerData, const PrinterCap* printerCap) : GraphicsDriver(message, printerData, printerCap) { } void GPDriver::Write(const void* buffer, size_t size) { WriteSpoolData(buffer, size); } bool GPDriver::StartDocument() { try { const GPData* data = dynamic_cast(GetPrinterData()); ASSERT(data != NULL); fConfiguration.fDriver = data->fGutenprintDriverName; SetParameter(fConfiguration.fPageSize, PrinterCap::kPaper, GetJobData()->GetPaper()); SetParameter(fConfiguration.fResolution, PrinterCap::kResolution, GetJobData()->GetResolutionID()); fConfiguration.fXDPI = GetJobData()->GetXres(); fConfiguration.fYDPI = GetJobData()->GetYres(); SetParameter(fConfiguration.fInputSlot, PrinterCap::kPaperSource, GetJobData()->GetPaperSource()); SetParameter(fConfiguration.fPrintingMode, PrinterCap::kColor, GetJobData()->GetColor()); if (GetPrinterCap()->Supports(PrinterCap::kDriverSpecificCapabilities)) SetDriverSpecificSettings(); fprintf(stderr, "Driver: %s\n", fConfiguration.fDriver.String()); fprintf(stderr, "PageSize %s\n", fConfiguration.fPageSize.String()); fprintf(stderr, "Resolution %s\n", fConfiguration.fResolution.String()); fprintf(stderr, "InputSlot %s\n", fConfiguration.fInputSlot.String()); fprintf(stderr, "PrintingMode %s\n", fConfiguration.fPrintingMode.String()); return fBinding.BeginJob(&fConfiguration, this) == B_OK; } catch (TransportException& err) { return false; } } void GPDriver::SetParameter(BString& parameter, PrinterCap::CapID category, int value) { const EnumCap* capability; capability = GetPrinterCap()->FindCap(category, value); if (capability != NULL && capability->fKey != "") parameter = capability->Key(); } void GPDriver::SetDriverSpecificSettings() { PrinterCap::CapID category = PrinterCap::kDriverSpecificCapabilities; int count = GetPrinterCap()->CountCap(category); const BaseCap** capabilities = GetPrinterCap()->GetCaps(category); for (int i = 0; i < count; i++) { const DriverSpecificCap* capability = dynamic_cast(capabilities[i]); if (capability == NULL) { fprintf(stderr, "Internal error: DriverSpecificCap name='%s' " "has wrong type!\n", capabilities[i]->Label()); continue; } PrinterCap::CapID id = static_cast(capability->ID()); const char* key = capability->fKey.c_str(); switch (capability->fType) { case DriverSpecificCap::kList: AddDriverSpecificSetting(id, key); break; case DriverSpecificCap::kBoolean: AddDriverSpecificBooleanSetting(id, key); break; case DriverSpecificCap::kIntRange: AddDriverSpecificIntSetting(id, key); break; case DriverSpecificCap::kIntDimension: AddDriverSpecificDimensionSetting(id, key); break; case DriverSpecificCap::kDoubleRange: AddDriverSpecificDoubleSetting(id, key); break; } } } void GPDriver::AddDriverSpecificSetting(PrinterCap::CapID category, const char* key) { const EnumCap* capability = NULL; if (GetJobData()->Settings().HasString(key)) { const string& value = GetJobData()->Settings().GetString(key); capability = GetPrinterCap()->FindCapWithKey(category, value.c_str()); } if (capability == NULL) { // job data should contain a value; // try to use the default value anyway capability = GetPrinterCap()->GetDefaultCap(category); } if (capability == NULL) { // should not reach here! return; } fConfiguration.fStringSettings[key] = capability->fKey; } void GPDriver::AddDriverSpecificBooleanSetting(PrinterCap::CapID category, const char* key) { if (GetJobData()->Settings().HasBoolean(key)) fConfiguration.fBooleanSettings[key] = GetJobData()->Settings().GetBoolean(key); } void GPDriver::AddDriverSpecificIntSetting(PrinterCap::CapID category, const char* key) { if (GetJobData()->Settings().HasInt(key)) fConfiguration.fIntSettings[key] = GetJobData()->Settings().GetInt(key); } void GPDriver::AddDriverSpecificDimensionSetting(PrinterCap::CapID category, const char* key) { if (GetJobData()->Settings().HasInt(key)) fConfiguration.fDimensionSettings[key] = GetJobData()->Settings().GetInt(key); } void GPDriver::AddDriverSpecificDoubleSetting(PrinterCap::CapID category, const char* key) { if (GetJobData()->Settings().HasDouble(key)) fConfiguration.fDoubleSettings[key] = GetJobData()->Settings().GetDouble(key); } bool GPDriver::StartPage(int) { fBinding.BeginPage(); return true; } bool GPDriver::EndPage(int) { try { fBinding.EndPage(); return true; } catch (TransportException& err) { ShowError(err.What()); return false; } } bool GPDriver::EndDocument(bool) { try { fBinding.EndJob(); return true; } catch (TransportException& err) { ShowError(err.What()); return false; } } bool GPDriver::NextBand(BBitmap* bitmap, BPoint* offset) { DBGMSG(("> nextBand\n")); try { BRect bounds = bitmap->Bounds(); RECT rc; rc.left = (int)bounds.left; rc.top = (int)bounds.top; rc.right = (int)bounds.right; rc.bottom = (int)bounds.bottom; int height = rc.bottom - rc.top + 1; int x = (int)offset->x; int y = (int)offset->y; int pageHeight = GetPageHeight(); if (y + height > pageHeight) height = pageHeight - y; rc.bottom = height - 1; DBGMSG(("height = %d\n", height)); DBGMSG(("x = %d\n", x)); DBGMSG(("y = %d\n", y)); if (get_valid_rect(bitmap, &rc)) { DBGMSG(("validate rect = %d, %d, %d, %d\n", rc.left, rc.top, rc.right, rc.bottom)); x = rc.left; y += rc.top; int width = rc.right - rc.left + 1; int height = rc.bottom - rc.top + 1; fprintf(stderr, "GPDriver nextBand x %d, y %d, width %d," " height %d\n", x, y, width, height); BRect imageRect(rc.left, rc.top, rc.right, rc.bottom); status_t status; status = fBinding.AddBitmapToPage(bitmap, imageRect, BPoint(x, y)); if (status == B_NO_MEMORY) { ShowError("Out of memory"); return false; } else if (status != B_OK) { ShowError("Unknown error"); return false; } } else { DBGMSG(("band bitmap is empty.\n")); } if (y >= pageHeight) { offset->x = -1.0; offset->y = -1.0; } else offset->y += height; DBGMSG(("< nextBand\n")); return true; } catch (TransportException& err) { ShowError(err.What()); return false; } } void GPDriver::ShowError(const char* message) { BString text; text << "An error occurred attempting to print with Gutenprint:"; text << "\n"; text << message; BAlert* alert = new BAlert("", text.String(), "OK"); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); }