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:
parent
8c0bf01979
commit
2e86189f50
@ -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 ;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
388
src/add-ons/print/drivers/pcl6/PCL6Rasterizer.cpp
Normal file
388
src/add-ons/print/drivers/pcl6/PCL6Rasterizer.cpp
Normal 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
|
111
src/add-ons/print/drivers/pcl6/PCL6Rasterizer.h
Normal file
111
src/add-ons/print/drivers/pcl6/PCL6Rasterizer.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
92
src/add-ons/print/drivers/pcl6/Rasterizer.cpp
Normal file
92
src/add-ons/print/drivers/pcl6/Rasterizer.cpp
Normal 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();
|
||||
}
|
||||
}
|
74
src/add-ons/print/drivers/pcl6/Rasterizer.h
Normal file
74
src/add-ons/print/drivers/pcl6/Rasterizer.h
Normal 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
|
Loading…
Reference in New Issue
Block a user