/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <private/qprintengine_qws_p.h>
#ifndef QT_NO_PRINTER
#include <private/qpaintengine_raster_p.h>
#include <qimage.h>
#include <qfile.h>
#include <qdebug.h>
#include <QCopChannel>
QT_BEGIN_NAMESPACE
#define MM(n) int((n * 720 + 127) / 254)
#define IN(n) int(n * 72)
extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size);
QtopiaPrintEngine::QtopiaPrintEngine(QPrinter::PrinterMode mode)
: QPaintEngine(*(new QtopiaPrintEnginePrivate( mode )))
{
d_func()->initialize();
}
bool QtopiaPrintEngine::begin(QPaintDevice *)
{
Q_D(QtopiaPrintEngine);
Q_ASSERT_X(d->printerState == QPrinter::Idle, "QtopiaPrintEngine", "printer already active");
// Create a new off-screen monochrome image to handle the drawing process.
QSize size = paperRect().size();
if ( d->pageImage )
delete d->pageImage;
d->pageImage = new QImage( size, QImage::Format_RGB32 );
if ( !(d->pageImage) )
return false;
// Recreate the paint engine on the new image.
delete d->_paintEngine;
d->_paintEngine = 0;
d->paintEngine()->state = state;
// Begin the paint process on the image.
if (!d->paintEngine()->begin(d->pageImage))
return false;
// Clear the first page to all-white.
clearPage();
// Clear the print buffer and output the image header.
d->buffer.clear();
d->writeG3FaxHeader();
// The print engine is currently active.
d->printerState = QPrinter::Active;
return true;
}
bool QtopiaPrintEngine::end()
{
Q_D(QtopiaPrintEngine);
d->paintEngine()->end();
// Flush the last page.
flushPage();
// Output the fax data to a file (TODO: send to the print queuing daemon).
QString filename;
if ( !d->outputFileName.isEmpty() )
filename = QString::fromLocal8Bit(qgetenv("HOME").constData()) + QLatin1String("/Documents/") + d->outputFileName;
else
filename = QString::fromLocal8Bit(qgetenv("HOME").constData()) + QLatin1String("/tmp/qwsfax.tiff");
setProperty(QPrintEngine::PPK_OutputFileName, filename);
QFile file( filename );
if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) {
qDebug( "Failed to open %s for printer output",
filename.toLatin1().constData() );
} else {
file.write( d->buffer.data() );
file.close();
}
// Free up the memory for the image buffer.
d->buffer.clear();
// Finalize the print job.
d->printerState = QPrinter::Idle;
// call qcop service
QMap<QString, QVariant> map;
for ( int x = 0; x <= QPrintEngine::PPK_Duplex; x++ )
map.insert( QString::number(x), property((QPrintEngine::PrintEnginePropertyKey)(x)));
QVariant variant(map);
QByteArray data;
QDataStream out(&data, QIODevice::WriteOnly);
out << variant;
QCopChannel::send(QLatin1String("QPE/Service/Print"), QLatin1String("print(QVariant)"), data);
return true;
}
QPaintEngine *QtopiaPrintEngine::paintEngine() const
{
return const_cast<QtopiaPrintEnginePrivate *>(d_func())->paintEngine();
}
void QtopiaPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
{
Q_D(QtopiaPrintEngine);
Q_ASSERT(d->printerState == QPrinter::Active);
d->paintEngine()->drawPixmap(r, pm, sr);
}
void QtopiaPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti)
{
Q_D(QtopiaPrintEngine);
Q_ASSERT(d->printerState == QPrinter::Active);
d->paintEngine()->drawTextItem(p, ti);
}
void QtopiaPrintEngine::updateState(const QPaintEngineState &state)
{
Q_D(QtopiaPrintEngine);
d->paintEngine()->updateState(state);
}
QRect QtopiaPrintEngine::paperRect() const
{
QSizeF s = qt_paperSizeToQSizeF(d_func()->paperSize);
s.rwidth() = MM(s.width());
s.rheight() = MM(s.height());
int w = qRound(s.width()*d_func()->resolution/72.);
int h = qRound(s.height()*d_func()->resolution/72.);
if (d_func()->orientation == QPrinter::Portrait)
return QRect(0, 0, w, h);
else
return QRect(0, 0, h, w);
}
QRect QtopiaPrintEngine::pageRect() const
{
QRect r = paperRect();
if (d_func()->fullPage)
return r;
// would be nice to get better margins than this.
return QRect(d_func()->resolution/3, d_func()->resolution/3, r.width()-2*d_func()->resolution/3, r.height()-2*d_func()->resolution/3);
}
bool QtopiaPrintEngine::newPage()
{
flushPage();
clearPage();
++(d_func()->pageNumber);
return true;
}
bool QtopiaPrintEngine::abort()
{
return false;
}
QPrinter::PrinterState QtopiaPrintEngine::printerState() const
{
return d_func()->printerState;
}
int QtopiaPrintEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
{
int val;
QRect r = d_func()->fullPage ? paperRect() : pageRect();
switch (metricType) {
case QPaintDevice::PdmWidth:
val = r.width();
break;
case QPaintDevice::PdmHeight:
val = r.height();
break;
case QPaintDevice::PdmDpiX:
val = d_func()->resolution;
break;
case QPaintDevice::PdmDpiY:
val = d_func()->resolution;
break;
case QPaintDevice::PdmPhysicalDpiX:
case QPaintDevice::PdmPhysicalDpiY:
val = QT_QWS_PRINTER_DEFAULT_DPI;
break;
case QPaintDevice::PdmWidthMM:
val = qRound(r.width()*25.4/d_func()->resolution);
break;
case QPaintDevice::PdmHeightMM:
val = qRound(r.height()*25.4/d_func()->resolution);
break;
case QPaintDevice::PdmNumColors:
val = 2;
break;
case QPaintDevice::PdmDepth:
val = 1;
break;
default:
qWarning("QtopiaPrintEngine::metric: Invalid metric command");
return 0;
}
return val;
}
QVariant QtopiaPrintEngine::property(PrintEnginePropertyKey key) const
{
Q_D(const QtopiaPrintEngine);
QVariant ret;
switch (key) {
case PPK_CollateCopies:
ret = d->collateCopies;
break;
case PPK_ColorMode:
ret = d->colorMode;
break;
case PPK_Creator:
ret = d->creator;
break;
case PPK_DocumentName:
ret = d->docName;
break;
case PPK_FullPage:
ret = d->fullPage;
break;
case PPK_NumberOfCopies:
ret = d->numCopies;
break;
case PPK_Orientation:
ret = d->orientation;
break;
case PPK_OutputFileName:
ret = d->outputFileName;
break;
case PPK_PageOrder:
ret = d->pageOrder;
break;
case PPK_PageRect:
ret = pageRect();
break;
case PPK_PaperSize:
ret = d->paperSize;
break;
case PPK_PaperRect:
ret = paperRect();
break;
case PPK_PaperSource:
ret = d->paperSource;
break;
case PPK_PrinterName:
ret = d->printerName;
break;
case PPK_PrinterProgram:
ret = d->printProgram;
break;
case PPK_Resolution:
ret = d->resolution;
break;
case PPK_SupportedResolutions:
ret = QList<QVariant>() << QT_QWS_PRINTER_DEFAULT_DPI;
break;
default:
break;
}
return ret;
}
void QtopiaPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
{
Q_D(QtopiaPrintEngine);
switch (key) {
case PPK_CollateCopies:
d->collateCopies = value.toBool();
break;
case PPK_ColorMode:
d->colorMode = QPrinter::ColorMode(value.toInt());
break;
case PPK_Creator:
d->creator = value.toString();
break;
case PPK_DocumentName:
d->docName = value.toString();
break;
case PPK_FullPage:
d->fullPage = value.toBool();
break;
case PPK_NumberOfCopies:
d->numCopies = value.toInt();
break;
case PPK_Orientation:
d->orientation = QPrinter::Orientation(value.toInt());
break;
case PPK_OutputFileName:
d->outputFileName = value.toString();
break;
case PPK_PageOrder:
d->pageOrder = QPrinter::PageOrder(value.toInt());
break;
case PPK_PaperSize:
d->paperSize = QPrinter::PaperSize(value.toInt());
break;
case PPK_PaperSource:
d->paperSource = QPrinter::PaperSource(value.toInt());
case PPK_PrinterName:
d->printerName = value.toString();
break;
case PPK_PrinterProgram:
d->printProgram = value.toString();
break;
case PPK_Resolution:
d->resolution = value.toInt();
break;
default:
break;
}
}
void QtopiaPrintEngine::clearPage()
{
d_func()->pageImage->fill(QColor(255, 255, 255).rgb());
}
void QtopiaPrintEngine::flushPage()
{
d_func()->writeG3FaxPage();
}
QtopiaPrintEnginePrivate::~QtopiaPrintEnginePrivate()
{
if ( pageImage )
delete pageImage;
}
void QtopiaPrintEnginePrivate::initialize()
{
_paintEngine = 0;
}
QPaintEngine *QtopiaPrintEnginePrivate::paintEngine()
{
if (!_paintEngine)
_paintEngine = new QRasterPaintEngine(pageImage);
return _paintEngine;
}
void QtopiaPrintEnginePrivate::writeG3FaxHeader()
{
// Write the TIFF file magic number (little-endian TIFF).
buffer.append( (char)'I' );
buffer.append( (char)'I' );
buffer.append( (char)42 );
buffer.append( (char)0 );
// Leave a place-holder for the IFD offset of the first page.
ifdPatch = buffer.size();
buffer.append( (int)0 );
}
// Tag values, from RFC 2301.
#define TIFF_IFD_NEW_SUB_FILE_TYPE 254
#define TIFF_IFD_IMAGE_WIDTH 256
#define TIFF_IFD_IMAGE_LENGTH 257
#define TIFF_IFD_BITS_PER_SAMPLE 258
#define TIFF_IFD_COMPRESSION 259
#define TIFF_IFD_PHOTOMETRIC_INTERP 262
#define TIFF_IFD_FILL_ORDER 266
#define TIFF_IFD_STRIP_OFFSETS 273
#define TIFF_IFD_ORIENTATION 274
#define TIFF_IFD_SAMPLES_PER_PIXEL 277
#define TIFF_IFD_ROWS_PER_STRIP 278
#define TIFF_IFD_STRIP_BYTE_COUNTS 279
#define TIFF_IFD_X_RESOLUTION 282
#define TIFF_IFD_Y_RESOLUTION 283
#define TIFF_IFD_PLANAR_CONFIG 284
#define TIFF_IFD_T4_OPTIONS 292
#define TIFF_IFD_RESOLUTION_UNIT 296
#define TIFF_IFD_PAGE_NUMBER 297
#define TIFF_IFD_CLEAN_FAX_DATA 327
// IFD type values.
#define TIFF_TYPE_SHORT 3
#define TIFF_TYPE_LONG 4
#define TIFF_TYPE_RATIONAL 5
// Construct a SHORT pair from two values.
#define TIFF_SHORT_PAIR(a,b) (((a) & 0xFFFF) | ((b) << 16))
// Width of a FAX page in pixels, in the baseline specification from RFC 2301.
// This must be hard-wired, as per the RFC. We truncate any pixels that
// are beyond this limit, or pad lines to reach this limit.
#define TIFF_FAX_WIDTH 1728
void QtopiaPrintEnginePrivate::writeG3FaxPage()
{
// Pad the image file to a word boundary, just in case.
buffer.pad();
// Back-patch the IFD link for the previous page.
buffer.patch( ifdPatch, buffer.size() );
// Output the contents of the IFD for this page (these must be
// in ascending order of tag value).
buffer.append( (short)19 ); // Number of IFD entries.
writeG3IFDEntry( TIFF_IFD_NEW_SUB_FILE_TYPE, TIFF_TYPE_LONG, 1, 2 );
writeG3IFDEntry( TIFF_IFD_IMAGE_WIDTH, TIFF_TYPE_LONG, 1, TIFF_FAX_WIDTH );
writeG3IFDEntry
( TIFF_IFD_IMAGE_LENGTH, TIFF_TYPE_LONG, 1, pageImage->height() );
writeG3IFDEntry( TIFF_IFD_BITS_PER_SAMPLE, TIFF_TYPE_SHORT, 1, 1 );
writeG3IFDEntry( TIFF_IFD_COMPRESSION, TIFF_TYPE_SHORT, 1, 3 );
writeG3IFDEntry( TIFF_IFD_PHOTOMETRIC_INTERP, TIFF_TYPE_SHORT, 1, 0 );
writeG3IFDEntry( TIFF_IFD_FILL_ORDER, TIFF_TYPE_SHORT, 1, 1 );
int stripOffsets =
writeG3IFDEntry( TIFF_IFD_STRIP_OFFSETS, TIFF_TYPE_LONG, 1, 0 );
writeG3IFDEntry( TIFF_IFD_ORIENTATION, TIFF_TYPE_SHORT, 1, 1 );
writeG3IFDEntry( TIFF_IFD_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, 1 );
writeG3IFDEntry
( TIFF_IFD_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, pageImage->height() );
int stripBytes = writeG3IFDEntry
( TIFF_IFD_STRIP_BYTE_COUNTS, TIFF_TYPE_LONG, 1, 0 );
int xres =
writeG3IFDEntry( TIFF_IFD_X_RESOLUTION, TIFF_TYPE_RATIONAL, 1, 0 );
int yres =
writeG3IFDEntry( TIFF_IFD_Y_RESOLUTION, TIFF_TYPE_RATIONAL, 1, 0 );
writeG3IFDEntry( TIFF_IFD_PLANAR_CONFIG, TIFF_TYPE_SHORT, 1, 1 );
writeG3IFDEntry( TIFF_IFD_T4_OPTIONS, TIFF_TYPE_LONG, 1, 2 );
writeG3IFDEntry( TIFF_IFD_RESOLUTION_UNIT, TIFF_TYPE_SHORT, 1, 2 );
writeG3IFDEntry( TIFF_IFD_PAGE_NUMBER, TIFF_TYPE_SHORT, 2,
TIFF_SHORT_PAIR( pageNumber, 0 ) );
writeG3IFDEntry( TIFF_IFD_CLEAN_FAX_DATA, TIFF_TYPE_SHORT, 1, 0 );
// Leave a place-holder for the IFD offset of the next page.
ifdPatch = buffer.size();
buffer.append( (int)0 );
// Output the X and Y resolutions, as rational values (usually 200/1).
buffer.patch( xres, buffer.size() );
buffer.append( (int)resolution );
buffer.append( (int)1 );
buffer.patch( yres, buffer.size() );
buffer.append( (int)resolution );
buffer.append( (int)1 );
// We are now at the start of the image data - set the strip offset.
int start = buffer.size();
buffer.patch( stripOffsets, start );
// Output the image data.
int width = pageImage->width();
QImage::Format imageFormat = pageImage->format();
for ( int y = 0; y < pageImage->height(); ++y ) {
unsigned char *scan = pageImage->scanLine(y);
int prev, pixel, len;
writeG3EOL();
prev = 0;
len = 0;
uint currentColor = qRgb(255, 255, 255); // start with white
for ( int x = 0; x < width && x < TIFF_FAX_WIDTH; ++x ) {
if ( imageFormat == QImage::Format_RGB32 ) {
// read color of the current pixel
uint *p = (uint *)scan + x;
if ( *p == currentColor ) { // if it is the same color
len++; // imcrement length
} else { // otherwise write color into the buffer
if ( len > 0 ) {
if ( currentColor == qRgb(0, 0, 0) )
writeG3BlackRun( len );
else
writeG3WhiteRun( len );
}
// initialise length and color;
len = 1;
currentColor = *p;
}
} else if ( imageFormat == QImage::Format_Mono ) {
pixel = ((scan[x >> 3] & (1 << (x & 7))) != 0);
if ( pixel != prev ) {
if ( prev ) {
writeG3BlackRun( len );
} else {
writeG3WhiteRun( len );
}
prev = pixel;
len = 1;
} else {
++len;
}
}
}
if ( imageFormat == QImage::Format_RGB32 ) {
// Output the last run on the line, and pad to TIFF_FAX_WIDTH.
if ( len != 0 ) {
if ( currentColor == qRgb(0, 0, 0) )
writeG3BlackRun( len );
else
writeG3WhiteRun( len );
}
if ( width < TIFF_FAX_WIDTH )
writeG3WhiteRun( TIFF_FAX_WIDTH - width );
} else if ( imageFormat == QImage::Format_Mono ) {
if ( len != 0 ) {
if ( prev ) {
writeG3BlackRun( len );
if ( width < TIFF_FAX_WIDTH ) {
writeG3WhiteRun( TIFF_FAX_WIDTH - width );
}
} else {
if ( width < TIFF_FAX_WIDTH ) {
writeG3WhiteRun( len + ( TIFF_FAX_WIDTH - width ) );
} else {
writeG3WhiteRun( len );
}
}
}
}
}
// Flush the last partial byte, which is padded with zero fill bits.
if ( partialBits > 0 ) {
buffer.append( (char)( partialByte << ( 8 - partialBits ) ) );
partialByte = 0;
partialBits = 0;
}
// end of page add six EOLs
for ( int i = 0; i < 6; i++ )
writeG3EOL();
// Update the byte count for the image data strip.
buffer.patch( stripBytes, buffer.size() - start );
}
int QtopiaPrintEnginePrivate::writeG3IFDEntry
( int tag, int type, int count, int value )
{
buffer.append( (short)tag );
buffer.append( (short)type );
buffer.append( count );
buffer.append( value );
return buffer.size() - 4; // Offset of the value for back-patching.
}
void QtopiaPrintEnginePrivate::writeG3Code( int code, int bits )
{
partialByte = ( ( partialByte << bits ) | code );
partialBits += bits;
while ( partialBits >= 8 ) {
partialBits -= 8;
buffer.append( (char)( partialByte >> partialBits ) );
}
}
void QtopiaPrintEnginePrivate::writeG3WhiteRun( int len )
{
static struct {
unsigned short code;
unsigned short bits;
} whiteCodes[64 + 27] = {
{0x0035, 8}, // 0
{0x0007, 6},
{0x0007, 4},
{0x0008, 4},
{0x000B, 4},
{0x000C, 4},
{0x000E, 4},
{0x000F, 4},
{0x0013, 5}, // 8
{0x0014, 5},
{0x0007, 5},
{0x0008, 5},
{0x0008, 6},
{0x0003, 6},
{0x0034, 6},
{0x0035, 6},
{0x002A, 6}, // 16
{0x002B, 6},
{0x0027, 7},
{0x000C, 7},
{0x0008, 7},
{0x0017, 7},
{0x0003, 7},
{0x0004, 7},
{0x0028, 7}, // 24
{0x002B, 7},
{0x0013, 7},
{0x0024, 7},
{0x0018, 7},
{0x0002, 8},
{0x0003, 8},
{0x001A, 8},
{0x001B, 8}, // 32
{0x0012, 8},
{0x0013, 8},
{0x0014, 8},
{0x0015, 8},
{0x0016, 8},
{0x0017, 8},
{0x0028, 8},
{0x0029, 8}, // 40
{0x002A, 8},
{0x002B, 8},
{0x002C, 8},
{0x002D, 8},
{0x0004, 8},
{0x0005, 8},
{0x000A, 8},
{0x000B, 8}, // 48
{0x0052, 8},
{0x0053, 8},
{0x0054, 8},
{0x0055, 8},
{0x0024, 8},
{0x0025, 8},
{0x0058, 8},
{0x0059, 8}, // 56
{0x005A, 8},
{0x005B, 8},
{0x004A, 8},
{0x004B, 8},
{0x0032, 8},
{0x0033, 8},
{0x0034, 8},
{0x001B, 5}, // Make up codes: 64
{0x0012, 5}, // 128
{0x0017, 6}, // 192
{0x0037, 7}, // 256
{0x0036, 8}, // 320
{0x0037, 8}, // 384
{0x0064, 8}, // 448
{0x0065, 8}, // 512
{0x0068, 8}, // 576
{0x0067, 8}, // 640
{0x00CC, 9}, // 704
{0x00CD, 9}, // 768
{0x00D2, 9}, // 832
{0x00D3, 9}, // 896
{0x00D4, 9}, // 960
{0x00D5, 9}, // 1024
{0x00D6, 9}, // 1088
{0x00D7, 9}, // 1152
{0x00D8, 9}, // 1216
{0x00D9, 9}, // 1280
{0x00DA, 9}, // 1344
{0x00DB, 9}, // 1408
{0x0098, 9}, // 1472
{0x0099, 9}, // 1536
{0x009A, 9}, // 1600
{0x0018, 6}, // 1664
{0x009B, 9}, // 1728
};
if ( len >= 64 ) {
int index = 63 + (len >> 6);
writeG3Code( whiteCodes[index].code, whiteCodes[index].bits );
len &= 63;
}
writeG3Code( whiteCodes[len].code, whiteCodes[len].bits );
}
void QtopiaPrintEnginePrivate::writeG3BlackRun( int len )
{
static struct {
unsigned short code;
unsigned short bits;
} blackCodes[64 + 27] = {
{0x0037, 10}, // 0
{0x0002, 3},
{0x0003, 2},
{0x0002, 2},
{0x0003, 3},
{0x0003, 4},
{0x0002, 4},
{0x0003, 5},
{0x0005, 6}, // 8
{0x0004, 6},
{0x0004, 7},
{0x0005, 7},
{0x0007, 7},
{0x0004, 8},
{0x0007, 8},
{0x0018, 9},
{0x0017, 10}, // 16
{0x0018, 10},
{0x0008, 10},
{0x0067, 11},
{0x0068, 11},
{0x006C, 11},
{0x0037, 11},
{0x0028, 11},
{0x0017, 11}, // 24
{0x0018, 11},
{0x00CA, 12},
{0x00CB, 12},
{0x00CC, 12},
{0x00CD, 12},
{0x0068, 12},
{0x0069, 12},
{0x006A, 12}, // 32
{0x006B, 12},
{0x00D2, 12},
{0x00D3, 12},
{0x00D4, 12},
{0x00D5, 12},
{0x00D6, 12},
{0x00D7, 12},
{0x006C, 12}, // 40
{0x006D, 12},
{0x00DA, 12},
{0x00DB, 12},
{0x0054, 12},
{0x0055, 12},
{0x0056, 12},
{0x0057, 12},
{0x0064, 12}, // 48
{0x0065, 12},
{0x0052, 12},
{0x0053, 12},
{0x0024, 12},
{0x0037, 12},
{0x0038, 12},
{0x0027, 12},
{0x0028, 12}, // 56
{0x0058, 12},
{0x0059, 12},
{0x002B, 12},
{0x002C, 12},
{0x005A, 12},
{0x0066, 12},
{0x0067, 12},
{0x000F, 10}, // Make up codes: 64
{0x00C8, 12}, // 128
{0x00C9, 12}, // 192
{0x005B, 12}, // 256
{0x0033, 12}, // 320
{0x0034, 12}, // 384
{0x0035, 12}, // 448
{0x006C, 13}, // 512
{0x006D, 13}, // 576
{0x004A, 13}, // 640
{0x004B, 13}, // 704
{0x004C, 13}, // 768
{0x004D, 13}, // 832
{0x0072, 13}, // 896
{0x0073, 13}, // 960
{0x0074, 13}, // 1024
{0x0075, 13}, // 1088
{0x0076, 13}, // 1152
{0x0077, 13}, // 1216
{0x0052, 13}, // 1280
{0x0053, 13}, // 1344
{0x0054, 13}, // 1408
{0x0055, 13}, // 1472
{0x005A, 13}, // 1536
{0x005B, 13}, // 1600
{0x0064, 13}, // 1664
{0x0065, 13}, // 1728
};
if ( len >= 64 ) {
int index = 63 + (len >> 6);
writeG3Code( blackCodes[index].code, blackCodes[index].bits );
len &= 63;
}
writeG3Code( blackCodes[len].code, blackCodes[len].bits );
}
void QtopiaPrintEnginePrivate::writeG3EOL()
{
int bitToPad;
if ( partialBits <= 4 ) {
bitToPad = 4 - partialBits;
} else {
bitToPad = 8 - partialBits + 4;
}
partialByte = ((partialByte << (bitToPad + 12)) | 0x0001);
partialBits += bitToPad + 12;
while ( partialBits >= 8 ) {
partialBits -= 8;
buffer.append( (char)(partialByte >> partialBits ) );
}
// writeG3Code( 0x0001, 12 );
}
void QtopiaPrintBuffer::append( short value )
{
if ( _bigEndian ) {
_data.append( (char)(value >> 8) );
_data.append( (char)value );
} else {
_data.append( (char)value );
_data.append( (char)(value >> 8) );
}
}
void QtopiaPrintBuffer::append( int value )
{
if ( _bigEndian ) {
_data.append( (char)(value >> 24) );
_data.append( (char)(value >> 16) );
_data.append( (char)(value >> 8) );
_data.append( (char)value );
} else {
_data.append( (char)value );
_data.append( (char)(value >> 8) );
_data.append( (char)(value >> 16) );
_data.append( (char)(value >> 24) );
}
}
void QtopiaPrintBuffer::patch( int posn, int value )
{
if ( _bigEndian ) {
_data[posn] = (char)(value >> 24);
_data[posn + 1] = (char)(value >> 16);
_data[posn + 2] = (char)(value >> 8);
_data[posn + 3] = (char)value;
} else {
_data[posn] = (char)value;
_data[posn + 1] = (char)(value >> 8);
_data[posn + 2] = (char)(value >> 16);
_data[posn + 3] = (char)(value >> 24);
}
}
void QtopiaPrintBuffer::pad()
{
while ( ( _data.size() % 4 ) != 0 )
_data.append( (char)0 );
}
QT_END_NAMESPACE
#endif // QT_NO_PRINTER