Rotate page contents in landscape mode.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31404 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2009-07-04 07:19:51 +00:00
parent 35c255e59d
commit a269184003

View File

@ -1,299 +1,307 @@
/* /*
* PS.cpp * PS.cpp
* Copyright 1999-2000 Y.Takagi. All Rights Reserved. * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
* Copyright 2003 Michael Pfeiffer. * Copyright 2003 Michael Pfeiffer.
*/ */
#include <Alert.h> #include <Alert.h>
#include <Bitmap.h> #include <Bitmap.h>
#include <File.h> #include <File.h>
#include <memory> #include <memory>
#include <stdio.h> #include <stdio.h>
#include "PS.h" #include "PS.h"
#include "UIDriver.h" #include "UIDriver.h"
#include "JobData.h" #include "JobData.h"
#include "PrinterData.h" #include "PrinterData.h"
#include "PSCap.h" #include "PSCap.h"
#include "PackBits.h" #include "PackBits.h"
#include "Halftone.h" #include "Halftone.h"
#include "ValidRect.h" #include "ValidRect.h"
#include "DbgMsg.h" #include "DbgMsg.h"
#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE)) #if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
using namespace std; using namespace std;
#else #else
#define std #define std
#endif #endif
PSDriver::PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap) PSDriver::PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
: GraphicsDriver(msg, printer_data, printer_cap) : GraphicsDriver(msg, printer_data, printer_cap)
{ {
fPrintedPages = 0; fPrintedPages = 0;
fHalftone = NULL; fHalftone = NULL;
} }
bool PSDriver::startDoc() bool PSDriver::startDoc()
{ {
try { try {
jobStart(); jobStart();
fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType()); fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType());
return true; return true;
} }
catch (TransportException &err) { catch (TransportException &err) {
return false; return false;
} }
} }
bool PSDriver::startPage(int page) bool PSDriver::startPage(int page)
{ {
page ++; page ++;
writeSpoolString("%%%%Page: %d %d\n", page, page); writeSpoolString("%%%%Page: %d %d\n", page, page);
writeSpoolString("gsave\n"); writeSpoolString("gsave\n");
setupCTM(); setupCTM();
return true; return true;
} }
bool PSDriver::endPage(int) bool PSDriver::endPage(int)
{ {
try { try {
fPrintedPages ++; fPrintedPages ++;
writeSpoolString("grestore\n"); writeSpoolString("grestore\n");
writeSpoolString("showpage\n"); writeSpoolString("showpage\n");
return true; return true;
} }
catch (TransportException &err) { catch (TransportException &err) {
return false; return false;
} }
} }
void PSDriver::setupCTM() { void PSDriver::setupCTM() {
const float leftMargin = getJobData()->getPrintableRect().left; const float leftMargin = getJobData()->getPrintableRect().left;
const float topMargin = getJobData()->getPrintableRect().top; const float topMargin = getJobData()->getPrintableRect().top;
// move origin from bottom left to top left if (getJobData()->getOrientation() == JobData::kPortrait) {
// and set margin // move origin from bottom left to top left
writeSpoolString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin); // and set margin
// y values increase from top to bottom writeSpoolString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin);
// units of measure is dpi } else {
writeSpoolString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres()); // landscape:
} // move origin from bottom left to margin top and left
// and rotate page contents
bool PSDriver::endDoc(bool) writeSpoolString("%f %f translate\n", topMargin, leftMargin);
{ writeSpoolString("90 rotate\n");
try { }
if (fHalftone) { // y values increase from top to bottom
delete fHalftone; // units of measure is dpi
} writeSpoolString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres());
jobEnd(); }
return true;
} bool PSDriver::endDoc(bool)
catch (TransportException &err) { {
return false; try {
} if (fHalftone) {
} delete fHalftone;
}
inline uchar hex_digit(uchar value) jobEnd();
{ return true;
if (value <= 9) return '0'+value; }
else return 'a'+(value-10); catch (TransportException &err) {
} return false;
}
bool PSDriver::nextBand(BBitmap *bitmap, BPoint *offset) }
{
DBGMSG(("> nextBand\n")); inline uchar hex_digit(uchar value)
{
try { if (value <= 9) return '0'+value;
BRect bounds = bitmap->Bounds(); else return 'a'+(value-10);
}
RECT rc;
rc.left = (int)bounds.left; bool PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
rc.top = (int)bounds.top; {
rc.right = (int)bounds.right; DBGMSG(("> nextBand\n"));
rc.bottom = (int)bounds.bottom;
try {
int height = rc.bottom - rc.top + 1; BRect bounds = bitmap->Bounds();
int x = (int)offset->x; RECT rc;
int y = (int)offset->y; rc.left = (int)bounds.left;
rc.top = (int)bounds.top;
int page_height = getPageHeight(); rc.right = (int)bounds.right;
rc.bottom = (int)bounds.bottom;
if (y + height > page_height) {
height = page_height - y; int height = rc.bottom - rc.top + 1;
}
int x = (int)offset->x;
rc.bottom = height - 1; int y = (int)offset->y;
DBGMSG(("height = %d\n", height)); int page_height = getPageHeight();
DBGMSG(("x = %d\n", x));
DBGMSG(("y = %d\n", y)); if (y + height > page_height) {
height = page_height - y;
if (get_valid_rect(bitmap, &rc)) { }
DBGMSG(("validate rect = %d, %d, %d, %d\n", rc.bottom = height - 1;
rc.left, rc.top, rc.right, rc.bottom));
DBGMSG(("height = %d\n", height));
x = rc.left; DBGMSG(("x = %d\n", x));
y += rc.top; DBGMSG(("y = %d\n", y));
bool color = getJobData()->getColor() == JobData::kColor; if (get_valid_rect(bitmap, &rc)) {
int width = rc.right - rc.left + 1;
int widthByte = (width + 7) / 8; /* byte boundary */ DBGMSG(("validate rect = %d, %d, %d, %d\n",
int height = rc.bottom - rc.top + 1; rc.left, rc.top, rc.right, rc.bottom));
int in_size = color ? width : widthByte;
int out_size = color ? width * 6: widthByte * 2; x = rc.left;
int delta = bitmap->BytesPerRow(); y += rc.top;
DBGMSG(("width = %d\n", width)); bool color = getJobData()->getColor() == JobData::kColor;
DBGMSG(("widthByte = %d\n", widthByte)); int width = rc.right - rc.left + 1;
DBGMSG(("height = %d\n", height)); int widthByte = (width + 7) / 8; /* byte boundary */
DBGMSG(("out_size = %d\n", out_size)); int height = rc.bottom - rc.top + 1;
DBGMSG(("delta = %d\n", delta)); int in_size = color ? width : widthByte;
DBGMSG(("renderobj->get_pixel_depth() = %d\n", fHalftone->getPixelDepth())); int out_size = color ? width * 6: widthByte * 2;
int delta = bitmap->BytesPerRow();
uchar *ptr = (uchar *)bitmap->Bits()
+ rc.top * delta DBGMSG(("width = %d\n", width));
+ (rc.left * fHalftone->getPixelDepth()) / 8; DBGMSG(("widthByte = %d\n", widthByte));
DBGMSG(("height = %d\n", height));
int compression_method; DBGMSG(("out_size = %d\n", out_size));
int compressed_size; DBGMSG(("delta = %d\n", delta));
const uchar *buffer; DBGMSG(("renderobj->get_pixel_depth() = %d\n", fHalftone->getPixelDepth()));
uchar *in_buffer = new uchar[in_size]; // gray values uchar *ptr = (uchar *)bitmap->Bits()
uchar *out_buffer = new uchar[out_size]; // gray values in hexadecimal + rc.top * delta
+ (rc.left * fHalftone->getPixelDepth()) / 8;
auto_ptr<uchar> _in_buffer(in_buffer);
auto_ptr<uchar> _out_buffer(out_buffer); int compression_method;
int compressed_size;
DBGMSG(("move\n")); const uchar *buffer;
int size = color ? width*3 : in_size; uchar *in_buffer = new uchar[in_size]; // gray values
startRasterGraphics(x, y, width, height, size); uchar *out_buffer = new uchar[out_size]; // gray values in hexadecimal
for (int i = rc.top; i <= rc.bottom; i++) { auto_ptr<uchar> _in_buffer(in_buffer);
if (color) { auto_ptr<uchar> _out_buffer(out_buffer);
uchar* out = out_buffer;
uchar* in = ptr; DBGMSG(("move\n"));
for (int w = width; w > 0; w --) {
*out++ = hex_digit((in[2]) >> 4); int size = color ? width*3 : in_size;
*out++ = hex_digit((in[2]) & 15); startRasterGraphics(x, y, width, height, size);
*out++ = hex_digit((in[1]) >> 4);
*out++ = hex_digit((in[1]) & 15); for (int i = rc.top; i <= rc.bottom; i++) {
*out++ = hex_digit((in[0]) >> 4); if (color) {
*out++ = hex_digit((in[0]) & 15); uchar* out = out_buffer;
in += 4; uchar* in = ptr;
} for (int w = width; w > 0; w --) {
} else { *out++ = hex_digit((in[2]) >> 4);
fHalftone->dither(in_buffer, ptr, x, y, width); *out++ = hex_digit((in[2]) & 15);
*out++ = hex_digit((in[1]) >> 4);
uchar* in = in_buffer; *out++ = hex_digit((in[1]) & 15);
uchar* out = out_buffer; *out++ = hex_digit((in[0]) >> 4);
*out++ = hex_digit((in[0]) & 15);
for (int w = in_size; w > 0; w --, in ++) { in += 4;
*in = ~*in; // invert pixels }
*out++ = hex_digit((*in) >> 4); } else {
*out++ = hex_digit((*in) & 15); fHalftone->dither(in_buffer, ptr, x, y, width);
}
} uchar* in = in_buffer;
uchar* out = out_buffer;
{
compression_method = 0; // uncompressed for (int w = in_size; w > 0; w --, in ++) {
buffer = out_buffer; *in = ~*in; // invert pixels
compressed_size = out_size; *out++ = hex_digit((*in) >> 4);
} *out++ = hex_digit((*in) & 15);
}
rasterGraphics( }
compression_method,
buffer, {
compressed_size); compression_method = 0; // uncompressed
buffer = out_buffer;
ptr += delta; compressed_size = out_size;
y++; }
}
rasterGraphics(
endRasterGraphics(); compression_method,
buffer,
} else { compressed_size);
DBGMSG(("band bitmap is clean.\n"));
} ptr += delta;
y++;
if (y >= page_height) { }
offset->x = -1.0;
offset->y = -1.0; endRasterGraphics();
} else {
offset->y += height; } else {
} DBGMSG(("band bitmap is clean.\n"));
}
DBGMSG(("< nextBand\n")); if (y >= page_height) {
return true; offset->x = -1.0;
} offset->y = -1.0;
catch (TransportException &err) { } else {
BAlert *alert = new BAlert("", err.what(), "OK"); offset->y += height;
alert->Go(); }
return false;
}
} DBGMSG(("< nextBand\n"));
return true;
void PSDriver::jobStart() }
{ catch (TransportException &err) {
// PostScript header BAlert *alert = new BAlert("", err.what(), "OK");
writeSpoolString("%%!PS-Adobe-3.0\n"); alert->Go();
writeSpoolString("%%%%LanguageLevel: 1\n"); return false;
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()); void PSDriver::jobStart()
writeSpoolString("%%%%Pages: (atend)\n"); {
writeSpoolString("%%%%EndComments\n"); // PostScript header
writeSpoolString("%%!PS-Adobe-3.0\n");
writeSpoolString("%%%%BeginDefaults\n"); writeSpoolString("%%%%LanguageLevel: 1\n");
writeSpoolString("%%%%PageMedia: Plain\n"); writeSpoolString("%%%%Title: %s\n", getSpoolMetaData()->getDescription().c_str());
writeSpoolString("%%%%EndDefaults\n"); 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());
void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte) writeSpoolString("%%%%Pages: (atend)\n");
{ writeSpoolString("%%%%EndComments\n");
bool color = getJobData()->getColor() == JobData::kColor;
fCompressionMethod = -1; writeSpoolString("%%%%BeginDefaults\n");
writeSpoolString("gsave\n"); writeSpoolString("%%%%PageMedia: Plain\n");
writeSpoolString("/s %d string def\n", widthByte); writeSpoolString("%%%%EndDefaults\n");
writeSpoolString("%d %d translate\n", x, y); }
writeSpoolString("%d %d scale\n", width, height);
if (color) { void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte)
writeSpoolString("%d %d 8\n", width, height); // 8 bpp {
} else { bool color = getJobData()->getColor() == JobData::kColor;
writeSpoolString("%d %d 1\n", width, height); // 1 bpp fCompressionMethod = -1;
} writeSpoolString("gsave\n");
writeSpoolString("[%d 0 0 %d 0 0]\n", width, height); writeSpoolString("/s %d string def\n", widthByte);
writeSpoolString("{ currentfile s readhexstring pop }\n"); writeSpoolString("%d %d translate\n", x, y);
if (color) { writeSpoolString("%d %d scale\n", width, height);
writeSpoolString("false 3\n"); // single data source, 3 color components if (color) {
writeSpoolString("colorimage\n"); writeSpoolString("%d %d 8\n", width, height); // 8 bpp
} else { } else {
writeSpoolString("image\n\n"); 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");
void PSDriver::endRasterGraphics() if (color) {
{ writeSpoolString("false 3\n"); // single data source, 3 color components
writeSpoolString("grestore\n"); writeSpoolString("colorimage\n");
} } else {
writeSpoolString("image\n\n");
void PSDriver::rasterGraphics( }
int compression_method, }
const uchar *buffer,
int size) void PSDriver::endRasterGraphics()
{ {
if (fCompressionMethod != compression_method) { writeSpoolString("grestore\n");
fCompressionMethod = compression_method; }
}
writeSpoolData(buffer, size); void PSDriver::rasterGraphics(
writeSpoolString("\n"); int compression_method,
} const uchar *buffer,
int size)
void PSDriver::jobEnd() {
{ if (fCompressionMethod != compression_method) {
writeSpoolString("%%%%Pages: %d\n", fPrintedPages); fCompressionMethod = compression_method;
writeSpoolString("%%%%EOF\n"); }
} writeSpoolData(buffer, size);
writeSpoolString("\n");
}
void PSDriver::jobEnd()
{
writeSpoolString("%%%%Pages: %d\n", fPrintedPages);
writeSpoolString("%%%%EOF\n");
}