diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 10:18:55 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 10:18:55 +0100 |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/painting/qprintengine_qws.cpp | |
download | qt4-tools-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz |
Long live Qt 4.5!
Diffstat (limited to 'src/gui/painting/qprintengine_qws.cpp')
-rw-r--r-- | src/gui/painting/qprintengine_qws.cpp | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/src/gui/painting/qprintengine_qws.cpp b/src/gui/painting/qprintengine_qws.cpp new file mode 100644 index 0000000000..1a8ffbc976 --- /dev/null +++ b/src/gui/painting/qprintengine_qws.cpp @@ -0,0 +1,881 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 |