diff --git a/src/add-ons/print/drivers/postscript/Jamfile b/src/add-ons/print/drivers/postscript/Jamfile new file mode 100644 index 0000000000..3f52e8cf5e --- /dev/null +++ b/src/add-ons/print/drivers/postscript/Jamfile @@ -0,0 +1,15 @@ +SubDir OBOS_TOP src add-ons print drivers postscript ; + +SubDirHdrs [ FDirName $(OBOS_TOP) src add-ons print drivers canon_lips + libprint ] ; + +AddResources PS\ Compatible : PS.rsrc ; + +Addon PS\ Compatible : print : + PSEntry.cpp + PS.cpp + PSCap.cpp +; + +LinkSharedOSLibs PS\ Compatible : be stdc++.r4 libprint.a ; + diff --git a/src/add-ons/print/drivers/postscript/PS.cpp b/src/add-ons/print/drivers/postscript/PS.cpp new file mode 100644 index 0000000000..ef5567f79b --- /dev/null +++ b/src/add-ons/print/drivers/postscript/PS.cpp @@ -0,0 +1,287 @@ +/* + * PS.cpp + * Copyright 1999-2000 Y.Takagi. All Rights Reserved. + * Copyright 2003 Michael Pfeiffer. + */ + +#include +#include +#include +#include +#include +#include "PS.h" +#include "UIDriver.h" +#include "JobData.h" +#include "PrinterData.h" +#include "PSCap.h" +#include "PackBits.h" +#include "Halftone.h" +#include "ValidRect.h" +#include "DbgMsg.h" + +#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) +using namespace std; +#else +#define std +#endif + +PSDriver::PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) + : GraphicsDriver(msg, printer_data, printer_cap) +{ + __printed_pages = 0; + __halftone = NULL; +} + +bool PSDriver::startDoc() +{ + try { + jobStart(); + __halftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma()); + return true; + } + catch (TransportException &err) { + return false; + } +} + +bool PSDriver::startPage(int page) +{ + page ++; + writeSpoolString("%%%%Page: %d %d\n", page, page); + return true; +} + +bool PSDriver::endPage(int) +{ + try { + __printed_pages ++; + writeSpoolString("showpage\n"); + return true; + } + catch (TransportException &err) { + return false; + } +} + +bool PSDriver::endDoc(bool) +{ + try { + if (__halftone) { + delete __halftone; + } + jobEnd(); + return true; + } + catch (TransportException &err) { + return false; + } +} + +inline uchar hex_digit(uchar value) +{ + if (value <= 9) return '0'+value; + else return 'a'+(value-10); +} + +bool PSDriver::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 page_height = getPageHeight(); + + if (y + height > page_height) { + height = page_height - 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, __halftone->getPalette(), &rc)) { + + DBGMSG(("validate rect = %d, %d, %d, %d\n", + rc.left, rc.top, rc.right, rc.bottom)); + + x = rc.left; + y += rc.top; + + bool color = getJobData()->getColor() == JobData::kCOLOR; + int width = rc.right - rc.left + 1; + int widthByte = (width + 7) / 8; /* byte boundary */ + int height = rc.bottom - rc.top + 1; + int in_size = color ? width : widthByte; + int out_size = color ? width * 6: widthByte * 2; + int delta = bitmap->BytesPerRow(); + + DBGMSG(("width = %d\n", width)); + DBGMSG(("widthByte = %d\n", widthByte)); + DBGMSG(("height = %d\n", height)); + DBGMSG(("out_size = %d\n", out_size)); + DBGMSG(("delta = %d\n", delta)); + DBGMSG(("renderobj->get_pixel_depth() = %d\n", __halftone->getPixelDepth())); + + uchar *ptr = (uchar *)bitmap->Bits() + + rc.top * delta + + (rc.left * __halftone->getPixelDepth()) / 8; + + int compression_method; + int compressed_size; + const uchar *buffer; + + uchar *in_buffer = new uchar[in_size]; // gray values + uchar *out_buffer = new uchar[out_size]; // gray values in hexadecimal + + auto_ptr _in_buffer(in_buffer); + auto_ptr _out_buffer(out_buffer); + + DBGMSG(("move\n")); + + int size = color ? width*3 : in_size; + startRasterGraphics(x, y, width, height, size); + + for (int i = rc.top; i <= rc.bottom; i++) { + if (color) { + uchar* out = out_buffer; + uchar* in = ptr; + for (int w = width; w > 0; w --) { + *out++ = hex_digit((in[2]) >> 4); + *out++ = hex_digit((in[2]) & 15); + *out++ = hex_digit((in[1]) >> 4); + *out++ = hex_digit((in[1]) & 15); + *out++ = hex_digit((in[0]) >> 4); + *out++ = hex_digit((in[0]) & 15); + in += 4; + } + } else { + __halftone->dither(in_buffer, ptr, x, y, width); + + uchar* in = in_buffer; + uchar* out = out_buffer; + + for (int w = in_size; w > 0; w --, in ++) { + *in = ~*in; // invert pixels + *out++ = hex_digit((*in) >> 4); + *out++ = hex_digit((*in) & 15); + } + } + + { + compression_method = 0; // uncompressed + buffer = out_buffer; + compressed_size = out_size; + } + + rasterGraphics( + compression_method, + buffer, + compressed_size); + + ptr += delta; + y++; + } + + endRasterGraphics(); + + } else { + DBGMSG(("band bitmap is clean.\n")); + } + + if (y >= page_height) { + offset->x = -1.0; + offset->y = -1.0; + } else { + offset->y += height; + } + + + DBGMSG(("< nextBand\n")); + return true; + } + catch (TransportException &err) { + BAlert *alert = new BAlert("", err.what(), "OK"); + alert->Go(); + return false; + } +} + +void PSDriver::jobStart() +{ + // PostScript header + writeSpoolString("%%!PS-Adobe-3.0\n"); + writeSpoolString("%%%%LanguageLevel: 1\n"); + writeSpoolString("%%%%Title: %s\n", getSpoolMetaData()->getDescription().c_str()); + writeSpoolString("%%%%Creator: %s\n", getSpoolMetaData()->getMimeType().c_str()); + writeSpoolString("%%%%CreationDate: %s", getSpoolMetaData()->getCreationTime().c_str()); + writeSpoolString("%%%%Pages: (atend)\n"); + writeSpoolString("%%%%EndComments\n"); + // setup CTM + writeSpoolString("%%%%BeginSetup\n"); + // move origin from bottom left to top left + writeSpoolString("0 %f translate\n", getJobData()->getPaperRect().Height()); + // y values increase from top to bottom + // units of measure is dpi + writeSpoolString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres()); + writeSpoolString("%%%%EndSetup\n"); +} + +void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte) +{ + bool color = getJobData()->getColor() == JobData::kCOLOR; + __compression_method = -1; + writeSpoolString("gsave\n"); + writeSpoolString("/s %d string def\n", widthByte); + writeSpoolString("%d %d translate\n", x, y); + writeSpoolString("%d %d scale\n", width, height); + if (color) { + writeSpoolString("%d %d 8\n", width, height); // 8 bpp + } else { + writeSpoolString("%d %d 1\n", width, height); // 1 bpp + } + writeSpoolString("[%d 0 0 %d 0 0]\n", width, height); + writeSpoolString("{ currentfile s readhexstring pop }\n"); + if (color) { + writeSpoolString("false 3\n"); // single data source, 3 color components + writeSpoolString("colorimage\n"); + } else { + writeSpoolString("image\n\n"); + } +} + +void PSDriver::endRasterGraphics() +{ + writeSpoolString("grestore\n"); +} + +void PSDriver::rasterGraphics( + int compression_method, + const uchar *buffer, + int size) +{ + if (__compression_method != compression_method) { + __compression_method = compression_method; + } + writeSpoolData(buffer, size); + writeSpoolString("\n"); +} + +void PSDriver::jobEnd() +{ + writeSpoolString("%%%%Pages: %d\n", __printed_pages); + writeSpoolString("%%%%EOF\n"); +} diff --git a/src/add-ons/print/drivers/postscript/PS.h b/src/add-ons/print/drivers/postscript/PS.h new file mode 100644 index 0000000000..ace8dd8e05 --- /dev/null +++ b/src/add-ons/print/drivers/postscript/PS.h @@ -0,0 +1,40 @@ +/* + * PS.h + * Copyright 1999-2000 Y.Takagi. All Rights Reserved. + */ + +#ifndef __PS_H +#define __PS_H + +#include "GraphicsDriver.h" + +class Halftone; + +class PSDriver : public GraphicsDriver { +public: + PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap); + +protected: + virtual bool startDoc(); + virtual bool startPage(int page); + virtual bool nextBand(BBitmap *bitmap, BPoint *offset); + virtual bool endPage(int page); + virtual bool endDoc(bool success); + +private: + void jobStart(); + float scale(int d); + void startRasterGraphics(int x, int y, int width, int height, int widthByte); + void endRasterGraphics(); + void rasterGraphics( + int compression_method, + const uchar *buffer, + int size); + void jobEnd(); + + int __printed_pages; + int __compression_method; + Halftone *__halftone; +}; + +#endif /* __PS_H */ diff --git a/src/add-ons/print/drivers/postscript/PS.rsrc b/src/add-ons/print/drivers/postscript/PS.rsrc new file mode 100644 index 0000000000..6635cc515b Binary files /dev/null and b/src/add-ons/print/drivers/postscript/PS.rsrc differ diff --git a/src/add-ons/print/drivers/postscript/PSCap.cpp b/src/add-ons/print/drivers/postscript/PSCap.cpp new file mode 100644 index 0000000000..0904ab900c --- /dev/null +++ b/src/add-ons/print/drivers/postscript/PSCap.cpp @@ -0,0 +1,149 @@ +/* + * PSCap.cpp + * Copyright 1999-2000 Y.Takagi. All Rights Reserved. + */ + +#include "PrinterData.h" +#include "PSCap.h" + +#define TO72DPI(a) (a * 72.0f / 600.0f) + +const PaperCap a3( + "A3", + false, + JobData::A3, + BRect(0.0f, 0.0f, TO72DPI(7014.0f), TO72DPI(9920.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(6894.0f), TO72DPI(9800.0f))); + +const PaperCap a4( + "A4", + true, + JobData::A4, + BRect(0.0f, 0.0f, TO72DPI(4960.0f), TO72DPI(7014.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4840.0f), TO72DPI(6894.0f))); + +const PaperCap a5( + "A5", + false, + JobData::A5, + BRect(0.0f, 0.0f, TO72DPI(3506.0f), TO72DPI(4960.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(3386.0f), TO72DPI(4840.0f))); + +const PaperCap japanese_postcard( + "Japanese Postcard", + false, + JobData::JAPANESE_POSTCARD, + BRect(0.0f, 0.0f, TO72DPI(2362.0f), TO72DPI(3506.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(2242.0f), TO72DPI(3386.0f))); + +const PaperCap b4( + "B4", + false, + JobData::B4, + BRect(0.0f, 0.0f, TO72DPI(6070.0f), TO72DPI(8598.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(5950.0f), TO72DPI(8478.0f))); + +const PaperCap b5( + "B5", + false, + JobData::B5, + BRect(0.0f, 0.0f, TO72DPI(4298.0f), TO72DPI(6070.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4178.0f), TO72DPI(5950.0f))); + +const PaperCap letter( + "Letter", + false, + JobData::LETTER, + BRect(0.0f, 0.0f, TO72DPI(5100.0f), TO72DPI(6600.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4980.0f), TO72DPI(6480.0f))); + +const PaperCap legal( + "Legal", + false, + JobData::LEGAL, + BRect(0.0f, 0.0f, TO72DPI(5100.0f), TO72DPI(8400.0f)), + BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4980.0f), TO72DPI(8280.0f))); + +const PaperSourceCap autobin("Auto", true, JobData::AUTO); + +const ResolutionCap dpi300("300dpi", true, 300, 300); +const ResolutionCap dpi600("600dpi", false, 600, 600); +const ResolutionCap dpi1200("1200dpi", false, 1200, 1200); + +const PaperCap *papers[] = { + &a4, + &a3, + &a5, + &b4, + &b5, + &letter, + &legal +}; + +const PaperSourceCap *papersources[] = { + &autobin, +}; + +const ResolutionCap *resolutions[] = { + &dpi300, + &dpi600, + &dpi1200, +}; + +const ColorCap color("Color", false, JobData::kCOLOR); +const ColorCap monochrome("Monochrome", true, JobData::kMONOCHROME); + +const ColorCap *colors[] = { + &color, + &monochrome +}; + +PSCap::PSCap(const PrinterData *printer_data) + : PrinterCap(printer_data) +{ +} + +int PSCap::countCap(CAPID capid) const +{ + switch (capid) { + case PAPER: + return sizeof(papers) / sizeof(papers[0]); + case PAPERSOURCE: + return sizeof(papersources) / sizeof(papersources[0]); + case RESOLUTION: + return sizeof(resolutions) / sizeof(resolutions[0]); + case COLOR: + return sizeof(colors) / sizeof(colors[0]); + default: + return 0; + } +} + +const BaseCap **PSCap::enumCap(CAPID capid) const +{ + switch (capid) { + case PAPER: + return (const BaseCap **)papers; + case PAPERSOURCE: + return (const BaseCap **)papersources; + case RESOLUTION: + return (const BaseCap **)resolutions; + case COLOR: + return (const BaseCap **)colors; + default: + return NULL; + } +} + +bool PSCap::isSupport(CAPID capid) const +{ + switch (capid) { + case PAPER: + case PAPERSOURCE: + case RESOLUTION: + case COLOR: + return true; + default: + return false; + } +} diff --git a/src/add-ons/print/drivers/postscript/PSCap.h b/src/add-ons/print/drivers/postscript/PSCap.h new file mode 100644 index 0000000000..d917f230e3 --- /dev/null +++ b/src/add-ons/print/drivers/postscript/PSCap.h @@ -0,0 +1,19 @@ +/* + * PSCap.h + * Copyright 1999-2000 Y.Takagi. All Rights Reserved. + */ + +#ifndef __PSCAP_H +#define __PSCAP_H + +#include "PrinterCap.h" + +class PSCap : public PrinterCap { +public: + PSCap(const PrinterData *printer_data); + virtual int countCap(CAPID) const; + virtual bool isSupport(CAPID) const; + virtual const BaseCap **enumCap(CAPID) const; +}; + +#endif /* __PSCAP_H */ diff --git a/src/add-ons/print/drivers/postscript/PSEntry.cpp b/src/add-ons/print/drivers/postscript/PSEntry.cpp new file mode 100644 index 0000000000..af40d10567 --- /dev/null +++ b/src/add-ons/print/drivers/postscript/PSEntry.cpp @@ -0,0 +1,83 @@ +/* + * PSEntry.cpp + * Copyright 1999-2000 Y.Takagi. All Rights Reserved. + * Copyright 2003 Michael Pfeiffer. + */ + +#include +#include +#include + +#include "Exports.h" +#include "PS.h" +#include "PrinterData.h" +#include "PSCap.h" +#include "UIDriver.h" +#include "AboutBox.h" +#include "DbgMsg.h" + +char *add_printer(char *printer_name) +{ + DBGMSG((">PS: add_printer\n")); + DBGMSG(("\tprinter_name: %s\n", printer_name)); + DBGMSG(("PS: config_page\n")); + DUMP_BMESSAGE(msg); + DUMP_BNODE(node); + + PrinterData printer_data(node); + PSCap printer_cap(&printer_data); + UIDriver drv(msg, &printer_data, &printer_cap); + BMessage *result = drv.configPage(); + + DUMP_BMESSAGE(result); + DBGMSG(("PS: config_job\n")); + DUMP_BMESSAGE(msg); + DUMP_BNODE(node); + + PrinterData printer_data(node); + PSCap printer_cap(&printer_data); + UIDriver drv(msg, &printer_data, &printer_cap); + BMessage *result = drv.configJob(); + + DUMP_BMESSAGE(result); + DBGMSG(("PS: take_job\n")); + DUMP_BMESSAGE(msg); + DUMP_BNODE(node); + + PrinterData printer_data(node); + PSCap printer_cap(&printer_data); + PSDriver drv(msg, &printer_data, &printer_cap); + BMessage *result = drv.takeJob(spool); + +// DUMP_BMESSAGE(result); + DBGMSG(("