Implemented PCL5 printer driver using Y. Takagis excellent libprint.
Color printing not supported yet! git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2589 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
SubDir OBOS_TOP src add-ons print drivers pcl5 ;
|
||||
|
||||
SubDirHdrs [ FDirName $(OBOS_TOP) src add-ons print drivers canon_lips
|
||||
libprint ] ;
|
||||
|
||||
AddResources PCL5\ Compatible : PCL5.rsrc ;
|
||||
|
||||
Addon PCL5\ Compatible : print :
|
||||
PCL5Entry.cpp
|
||||
PCL5.cpp
|
||||
PCL5Cap.cpp
|
||||
;
|
||||
|
||||
LinkSharedOSLibs PCL5\ Compatible : be stdc++.r4 libprint.a ;
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* PCL5.cpp
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
* Copyright 2003 Michael Pfeiffer.
|
||||
*/
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Bitmap.h>
|
||||
#include <File.h>
|
||||
#include <memory>
|
||||
#include "PCL5.h"
|
||||
#include "UIDriver.h"
|
||||
#include "JobData.h"
|
||||
#include "PrinterData.h"
|
||||
#include "PCL5Cap.h"
|
||||
#include "PackBits.h"
|
||||
#include "Halftone.h"
|
||||
#include "ValidRect.h"
|
||||
#include "DbgMsg.h"
|
||||
|
||||
#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
|
||||
using namespace std;
|
||||
#else
|
||||
#define std
|
||||
#endif
|
||||
|
||||
PCL5Driver::PCL5Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
|
||||
: GraphicsDriver(msg, printer_data, printer_cap)
|
||||
{
|
||||
__halftone = NULL;
|
||||
}
|
||||
|
||||
bool PCL5Driver::startDoc()
|
||||
{
|
||||
try {
|
||||
jobStart();
|
||||
__halftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma());
|
||||
return true;
|
||||
}
|
||||
catch (TransportException &err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PCL5Driver::startPage(int)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PCL5Driver::endPage(int)
|
||||
{
|
||||
try {
|
||||
writeSpoolChar('\014');
|
||||
return true;
|
||||
}
|
||||
catch (TransportException &err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PCL5Driver::endDoc(bool)
|
||||
{
|
||||
try {
|
||||
if (__halftone) {
|
||||
delete __halftone;
|
||||
}
|
||||
jobEnd();
|
||||
return true;
|
||||
}
|
||||
catch (TransportException &err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PCL5Driver::nextBand(BBitmap *bitmap, BPoint *offset)
|
||||
{
|
||||
DBGMSG(("> nextBand\n"));
|
||||
|
||||
try {
|
||||
BRect bounds = bitmap->Bounds();
|
||||
|
||||
RECT rc;
|
||||
rc.left = (int)bounds.left;
|
||||
rc.top = (int)bounds.top;
|
||||
rc.right = (int)bounds.right;
|
||||
rc.bottom = (int)bounds.bottom;
|
||||
|
||||
int height = rc.bottom - rc.top + 1;
|
||||
|
||||
int x = (int)offset->x;
|
||||
int y = (int)offset->y;
|
||||
|
||||
int page_height = getPageHeight();
|
||||
|
||||
if (y + height > page_height) {
|
||||
height = page_height - y;
|
||||
}
|
||||
|
||||
rc.bottom = height - 1;
|
||||
|
||||
DBGMSG(("height = %d\n", height));
|
||||
DBGMSG(("x = %d\n", x));
|
||||
DBGMSG(("y = %d\n", y));
|
||||
|
||||
if (get_valid_rect(bitmap, __halftone->getPalette(), &rc)) {
|
||||
|
||||
DBGMSG(("validate rect = %d, %d, %d, %d\n",
|
||||
rc.left, rc.top, rc.right, rc.bottom));
|
||||
|
||||
x = rc.left;
|
||||
y += rc.top;
|
||||
|
||||
int width = rc.right - rc.left + 1;
|
||||
int widthByte = (width + 7) / 8; /* byte boundary */
|
||||
int height = rc.bottom - rc.top + 1;
|
||||
int in_size = widthByte;
|
||||
int out_size = (widthByte * 6 + 4) / 5;
|
||||
int delta = bitmap->BytesPerRow();
|
||||
|
||||
DBGMSG(("width = %d\n", width));
|
||||
DBGMSG(("widthByte = %d\n", widthByte));
|
||||
DBGMSG(("height = %d\n", height));
|
||||
DBGMSG(("in_size = %d\n", in_size));
|
||||
DBGMSG(("out_size = %d\n", out_size));
|
||||
DBGMSG(("delta = %d\n", delta));
|
||||
DBGMSG(("renderobj->get_pixel_depth() = %d\n", __halftone->getPixelDepth()));
|
||||
|
||||
uchar *ptr = (uchar *)bitmap->Bits()
|
||||
+ rc.top * delta
|
||||
+ (rc.left * __halftone->getPixelDepth()) / 8;
|
||||
|
||||
int compression_method;
|
||||
int compressed_size;
|
||||
const uchar *buffer;
|
||||
|
||||
uchar *in_buffer = new uchar[in_size];
|
||||
uchar *out_buffer = new uchar[out_size];
|
||||
|
||||
auto_ptr<uchar> _in_buffer (in_buffer);
|
||||
auto_ptr<uchar> _out_buffer(out_buffer);
|
||||
|
||||
DBGMSG(("move\n"));
|
||||
|
||||
move(x, y);
|
||||
startRasterGraphics();
|
||||
|
||||
for (int i = rc.top; i <= rc.bottom; i++) {
|
||||
__halftone->dither(in_buffer, ptr, x, y, width);
|
||||
|
||||
compressed_size = pack_bits(out_buffer, in_buffer, in_size);
|
||||
|
||||
if (compressed_size < in_size) {
|
||||
compression_method = 2; // back bits
|
||||
buffer = out_buffer;
|
||||
} else {
|
||||
compression_method = 0; // uncompressed
|
||||
buffer = in_buffer;
|
||||
compressed_size = in_size;
|
||||
}
|
||||
|
||||
rasterGraphics(
|
||||
compression_method,
|
||||
buffer,
|
||||
compressed_size);
|
||||
|
||||
ptr += delta;
|
||||
y++;
|
||||
}
|
||||
|
||||
endRasterGraphics();
|
||||
|
||||
} else {
|
||||
DBGMSG(("band bitmap is clean.\n"));
|
||||
}
|
||||
|
||||
if (y >= page_height) {
|
||||
offset->x = -1.0;
|
||||
offset->y = -1.0;
|
||||
} else {
|
||||
offset->y += height;
|
||||
}
|
||||
|
||||
DBGMSG(("< nextBand\n"));
|
||||
return true;
|
||||
}
|
||||
catch (TransportException &err) {
|
||||
BAlert *alert = new BAlert("", err.what(), "OK");
|
||||
alert->Go();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void PCL5Driver::jobStart()
|
||||
{
|
||||
// reset
|
||||
writeSpoolString("\033E");
|
||||
// dpi
|
||||
writeSpoolString("\033*t%dR", getJobData()->getXres());
|
||||
// unit of measure
|
||||
writeSpoolString("\033&u%dD", getJobData()->getXres());
|
||||
// page size
|
||||
writeSpoolString("\033&l0A");
|
||||
// page orientation
|
||||
writeSpoolString("\033&l0O");
|
||||
// raster presentation
|
||||
writeSpoolString("\033*r0F");
|
||||
// top maring and perforation skip
|
||||
writeSpoolString("\033&l0e0L");
|
||||
// clear horizontal margins
|
||||
writeSpoolString("\0339");
|
||||
// number of copies
|
||||
// writeSpoolString("\033&l%ldL", getJobData()->getCopies());
|
||||
}
|
||||
|
||||
void PCL5Driver::startRasterGraphics()
|
||||
{
|
||||
writeSpoolString("\033*r1A");
|
||||
__compression_method = -1;
|
||||
}
|
||||
|
||||
void PCL5Driver::endRasterGraphics()
|
||||
{
|
||||
writeSpoolString("\033*rB");
|
||||
}
|
||||
|
||||
void PCL5Driver::rasterGraphics(
|
||||
int compression_method,
|
||||
const uchar *buffer,
|
||||
int size)
|
||||
{
|
||||
if (__compression_method != compression_method) {
|
||||
writeSpoolString("\033*b%dM", compression_method);
|
||||
__compression_method = compression_method;
|
||||
}
|
||||
writeSpoolString("\033*b%dW", size);
|
||||
writeSpoolData(buffer, size);
|
||||
}
|
||||
|
||||
void PCL5Driver::jobEnd()
|
||||
{
|
||||
writeSpoolString("\033&l1T");
|
||||
writeSpoolString("\033E");
|
||||
}
|
||||
|
||||
void PCL5Driver::move(int x, int y)
|
||||
{
|
||||
writeSpoolString("\033*p%dx%dY", x, y+75);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* PCL5.h
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef __PCL5_H
|
||||
#define __PCL5_H
|
||||
|
||||
#include "GraphicsDriver.h"
|
||||
|
||||
class Halftone;
|
||||
|
||||
class PCL5Driver : public GraphicsDriver {
|
||||
public:
|
||||
PCL5Driver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap);
|
||||
|
||||
protected:
|
||||
virtual bool startDoc();
|
||||
virtual bool startPage(int page);
|
||||
virtual bool nextBand(BBitmap *bitmap, BPoint *offset);
|
||||
virtual bool endPage(int page);
|
||||
virtual bool endDoc(bool success);
|
||||
|
||||
private:
|
||||
void move(int x, int y);
|
||||
void jobStart();
|
||||
void startRasterGraphics();
|
||||
void endRasterGraphics();
|
||||
void rasterGraphics(
|
||||
int compression_method,
|
||||
const uchar *buffer,
|
||||
int size);
|
||||
void jobEnd();
|
||||
|
||||
int __compression_method;
|
||||
Halftone *__halftone;
|
||||
};
|
||||
|
||||
#endif /* __PCL5_H */
|
||||
Binary file not shown.
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* PCL5Cap.cpp
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "PrinterData.h"
|
||||
#include "PCL5Cap.h"
|
||||
|
||||
#define TO72DPI(a) (a * 72.0f / 600.0f)
|
||||
|
||||
const PaperCap a3(
|
||||
"A3",
|
||||
false,
|
||||
JobData::A3,
|
||||
BRect(0.0f, 0.0f, TO72DPI(7014.0f), TO72DPI(9920.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(6894.0f), TO72DPI(9800.0f)));
|
||||
|
||||
const PaperCap a4(
|
||||
"A4",
|
||||
true,
|
||||
JobData::A4,
|
||||
BRect(0.0f, 0.0f, TO72DPI(4960.0f), TO72DPI(7014.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4840.0f), TO72DPI(6894.0f)));
|
||||
|
||||
const PaperCap a5(
|
||||
"A5",
|
||||
false,
|
||||
JobData::A5,
|
||||
BRect(0.0f, 0.0f, TO72DPI(3506.0f), TO72DPI(4960.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(3386.0f), TO72DPI(4840.0f)));
|
||||
|
||||
const PaperCap japanese_postcard(
|
||||
"Japanese Postcard",
|
||||
false,
|
||||
JobData::JAPANESE_POSTCARD,
|
||||
BRect(0.0f, 0.0f, TO72DPI(2362.0f), TO72DPI(3506.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(2242.0f), TO72DPI(3386.0f)));
|
||||
|
||||
const PaperCap b4(
|
||||
"B4",
|
||||
false,
|
||||
JobData::B4,
|
||||
BRect(0.0f, 0.0f, TO72DPI(6070.0f), TO72DPI(8598.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(5950.0f), TO72DPI(8478.0f)));
|
||||
|
||||
const PaperCap b5(
|
||||
"B5",
|
||||
false,
|
||||
JobData::B5,
|
||||
BRect(0.0f, 0.0f, TO72DPI(4298.0f), TO72DPI(6070.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4178.0f), TO72DPI(5950.0f)));
|
||||
|
||||
const PaperCap letter(
|
||||
"Letter",
|
||||
false,
|
||||
JobData::LETTER,
|
||||
BRect(0.0f, 0.0f, TO72DPI(5100.0f), TO72DPI(6600.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4980.0f), TO72DPI(6480.0f)));
|
||||
|
||||
const PaperCap legal(
|
||||
"Legal",
|
||||
false,
|
||||
JobData::LEGAL,
|
||||
BRect(0.0f, 0.0f, TO72DPI(5100.0f), TO72DPI(8400.0f)),
|
||||
BRect(TO72DPI(120.0f), TO72DPI(120.0f), TO72DPI(4980.0f), TO72DPI(8280.0f)));
|
||||
|
||||
const PaperSourceCap autobin("Auto", true, JobData::AUTO);
|
||||
|
||||
const ResolutionCap dpi300("300dpi", true, 300, 300);
|
||||
const ResolutionCap dpi600("600dpi", false, 600, 600);
|
||||
|
||||
const PaperCap *papers[] = {
|
||||
&a4,
|
||||
&a3,
|
||||
&a5,
|
||||
&b4,
|
||||
&b5,
|
||||
&letter,
|
||||
&legal
|
||||
};
|
||||
|
||||
const PaperSourceCap *papersources[] = {
|
||||
&autobin,
|
||||
};
|
||||
|
||||
const ResolutionCap *resolutions[] = {
|
||||
&dpi300,
|
||||
&dpi600
|
||||
};
|
||||
|
||||
PCL5Cap::PCL5Cap(const PrinterData *printer_data)
|
||||
: PrinterCap(printer_data)
|
||||
{
|
||||
}
|
||||
|
||||
int PCL5Cap::countCap(CAPID capid) const
|
||||
{
|
||||
switch (capid) {
|
||||
case PAPER:
|
||||
return sizeof(papers) / sizeof(papers[0]);
|
||||
case PAPERSOURCE:
|
||||
return sizeof(papersources) / sizeof(papersources[0]);
|
||||
case RESOLUTION:
|
||||
return sizeof(resolutions) / sizeof(resolutions[0]);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const BaseCap **PCL5Cap::enumCap(CAPID capid) const
|
||||
{
|
||||
switch (capid) {
|
||||
case PAPER:
|
||||
return (const BaseCap **)papers;
|
||||
case PAPERSOURCE:
|
||||
return (const BaseCap **)papersources;
|
||||
case RESOLUTION:
|
||||
return (const BaseCap **)resolutions;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool PCL5Cap::isSupport(CAPID capid) const
|
||||
{
|
||||
switch (capid) {
|
||||
case PAPER:
|
||||
case PAPERSOURCE:
|
||||
case RESOLUTION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* PCL5Cap.h
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef __PCL5CAP_H
|
||||
#define __PCL5CAP_H
|
||||
|
||||
#include "PrinterCap.h"
|
||||
|
||||
class PCL5Cap : public PrinterCap {
|
||||
public:
|
||||
PCL5Cap(const PrinterData *printer_data);
|
||||
virtual int countCap(CAPID) const;
|
||||
virtual bool isSupport(CAPID) const;
|
||||
virtual const BaseCap **enumCap(CAPID) const;
|
||||
};
|
||||
|
||||
#endif /* __PCL5CAP_H */
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* PCL5Entry.cpp
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
* Copyright 2003 Michael Pfeiffer.
|
||||
*/
|
||||
|
||||
#include <File.h>
|
||||
#include <Message.h>
|
||||
#include <Node.h>
|
||||
|
||||
#include "Exports.h"
|
||||
#include "PCL5.h"
|
||||
#include "PrinterData.h"
|
||||
#include "PCL5Cap.h"
|
||||
#include "UIDriver.h"
|
||||
#include "AboutBox.h"
|
||||
#include "DbgMsg.h"
|
||||
|
||||
char *add_printer(char *printer_name)
|
||||
{
|
||||
DBGMSG((">PCL5: add_printer\n"));
|
||||
DBGMSG(("\tprinter_name: %s\n", printer_name));
|
||||
DBGMSG(("<PCL5: add_printer\n"));
|
||||
return printer_name;
|
||||
}
|
||||
|
||||
BMessage *config_page(BNode *node, BMessage *msg)
|
||||
{
|
||||
DBGMSG((">PCL5: config_page\n"));
|
||||
DUMP_BMESSAGE(msg);
|
||||
DUMP_BNODE(node);
|
||||
|
||||
PrinterData printer_data(node);
|
||||
PCL5Cap printer_cap(&printer_data);
|
||||
UIDriver drv(msg, &printer_data, &printer_cap);
|
||||
BMessage *result = drv.configPage();
|
||||
|
||||
DUMP_BMESSAGE(result);
|
||||
DBGMSG(("<PCL5: config_page\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
BMessage *config_job(BNode *node, BMessage *msg)
|
||||
{
|
||||
DBGMSG((">PCL5: config_job\n"));
|
||||
DUMP_BMESSAGE(msg);
|
||||
DUMP_BNODE(node);
|
||||
|
||||
PrinterData printer_data(node);
|
||||
PCL5Cap printer_cap(&printer_data);
|
||||
UIDriver drv(msg, &printer_data, &printer_cap);
|
||||
BMessage *result = drv.configJob();
|
||||
|
||||
DUMP_BMESSAGE(result);
|
||||
DBGMSG(("<PCL5: config_job\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
BMessage *take_job(BFile *spool, BNode *node, BMessage *msg)
|
||||
{
|
||||
DBGMSG((">PCL5: take_job\n"));
|
||||
DUMP_BMESSAGE(msg);
|
||||
DUMP_BNODE(node);
|
||||
|
||||
PrinterData printer_data(node);
|
||||
PCL5Cap printer_cap(&printer_data);
|
||||
PCL5Driver drv(msg, &printer_data, &printer_cap);
|
||||
BMessage *result = drv.takeJob(spool);
|
||||
|
||||
// DUMP_BMESSAGE(result);
|
||||
DBGMSG(("<PCL5: take_job\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
AboutBox app("application/x-vnd.PCL5-compatible", "PCL5 Compatible", "0.1",
|
||||
"libprint Copyright © 1999-2000 Y.Takagi\n"
|
||||
"PCL5 driver Copyright © 2003 Michael Pfeiffer.\n"
|
||||
"All Rights Reserved.");
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
PCL5 Protocol
|
||||
|
||||
Esc 27 decimal, 1b hexadecimal, 33 octal
|
||||
|
||||
Soft Reset
|
||||
EscE
|
||||
|
||||
Page Size Command
|
||||
Esc&l<size>A
|
||||
size ... 1 Executive, 2 Letter, 3 Legal, 4 Ledge, 26 A4, 27 A3, etc ...
|
||||
|
||||
Logical Page Size Command
|
||||
Esc&l<size>O
|
||||
size ... 0 portrait, 1, landscape, 2 reverse portrait, 3 reverse landscape
|
||||
|
||||
Clear Horizontal Margins Command
|
||||
Esc9 resets margins to that of logical page
|
||||
|
||||
Top Margin Command
|
||||
Esc&l<lines>E
|
||||
lines ... number of lines
|
||||
|
||||
Unit of Measure
|
||||
Esc&u<units>D
|
||||
|
||||
Horizontal Cursor Positioning (PCL Units) Command
|
||||
Esc*p<x>X (default 1/300 inch)
|
||||
|
||||
Vertical Cursor Positioning (PCL Units) Command
|
||||
Esc*p<x>Y (default 1/300 inch)
|
||||
|
||||
Perforation Skip Command
|
||||
Esc&l<skip>L
|
||||
skip ... 0 disable, 1 enable
|
||||
|
||||
Number of copies
|
||||
Esc&l<copies>X
|
||||
|
||||
Print Direction Command
|
||||
ESC&a<degree>P degree ... 0, 90, 180, 270
|
||||
|
||||
Job Separation Command
|
||||
Esc&l1T (before reset at end of job)
|
||||
|
||||
Image Transfer
|
||||
|
||||
Raster Presentation
|
||||
Esc*r<mode>F
|
||||
mode ... 0 in orientation of logical page
|
||||
3 raster image prints along the width
|
||||
of the physical page
|
||||
Raster Resolution
|
||||
Esc*t<dpi>R
|
||||
dpi ... 75, 100, 150, 200, 300, 600
|
||||
Raster Height
|
||||
Esc*r<height>T
|
||||
height ... 0 to logical page length - current Y position
|
||||
Raster Width
|
||||
Esc*r<width>S
|
||||
width ... in pixels of the specified resolution
|
||||
Start Raster Graphics
|
||||
Esc*r0A start at default left graphics margin (X position 0)
|
||||
Esc*r1A start at current X position
|
||||
{
|
||||
Y Offset
|
||||
Esc*b<lines>Y
|
||||
lines ... number of raster lines of vertical movement
|
||||
Raster Compression
|
||||
Esc*b<mode>M
|
||||
mode ... 0 unencoded
|
||||
... 1 run length encoding
|
||||
... 2 tagged image file format (TIFF) rev. 4.0
|
||||
... 3 delta row compression
|
||||
... 4 reserved
|
||||
... 5 adaptie compression
|
||||
{Transfer Raster Data
|
||||
Esc*b<length>W<data>
|
||||
length ... 0 to 32767
|
||||
}
|
||||
}
|
||||
End Raster Graphics
|
||||
Esc*rC
|
||||
Esc*rB (old)
|
||||
|
||||
Reference in New Issue
Block a user