source: trunk/src/gui/painting/qprintengine_qws.cpp@ 714

Last change on this file since 714 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 23.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <private/qprintengine_qws_p.h>
43
44#ifndef QT_NO_PRINTER
45
46#include <private/qpaintengine_raster_p.h>
47#include <qimage.h>
48#include <qfile.h>
49#include <qdebug.h>
50#include <QCopChannel>
51
52QT_BEGIN_NAMESPACE
53
54#define MM(n) int((n * 720 + 127) / 254)
55#define IN(n) int(n * 72)
56
57extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size);
58
59QtopiaPrintEngine::QtopiaPrintEngine(QPrinter::PrinterMode mode)
60 : QPaintEngine(*(new QtopiaPrintEnginePrivate( mode )))
61{
62 d_func()->initialize();
63}
64
65bool QtopiaPrintEngine::begin(QPaintDevice *)
66{
67 Q_D(QtopiaPrintEngine);
68 Q_ASSERT_X(d->printerState == QPrinter::Idle, "QtopiaPrintEngine", "printer already active");
69
70 // Create a new off-screen monochrome image to handle the drawing process.
71 QSize size = paperRect().size();
72 if ( d->pageImage )
73 delete d->pageImage;
74 d->pageImage = new QImage( size, QImage::Format_RGB32 );
75 if ( !(d->pageImage) )
76 return false;
77
78 // Recreate the paint engine on the new image.
79 delete d->_paintEngine;
80 d->_paintEngine = 0;
81 d->paintEngine()->state = state;
82
83 // Begin the paint process on the image.
84 if (!d->paintEngine()->begin(d->pageImage))
85 return false;
86
87 // Clear the first page to all-white.
88 clearPage();
89
90 // Clear the print buffer and output the image header.
91 d->buffer.clear();
92 d->writeG3FaxHeader();
93
94 // The print engine is currently active.
95 d->printerState = QPrinter::Active;
96 return true;
97}
98
99bool QtopiaPrintEngine::end()
100{
101 Q_D(QtopiaPrintEngine);
102
103 d->paintEngine()->end();
104
105 // Flush the last page.
106 flushPage();
107
108 // Output the fax data to a file (TODO: send to the print queuing daemon).
109 QString filename;
110 if ( !d->outputFileName.isEmpty() )
111 filename = QString::fromLocal8Bit(qgetenv("HOME").constData()) + QLatin1String("/Documents/") + d->outputFileName;
112 else
113 filename = QString::fromLocal8Bit(qgetenv("HOME").constData()) + QLatin1String("/tmp/qwsfax.tiff");
114
115 setProperty(QPrintEngine::PPK_OutputFileName, filename);
116 QFile file( filename );
117 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) {
118 qDebug( "Failed to open %s for printer output",
119 filename.toLatin1().constData() );
120 } else {
121 file.write( d->buffer.data() );
122 file.close();
123 }
124
125 // Free up the memory for the image buffer.
126 d->buffer.clear();
127
128 // Finalize the print job.
129 d->printerState = QPrinter::Idle;
130
131 // call qcop service
132 QMap<QString, QVariant> map;
133 for ( int x = 0; x <= QPrintEngine::PPK_Duplex; x++ )
134 map.insert( QString::number(x), property((QPrintEngine::PrintEnginePropertyKey)(x)));
135 QVariant variant(map);
136
137 QByteArray data;
138 QDataStream out(&data, QIODevice::WriteOnly);
139 out << variant;
140 QCopChannel::send(QLatin1String("QPE/Service/Print"), QLatin1String("print(QVariant)"), data);
141
142 return true;
143}
144
145QPaintEngine *QtopiaPrintEngine::paintEngine() const
146{
147 return const_cast<QtopiaPrintEnginePrivate *>(d_func())->paintEngine();
148}
149
150void QtopiaPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
151{
152 Q_D(QtopiaPrintEngine);
153 Q_ASSERT(d->printerState == QPrinter::Active);
154 d->paintEngine()->drawPixmap(r, pm, sr);
155}
156
157void QtopiaPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti)
158{
159 Q_D(QtopiaPrintEngine);
160 Q_ASSERT(d->printerState == QPrinter::Active);
161 d->paintEngine()->drawTextItem(p, ti);
162}
163
164void QtopiaPrintEngine::updateState(const QPaintEngineState &state)
165{
166 Q_D(QtopiaPrintEngine);
167 d->paintEngine()->updateState(state);
168}
169
170QRect QtopiaPrintEngine::paperRect() const
171{
172 QSizeF s = qt_paperSizeToQSizeF(d_func()->paperSize);
173 s.rwidth() = MM(s.width());
174 s.rheight() = MM(s.height());
175 int w = qRound(s.width()*d_func()->resolution/72.);
176 int h = qRound(s.height()*d_func()->resolution/72.);
177 if (d_func()->orientation == QPrinter::Portrait)
178 return QRect(0, 0, w, h);
179 else
180 return QRect(0, 0, h, w);
181}
182
183QRect QtopiaPrintEngine::pageRect() const
184{
185 QRect r = paperRect();
186 if (d_func()->fullPage)
187 return r;
188 // would be nice to get better margins than this.
189 return QRect(d_func()->resolution/3, d_func()->resolution/3, r.width()-2*d_func()->resolution/3, r.height()-2*d_func()->resolution/3);
190}
191
192bool QtopiaPrintEngine::newPage()
193{
194 flushPage();
195 clearPage();
196 ++(d_func()->pageNumber);
197 return true;
198}
199
200bool QtopiaPrintEngine::abort()
201{
202 return false;
203}
204
205QPrinter::PrinterState QtopiaPrintEngine::printerState() const
206{
207 return d_func()->printerState;
208}
209
210int QtopiaPrintEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
211{
212 int val;
213 QRect r = d_func()->fullPage ? paperRect() : pageRect();
214 switch (metricType) {
215 case QPaintDevice::PdmWidth:
216 val = r.width();
217 break;
218 case QPaintDevice::PdmHeight:
219 val = r.height();
220 break;
221 case QPaintDevice::PdmDpiX:
222 val = d_func()->resolution;
223 break;
224 case QPaintDevice::PdmDpiY:
225 val = d_func()->resolution;
226 break;
227 case QPaintDevice::PdmPhysicalDpiX:
228 case QPaintDevice::PdmPhysicalDpiY:
229 val = QT_QWS_PRINTER_DEFAULT_DPI;
230 break;
231 case QPaintDevice::PdmWidthMM:
232 val = qRound(r.width()*25.4/d_func()->resolution);
233 break;
234 case QPaintDevice::PdmHeightMM:
235 val = qRound(r.height()*25.4/d_func()->resolution);
236 break;
237 case QPaintDevice::PdmNumColors:
238 val = 2;
239 break;
240 case QPaintDevice::PdmDepth:
241 val = 1;
242 break;
243 default:
244 qWarning("QtopiaPrintEngine::metric: Invalid metric command");
245 return 0;
246 }
247 return val;
248}
249
250QVariant QtopiaPrintEngine::property(PrintEnginePropertyKey key) const
251{
252 Q_D(const QtopiaPrintEngine);
253 QVariant ret;
254
255 switch (key) {
256 case PPK_CollateCopies:
257 ret = d->collateCopies;
258 break;
259 case PPK_ColorMode:
260 ret = d->colorMode;
261 break;
262 case PPK_Creator:
263 ret = d->creator;
264 break;
265 case PPK_DocumentName:
266 ret = d->docName;
267 break;
268 case PPK_FullPage:
269 ret = d->fullPage;
270 break;
271 case PPK_NumberOfCopies:
272 ret = d->numCopies;
273 break;
274 case PPK_Orientation:
275 ret = d->orientation;
276 break;
277 case PPK_OutputFileName:
278 ret = d->outputFileName;
279 break;
280 case PPK_PageOrder:
281 ret = d->pageOrder;
282 break;
283 case PPK_PageRect:
284 ret = pageRect();
285 break;
286 case PPK_PaperSize:
287 ret = d->paperSize;
288 break;
289 case PPK_PaperRect:
290 ret = paperRect();
291 break;
292 case PPK_PaperSource:
293 ret = d->paperSource;
294 break;
295 case PPK_PrinterName:
296 ret = d->printerName;
297 break;
298 case PPK_PrinterProgram:
299 ret = d->printProgram;
300 break;
301 case PPK_Resolution:
302 ret = d->resolution;
303 break;
304 case PPK_SupportedResolutions:
305 ret = QList<QVariant>() << QT_QWS_PRINTER_DEFAULT_DPI;
306 break;
307 default:
308 break;
309 }
310 return ret;
311}
312
313void QtopiaPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
314{
315 Q_D(QtopiaPrintEngine);
316 switch (key) {
317 case PPK_CollateCopies:
318 d->collateCopies = value.toBool();
319 break;
320 case PPK_ColorMode:
321 d->colorMode = QPrinter::ColorMode(value.toInt());
322 break;
323 case PPK_Creator:
324 d->creator = value.toString();
325 break;
326 case PPK_DocumentName:
327 d->docName = value.toString();
328 break;
329 case PPK_FullPage:
330 d->fullPage = value.toBool();
331 break;
332 case PPK_NumberOfCopies:
333 d->numCopies = value.toInt();
334 break;
335 case PPK_Orientation:
336 d->orientation = QPrinter::Orientation(value.toInt());
337 break;
338 case PPK_OutputFileName:
339 d->outputFileName = value.toString();
340 break;
341 case PPK_PageOrder:
342 d->pageOrder = QPrinter::PageOrder(value.toInt());
343 break;
344 case PPK_PaperSize:
345 d->paperSize = QPrinter::PaperSize(value.toInt());
346 break;
347 case PPK_PaperSource:
348 d->paperSource = QPrinter::PaperSource(value.toInt());
349 case PPK_PrinterName:
350 d->printerName = value.toString();
351 break;
352 case PPK_PrinterProgram:
353 d->printProgram = value.toString();
354 break;
355 case PPK_Resolution:
356 d->resolution = value.toInt();
357 break;
358 default:
359 break;
360 }
361}
362
363void QtopiaPrintEngine::clearPage()
364{
365 d_func()->pageImage->fill(QColor(255, 255, 255).rgb());
366}
367
368void QtopiaPrintEngine::flushPage()
369{
370 d_func()->writeG3FaxPage();
371}
372
373QtopiaPrintEnginePrivate::~QtopiaPrintEnginePrivate()
374{
375 if ( pageImage )
376 delete pageImage;
377}
378
379void QtopiaPrintEnginePrivate::initialize()
380{
381 _paintEngine = 0;
382}
383
384QPaintEngine *QtopiaPrintEnginePrivate::paintEngine()
385{
386 if (!_paintEngine)
387 _paintEngine = new QRasterPaintEngine(pageImage);
388 return _paintEngine;
389}
390
391void QtopiaPrintEnginePrivate::writeG3FaxHeader()
392{
393 // Write the TIFF file magic number (little-endian TIFF).
394 buffer.append( (char)'I' );
395 buffer.append( (char)'I' );
396 buffer.append( (char)42 );
397 buffer.append( (char)0 );
398
399 // Leave a place-holder for the IFD offset of the first page.
400 ifdPatch = buffer.size();
401 buffer.append( (int)0 );
402}
403
404// Tag values, from RFC 2301.
405#define TIFF_IFD_NEW_SUB_FILE_TYPE 254
406#define TIFF_IFD_IMAGE_WIDTH 256
407#define TIFF_IFD_IMAGE_LENGTH 257
408#define TIFF_IFD_BITS_PER_SAMPLE 258
409#define TIFF_IFD_COMPRESSION 259
410#define TIFF_IFD_PHOTOMETRIC_INTERP 262
411#define TIFF_IFD_FILL_ORDER 266
412#define TIFF_IFD_STRIP_OFFSETS 273
413#define TIFF_IFD_ORIENTATION 274
414#define TIFF_IFD_SAMPLES_PER_PIXEL 277
415#define TIFF_IFD_ROWS_PER_STRIP 278
416#define TIFF_IFD_STRIP_BYTE_COUNTS 279
417#define TIFF_IFD_X_RESOLUTION 282
418#define TIFF_IFD_Y_RESOLUTION 283
419#define TIFF_IFD_PLANAR_CONFIG 284
420#define TIFF_IFD_T4_OPTIONS 292
421#define TIFF_IFD_RESOLUTION_UNIT 296
422#define TIFF_IFD_PAGE_NUMBER 297
423#define TIFF_IFD_CLEAN_FAX_DATA 327
424
425// IFD type values.
426#define TIFF_TYPE_SHORT 3
427#define TIFF_TYPE_LONG 4
428#define TIFF_TYPE_RATIONAL 5
429
430// Construct a SHORT pair from two values.
431#define TIFF_SHORT_PAIR(a,b) (((a) & 0xFFFF) | ((b) << 16))
432
433// Width of a FAX page in pixels, in the baseline specification from RFC 2301.
434// This must be hard-wired, as per the RFC. We truncate any pixels that
435// are beyond this limit, or pad lines to reach this limit.
436#define TIFF_FAX_WIDTH 1728
437
438void QtopiaPrintEnginePrivate::writeG3FaxPage()
439{
440 // Pad the image file to a word boundary, just in case.
441 buffer.pad();
442
443 // Back-patch the IFD link for the previous page.
444 buffer.patch( ifdPatch, buffer.size() );
445
446 // Output the contents of the IFD for this page (these must be
447 // in ascending order of tag value).
448 buffer.append( (short)19 ); // Number of IFD entries.
449 writeG3IFDEntry( TIFF_IFD_NEW_SUB_FILE_TYPE, TIFF_TYPE_LONG, 1, 2 );
450 writeG3IFDEntry( TIFF_IFD_IMAGE_WIDTH, TIFF_TYPE_LONG, 1, TIFF_FAX_WIDTH );
451 writeG3IFDEntry
452 ( TIFF_IFD_IMAGE_LENGTH, TIFF_TYPE_LONG, 1, pageImage->height() );
453 writeG3IFDEntry( TIFF_IFD_BITS_PER_SAMPLE, TIFF_TYPE_SHORT, 1, 1 );
454 writeG3IFDEntry( TIFF_IFD_COMPRESSION, TIFF_TYPE_SHORT, 1, 3 );
455 writeG3IFDEntry( TIFF_IFD_PHOTOMETRIC_INTERP, TIFF_TYPE_SHORT, 1, 0 );
456 writeG3IFDEntry( TIFF_IFD_FILL_ORDER, TIFF_TYPE_SHORT, 1, 1 );
457 int stripOffsets =
458 writeG3IFDEntry( TIFF_IFD_STRIP_OFFSETS, TIFF_TYPE_LONG, 1, 0 );
459 writeG3IFDEntry( TIFF_IFD_ORIENTATION, TIFF_TYPE_SHORT, 1, 1 );
460 writeG3IFDEntry( TIFF_IFD_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, 1 );
461 writeG3IFDEntry
462 ( TIFF_IFD_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, pageImage->height() );
463 int stripBytes = writeG3IFDEntry
464 ( TIFF_IFD_STRIP_BYTE_COUNTS, TIFF_TYPE_LONG, 1, 0 );
465 int xres =
466 writeG3IFDEntry( TIFF_IFD_X_RESOLUTION, TIFF_TYPE_RATIONAL, 1, 0 );
467 int yres =
468 writeG3IFDEntry( TIFF_IFD_Y_RESOLUTION, TIFF_TYPE_RATIONAL, 1, 0 );
469 writeG3IFDEntry( TIFF_IFD_PLANAR_CONFIG, TIFF_TYPE_SHORT, 1, 1 );
470 writeG3IFDEntry( TIFF_IFD_T4_OPTIONS, TIFF_TYPE_LONG, 1, 2 );
471 writeG3IFDEntry( TIFF_IFD_RESOLUTION_UNIT, TIFF_TYPE_SHORT, 1, 2 );
472 writeG3IFDEntry( TIFF_IFD_PAGE_NUMBER, TIFF_TYPE_SHORT, 2,
473 TIFF_SHORT_PAIR( pageNumber, 0 ) );
474 writeG3IFDEntry( TIFF_IFD_CLEAN_FAX_DATA, TIFF_TYPE_SHORT, 1, 0 );
475
476 // Leave a place-holder for the IFD offset of the next page.
477 ifdPatch = buffer.size();
478 buffer.append( (int)0 );
479
480 // Output the X and Y resolutions, as rational values (usually 200/1).
481 buffer.patch( xres, buffer.size() );
482 buffer.append( (int)resolution );
483 buffer.append( (int)1 );
484 buffer.patch( yres, buffer.size() );
485 buffer.append( (int)resolution );
486 buffer.append( (int)1 );
487
488 // We are now at the start of the image data - set the strip offset.
489 int start = buffer.size();
490 buffer.patch( stripOffsets, start );
491
492 // Output the image data.
493 int width = pageImage->width();
494 QImage::Format imageFormat = pageImage->format();
495 for ( int y = 0; y < pageImage->height(); ++y ) {
496 unsigned char *scan = pageImage->scanLine(y);
497 int prev, pixel, len;
498 writeG3EOL();
499 prev = 0;
500 len = 0;
501
502 uint currentColor = qRgb(255, 255, 255); // start with white
503
504 for ( int x = 0; x < width && x < TIFF_FAX_WIDTH; ++x ) {
505 if ( imageFormat == QImage::Format_RGB32 ) {
506 // read color of the current pixel
507 uint *p = (uint *)scan + x;
508
509 if ( *p == currentColor ) { // if it is the same color
510 len++; // imcrement length
511 } else { // otherwise write color into the buffer
512 if ( len > 0 ) {
513 if ( currentColor == qRgb(0, 0, 0) )
514 writeG3BlackRun( len );
515 else
516 writeG3WhiteRun( len );
517 }
518 // initialise length and color;
519 len = 1;
520 currentColor = *p;
521 }
522 } else if ( imageFormat == QImage::Format_Mono ) {
523 pixel = ((scan[x >> 3] & (1 << (x & 7))) != 0);
524 if ( pixel != prev ) {
525 if ( prev ) {
526 writeG3BlackRun( len );
527 } else {
528 writeG3WhiteRun( len );
529 }
530 prev = pixel;
531 len = 1;
532 } else {
533 ++len;
534 }
535 }
536 }
537
538 if ( imageFormat == QImage::Format_RGB32 ) {
539 // Output the last run on the line, and pad to TIFF_FAX_WIDTH.
540 if ( len != 0 ) {
541 if ( currentColor == qRgb(0, 0, 0) )
542 writeG3BlackRun( len );
543 else
544 writeG3WhiteRun( len );
545 }
546 if ( width < TIFF_FAX_WIDTH )
547 writeG3WhiteRun( TIFF_FAX_WIDTH - width );
548 } else if ( imageFormat == QImage::Format_Mono ) {
549 if ( len != 0 ) {
550 if ( prev ) {
551 writeG3BlackRun( len );
552 if ( width < TIFF_FAX_WIDTH ) {
553 writeG3WhiteRun( TIFF_FAX_WIDTH - width );
554 }
555 } else {
556 if ( width < TIFF_FAX_WIDTH ) {
557 writeG3WhiteRun( len + ( TIFF_FAX_WIDTH - width ) );
558 } else {
559 writeG3WhiteRun( len );
560 }
561 }
562 }
563 }
564 }
565
566 // Flush the last partial byte, which is padded with zero fill bits.
567 if ( partialBits > 0 ) {
568 buffer.append( (char)( partialByte << ( 8 - partialBits ) ) );
569 partialByte = 0;
570 partialBits = 0;
571 }
572
573 // end of page add six EOLs
574 for ( int i = 0; i < 6; i++ )
575 writeG3EOL();
576
577 // Update the byte count for the image data strip.
578 buffer.patch( stripBytes, buffer.size() - start );
579}
580
581int QtopiaPrintEnginePrivate::writeG3IFDEntry
582 ( int tag, int type, int count, int value )
583{
584 buffer.append( (short)tag );
585 buffer.append( (short)type );
586 buffer.append( count );
587 buffer.append( value );
588 return buffer.size() - 4; // Offset of the value for back-patching.
589}
590
591void QtopiaPrintEnginePrivate::writeG3Code( int code, int bits )
592{
593 partialByte = ( ( partialByte << bits ) | code );
594 partialBits += bits;
595 while ( partialBits >= 8 ) {
596 partialBits -= 8;
597 buffer.append( (char)( partialByte >> partialBits ) );
598 }
599}
600
601void QtopiaPrintEnginePrivate::writeG3WhiteRun( int len )
602{
603 static struct {
604 unsigned short code;
605 unsigned short bits;
606 } whiteCodes[64 + 27] = {
607 {0x0035, 8}, // 0
608 {0x0007, 6},
609 {0x0007, 4},
610 {0x0008, 4},
611 {0x000B, 4},
612 {0x000C, 4},
613 {0x000E, 4},
614 {0x000F, 4},
615 {0x0013, 5}, // 8
616 {0x0014, 5},
617 {0x0007, 5},
618 {0x0008, 5},
619 {0x0008, 6},
620 {0x0003, 6},
621 {0x0034, 6},
622 {0x0035, 6},
623 {0x002A, 6}, // 16
624 {0x002B, 6},
625 {0x0027, 7},
626 {0x000C, 7},
627 {0x0008, 7},
628 {0x0017, 7},
629 {0x0003, 7},
630 {0x0004, 7},
631 {0x0028, 7}, // 24
632 {0x002B, 7},
633 {0x0013, 7},
634 {0x0024, 7},
635 {0x0018, 7},
636 {0x0002, 8},
637 {0x0003, 8},
638 {0x001A, 8},
639 {0x001B, 8}, // 32
640 {0x0012, 8},
641 {0x0013, 8},
642 {0x0014, 8},
643 {0x0015, 8},
644 {0x0016, 8},
645 {0x0017, 8},
646 {0x0028, 8},
647 {0x0029, 8}, // 40
648 {0x002A, 8},
649 {0x002B, 8},
650 {0x002C, 8},
651 {0x002D, 8},
652 {0x0004, 8},
653 {0x0005, 8},
654 {0x000A, 8},
655 {0x000B, 8}, // 48
656 {0x0052, 8},
657 {0x0053, 8},
658 {0x0054, 8},
659 {0x0055, 8},
660 {0x0024, 8},
661 {0x0025, 8},
662 {0x0058, 8},
663 {0x0059, 8}, // 56
664 {0x005A, 8},
665 {0x005B, 8},
666 {0x004A, 8},
667 {0x004B, 8},
668 {0x0032, 8},
669 {0x0033, 8},
670 {0x0034, 8},
671 {0x001B, 5}, // Make up codes: 64
672 {0x0012, 5}, // 128
673 {0x0017, 6}, // 192
674 {0x0037, 7}, // 256
675 {0x0036, 8}, // 320
676 {0x0037, 8}, // 384
677 {0x0064, 8}, // 448
678 {0x0065, 8}, // 512
679 {0x0068, 8}, // 576
680 {0x0067, 8}, // 640
681 {0x00CC, 9}, // 704
682 {0x00CD, 9}, // 768
683 {0x00D2, 9}, // 832
684 {0x00D3, 9}, // 896
685 {0x00D4, 9}, // 960
686 {0x00D5, 9}, // 1024
687 {0x00D6, 9}, // 1088
688 {0x00D7, 9}, // 1152
689 {0x00D8, 9}, // 1216
690 {0x00D9, 9}, // 1280
691 {0x00DA, 9}, // 1344
692 {0x00DB, 9}, // 1408
693 {0x0098, 9}, // 1472
694 {0x0099, 9}, // 1536
695 {0x009A, 9}, // 1600
696 {0x0018, 6}, // 1664
697 {0x009B, 9}, // 1728
698 };
699 if ( len >= 64 ) {
700 int index = 63 + (len >> 6);
701 writeG3Code( whiteCodes[index].code, whiteCodes[index].bits );
702 len &= 63;
703 }
704 writeG3Code( whiteCodes[len].code, whiteCodes[len].bits );
705}
706
707void QtopiaPrintEnginePrivate::writeG3BlackRun( int len )
708{
709 static struct {
710 unsigned short code;
711 unsigned short bits;
712 } blackCodes[64 + 27] = {
713 {0x0037, 10}, // 0
714 {0x0002, 3},
715 {0x0003, 2},
716 {0x0002, 2},
717 {0x0003, 3},
718 {0x0003, 4},
719 {0x0002, 4},
720 {0x0003, 5},
721 {0x0005, 6}, // 8
722 {0x0004, 6},
723 {0x0004, 7},
724 {0x0005, 7},
725 {0x0007, 7},
726 {0x0004, 8},
727 {0x0007, 8},
728 {0x0018, 9},
729 {0x0017, 10}, // 16
730 {0x0018, 10},
731 {0x0008, 10},
732 {0x0067, 11},
733 {0x0068, 11},
734 {0x006C, 11},
735 {0x0037, 11},
736 {0x0028, 11},
737 {0x0017, 11}, // 24
738 {0x0018, 11},
739 {0x00CA, 12},
740 {0x00CB, 12},
741 {0x00CC, 12},
742 {0x00CD, 12},
743 {0x0068, 12},
744 {0x0069, 12},
745 {0x006A, 12}, // 32
746 {0x006B, 12},
747 {0x00D2, 12},
748 {0x00D3, 12},
749 {0x00D4, 12},
750 {0x00D5, 12},
751 {0x00D6, 12},
752 {0x00D7, 12},
753 {0x006C, 12}, // 40
754 {0x006D, 12},
755 {0x00DA, 12},
756 {0x00DB, 12},
757 {0x0054, 12},
758 {0x0055, 12},
759 {0x0056, 12},
760 {0x0057, 12},
761 {0x0064, 12}, // 48
762 {0x0065, 12},
763 {0x0052, 12},
764 {0x0053, 12},
765 {0x0024, 12},
766 {0x0037, 12},
767 {0x0038, 12},
768 {0x0027, 12},
769 {0x0028, 12}, // 56
770 {0x0058, 12},
771 {0x0059, 12},
772 {0x002B, 12},
773 {0x002C, 12},
774 {0x005A, 12},
775 {0x0066, 12},
776 {0x0067, 12},
777 {0x000F, 10}, // Make up codes: 64
778 {0x00C8, 12}, // 128
779 {0x00C9, 12}, // 192
780 {0x005B, 12}, // 256
781 {0x0033, 12}, // 320
782 {0x0034, 12}, // 384
783 {0x0035, 12}, // 448
784 {0x006C, 13}, // 512
785 {0x006D, 13}, // 576
786 {0x004A, 13}, // 640
787 {0x004B, 13}, // 704
788 {0x004C, 13}, // 768
789 {0x004D, 13}, // 832
790 {0x0072, 13}, // 896
791 {0x0073, 13}, // 960
792 {0x0074, 13}, // 1024
793 {0x0075, 13}, // 1088
794 {0x0076, 13}, // 1152
795 {0x0077, 13}, // 1216
796 {0x0052, 13}, // 1280
797 {0x0053, 13}, // 1344
798 {0x0054, 13}, // 1408
799 {0x0055, 13}, // 1472
800 {0x005A, 13}, // 1536
801 {0x005B, 13}, // 1600
802 {0x0064, 13}, // 1664
803 {0x0065, 13}, // 1728
804 };
805 if ( len >= 64 ) {
806 int index = 63 + (len >> 6);
807 writeG3Code( blackCodes[index].code, blackCodes[index].bits );
808 len &= 63;
809 }
810 writeG3Code( blackCodes[len].code, blackCodes[len].bits );
811}
812
813void QtopiaPrintEnginePrivate::writeG3EOL()
814{
815 int bitToPad;
816 if ( partialBits <= 4 ) {
817 bitToPad = 4 - partialBits;
818 } else {
819 bitToPad = 8 - partialBits + 4;
820 }
821
822 partialByte = ((partialByte << (bitToPad + 12)) | 0x0001);
823 partialBits += bitToPad + 12;
824
825 while ( partialBits >= 8 ) {
826 partialBits -= 8;
827 buffer.append( (char)(partialByte >> partialBits ) );
828 }
829// writeG3Code( 0x0001, 12 );
830}
831
832void QtopiaPrintBuffer::append( short value )
833{
834 if ( _bigEndian ) {
835 _data.append( (char)(value >> 8) );
836 _data.append( (char)value );
837 } else {
838 _data.append( (char)value );
839 _data.append( (char)(value >> 8) );
840 }
841}
842
843void QtopiaPrintBuffer::append( int value )
844{
845 if ( _bigEndian ) {
846 _data.append( (char)(value >> 24) );
847 _data.append( (char)(value >> 16) );
848 _data.append( (char)(value >> 8) );
849 _data.append( (char)value );
850 } else {
851 _data.append( (char)value );
852 _data.append( (char)(value >> 8) );
853 _data.append( (char)(value >> 16) );
854 _data.append( (char)(value >> 24) );
855 }
856}
857
858void QtopiaPrintBuffer::patch( int posn, int value )
859{
860 if ( _bigEndian ) {
861 _data[posn] = (char)(value >> 24);
862 _data[posn + 1] = (char)(value >> 16);
863 _data[posn + 2] = (char)(value >> 8);
864 _data[posn + 3] = (char)value;
865 } else {
866 _data[posn] = (char)value;
867 _data[posn + 1] = (char)(value >> 8);
868 _data[posn + 2] = (char)(value >> 16);
869 _data[posn + 3] = (char)(value >> 24);
870 }
871}
872
873void QtopiaPrintBuffer::pad()
874{
875 while ( ( _data.size() % 4 ) != 0 )
876 _data.append( (char)0 );
877}
878
879QT_END_NAMESPACE
880
881#endif // QT_NO_PRINTER
Note: See TracBrowser for help on using the repository browser.