Added color dithering to reduce the size of data to be sent to printer by about 800 percent.

Added Add Printer dialog that allows the selection of the protocol class.
Made some features dependent on the chosen protocol class.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11275 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2005-02-06 18:38:01 +00:00
parent 8c0bf01979
commit 2e86189f50
11 changed files with 1111 additions and 251 deletions

View File

@ -9,7 +9,9 @@ Addon PCL6\ Compatible : Print :
PCL6Entry.cpp
PCL6.cpp
PCL6Cap.cpp
PCL6Rasterizer.cpp
PCL6Writer.cpp
Rasterizer.cpp
;
ObjectC++Flags [ FGristFiles jetlib.o ] : -w ;

View File

@ -8,16 +8,19 @@
#include <Bitmap.h>
#include <File.h>
#include <memory>
#include "PCL6.h"
#include "UIDriver.h"
#include "JobData.h"
#include "PrinterData.h"
#include "PCL6Cap.h"
#include "PackBits.h"
#include "Halftone.h"
#include "ValidRect.h"
#include "DbgMsg.h"
#include "DeltaRowCompression.h"
#include "Halftone.h"
#include "JobData.h"
#include "PackBits.h"
#include "PCL6Cap.h"
#include "PrinterData.h"
#include "PCL6Rasterizer.h"
#include "UIDriver.h"
#include "ValidRect.h"
#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
using namespace std;
@ -31,10 +34,16 @@ using namespace std;
// Run-Length-Encoding Compression
// DO NOT ENABLE HP_M2TIFF_Compress seems to be broken!!!
#define ENABLE_RLE_COMPRESSION 0
#define ENABLE_RLE_COMPRESSION 0
// Delta Row Compression
#define ENABLE_DELTA_ROW_COMPRESSION 0
#define ENABLE_DELTA_ROW_COMPRESSION 1
// Color depth for color printing.
// Use either 1 or 8.
// If 1 bit depth is used, the class Halftone is used for dithering
// otherwise dithering is not performed.
#define COLOR_DEPTH 1
// DeltaRowStreamCompressor writes the delta row directly to the
// in the contructor specified stream.
@ -57,6 +66,7 @@ private:
PCL6Writer *fWriter;
};
PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
: GraphicsDriver(msg, printer_data, printer_cap)
{
@ -64,7 +74,7 @@ PCL6Driver::PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCa
fWriter = NULL;
}
void PCL6Driver::writeData(const uint8 *data, uint32 size)
void PCL6Driver::write(const uint8 *data, uint32 size)
{
writeSpoolData(data, size);
}
@ -100,145 +110,68 @@ bool PCL6Driver::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;
PCL6Rasterizer *rasterizer;
if (getJobData()->getColor() == JobData::kColor) {
#if COLOR_DEPTH == 8
rasterizer = new ColorRGBRasterizer(fHalftone);
#elif COLOR_DEPTH == 1
rasterizer = new ColorRasterizer(fHalftone);
#else
#error COLOR_DEPTH must be either 1 or 8!
#endif
} else {
rasterizer = new MonochromeRasterizer(fHalftone);
}
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;
int width;
int widthByte;
int padBytes;
int out_row_length;
int height;
int out_size;
int delta;
color = getJobData()->getColor() == JobData::kColor;
width = rc.right - rc.left + 1;
height = rc.bottom - rc.top + 1;
delta = bitmap->BytesPerRow();
if (color) {
widthByte = 3 * width;
} else {
widthByte = (width + 7) / 8; /* byte boundary */
}
out_row_length = 4*((widthByte+3)/4);
padBytes = out_row_length - widthByte; /* line length is a multiple of 4 bytes */
out_size = out_row_length * height;
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;
const uchar *buffer;
uchar *out_buffer = new uchar[out_size];
uchar *out_ptr = out_buffer;
auto_ptr<uchar> _out_buffer(out_buffer);
DBGMSG(("move\n"));
buffer = out_buffer;
int xPage = x;
int yPage = y;
auto_ptr<Rasterizer> _rasterizer(rasterizer);
bool valid = rasterizer->SetBitmap((int)offset->x, (int)offset->y, bitmap, getPageHeight());
if (valid) {
rasterizer->InitializeBuffer();
DeltaRowCompressor deltaRowCompressor(out_row_length, 0);
if (deltaRowCompressor.InitCheck() != B_OK) {
return false;
// Use compressor to calculate delta row size
DeltaRowCompressor *deltaRowCompressor = NULL;
if (supportsDeltaRowCompression()) {
deltaRowCompressor = new DeltaRowCompressor(rasterizer->GetOutRowSize(), 0);
if (deltaRowCompressor->InitCheck() != B_OK) {
delete deltaRowCompressor;
return false;
}
}
auto_ptr<DeltaRowCompressor> _deltaRowCompressor(deltaRowCompressor);
int deltaRowSize = 0;
// remember position
int xPage = rasterizer->GetX();
int yPage = rasterizer->GetY();
// dither entire band into out_buffer
for (int i = rc.top; i <= rc.bottom; i++) {
uchar* out = out_ptr;
if (color) {
uchar* in = ptr;
for (int w = width; w > 0; w --) {
*out++ = in[2];
*out++ = in[1];
*out++ = in[0];
in += 4;
}
} else {
fHalftone->dither(out_ptr, ptr, x, y, width);
// invert pixels
for (int w = widthByte; w > 0; w --, out ++) {
*out = ~*out;
}
}
// pad with 0s
for (int w = padBytes; w > 0; w --, out ++) {
*out = 0;
}
{
int size = deltaRowCompressor.CalculateSize(out_ptr, true);
while (rasterizer->HasNextLine()) {
const uchar *rowBuffer = (uchar*)rasterizer->RasterizeNextLine();
if (deltaRowCompressor != NULL) {
int size = deltaRowCompressor->CalculateSize(rowBuffer, true);
deltaRowSize += size + 2; // two bytes for the row byte count
}
ptr += delta;
out_ptr += out_row_length;
y++;
}
writeBitmap(buffer, out_size, out_row_length, xPage, yPage, width, height, deltaRowSize);
} else {
DBGMSG(("band bitmap is clean.\n"));
y = rasterizer->GetY();
uchar *outBuffer = rasterizer->GetOutBuffer();
int outBufferSize = rasterizer->GetOutBufferSize();
int outRowSize = rasterizer->GetOutRowSize();
int width = rasterizer->GetWidth();
int height = rasterizer->GetHeight();
writeBitmap(outBuffer, outBufferSize, outRowSize, xPage, yPage, width, height, deltaRowSize);
}
if (y >= page_height) {
if (y >= getPageHeight()) {
offset->x = -1.0;
offset->y = -1.0;
} else {
offset->y += height;
offset->y += bitmap->Bounds().IntegerHeight()+1;
}
DBGMSG(("< nextBand\n"));
return true;
}
catch (TransportException &err) {
@ -255,7 +188,7 @@ void PCL6Driver::writeBitmap(const uchar* buffer, int outSize, int rowSize, int
int dataSize = outSize;
#if ENABLE_DELTA_ROW_COMPRESSION
if (deltaRowSize < dataSize) {
if (supportsDeltaRowCompression() && deltaRowSize < dataSize) {
compressionMethod = PCL6Writer::kDeltaRowCompression;
dataSize = deltaRowSize;
}
@ -279,7 +212,7 @@ void PCL6Driver::writeBitmap(const uchar* buffer, int outSize, int rowSize, int
endRasterGraphics();
#if 1
#if 0
fprintf(stderr, "Out Size %d %2.2f\n", (int)outSize, 100.0);
#if ENABLE_RLE_COMPRESSION
fprintf(stderr, "RLE Size %d %2.2f\n", (int)compressedSize, 100.0 * compressedSize / outSize);
@ -294,15 +227,9 @@ void PCL6Driver::writeBitmap(const uchar* buffer, int outSize, int rowSize, int
void PCL6Driver::jobStart()
{
// PJL header
writeSpoolString("\033%%-12345X@PJL JOB\n"
"@PJL SET RESOLUTION=%d\n"
"@PJL ENTER LANGUAGE=PCLXL\n"
") HP-PCL XL;1;1;"
"Comment Copyright (c) 2003, 2004 Haiku\n",
getJobData()->getXres());
// PCL6 begin
fWriter = new PCL6Writer(this);
fWriter->PJLHeader(PCL6Writer::kProtocolClass1_1, getJobData()->getXres(), "Copyright (c) 2003, 2004 Haiku");
fWriter->BeginSession(getJobData()->getXres(), getJobData()->getYres(), PCL6Writer::kInch, PCL6Writer::kBackChAndErrPage);
fWriter->OpenDataSource();
fMediaSide = PCL6Writer::kFrontMediaSide;
@ -347,7 +274,19 @@ bool PCL6Driver::startPage(int)
void PCL6Driver::startRasterGraphics(int x, int y, int width, int height, PCL6Writer::Compression compressionMethod)
{
bool color = getJobData()->getColor() == JobData::kColor;
fWriter->BeginImage(PCL6Writer::kDirectPixel, color ? PCL6Writer::k8Bit : PCL6Writer::k1Bit, width, height, width, height);
PCL6Writer::ColorDepth colorDepth;
if (color) {
#if COLOR_DEPTH == 8
colorDepth = PCL6Writer::k8Bit;
#elif COLOR_DEPTH == 1
colorDepth = PCL6Writer::k1Bit;
#else
#error COLOR_DEPTH must be either 1 or 8!
#endif
} else {
colorDepth = PCL6Writer::k1Bit;
}
fWriter->BeginImage(PCL6Writer::kDirectPixel, colorDepth, width, height, width, height);
fWriter->ReadImage(compressionMethod, 0, height);
}
@ -415,12 +354,10 @@ void PCL6Driver::jobEnd()
{
fWriter->CloseDataSource();
fWriter->EndSession();
fWriter->PJLFooter();
fWriter->Flush();
delete fWriter;
fWriter = NULL;
// PJL footer
writeSpoolString("\033%%-12345X@PJL EOJ\n"
"\033%%-12345X");
}
void PCL6Driver::move(int x, int y)
@ -428,6 +365,12 @@ void PCL6Driver::move(int x, int y)
fWriter->SetCursor(x, y);
}
bool
PCL6Driver::supportsDeltaRowCompression()
{
return getProtocolClass() >= kProtocolClass2_1;
}
PCL6Writer::MediaSize PCL6Driver::mediaSize(JobData::Paper paper)
{
switch (paper) {
@ -437,6 +380,11 @@ PCL6Writer::MediaSize PCL6Driver::mediaSize(JobData::Paper paper)
case JobData::kExecutive: return PCL6Writer::kExecPaper;
case JobData::kLedger: return PCL6Writer::kLedgerPaper;
case JobData::kA3: return PCL6Writer::kA3Paper;
case JobData::kB5: return PCL6Writer::kB5Paper;
case JobData::kJapanesePostcard:
return PCL6Writer::kJPostcard;
case JobData::kA5: return PCL6Writer::kA5Paper;
case JobData::kB4: return PCL6Writer::kJB4Paper;
/*
case : return PCL6Writer::kCOM10Envelope;
case : return PCL6Writer::kMonarchEnvelope;
@ -445,7 +393,6 @@ PCL6Writer::MediaSize PCL6Driver::mediaSize(JobData::Paper paper)
case : return PCL6Writer::kJB4Paper;
case : return PCL6Writer::kJB5Paper;
case : return PCL6Writer::kB5Envelope;
case : return PCL6Writer::kB5Paper;
case : return PCL6Writer::kJPostcard;
case : return PCL6Writer::kJDoublePostcard;
case : return PCL6Writer::kA5Paper;

View File

@ -13,12 +13,12 @@
class Halftone;
class PCL6Driver : public GraphicsDriver
class PCL6Driver : public GraphicsDriver, public PCL6WriterStream
{
public:
PCL6Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap);
void writeData(const uint8 *data, uint32 size);
void write(const uint8 *data, uint32 size);
protected:
virtual bool startDoc();
@ -28,6 +28,7 @@ protected:
virtual bool endDoc(bool success);
private:
bool supportsDeltaRowCompression();
PCL6Writer::MediaSize mediaSize(JobData::Paper paper);
PCL6Writer::MediaSource mediaSource(JobData::PaperSource source);
void move(int x, int y);

View File

@ -8,48 +8,7 @@
#define TO72DPI(a) (a * 72.0f / 600.0f)
const PaperCap a3(
"A3",
false,
JobData::kA3,
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::kA4,
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::kA5,
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::kJapanesePostcard,
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::kB4,
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::kB5,
BRect(0.0f, 0.0f, TO72DPI(4298.0f), TO72DPI(6070.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4178.0f), TO72DPI(5950.0f)));
// since 1.1
const PaperCap letter(
"Letter",
false,
@ -57,6 +16,7 @@ const PaperCap 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)));
// since 1.1
const PaperCap legal(
"Legal",
false,
@ -64,14 +24,121 @@ const PaperCap 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::kAuto);
// since 1.1
const PaperCap a4(
"A4",
true,
JobData::kA4,
BRect(0.0f, 0.0f, TO72DPI(4960.0f), TO72DPI(7014.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4840.0f), TO72DPI(6894.0f)));
// TODO
// since 1.1
const PaperCap exec(
"Executive",
true,
JobData::kA4,
BRect(0.0f, 0.0f, TO72DPI(4960.0f), TO72DPI(7014.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4840.0f), TO72DPI(6894.0f)));
// TODO
// since 1.1
const PaperCap ledger(
"Ledger",
false,
JobData::kLegal,
BRect(0.0f, 0.0f, TO72DPI(5100.0f), TO72DPI(8400.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4980.0f), TO72DPI(8280.0f)));
// since 1.1
const PaperCap a3(
"A3",
false,
JobData::kA3,
BRect(0.0f, 0.0f, TO72DPI(7014.0f), TO72DPI(9920.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(6894.0f), TO72DPI(9800.0f)));
// TODO
// COM10Envelope
// since 1.1
// MonarchEnvelope
// since 1.1
// C5Envelope
// since 1.1
// DLEnvelope
// since 1.1
// JB4Paper
// since 1.1
// JB5Paper
// since 1.1
// since 2.1
const PaperCap b5(
"B5",
false,
JobData::kB5,
BRect(0.0f, 0.0f, TO72DPI(4298.0f), TO72DPI(6070.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4178.0f), TO72DPI(5950.0f)));
// since 1.1
const PaperCap japanese_postcard(
"Japanese Postcard",
false,
JobData::kJapanesePostcard,
BRect(0.0f, 0.0f, TO72DPI(2362.0f), TO72DPI(3506.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(2242.0f), TO72DPI(3386.0f)));
// TODO
// JDoublePostcard
// since 1.1
// since 1.1
const PaperCap a5(
"A5",
false,
JobData::kA5,
BRect(0.0f, 0.0f, TO72DPI(3506.0f), TO72DPI(4960.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(3386.0f), TO72DPI(4840.0f)));
// TODO
// A6
// since 2.0
// JB6
// since 2.0
// TBD: Validate. Is this JB4?
const PaperCap b4(
"B4",
false,
JobData::kB4,
BRect(0.0f, 0.0f, TO72DPI(6070.0f), TO72DPI(8598.0f)),
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(5950.0f), TO72DPI(8478.0f)));
// JIS8K
// since 2.1
// JIS16K
// since 2.1
// JISExec
// since 2.1
// since 1.1
const PaperSourceCap defaultSource("Default", false, JobData::kCassette1);
const PaperSourceCap envelopeTray("Envelope Tray", false, JobData::kCassette2);
const PaperSourceCap lowerCassette("Lower Cassette", false, JobData::kLower);
const PaperSourceCap upperCassette("Upper Cassette", false, JobData::kUpper);
const PaperSourceCap thridCassette("Thrid Cassette", false, JobData::kMiddle);
const PaperSourceCap autobin("Auto", true, JobData::kAuto);
const PaperSourceCap manualFeed("Manual Feed", false, JobData::kManual);
const PaperSourceCap multiPurposeTray("Multi Purpose Tray", false, JobData::kCassette3);
const PaperSourceCap upperCassette("Upper Cassette", false, JobData::kUpper);
const PaperSourceCap lowerCassette("Lower Cassette", false, JobData::kLower);
const PaperSourceCap envelopeTray("Envelope Tray", false, JobData::kCassette2);
// since 2.0:
const PaperSourceCap thridCassette("Thrid Cassette", false, JobData::kMiddle);
const ResolutionCap dpi150("150dpi", true, 150, 150);
const ResolutionCap dpi300("300dpi", true, 300, 300);
@ -81,18 +148,53 @@ const ResolutionCap dpi1200("1200dpi", false, 1200, 1200);
const PrintStyleCap simplex("Simplex", true, JobData::kSimplex);
const PrintStyleCap duplex("Duplex", false, JobData::kDuplex);
const PaperCap *papers[] = {
const ProtocolClassCap pc1_1("PCL 6 Protocol Class 1.1", true, kProtocolClass1_1,
"Protocol Class 1.1\n"
"* No compression\n"
"* RLE compression (not implemented yet)");
const ProtocolClassCap pc2_0("PCL 6 Protocol Class 2.0", false, kProtocolClass2_0,
"Protocol Class 2.0\n"
"* Additonal Paper Source: Third Cassette\n"
"* JPEG compression (not implemented yet)");
const ProtocolClassCap pc2_1("PCL 6 Protocol Class 2.1", false, kProtocolClass2_1,
"Protocol Class 2.1\n"
"* Additional Paper Format: B5\n"
"* Delta Row Compression");
const ProtocolClassCap pc3_0("PCL 6 Protocol Class 3.0", false, kProtocolClass3_0,
"Protocol Class 3.0");
const PaperCap *papers1_1[] = {
&letter,
&legal,
&a4,
&a3,
&a5,
&b4,
&japanese_postcard
};
const PaperCap *papers2_1[] = {
&letter,
&legal,
&a4,
&a3,
&a5,
&b4,
&b5,
&letter,
&legal,
&japanese_postcard
};
const PaperSourceCap *papersources[] = {
const PaperSourceCap *paperSources1_1[] = {
&autobin,
&defaultSource,
&envelopeTray,
&lowerCassette,
&upperCassette,
&manualFeed,
&multiPurposeTray
};
const PaperSourceCap *paperSources2_0[] = {
&autobin,
&defaultSource,
&envelopeTray,
@ -115,6 +217,13 @@ const PrintStyleCap *printStyles[] = {
&duplex
};
const ProtocolClassCap *protocolClasses[] = {
&pc1_1,
&pc2_0,
&pc2_1,
&pc3_0
};
const ColorCap color("Color", false, JobData::kColor);
const ColorCap monochrome("Monochrome", true, JobData::kMonochrome);
@ -132,15 +241,23 @@ int PCL6Cap::countCap(CapID capid) const
{
switch (capid) {
case kPaper:
return sizeof(papers) / sizeof(papers[0]);
if (getProtocolClass() >= kProtocolClass2_1) {
return sizeof(papers2_1) / sizeof(papers2_1[0]);
}
return sizeof(papers1_1) / sizeof(papers1_1[0]);
case kPaperSource:
return sizeof(papersources) / sizeof(papersources[0]);
if (getProtocolClass() >= kProtocolClass2_0) {
return sizeof(paperSources2_0) / sizeof(paperSources2_0[0]);
}
return sizeof(paperSources1_1) / sizeof(paperSources1_1[0]);
case kResolution:
return sizeof(resolutions) / sizeof(resolutions[0]);
case kColor:
return sizeof(colors) / sizeof(colors[0]);
case kPrintStyle:
return sizeof(printStyles) / sizeof(printStyles[0]);
case kProtocolClass:
return sizeof(protocolClasses) / sizeof(protocolClasses[0]);
default:
return 0;
}
@ -150,15 +267,23 @@ const BaseCap **PCL6Cap::enumCap(CapID capid) const
{
switch (capid) {
case kPaper:
return (const BaseCap **)papers;
if (getProtocolClass() >= kProtocolClass2_1) {
return (const BaseCap **)papers2_1;
}
return (const BaseCap **)papers1_1;
case kPaperSource:
return (const BaseCap **)papersources;
if (getProtocolClass() >= kProtocolClass2_0) {
return (const BaseCap **)paperSources2_0;
}
return (const BaseCap **)paperSources1_1;
case kResolution:
return (const BaseCap **)resolutions;
case kColor:
return (const BaseCap **)colors;
case kPrintStyle:
return (const BaseCap **)printStyles;
case kProtocolClass:
return (const BaseCap **)protocolClasses;
default:
return NULL;
}
@ -173,6 +298,7 @@ bool PCL6Cap::isSupport(CapID capid) const
case kColor:
case kCopyCommand:
case kPrintStyle:
case kProtocolClass:
return true;
default:
return false;

View File

@ -8,6 +8,13 @@
#include "PrinterCap.h"
enum ProtocolClass {
kProtocolClass1_1,
kProtocolClass2_0,
kProtocolClass2_1,
kProtocolClass3_0,
};
class PCL6Cap : public PrinterCap {
public:
PCL6Cap(const PrinterData *printer_data);

View File

@ -0,0 +1,388 @@
/*
** PCL6Rasterizer.cpp
** Copyright 2005, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#include "PCL6Rasterizer.h"
#include <stdio.h>
#ifdef _PCL6_RASTERIZER_TEST_
static void dump(uchar *buffer, int size);
static void dump_bits(uchar *buffer, int size);
#define DUMP(text, buffer, size) { fprintf text; dump(buffer, size); }
#define DUMP_BITS(text, buffer, size) { fprintf text; dump_bits(buffer, size); }
#else
#define DUMP(text, buffer, size) {}
#define DUMP_BITS(text, buffer, size) {}
#endif
// MonochromeRasterizer
MonochromeRasterizer::MonochromeRasterizer(Halftone *halftone)
: PCL6Rasterizer(halftone)
, fOutBuffer(NULL)
{ }
void
MonochromeRasterizer::InitializeBuffer() {
fWidthByte = RowBufferSize(GetWidth(), 1, 1);
/* line length is a multiple of 4 bytes */
fOutRowSize = RowBufferSize(GetWidth(), 1, 4);
fPadBytes = fOutRowSize - fWidthByte;
// Total size
SetOutBufferSize(fOutRowSize * GetHeight());
PCL6Rasterizer::InitializeBuffer();
fCurrentLine = GetOutBuffer();
}
const void *
MonochromeRasterizer::RasterizeLine(int x, int y, const ColorRGB32Little* source) {
GetHalftone()->dither(fCurrentLine, (const uchar*)source, x, y, GetWidth());
uchar *out = fCurrentLine;
// invert pixels
for (int w = fWidthByte; w > 0; w --, out ++) {
*out = ~*out;
}
// pad with 0s
for (int w = fPadBytes; w > 0; w --, out ++) {
*out = 0;
}
void *result = fCurrentLine;
fCurrentLine += fOutRowSize;
return result;
}
// ColorRGBRasterizer
ColorRGBRasterizer::ColorRGBRasterizer(Halftone *halftone)
: PCL6Rasterizer(halftone)
{ }
void
ColorRGBRasterizer::InitializeBuffer() {
fWidthByte = RowBufferSize(GetWidth(), 24, 1);
// line length is a multiple of 4 bytes
fOutRowSize = RowBufferSize(GetWidth(), 24, 4);
fPadBytes = fOutRowSize - fWidthByte;
// Total size
SetOutBufferSize(fOutRowSize * GetHeight());
PCL6Rasterizer::InitializeBuffer();
fCurrentLine = GetOutBuffer();
}
const void *
ColorRGBRasterizer::RasterizeLine(int x, int y, const ColorRGB32Little* source) {
uchar *out = fCurrentLine;
int width = GetWidth();
for (int w = width; w > 0; w --) {
*out++ = source->red;
*out++ = source->green;
*out++ = source->blue;
source ++;
}
// pad with 0s
for (int w = fPadBytes; w > 0; w --, out ++) {
*out = 0;
}
void *result = fCurrentLine;
fCurrentLine += fOutRowSize;
return result;
}
// ColorRasterizer
ColorRasterizer::ColorRasterizer::ColorRasterizer(Halftone *halftone)
: PCL6Rasterizer(halftone)
{
for (int plane = 0; plane < 3; plane ++) {
fPlaneBuffers[plane] = NULL;
}
halftone->setPlanes(Halftone::kPlaneRGB1);
halftone->setBlackValue(Halftone::kLowValueMeansBlack);
}
ColorRasterizer::~ColorRasterizer() {
for (int plane = 0; plane < 3; plane ++) {
delete fPlaneBuffers[plane];
fPlaneBuffers[plane] = NULL;
}
}
void
ColorRasterizer::InitializeBuffer() {
fWidthByte = RowBufferSize(GetWidth(), 3, 1);
// line length is a multiple of 4 bytes
fOutRowSize = RowBufferSize(GetWidth(), 3, 4);
fPadBytes = fOutRowSize - fWidthByte;
// Total size
SetOutBufferSize(fOutRowSize * GetHeight());
PCL6Rasterizer::InitializeBuffer();
fCurrentLine = GetOutBuffer();
fPlaneBufferSize = RowBufferSize(GetWidth(), 1, 1);
for (int plane = 0; plane < 3; plane ++) {
fPlaneBuffers[plane] = new uchar[fPlaneBufferSize];
}
}
enum {
kRed = 1,
kGreen = 2,
kBlue = 4,
};
const void *
ColorRasterizer::RasterizeLine(int x, int y, const ColorRGB32Little* source) {
DUMP((stderr, "\nRGB32 row at x %d y %d:\n", x, y), (uchar*)source, GetWidth() * 4);
// dither each color component
for (int plane = 0; plane < 3; plane ++) {
GetHalftone()->dither(fPlaneBuffers[plane], (const uchar*)source, x, y, GetWidth());
}
DUMP_BITS((stderr, "red "), fPlaneBuffers[0], fPlaneBufferSize);
DUMP_BITS((stderr, "green "), fPlaneBuffers[1], fPlaneBufferSize);
DUMP_BITS((stderr, "blue "), fPlaneBuffers[2], fPlaneBufferSize);
MergePlaneBuffersToCurrentLine();
DUMP_BITS((stderr, "merged\n"), fCurrentLine, fOutRowSize);
DUMP((stderr, "\n"), fCurrentLine, fOutRowSize);
void *result = fCurrentLine;
fCurrentLine += fOutRowSize;
return result;
}
void
ColorRasterizer::MergePlaneBuffersToCurrentLine()
{
// merge the three planes into output buffer
int remainingPixels = GetWidth();
uchar *out = fCurrentLine;
uchar value = 0;
uchar outMask = 0x80; // current bit mask (1 << (8 - bit)) in output buffer
// iterate over the three plane buffers
for (int i = 0; i < fPlaneBufferSize; i ++) {
const uchar values[3] = {
fPlaneBuffers[0][i],
fPlaneBuffers[1][i],
fPlaneBuffers[2][i]
};
int pixels = 8;
if (remainingPixels < 8) {
pixels = remainingPixels;
}
remainingPixels -= pixels;
// for each bit in the current byte of each plane
uchar mask = 0x80;
for (; pixels > 0; pixels --) {
int rgb = 0;
if (values[0] & mask) {
rgb |= kRed;
}
if (values[1] & mask) {
rgb |= kGreen;
}
if (values[2] & mask) {
rgb |= kBlue;
}
for (int plane = 0; plane < 3; plane ++) {
// copy pixel value to output value
if (rgb & (1 << plane)) {
value |= outMask;
}
// increment output mask
if (outMask == 0x01) {
outMask = 0x80;
// write output value to output buffer
*out = value;
out ++;
value = 0;
} else {
outMask >>= 1;
}
}
mask >>= 1;
}
}
// write last output value
if (outMask != 0x80) {
do {
value |= outMask;
outMask >>= 1;
} while (outMask > 0);
*out = value;
out ++;
}
if (out - fCurrentLine != fWidthByte) {
fprintf(stderr, "Error buffer overflow: %d != %d\n", fWidthByte, (int)(out - fCurrentLine));
}
// pad with 0s
for (int w = fPadBytes; w > 0; w --, out ++) {
*out = 0xff;
}
if (out - fCurrentLine != fOutRowSize) {
fprintf(stderr, "Error buffer overflow: %d != %d\n", fOutRowSize, (int)(out - fCurrentLine));
}
}
#ifdef _PCL6_RASTERIZER_TEST_
#include <Application.h>
#include <Bitmap.h>
#include <stdio.h>
#define COLUMNS 40
#define BIT_COLUMNS 6
static void dump(uchar *buffer, int size)
{
int x = 0;
for (int i = 0; i < size; i ++) {
if ((x % COLUMNS) == COLUMNS - 1) {
fprintf(stderr, "\n");
} else if (i > 0) {
fprintf(stderr, " ");
}
fprintf(stderr, "%2.2x", (int)*buffer);
buffer ++;
x ++;
}
fprintf(stderr, "\n");
}
static void dump_bits(uchar *buffer, int size)
{
int x = 0;
for (int i = 0; i < size; i ++) {
if ((x % COLUMNS) == COLUMNS - 1) {
fprintf(stderr, "\n");
} else if (i > 0) {
fprintf(stderr, " ");
}
uchar value = *buffer;
for (int bit = 0; bit < 8; bit ++) {
if (value & (1 << bit)) {
fprintf(stderr, "*");
} else {
fprintf(stderr, ".");
}
}
buffer ++;
x ++;
}
fprintf(stderr, "\n");
}
static void fill(uchar *_row, int width, ColorRGB32Little color)
{
ColorRGB32Little *row = (ColorRGB32Little *)_row;
for (int i = 0; i < width; i ++) {
*row = color;
row ++;
}
}
static void initializeBitmap(BBitmap *bitmap, int width, int height)
{
int bpr = bitmap->BytesPerRow();
uchar *row = (uchar*)bitmap->Bits();
// BGRA
ColorRGB32Little black = {0, 0, 0, 0};
ColorRGB32Little white = {255, 255, 255, 0};
ColorRGB32Little red = {0, 0, 255, 0};
ColorRGB32Little green = {0, 255, 0, 0};
ColorRGB32Little blue = {255, 0, 0, 0};
fprintf(stderr, "black row\n");
fill(row, width, black);
row += bpr;
fprintf(stderr, "white row\n");
fill(row, width, white);
row += bpr;
fprintf(stderr, "red row\n");
fill(row, width, red);
row += bpr;
fprintf(stderr, "red green blue pattern");
ColorRGB32Little *color = (ColorRGB32Little*)row;
for (int i = 0; i < width; i++) {
switch (i % 3) {
case 0:
*color = red;
break;
case 1:
*color = green;
break;
case 2:
*color = blue;
break;
}
color ++;
}
}
#if 1
int main()
{
const int width = 10;
const int height = 4;
fprintf(stderr, "width: %d\nheight: %d\n", width, height);
BApplication app("application/pcl6-rasterizer-test");
#if 1
Halftone halftone(B_RGB32, 0.25f, 0.0f, Halftone::kType1);
#else
Halftone halftone(B_RGB32, 0.25f, 0.0f, Halftone::kTypeFloydSteinberg);
#endif
ColorRasterizer rasterizer(&halftone);
BBitmap bitmap(BRect(0, 0, width-1, height-1), B_RGB32);
initializeBitmap(&bitmap, width, height);
rasterizer.SetBitmap(0, 0, &bitmap, height);
rasterizer.InitializeBuffer();
while (rasterizer.HasNextLine()) {
// const uchar *rowBuffer = (uchar*)
rasterizer.RasterizeNextLine();
}
}
#endif
#endif

View File

@ -0,0 +1,111 @@
/*
** PCL6Rasterizer.h
** Copyright 2005, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#ifndef _PCL6_RASTERIZER_H
#define _PCL6_RASTERIZER_H
#include "Rasterizer.h"
class PCL6Rasterizer : public Rasterizer
{
public:
PCL6Rasterizer(Halftone *halftone)
: Rasterizer(halftone)
, fOutBuffer(NULL)
, fOutBufferSize(0)
{
}
~PCL6Rasterizer()
{
delete fOutBuffer;
fOutBuffer = NULL;
}
void SetOutBufferSize(int size) { fOutBufferSize = size; }
int GetOutBufferSize() { return fOutBufferSize; }
uchar *GetOutBuffer() { return fOutBuffer; }
virtual void InitializeBuffer() {
fOutBuffer = new uchar[fOutBufferSize];
}
virtual int GetOutRowSize() = 0;
private:
uchar *fOutBuffer;
int fOutBufferSize;
};
class MonochromeRasterizer : public PCL6Rasterizer
{
public:
MonochromeRasterizer(Halftone *halftone);
void InitializeBuffer();
int GetOutRowSize() { return fOutRowSize; }
const void *RasterizeLine(int x, int y, const ColorRGB32Little* source);
private:
int fWidthByte;
int fOutRowSize;
int fPadBytes;
int fOutSize;
uchar *fOutBuffer;
uchar *fCurrentLine;
};
// Output format RGB 8bit per channel
class ColorRGBRasterizer : public PCL6Rasterizer
{
public:
ColorRGBRasterizer(Halftone *halftone) ;
void InitializeBuffer();
int GetOutRowSize() { return fOutRowSize; }
const void *RasterizeLine(int x, int y, const ColorRGB32Little* source);
private:
int fWidthByte;
int fOutRowSize;
int fPadBytes;
uchar *fCurrentLine;
};
typedef uchar *PlaneBuffer;
// Output format: RGB 1bit per channel
// Class Halftone is used for dithering
class ColorRasterizer : public PCL6Rasterizer
{
public:
ColorRasterizer(Halftone *halftone);
~ColorRasterizer();
void InitializeBuffer();
int GetOutRowSize() { return fOutRowSize; }
const void *RasterizeLine(int x, int y, const ColorRGB32Little* source);
private:
void MergePlaneBuffersToCurrentLine();
int fWidthByte;
int fOutRowSize;
int fPadBytes;
uchar *fCurrentLine;
int fPlaneBufferSize;
PlaneBuffer fPlaneBuffers[3];
};
#endif

View File

@ -4,14 +4,14 @@
** Distributed under the terms of the OpenBeOS License.
*/
#include "PCL6Writer.h"
#include "PCL6.h"
#include <ByteOrder.h>
#include <String.h>
#define BYTE_AT(lvalue, index) (((uint8*)(&lvalue))[index])
PCL6Writer::PCL6Writer(PCL6Driver *driver, uint32 bufferSize)
: fDriver(driver),
PCL6Writer::PCL6Writer(PCL6WriterStream *stream, uint32 bufferSize)
: fStream(stream),
fBuffer(new uint8[bufferSize]),
fSize(bufferSize),
fIndex(0)
@ -24,7 +24,8 @@ PCL6Writer::~PCL6Writer() {
}
// throws TransportException
void PCL6Writer::Append(uint8 value) {
void
PCL6Writer::Append(uint8 value) {
if (fIndex == fSize) {
Flush();
}
@ -32,26 +33,30 @@ void PCL6Writer::Append(uint8 value) {
fIndex ++;
}
void PCL6Writer::Flush() {
void
PCL6Writer::Flush() {
if (fIndex > 0) {
fDriver->writeData(fBuffer, fIndex);
fStream->write(fBuffer, fIndex);
fIndex = 0;
}
}
void PCL6Writer::Append(int16 value) {
void
PCL6Writer::Append(int16 value) {
int16 v = B_HOST_TO_LENDIAN_INT16(value);
Append(BYTE_AT(v, 0));
Append(BYTE_AT(v, 1));
}
void PCL6Writer::Append(uint16 value) {
void
PCL6Writer::Append(uint16 value) {
int16 v = B_HOST_TO_LENDIAN_INT16(value);
Append(BYTE_AT(v, 0));
Append(BYTE_AT(v, 1));
}
void PCL6Writer::Append(int32 value) {
void
PCL6Writer::Append(int32 value) {
int32 v = B_HOST_TO_LENDIAN_INT32(value);
Append(BYTE_AT(v, 0));
Append(BYTE_AT(v, 1));
@ -59,7 +64,8 @@ void PCL6Writer::Append(int32 value) {
Append(BYTE_AT(v, 3));
}
void PCL6Writer::Append(uint32 value) {
void
PCL6Writer::Append(uint32 value) {
int32 v = B_HOST_TO_LENDIAN_INT32(value);
Append(BYTE_AT(v, 0));
Append(BYTE_AT(v, 1));
@ -67,7 +73,8 @@ void PCL6Writer::Append(uint32 value) {
Append(BYTE_AT(v, 3));
}
void PCL6Writer::Append(float value) {
void
PCL6Writer::Append(float value) {
float v = B_HOST_TO_LENDIAN_FLOAT(value);
Append(BYTE_AT(v, 0));
Append(BYTE_AT(v, 1));
@ -75,56 +82,78 @@ void PCL6Writer::Append(float value) {
Append(BYTE_AT(v, 3));
}
void PCL6Writer::Append(const uint8* data, uint32 size) {
void
PCL6Writer::Append(const uint8* data, uint32 size) {
for (uint32 i = 0; i < size; i++) {
Append(data[i]);
}
}
void PCL6Writer::AppendOperator(Operator op) {
void
PCL6Writer::AppendString(const char *string) {
uint8 ch = *string;
while (ch != 0) {
Append(ch);
string ++;
ch = *string;
}
}
void
PCL6Writer::AppendOperator(Operator op) {
Append((uint8)op);
}
void PCL6Writer::AppendAttribute(Attribute attr) {
void
PCL6Writer::AppendAttribute(Attribute attr) {
AppendDataTag(k8BitAttrId);
Append((uint8)attr);
}
void PCL6Writer::AppendDataTag(DataTag tag) {
void
PCL6Writer::AppendDataTag(DataTag tag) {
Append((uint8)tag);
}
void PCL6Writer::AppendData(uint8 value) {
void
PCL6Writer::AppendData(uint8 value) {
AppendDataTag(kUByteData);
Append(value);
}
void PCL6Writer::AppendData(int16 value) {
void
PCL6Writer::AppendData(int16 value) {
AppendDataTag(kSInt16Data);
Append(value);
}
void PCL6Writer::AppendData(uint16 value) {
void
PCL6Writer::AppendData(uint16 value) {
AppendDataTag(kUInt16Data);
Append(value);
}
void PCL6Writer::AppendData(int32 value) {
void
PCL6Writer::AppendData(int32 value) {
AppendDataTag(kSInt32Data);
Append(value);
}
void PCL6Writer::AppendData(uint32 value) {
void
PCL6Writer::AppendData(uint32 value) {
AppendDataTag(kUInt32Data);
Append(value);
}
void PCL6Writer::AppendData(float value) {
void
PCL6Writer::AppendData(float value) {
AppendDataTag(kReal32Data);
Append(value);
}
void PCL6Writer::EmbeddedDataPrefix(uint32 size) {
void
PCL6Writer::EmbeddedDataPrefix(uint32 size) {
if (size < 256) {
AppendDataTag(kEmbeddedDataByte);
Append((uint8)size);
@ -134,44 +163,95 @@ void PCL6Writer::EmbeddedDataPrefix(uint32 size) {
}
}
void PCL6Writer::EmbeddedDataPrefix32(uint32 size) {
void
PCL6Writer::EmbeddedDataPrefix32(uint32 size) {
AppendDataTag(kEmbeddedData);
Append(size);
}
void PCL6Writer::AppendDataXY(uint8 x, uint8 y) {
void
PCL6Writer::AppendDataXY(uint8 x, uint8 y) {
AppendDataTag(kUByteXY);
Append(x); Append(y);
}
void PCL6Writer::AppendDataXY(int16 x, int16 y) {
void
PCL6Writer::AppendDataXY(int16 x, int16 y) {
AppendDataTag(kSInt16XY);
Append(x); Append(y);
}
void PCL6Writer::AppendDataXY(uint16 x, uint16 y) {
void
PCL6Writer::AppendDataXY(uint16 x, uint16 y) {
AppendDataTag(kUInt16XY);
Append(x); Append(y);
}
void PCL6Writer::AppendDataXY(int32 x, int32 y) {
void
PCL6Writer::AppendDataXY(int32 x, int32 y) {
AppendDataTag(kSInt32XY);
Append(x); Append(y);
}
void PCL6Writer::AppendDataXY(uint32 x, uint32 y) {
void
PCL6Writer::AppendDataXY(uint32 x, uint32 y) {
AppendDataTag(kUInt32XY);
Append(x); Append(y);
}
void PCL6Writer::AppendDataXY(float x, float y) {
void
PCL6Writer::AppendDataXY(float x, float y) {
AppendDataTag(kReal32XY);
Append(x); Append(y);
}
void
PCL6Writer::PJLHeader(ProtocolClass protocolClass, int dpi, const char *comment)
{
BString string;
AppendString("\033%-12345X@PJL JOB\n"
"@PJL SET RESOLUTION=");
string << dpi;
AppendString(string.String());
AppendString("\n"
"@PJL ENTER LANGUAGE=PCLXL\n"
") HP-PCL XL;");
const char* pc = "";
switch (protocolClass) {
case kProtocolClass1_1:
pc = "1;1;";
break;
case kProtocolClass2_0:
pc = "2;0;";
break;
case kProtocolClass2_1:
pc = "2;1;";
break;
case kProtocolClass3_0:
pc = "3;0;";
break;
}
AppendString(pc);
if (comment != NULL) {
AppendString("Comment ");
AppendString(comment);
}
AppendString("\n");
}
void
PCL6Writer::PJLFooter()
{
AppendString("\033%-12345X@PJL EOJ\n"
"\033%-12345X");
}
void PCL6Writer::BeginSession(uint16 xres, uint16 yres, UnitOfMeasure unitOfMeasure, ErrorReporting errorReporting) {
void
PCL6Writer::BeginSession(uint16 xres, uint16 yres, UnitOfMeasure unitOfMeasure, ErrorReporting errorReporting) {
AppendDataXY(xres, yres);
AppendAttribute(kUnitsPerMeasure);
@ -184,11 +264,13 @@ void PCL6Writer::BeginSession(uint16 xres, uint16 yres, UnitOfMeasure unitOfMeas
AppendOperator(kBeginSession);
}
void PCL6Writer::EndSession() {
void
PCL6Writer::EndSession() {
AppendOperator(kEndSession);
}
void PCL6Writer::OpenDataSource() {
void
PCL6Writer::OpenDataSource() {
AppendData((uint8)kDefaultDataSource);
AppendAttribute(kSourceType);
@ -198,12 +280,14 @@ void PCL6Writer::OpenDataSource() {
AppendOperator(kOpenDataSource);
}
void PCL6Writer::CloseDataSource() {
void
PCL6Writer::CloseDataSource() {
AppendOperator(kCloseDataSource);
}
void PCL6Writer::BeginPage(Orientation orientation, MediaSize mediaSize, MediaSource mediaSource) {
void
PCL6Writer::BeginPage(Orientation orientation, MediaSize mediaSize, MediaSource mediaSource) {
AppendData((uint8)orientation);
AppendAttribute(kOrientation);
@ -216,7 +300,8 @@ void PCL6Writer::BeginPage(Orientation orientation, MediaSize mediaSize, MediaSo
AppendOperator(kBeginPage);
}
void PCL6Writer::BeginPage(Orientation orientation, MediaSize mediaSize, MediaSource mediaSource, DuplexPageMode duplexPageMode, MediaSide mediaSide) {
void
PCL6Writer::BeginPage(Orientation orientation, MediaSize mediaSize, MediaSource mediaSource, DuplexPageMode duplexPageMode, MediaSide mediaSide) {
AppendData((uint8)orientation);
AppendAttribute(kOrientation);
@ -235,7 +320,8 @@ void PCL6Writer::BeginPage(Orientation orientation, MediaSize mediaSize, MediaSo
AppendOperator(kBeginPage);
}
void PCL6Writer::EndPage(uint16 copies) {
void
PCL6Writer::EndPage(uint16 copies) {
// if (copies != 1) {
AppendData(copies);
AppendAttribute(kPageCopies);
@ -245,42 +331,48 @@ void PCL6Writer::EndPage(uint16 copies) {
}
void PCL6Writer::SetPageOrigin(int16 x, int16 y) {
void
PCL6Writer::SetPageOrigin(int16 x, int16 y) {
AppendDataXY(x, y);
AppendAttribute(kPageOrigin);
AppendOperator(kSetPageOrigin);
}
void PCL6Writer::SetColorSpace(ColorSpace colorSpace) {
void
PCL6Writer::SetColorSpace(ColorSpace colorSpace) {
AppendData((uint8)colorSpace);
AppendAttribute(kColorSpace);
AppendOperator(kSetColorSpace);
}
void PCL6Writer::SetPaintTxMode(Transparency transparency) {
void
PCL6Writer::SetPaintTxMode(Transparency transparency) {
AppendData((uint8)transparency);
AppendAttribute(kTxMode);
AppendOperator(kSetPaintTxMode);
}
void PCL6Writer::SetSourceTxMode(Transparency transparency) {
void
PCL6Writer::SetSourceTxMode(Transparency transparency) {
AppendData((uint8)transparency);
AppendAttribute(kTxMode);
AppendOperator(kSetSourceTxMode);
}
void PCL6Writer::SetROP(uint8 rop) {
void
PCL6Writer::SetROP(uint8 rop) {
AppendData((uint8)rop);
AppendAttribute(kROP3);
AppendOperator(kSetROP);
}
void PCL6Writer::SetCursor(int16 x, int16 y) {
void
PCL6Writer::SetCursor(int16 x, int16 y) {
AppendDataXY(x, y);
AppendAttribute(kPoint);
@ -288,7 +380,8 @@ void PCL6Writer::SetCursor(int16 x, int16 y) {
}
void PCL6Writer::BeginImage(ColorMapping colorMapping, ColorDepth colorDepth, uint16 sourceWidth, uint16 sourceHeight, uint16 destWidth, uint16 destHeight) {
void
PCL6Writer::BeginImage(ColorMapping colorMapping, ColorDepth colorDepth, uint16 sourceWidth, uint16 sourceHeight, uint16 destWidth, uint16 destHeight) {
AppendData((uint8)colorMapping);
AppendAttribute(kColorMapping);
@ -307,7 +400,8 @@ void PCL6Writer::BeginImage(ColorMapping colorMapping, ColorDepth colorDepth, ui
AppendOperator(kBeginImage);
}
void PCL6Writer::ReadImage(Compression compression, uint16 startLine, uint16 blockHeight, uint8 padBytes) {
void
PCL6Writer::ReadImage(Compression compression, uint16 startLine, uint16 blockHeight, uint8 padBytes) {
AppendData(startLine);
AppendAttribute(kStartLine);
@ -329,7 +423,8 @@ void PCL6Writer::ReadImage(Compression compression, uint16 startLine, uint16 blo
AppendOperator(kReadImage);
}
void PCL6Writer::EndImage() {
void
PCL6Writer::EndImage() {
AppendOperator(kEndImage);
}

View File

@ -10,6 +10,12 @@
class PCL6Driver;
class PCL6WriterStream {
public:
virtual void write(const uint8 *data, uint32 size) = 0;
};
class PCL6Writer {
public:
// DO NOT change this enumerations the order is important!!!
@ -130,13 +136,23 @@ public:
kTrue
};
PCL6Writer(PCL6Driver* driver, uint32 bufferSize = 16 * 1024);
enum ProtocolClass {
kProtocolClass1_1,
kProtocolClass2_0,
kProtocolClass2_1,
kProtocolClass3_0,
};
PCL6Writer(PCL6WriterStream* stream, uint32 bufferSize = 16 * 1024);
virtual ~PCL6Writer();
// these methods throw TransportException if data could not
// be written
void Flush();
void PJLHeader(ProtocolClass protocolClass, int dpi, const char *comment = NULL);
void PJLFooter();
void BeginSession(uint16 xres, uint16 yres, UnitOfMeasure unitOfMeasure, ErrorReporting errorReporting);
void EndSession();
@ -330,11 +346,12 @@ private:
kBinaryLowByteFirst
};
void AppendString(const char* string);
void AppendOperator(Operator op);
void AppendAttribute(Attribute attr);
void AppendDataTag(DataTag tag);
PCL6Driver *fDriver; // the driver used for writing the generated PCL6 data
PCL6WriterStream *fStream; // the stream used for writing the generated PCL6 data
uint8 *fBuffer; // the buffer
uint32 fSize; // the size of the buffer
uint32 fIndex; // the index of the next byte to be written

View File

@ -0,0 +1,92 @@
#include "Rasterizer.h"
#include <stdio.h>
Rasterizer::Rasterizer(Halftone* halftone)
: fHalftone(halftone)
, fIndex(-1)
{
fBounds.bottom = -2;
}
Rasterizer::~Rasterizer()
{
}
bool
Rasterizer::SetBitmap(int x, int y, BBitmap *bitmap, int pageHeight)
{
fX = x;
fY = y;
BRect bounds = bitmap->Bounds();
fBounds.left = (int)bounds.left;
fBounds.top = (int)bounds.top;
fBounds.right = (int)bounds.right;
fBounds.bottom = (int)bounds.bottom;
int height = fBounds.bottom - fBounds.top + 1;
if (y + height > pageHeight) {
height = pageHeight - y;
fBounds.bottom = fBounds.top + height - 1;
}
if (!get_valid_rect(bitmap, &fBounds)) {
return false;
}
fprintf(stderr, "valid rect (%d, %d, %d, %d)\n",
fBounds.left, fBounds.top, fBounds.right, fBounds.bottom);
fWidth = fBounds.right - fBounds.left + 1;
fHeight = fBounds.bottom - fBounds.top + 1;
if (fWidth < 0 || fHeight < 0) {
fprintf(stderr, "Error: get_valid_rect returned an empty rect (%f, %f, %f, %f) -> (%d, %d, %d, %d)!",
bounds.left, bounds.top, bounds.right, bounds.bottom,
fBounds.left, fBounds.top, fBounds.right, fBounds.bottom);
return false;
}
fBPR = bitmap->BytesPerRow();
fBits = (uchar*)bitmap->Bits();
// offset to top, left point of rect
fBits += fBounds.top * fBPR + fBounds.left * 4;
// XXX why not fX += ...?
fX = fBounds.left;
fY += fBounds.top;
fIndex = fBounds.top;
return true;
}
bool
Rasterizer::HasNextLine()
{
return fIndex <= fBounds.bottom;
}
const void*
Rasterizer::RasterizeNextLine()
{
if (!HasNextLine()) {
return NULL;
}
const void *result;
result = RasterizeLine(fX, fY, (const ColorRGB32Little*)fBits);
fBits += fBPR;
fY ++;
fIndex ++;
return result;
}
void
Rasterizer::RasterizeBitmap()
{
while (HasNextLine()) {
RasterizeNextLine();
}
}

View File

@ -0,0 +1,74 @@
#ifndef _RASTERIZER_H
#define _RASTERIZER_H
#include "Halftone.h"
#include "ValidRect.h"
#include <Bitmap.h>
//
class Rasterizer {
public:
Rasterizer(Halftone *halftone);
virtual ~Rasterizer();
/**
* Sets the bitmap to be rasterized
* Either the iterator methods HasNextLine() and RasterizeNextLine()
* can be used to rasterize the bitmap line per line or the method RasterizeBitamp()
* can be used to rasterize the entire bitmap at once.
* @param x the x position of the image on the page.
* @param y the y position of the image on the page.
* @param bitmap the bitamp to be rasterized.
* @param height the page height.
* @return true if the bitmap is not empty and false if the bitmap is empty.
*/
bool SetBitmap(int x, int y, BBitmap *bitmap, int pageHeight);
// Is there a next line?
bool HasNextLine();
// Rasterizes the next line and returns the line.
const void *RasterizeNextLine();
// Iterates over all lines.
void RasterizeBitmap();
// Returns the Halftone object specified in the constructor
Halftone *GetHalftone() { return fHalftone; }
// The bounds of the bitmap to be rasterized
RECT GetBounds() { return fBounds; }
// The width (in pixels) of the bounds passed to Rasterized()
int GetWidth() { return fWidth; }
// The height (in pixels) of the bounds passed to Rasterize()
int GetHeight() { return fHeight; }
// Returns the current x position
int GetX() { return fX; }
// Returns the current y position
int GetY() { return fY; }
// The method is called for each line in the bitmap.
virtual const void *RasterizeLine(int x, int y, const ColorRGB32Little* source) = 0;
// Returns the number of bytes to store widthInPixels pixels with BPP = bitsPerPixel
// and padBytes number of pad bytes.
static int RowBufferSize(int widthInPixels, int bitsPerPixel, int padBytes = 1) {
int sizeInBytes = (widthInPixels * bitsPerPixel + 7) / 8;
return padBytes * ((sizeInBytes + padBytes - 1) / padBytes);
}
private:
Halftone *fHalftone;
RECT fBounds;
int fWidth;
int fHeight;
int fX;
int fY;
const uchar *fBits;
int fBPR;
int fIndex;
};
#endif