From a2691840033027c58541fa8461f51ba1cb8e34ae Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Sat, 4 Jul 2009 07:19:51 +0000 Subject: [PATCH] Rotate page contents in landscape mode. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31404 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/print/drivers/postscript/PS.cpp | 606 ++++++++++---------- 1 file changed, 307 insertions(+), 299 deletions(-) diff --git a/src/add-ons/print/drivers/postscript/PS.cpp b/src/add-ons/print/drivers/postscript/PS.cpp index c5cf8c5f86..8cca54d6a7 100644 --- a/src/add-ons/print/drivers/postscript/PS.cpp +++ b/src/add-ons/print/drivers/postscript/PS.cpp @@ -1,299 +1,307 @@ -/* - * 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) -{ - fPrintedPages = 0; - fHalftone = NULL; -} - -bool PSDriver::startDoc() -{ - try { - jobStart(); - fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); - return true; - } - catch (TransportException &err) { - return false; - } -} - -bool PSDriver::startPage(int page) -{ - page ++; - writeSpoolString("%%%%Page: %d %d\n", page, page); - writeSpoolString("gsave\n"); - setupCTM(); - return true; -} - -bool PSDriver::endPage(int) -{ - try { - fPrintedPages ++; - writeSpoolString("grestore\n"); - writeSpoolString("showpage\n"); - return true; - } - catch (TransportException &err) { - return false; - } -} - -void PSDriver::setupCTM() { - const float leftMargin = getJobData()->getPrintableRect().left; - const float topMargin = getJobData()->getPrintableRect().top; - // move origin from bottom left to top left - // and set margin - writeSpoolString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin); - // 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()); -} - -bool PSDriver::endDoc(bool) -{ - try { - if (fHalftone) { - delete fHalftone; - } - 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, &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", fHalftone->getPixelDepth())); - - uchar *ptr = (uchar *)bitmap->Bits() - + rc.top * delta - + (rc.left * fHalftone->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 { - fHalftone->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("%%%%DocumentMedia: Plain %d %d white 0 ( )\n", getJobData()->getPaperRect().IntegerWidth(), getJobData()->getPaperRect().IntegerHeight()); - writeSpoolString("%%%%Pages: (atend)\n"); - writeSpoolString("%%%%EndComments\n"); - - writeSpoolString("%%%%BeginDefaults\n"); - writeSpoolString("%%%%PageMedia: Plain\n"); - writeSpoolString("%%%%EndDefaults\n"); -} - -void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte) -{ - bool color = getJobData()->getColor() == JobData::kColor; - fCompressionMethod = -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 (fCompressionMethod != compression_method) { - fCompressionMethod = compression_method; - } - writeSpoolData(buffer, size); - writeSpoolString("\n"); -} - -void PSDriver::jobEnd() -{ - writeSpoolString("%%%%Pages: %d\n", fPrintedPages); - writeSpoolString("%%%%EOF\n"); -} +/* + * 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) +{ + fPrintedPages = 0; + fHalftone = NULL; +} + +bool PSDriver::startDoc() +{ + try { + jobStart(); + fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); + return true; + } + catch (TransportException &err) { + return false; + } +} + +bool PSDriver::startPage(int page) +{ + page ++; + writeSpoolString("%%%%Page: %d %d\n", page, page); + writeSpoolString("gsave\n"); + setupCTM(); + return true; +} + +bool PSDriver::endPage(int) +{ + try { + fPrintedPages ++; + writeSpoolString("grestore\n"); + writeSpoolString("showpage\n"); + return true; + } + catch (TransportException &err) { + return false; + } +} + +void PSDriver::setupCTM() { + const float leftMargin = getJobData()->getPrintableRect().left; + const float topMargin = getJobData()->getPrintableRect().top; + if (getJobData()->getOrientation() == JobData::kPortrait) { + // move origin from bottom left to top left + // and set margin + writeSpoolString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin); + } else { + // landscape: + // move origin from bottom left to margin top and left + // and rotate page contents + writeSpoolString("%f %f translate\n", topMargin, leftMargin); + writeSpoolString("90 rotate\n"); + } + // 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()); +} + +bool PSDriver::endDoc(bool) +{ + try { + if (fHalftone) { + delete fHalftone; + } + 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, &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", fHalftone->getPixelDepth())); + + uchar *ptr = (uchar *)bitmap->Bits() + + rc.top * delta + + (rc.left * fHalftone->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 { + fHalftone->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("%%%%DocumentMedia: Plain %d %d white 0 ( )\n", getJobData()->getPaperRect().IntegerWidth(), getJobData()->getPaperRect().IntegerHeight()); + writeSpoolString("%%%%Pages: (atend)\n"); + writeSpoolString("%%%%EndComments\n"); + + writeSpoolString("%%%%BeginDefaults\n"); + writeSpoolString("%%%%PageMedia: Plain\n"); + writeSpoolString("%%%%EndDefaults\n"); +} + +void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte) +{ + bool color = getJobData()->getColor() == JobData::kColor; + fCompressionMethod = -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 (fCompressionMethod != compression_method) { + fCompressionMethod = compression_method; + } + writeSpoolData(buffer, size); + writeSpoolString("\n"); +} + +void PSDriver::jobEnd() +{ + writeSpoolString("%%%%Pages: %d\n", fPrintedPages); + writeSpoolString("%%%%EOF\n"); +}