/* * Copyright 2010, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Pfeiffer */ #include "GPBinding.h" #include #include #include #include #include "GPCapabilityExtractor.h" using namespace std; // printer manufacturer static const char* kManufacturerId = "id"; static const char* kManufacturerDisplayName = "name"; // printer model static const char* kModelDisplayName = "model"; static const char* kModelDriver = "driver"; GPBinding::GPBinding() : fInitialized(false), fOutputStream(NULL) { } GPBinding::~GPBinding() { DeleteBands(); } status_t GPBinding::GetPrinterManufacturers(BMessage& manufacturers) { InitGutenprint(); list ids; set manufacturerSet; for (int i = 0; i < stp_printer_model_count(); i ++) { const stp_printer_t* printer = stp_get_printer_by_index(i); string manufacturer = stp_printer_get_manufacturer(printer); // ignore unnamed manufacturers if (manufacturer == "") continue; // add manufacturer only once if (manufacturerSet.find(manufacturer) != manufacturerSet.end()) continue; manufacturerSet.insert(manufacturer); ids.push_back(manufacturer); } ids.sort(); list::iterator it = ids.begin(); for (; it != ids.end(); it ++) { string manufacturer = *it; const char* id = manufacturer.c_str(); const char* name = manufacturer.c_str(); AddManufacturer(manufacturers, id, name); } return B_OK; } bool GPBinding::ExtractManufacturer(const BMessage& manufacturers, int32 index, BString& id, BString& displayName) { if (manufacturers.FindString(kManufacturerId, index, &id) != B_OK) return false; if (manufacturers.FindString(kManufacturerDisplayName, index, &displayName) != B_OK) return false; return true; } void GPBinding::AddManufacturer(BMessage& manufacturers, const char* id, const char* displayName) { manufacturers.AddString(kManufacturerId, id); manufacturers.AddString(kManufacturerDisplayName, displayName); } status_t GPBinding::GetPrinterModels(const char* manufacturer, BMessage& models) { for (int i = 0; i < stp_printer_model_count(); i ++) { const stp_printer_t* printer = stp_get_printer_by_index(i); if (strcmp(manufacturer, stp_printer_get_manufacturer(printer)) != 0) continue; const char* displayName = stp_printer_get_long_name(printer); const char* driver = stp_printer_get_driver(printer); AddModel(models, displayName, driver); } return B_OK; } bool GPBinding::ExtractModel(const BMessage& models, int32 index, BString& displayName, BString& driver) { if (models.FindString(kModelDisplayName, index, &displayName) != B_OK) return false; if (models.FindString(kModelDriver, index, &driver) != B_OK) return false; return true; } void GPBinding::AddModel(BMessage& models, const char* displayName, const char* driver) { models.AddString(kModelDisplayName, displayName); models.AddString(kModelDriver, driver); } status_t GPBinding::GetCapabilities(const char* driver, GPCapabilities* capabilities) { InitGutenprint(); const stp_printer_t* printer = stp_get_printer_by_driver(driver); if (printer == NULL) return B_ERROR; GPCapabilityExtractor extractor(capabilities); extractor.Visit(printer); return B_OK; } status_t GPBinding::BeginJob(GPJobConfiguration* configuration, OutputStream* outputStream) { fOutputStream = outputStream; fJob.SetApplicationName("Gutenprint"); fJob.SetConfiguration(configuration); fJob.SetOutputStream(outputStream); return fJob.Begin(); } void GPBinding::EndJob() { fJob.End(); fOutputStream = NULL; } void GPBinding::BeginPage() { } void GPBinding::EndPage() { status_t status = fJob.PrintPage(fBands); DeleteBands(); if (status == B_IO_ERROR) throw TransportException("I/O Error"); if (status == B_ERROR) { BString message; fJob.GetErrorMessage(message); throw TransportException(message.String()); } } status_t GPBinding::AddBitmapToPage(BBitmap* bitmap, BRect validRect, BPoint where) { GPBand* band = new(nothrow) GPBand(bitmap, validRect, where); if (band == NULL) { return B_NO_MEMORY; } fBands.push_back(band); return B_OK; } void GPBinding::InitGutenprint() { if (fInitialized) return; fInitialized = true; // there is no "destroy" counter part so this creates memory leaks // this is no problem because the print server loads printer add-ons // in a new application instance that is terminated when not used anymore stp_init(); stp_set_output_codeset("UTF-8"); } void GPBinding::DeleteBands() { list::iterator it = fBands.begin(); for (; it != fBands.end(); it ++) { GPBand* band = *it; delete band; } fBands.clear(); }