00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifdef __GNUC__
00011 #pragma implementation
00012 #endif
00013
00014 #include <aconf.h>
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <unistd.h>
00019 #include <string.h>
00020 #include <ctype.h>
00021 #include <math.h>
00022 #include <iostream>
00023
00024 #include "GString.h"
00025 #include "Object.h"
00026 #include "Stream.h"
00027 #include "Link.h"
00028 #include "GfxState.h"
00029 #include "GfxFont.h"
00030 #include "UnicodeMap.h"
00031 #include "CharCodeToUnicode.h"
00032 #include "FontFile.h"
00033 #include "Error.h"
00034 #include "TextOutputDev.h"
00035 #include "QOutputDev.h"
00036
00037
00038 #include <qpixmap.h>
00039 #include <qimage.h>
00040 #include <qpainter.h>
00041 #include <qdict.h>
00042 #include <qtimer.h>
00043 #include <qapplication.h>
00044 #include <qclipboard.h>
00045
00046
00047 #define QPDFDBG(x) // normal compilation
00048
00049
00050
00051
00052
00053
00054
00055 static inline QColor q_col ( const GfxRGB &rgb )
00056 {
00057 return QColor ( lrint ( rgb. r * 255 ), lrint ( rgb. g * 255 ), lrint ( rgb. b * 255 ));
00058 }
00059
00060
00061
00062
00063
00064
00065 struct QOutFontSubst {
00066 char * m_name;
00067 char * m_sname;
00068 bool m_bold;
00069 bool m_italic;
00070 QFont::StyleHint m_hint;
00071 };
00072
00073 static QOutFontSubst qStdFonts [] = {
00074 { "Helvetica", "Helvetica", false, false, QFont::Helvetica },
00075 { "Helvetica-Oblique", "Helvetica", false, true, QFont::Helvetica },
00076 { "Helvetica-Bold", "Helvetica", true, false, QFont::Helvetica },
00077 { "Helvetica-BoldOblique", "Helvetica", true, true, QFont::Helvetica },
00078 { "Times-Roman", "Times", false, false, QFont::Times },
00079 { "Times-Italic", "Times", false, true, QFont::Times },
00080 { "Times-Bold", "Times", true, false, QFont::Times },
00081 { "Times-BoldItalic", "Times", true, true, QFont::Times },
00082 { "Courier", "Courier", false, false, QFont::Courier },
00083 { "Courier-Oblique", "Courier", false, true, QFont::Courier },
00084 { "Courier-Bold", "Courier", true, false, QFont::Courier },
00085 { "Courier-BoldOblique", "Courier", true, true, QFont::Courier },
00086
00087 { "Symbol", 0, false, false, QFont::AnyStyle },
00088 { "Zapf-Dingbats", 0, false, false, QFont::AnyStyle },
00089
00090 { 0, 0, false, false, QFont::AnyStyle }
00091 };
00092
00093
00094
00095
00096
00097
00098
00099 QFont QOutputDev::matchFont ( GfxFont *gfxFont, fp_t m11, fp_t m12, fp_t m21, fp_t m22 )
00100 {
00101 static QDict<QOutFontSubst> stdfonts;
00102
00103
00104 if ( stdfonts. isEmpty ( )) {
00105 for ( QOutFontSubst *ptr = qStdFonts; ptr-> m_name; ptr++ ) {
00106 stdfonts. insert ( QString ( ptr-> m_name ), ptr );
00107 }
00108 }
00109
00110
00111 int size = lrint ( sqrt ( m21 * m21 + m22 * m22 ));
00112
00113 QPDFDBG( printf ( "SET FONT: Name=%s, Size=%d, Bold=%d, Italic=%d, Mono=%d, Serif=%d, Symbol=%d, CID=%d, EmbFN=%s, M=(%f,%f,%f,%f)\n",
00114 (( gfxFont-> getName ( )) ? gfxFont-> getName ( )-> getCString ( ) : "<n/a>" ),
00115 size,
00116 gfxFont-> isBold ( ),
00117 gfxFont-> isItalic ( ),
00118 gfxFont-> isFixedWidth ( ),
00119 gfxFont-> isSerif ( ),
00120 gfxFont-> isSymbolic ( ),
00121 gfxFont-> isCIDFont ( ),
00122 ( gfxFont-> getEmbeddedFontName ( ) ? gfxFont-> getEmbeddedFontName()-> getCString ( ) : "<n/a>" ),
00123 (double) m11, (double) m12, (double) m21, (double) m22 ) );
00124
00125
00126 QString fname (( gfxFont-> getName ( )) ? gfxFont-> getName ( )-> getCString ( ) : "<n/a>" );
00127
00128 QFont f;
00129 f. setPixelSize ( size > 0 ? size : 8 );
00130
00131
00132 QOutFontSubst *subst = stdfonts [fname];
00133
00134 if ( subst ) {
00135 if ( subst-> m_sname )
00136 f. setFamily ( subst-> m_sname );
00137 f. setStyleHint ( subst-> m_hint, (QFont::StyleStrategy) ( QFont::PreferOutline | QFont::PreferQuality ));
00138 f. setBold ( subst-> m_bold );
00139 f. setItalic ( subst-> m_italic );
00140 }
00141 else {
00142 QFont::StyleHint sty;
00143
00144 if ( gfxFont-> isSerif ( ))
00145 sty = QFont::Serif;
00146 else if ( gfxFont-> isFixedWidth ( ))
00147 sty = QFont::TypeWriter;
00148 else
00149 sty = QFont::Helvetica;
00150
00151 f. setStyleHint ( sty, (QFont::StyleStrategy) ( QFont::PreferOutline | QFont::PreferQuality ));
00152 f. setBold ( gfxFont-> isBold ( ) > 0 );
00153 f. setItalic ( gfxFont-> isItalic ( ) > 0 );
00154 f. setFixedPitch ( gfxFont-> isFixedWidth ( ) > 0 );
00155
00156
00157 if ( fname. contains ( "Oblique" ) || fname. contains ( "Italic" ))
00158 f. setItalic ( true );
00159 if ( fname. contains ( "Bold" ))
00160 f. setWeight ( QFont::Bold );
00161 if ( fname. contains ( "Demi" ))
00162 f. setWeight ( QFont::DemiBold );
00163 if ( fname. contains ( "Light" ))
00164 f. setWeight ( QFont::Light );
00165 if ( fname. contains ( "Black" ))
00166 f. setWeight ( QFont::Black );
00167 }
00168
00169 if (( m12 > -0.1 ) && ( m12 < 0.1 ) && ((( m21 > -5.0 ) && ( m21 < -0.1 )) || (( m21 > 0.1 ) && ( m21 < 5.0 )))) {
00170 f. setItalic ( true );
00171 }
00172 return f;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 QOutputDev::QOutputDev ( QWidget *parent, const char *name, int flags ) : QScrollView ( parent, name, WRepaintNoErase | WResizeNoErase | flags )
00182 {
00183 m_pixmap = 0;
00184 m_painter = 0;
00185
00186
00187 m_text = new TextPage ( gFalse );
00188 }
00189
00190 QOutputDev::~QOutputDev ( )
00191 {
00192 delete m_painter;
00193 delete m_pixmap;
00194 delete m_text;
00195 }
00196
00197
00198 void QOutputDev::startPage ( int , GfxState *state )
00199 {
00200 delete m_pixmap;
00201 delete m_painter;
00202
00203 m_pixmap = new QPixmap ( lrint ( state-> getPageWidth ( )), lrint ( state-> getPageHeight ( )));
00204 m_painter = new QPainter ( m_pixmap );
00205
00206 QPDFDBG( printf ( "NEW PIXMAP (%ld x %ld)\n", lrint ( state-> getPageWidth ( )), lrint ( state-> getPageHeight ( ))));
00207
00208 resizeContents ( m_pixmap-> width ( ), m_pixmap-> height ( ));
00209 setContentsPos ( 0, 0 );
00210
00211 m_pixmap-> fill ( white );
00212 m_text-> clear ( );
00213 viewport ( )-> repaint ( );
00214 }
00215
00216 void QOutputDev::endPage ( )
00217 {
00218 QPDFDBG( printf("End page\n") );
00219 m_text-> coalesce ( );
00220
00221
00222
00223
00224
00225 #if 0
00226 delete m_painter;
00227 m_painter = 0;
00228 #endif
00229
00230 updateContents ( 0, 0, contentsWidth ( ), contentsHeight ( ));
00231 }
00232
00233 void QOutputDev::drawLink ( Link *link, Catalog * )
00234 {
00235 fp_t x1, y1, x2, y2, w;
00236
00237 link-> getBorder ( &x1, &y1, &x2, &y2, &w );
00238
00239 if ( w > 0 ) {
00240 int x, y, dx, dy;
00241
00242 cvtUserToDev ( x1, y1, &x, &y );
00243 cvtUserToDev ( x2, y2, &dx, &dy );
00244
00245 QPen oldpen = m_painter-> pen ( );
00246 m_painter-> setPen ( blue );
00247 m_painter-> drawRect ( x, y, dx, dy );
00248 m_painter-> setPen ( oldpen );
00249 }
00250 }
00251
00252 void QOutputDev::saveState ( GfxState * )
00253 {
00254 if ( ! m_painter )
00255 return;
00256
00257 QPDFDBG( printf ( "SAVE (CLIP=%d/%d)\n", m_painter-> hasClipping ( ), !m_painter-> clipRegion ( ). isEmpty ( )));
00258
00259 m_painter-> save ( );
00260 }
00261
00262 void QOutputDev::restoreState ( GfxState * )
00263 {
00264 if( ! m_painter )
00265 return;
00266
00267 m_painter-> restore ( );
00268
00269
00270
00271 QPDFDBG ( printf ( "RESTORE (CLIP=%d/%d)\n", m_painter-> hasClipping ( ), !m_painter-> clipRegion ( ). isEmpty ( )));
00272 }
00273
00274 void QOutputDev::updateAll ( GfxState *state )
00275 {
00276 updateLineAttrs ( state, gTrue );
00277
00278
00279 updateFillColor ( state );
00280 updateStrokeColor ( state );
00281 updateFont ( state );
00282 }
00283
00284 void QOutputDev::updateCTM ( GfxState *state, fp_t , fp_t , fp_t , fp_t , fp_t , fp_t )
00285 {
00286 updateLineAttrs ( state, gTrue );
00287 }
00288
00289 void QOutputDev::updateLineDash ( GfxState *state )
00290 {
00291 updateLineAttrs ( state, gTrue );
00292 }
00293
00294 void QOutputDev::updateFlatness ( GfxState * )
00295 {
00296
00297 QPDFDBG( printf ( "updateFlatness not supported !\n" ));
00298 }
00299
00300 void QOutputDev::updateLineJoin ( GfxState *state )
00301 {
00302 updateLineAttrs ( state, gFalse );
00303 }
00304
00305 void QOutputDev::updateLineCap ( GfxState *state )
00306 {
00307 updateLineAttrs ( state, gFalse );
00308 }
00309
00310
00311 void QOutputDev::updateMiterLimit ( GfxState * )
00312 {
00313 QPDFDBG( printf ( "updateMiterLimit not supported !\n" ));
00314 }
00315
00316 void QOutputDev::updateLineWidth ( GfxState *state )
00317 {
00318 updateLineAttrs ( state, gFalse );
00319 }
00320
00321 void QOutputDev::updateLineAttrs ( GfxState *state, GBool updateDash )
00322 {
00323 fp_t *dashPattern;
00324 int dashLength;
00325 fp_t dashStart;
00326
00327 Qt::PenCapStyle cap;
00328 Qt::PenJoinStyle join;
00329 int width;
00330
00331 width = lrint ( state-> getTransformedLineWidth ( ));
00332
00333 switch ( state-> getLineCap ( )) {
00334 case 0: cap = FlatCap; break;
00335 case 1: cap = RoundCap; break;
00336 case 2: cap = SquareCap; break;
00337 default:
00338 qWarning ( "Bad line cap style (%d)\n", state-> getLineCap ( ));
00339 cap = FlatCap;
00340 break;
00341 }
00342
00343 switch (state->getLineJoin()) {
00344 case 0: join = MiterJoin; break;
00345 case 1: join = RoundJoin; break;
00346 case 2: join = BevelJoin; break;
00347 default:
00348 qWarning ( "Bad line join style (%d)\n", state->getLineJoin ( ));
00349 join = MiterJoin;
00350 break;
00351 }
00352
00353 state-> getLineDash ( &dashPattern, &dashLength, &dashStart );
00354
00355 QColor oldcol = m_painter-> pen ( ). color ( );
00356 GfxRGB rgb;
00357
00358 state-> getStrokeRGB ( &rgb );
00359 oldcol = q_col ( rgb );
00360
00361 m_painter-> setPen ( QPen ( oldcol, width, dashLength > 0 ? DashLine : SolidLine, cap, join ));
00362
00363 if ( updateDash && ( dashLength > 0 )) {
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 }
00377 }
00378
00379 void QOutputDev::updateFillColor ( GfxState *state )
00380 {
00381 GfxRGB rgb;
00382 state-> getFillRGB ( &rgb );
00383
00384 m_painter-> setBrush ( q_col ( rgb ));
00385 }
00386
00387 void QOutputDev::updateStrokeColor ( GfxState *state )
00388 {
00389 GfxRGB rgb;
00390 state-> getStrokeRGB ( &rgb );
00391
00392 QPen pen = m_painter-> pen ( );
00393 pen. setColor ( q_col ( rgb ));
00394 m_painter-> setPen ( pen );
00395 }
00396
00397 void QOutputDev::updateFont ( GfxState *state )
00398 {
00399 fp_t m11, m12, m21, m22;
00400 GfxFont *gfxFont = state-> getFont ( );
00401
00402 if ( !gfxFont )
00403 return;
00404
00405 state-> getFontTransMat ( &m11, &m12, &m21, &m22 );
00406 m11 *= state-> getHorizScaling ( );
00407 m12 *= state-> getHorizScaling ( );
00408
00409 QFont font = matchFont ( gfxFont, m11, m12, m21, m22 );
00410
00411 m_painter-> setFont ( font );
00412 m_text-> updateFont ( state );
00413 }
00414
00415 void QOutputDev::stroke ( GfxState *state )
00416 {
00417 QPointArray points;
00418 QArray<int> lengths;
00419
00420
00421 int n = convertPath ( state, points, lengths );
00422
00423 QPDFDBG( printf ( "DRAWING: %d POLYS\n", n ));
00424
00425
00426 int j = 0;
00427 for ( int i = 0; i < n; i++ ) {
00428 int len = lengths [i];
00429
00430 if ( len >= 2 ) {
00431 QPDFDBG( printf ( " - POLY %d: ", i ));
00432 QPDFDBG( for ( int ii = 0; ii < len; ii++ ))
00433 QPDFDBG( printf ( "(%d/%d) ", points [j+ii]. x ( ), points [j+ii]. y ( )));
00434 QPDFDBG( printf ( "\n" ));
00435
00436 m_painter-> drawPolyline ( points, j, len );
00437 }
00438 j += len;
00439 }
00440 qApp-> processEvents ( );
00441 }
00442
00443 void QOutputDev::fill ( GfxState *state )
00444 {
00445 doFill ( state, true );
00446 }
00447
00448 void QOutputDev::eoFill ( GfxState *state )
00449 {
00450 doFill ( state, false );
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 void QOutputDev::doFill ( GfxState *state, bool winding )
00463 {
00464 QPointArray points;
00465 QArray<int> lengths;
00466
00467
00468 int n = convertPath ( state, points, lengths );
00469
00470 QPDFDBG( printf ( "FILLING: %d POLYS\n", n ));
00471
00472 QPen oldpen = m_painter-> pen ( );
00473 m_painter-> setPen ( QPen ( NoPen ));
00474
00475
00476 int j = 0;
00477 for ( int i = 0; i < n; i++ ) {
00478 int len = lengths [i];
00479
00480 if ( len >= 3 ) {
00481 QPDFDBG( printf ( " - POLY %d: ", i ));
00482 QPDFDBG( for ( int ii = 0; ii < len; ii++ ))
00483 QPDFDBG( printf ( "(%d/%d) ", points [j+ii]. x ( ), points [j+ii]. y ( )));
00484 QPDFDBG( printf ( "\n" ));
00485
00486 m_painter-> drawPolygon ( points, winding, j, len );
00487 }
00488 j += len;
00489 }
00490 m_painter-> setPen ( oldpen );
00491
00492 qApp-> processEvents ( );
00493 }
00494
00495 void QOutputDev::clip ( GfxState *state )
00496 {
00497 doClip ( state, true );
00498 }
00499
00500 void QOutputDev::eoClip ( GfxState *state )
00501 {
00502 doClip ( state, false );
00503 }
00504
00505 void QOutputDev::doClip ( GfxState *state, bool winding )
00506 {
00507 QPointArray points;
00508 QArray<int> lengths;
00509
00510
00511 int n = convertPath ( state, points, lengths );
00512
00513 QRegion region;
00514
00515 QPDFDBG( printf ( "CLIPPING: %d POLYS\n", n ));
00516
00517
00518 int j = 0;
00519 for ( int i = 0; i < n; i++ ) {
00520 int len = lengths [i];
00521
00522 if ( len >= 3 ) {
00523 QPointArray dummy;
00524 dummy. setRawData ( points. data ( ) + j, len );
00525
00526 QPDFDBG( printf ( " - POLY %d: ", i ));
00527 QPDFDBG( for ( int ii = 0; ii < len; ii++ ) printf ( "(%d/%d) ", points [j+ii]. x ( ), points [j+ii]. y ( )));
00528 QPDFDBG( printf ( "\n" ));
00529
00530 region |= QRegion ( dummy, winding );
00531
00532 dummy. resetRawData ( points. data ( ) + j, len );
00533 }
00534 j += len;
00535 }
00536
00537 if ( m_painter && m_painter-> hasClipping ( ))
00538 region &= m_painter-> clipRegion ( );
00539
00540
00541
00542
00543
00544
00545 qApp-> processEvents ( );
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 int QOutputDev::convertPath ( GfxState *state, QPointArray &points, QArray<int> &lengths )
00558 {
00559 GfxPath *path = state-> getPath ( );
00560 int n = path-> getNumSubpaths ( );
00561
00562 lengths. resize ( n );
00563
00564
00565 for ( int i = 0; i < n; i++ ) {
00566
00567 lengths [i] = convertSubpath ( state, path-> getSubpath ( i ), points );
00568 }
00569
00570 return n;
00571 }
00572
00573
00574
00575
00576
00577 int QOutputDev::convertSubpath ( GfxState *state, GfxSubpath *subpath, QPointArray &points )
00578 {
00579 int oldcnt = points. count ( );
00580
00581 fp_t x0, y0, x1, y1, x2, y2, x3, y3;
00582
00583 int m = subpath-> getNumPoints ( );
00584 int i = 0;
00585
00586 while ( i < m ) {
00587 if ( i >= 1 && subpath-> getCurve ( i )) {
00588 state-> transform ( subpath-> getX ( i - 1 ), subpath-> getY ( i - 1 ), &x0, &y0 );
00589 state-> transform ( subpath-> getX ( i ), subpath-> getY ( i ), &x1, &y1 );
00590 state-> transform ( subpath-> getX ( i + 1 ), subpath-> getY ( i + 1 ), &x2, &y2 );
00591 state-> transform ( subpath-> getX ( i + 2 ), subpath-> getY ( i + 2 ), &x3, &y3 );
00592
00593 QPointArray tmp;
00594 tmp. setPoints ( 4, lrint ( x0 ), lrint ( y0 ), lrint ( x1 ), lrint ( y1 ),
00595 lrint ( x2 ), lrint ( y2 ), lrint ( x3 ), lrint ( y3 ));
00596
00597 #if QT_VERSION < 0x030000
00598 tmp = tmp. quadBezier ( );
00599
00600 for ( uint loop = 0; loop < tmp. count ( ); loop++ ) {
00601 QPoint p = tmp. point ( loop );
00602 points. putPoints ( points. count ( ), 1, p. x ( ), p. y ( ));
00603 }
00604 #else
00605 tmp = tmp. cubicBezier ( );
00606 points. putPoints ( points. count ( ), tmp. count ( ), tmp );
00607 #endif
00608
00609 i += 3;
00610 }
00611 else {
00612 state-> transform ( subpath-> getX ( i ), subpath-> getY ( i ), &x1, &y1 );
00613
00614 points. putPoints ( points. count ( ), 1, lrint ( x1 ), lrint ( y1 ));
00615 ++i;
00616 }
00617 }
00618 return points. count ( ) - oldcnt;
00619 }
00620
00621
00622 void QOutputDev::beginString ( GfxState *state, GString * )
00623 {
00624 m_text-> beginString ( state );
00625 }
00626
00627 void QOutputDev::endString ( GfxState * )
00628 {
00629 m_text-> endString ( );
00630 }
00631
00632 void QOutputDev::drawChar ( GfxState *state, fp_t x, fp_t y,
00633 fp_t dx, fp_t dy, fp_t originX, fp_t originY,
00634 CharCode code, Unicode *u, int uLen )
00635 {
00636 fp_t x1, y1, dx1, dy1;
00637
00638 if ( uLen > 0 )
00639 m_text-> addChar ( state, x, y, dx, dy, u, uLen );
00640
00641
00642 if (( state-> getRender ( ) & 3 ) == 3 ) {
00643 return;
00644 }
00645
00646 x -= originX;
00647 y -= originY;
00648 state-> transform ( x, y, &x1, &y1 );
00649 state-> transformDelta ( dx, dy, &dx1, &dy1 );
00650
00651
00652 if ( uLen > 0 ) {
00653 QString str;
00654 QFontMetrics fm = m_painter-> fontMetrics ( );
00655
00656 for ( int i = 0; i < uLen; i++ ) {
00657 QChar c = QChar ( u [i] );
00658
00659 if ( fm. inFont ( c )) {
00660 str [i] = QChar ( u [i] );
00661 }
00662 else {
00663 str [i] = ' ';
00664 QPDFDBG( printf ( "CHARACTER NOT IN FONT: %hx\n", c. unicode ( )));
00665 }
00666 }
00667
00668 if (( uLen == 1 ) && ( str [0] == ' ' ))
00669 return;
00670
00671
00672 fp_t m11, m12, m21, m22;
00673
00674 state-> getFontTransMat ( &m11, &m12, &m21, &m22 );
00675 m11 *= state-> getHorizScaling ( );
00676 m12 *= state-> getHorizScaling ( );
00677
00678 fp_t fsize = m_painter-> font ( ). pixelSize ( );
00679
00680 #ifndef QT_NO_TRANSFORMATIONS
00681 QWMatrix oldmat;
00682
00683 bool dorot = (( m12 < -0.1 ) || ( m12 > 0.1 )) && (( m21 < -0.1 ) || ( m21 > 0.1 ));
00684
00685 if ( dorot ) {
00686 oldmat = m_painter-> worldMatrix ( );
00687
00688 std::cerr << std::endl << "ROTATED: " << m11 << ", " << m12 << ", " << m21 << ", " << m22 << " / SIZE: " << fsize << " / TEXT: " << str. local8Bit ( ) << endl << endl;
00689
00690 QWMatrix mat ( lrint ( m11 / fsize ), lrint ( m12 / fsize ), -lrint ( m21 / fsize ), -lrint ( m22 / fsize ), lrint ( x1 ), lrint ( y1 ));
00691
00692 m_painter-> setWorldMatrix ( mat );
00693
00694 x1 = 0;
00695 y1 = 0;
00696 }
00697 #endif
00698
00699 QPen oldpen = m_painter-> pen ( );
00700
00701 if (!( state-> getRender ( ) & 1 )) {
00702 QPen fillpen = oldpen;
00703
00704 fillpen. setColor ( m_painter-> brush ( ). color ( ));
00705 m_painter-> setPen ( fillpen );
00706 }
00707
00708 if ( fsize > 5 )
00709 m_painter-> drawText ( lrint ( x1 ), lrint ( y1 ), str );
00710 else
00711 m_painter-> fillRect ( lrint ( x1 ), lrint ( y1 ), lrint ( QMAX( fp_t(1), dx1 )), lrint ( QMAX( fsize, dy1 )), m_painter-> pen ( ). color ( ));
00712
00713 m_painter-> setPen ( oldpen );
00714
00715 #ifndef QT_NO_TRANSFORMATIONS
00716 if ( dorot )
00717 m_painter-> setWorldMatrix ( oldmat );
00718 #endif
00719
00720 QPDFDBG( printf ( "DRAW TEXT: \"%s\" at (%ld/%ld)\n", str. local8Bit ( ). data ( ), lrint ( x1 ), lrint ( y1 )));
00721 }
00722 else if ( code != 0 ) {
00723
00724 qWarning ( "Unknown character (CID=%d Unicode=%hx)\n", code, (unsigned short) ( uLen > 0 ? u [0] : (Unicode) 0 ));
00725 }
00726 qApp-> processEvents ( );
00727 }
00728
00729
00730
00731 void QOutputDev::drawImageMask ( GfxState *state, Object *, Stream *str, int width, int height, GBool invert, GBool inlineImg )
00732 {
00733
00734 fp_t *ctm = state-> getCTM ( );
00735
00736 if ( fabs ( ctm [0] * ctm [3] - ctm [1] * ctm [2] ) < 0.000001 ) {
00737 qWarning ( "Singular CTM in drawImage\n" );
00738
00739 if ( inlineImg ) {
00740 str-> reset ( );
00741 int j = height * (( width + 7 ) / 8 );
00742 for ( int i = 0; i < j; i++ )
00743 str->getChar();
00744
00745 str->close();
00746 }
00747 return;
00748 }
00749
00750 GfxRGB rgb;
00751 state-> getFillRGB ( &rgb );
00752 uint val = ( lrint ( rgb. r * 255 ) & 0xff ) << 16 | ( lrint ( rgb. g * 255 ) & 0xff ) << 8 | ( lrint ( rgb. b * 255 ) & 0xff );
00753
00754
00755 QImage img ( width, height, 32 );
00756 img. setAlphaBuffer ( true );
00757
00758 QPDFDBG( printf ( "IMAGE MASK (%dx%d)\n", width, height ));
00759
00760
00761 ImageStream *imgStr = new ImageStream ( str, width, 1, 1 );
00762 imgStr-> reset ( );
00763
00764 uchar **scanlines = img. jumpTable ( );
00765
00766 if ( ctm [3] > 0 )
00767 scanlines += ( height - 1 );
00768
00769 for ( int y = 0; y < height; y++ ) {
00770 QRgb *scanline = (QRgb *) *scanlines;
00771
00772 if ( ctm [0] < 0 )
00773 scanline += ( width - 1 );
00774
00775 for ( int x = 0; x < width; x++ ) {
00776 Guchar alpha;
00777
00778 imgStr-> getPixel ( &alpha );
00779
00780 if ( invert )
00781 alpha ^= 1;
00782
00783 *scanline = ( alpha == 0 ) ? 0xff000000 | val : val;
00784
00785 ctm [0] < 0 ? scanline-- : scanline++;
00786 }
00787 ctm [3] > 0 ? scanlines-- : scanlines++;
00788
00789 qApp-> processEvents ( );
00790 }
00791
00792 #ifndef QT_NO_TRANSFORMATIONS
00793 QWMatrix mat ( ctm [0] / width, ctm [1], ctm [2], ctm [3] / height, ctm [4], ctm [5] );
00794
00795 std::cerr << "MATRIX T=" << mat. dx ( ) << "/" << mat. dy ( ) << std::endl
00796 << " - M=" << mat. m11 ( ) << "/" << mat. m12 ( ) << "/" << mat. m21 ( ) << "/" << mat. m22 ( ) << std::endl;
00797
00798 QWMatrix oldmat = m_painter-> worldMatrix ( );
00799 m_painter-> setWorldMatrix ( mat, true );
00800
00801 #ifdef QWS
00802 QPixmap pm;
00803 pm. convertFromImage ( img );
00804 m_painter-> drawPixmap ( 0, 0, pm );
00805 #else
00806 m_painter-> drawImage ( QPoint ( 0, 0 ), img );
00807 #endif
00808
00809 m_painter-> setWorldMatrix ( oldmat );
00810
00811 #else
00812 if (( ctm [1] < -0.1 ) || ( ctm [1] > 0.1 ) || ( ctm [2] < -0.1 ) || ( ctm [2] > 0.1 )) {
00813 QPDFDBG( printf ( "### ROTATED / SHEARED / ETC -- CANNOT DISPLAY THIS IMAGE\n" ));
00814 }
00815 else {
00816 int x = lrint ( ctm [4] );
00817 int y = lrint ( ctm [5] );
00818
00819 int w = lrint ( ctm [0] );
00820 int h = lrint ( ctm [3] );
00821
00822 if ( w < 0 ) {
00823 x += w;
00824 w = -w;
00825 }
00826 if ( h < 0 ) {
00827 y += h;
00828 h = -h;
00829 }
00830
00831 QPDFDBG( printf ( "DRAWING IMAGE MASKED: %d/%d - %dx%d\n", x, y, w, h ));
00832
00833 img = img. smoothScale ( w, h );
00834 qApp-> processEvents ( );
00835 m_painter-> drawImage ( x, y, img );
00836 }
00837
00838 #endif
00839
00840 delete imgStr;
00841 qApp-> processEvents ( );
00842 }
00843
00844
00845 void QOutputDev::drawImage(GfxState *state, Object *, Stream *str, int width, int height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg )
00846 {
00847 int nComps, nVals, nBits;
00848
00849
00850 nComps = colorMap->getNumPixelComps ( );
00851 nVals = width * nComps;
00852 nBits = colorMap-> getBits ( );
00853
00854
00855 fp_t *ctm = state-> getCTM ( );
00856
00857 if ( fabs ( ctm [0] * ctm [3] - ctm [1] * ctm [2] ) < 0.000001 ) {
00858 qWarning ( "Singular CTM in drawImage\n" );
00859
00860 if ( inlineImg ) {
00861 str-> reset ( );
00862 int j = height * (( nVals * nBits + 7 ) / 8 );
00863 for ( int i = 0; i < j; i++ )
00864 str->getChar();
00865
00866 str->close();
00867 }
00868 return;
00869 }
00870
00871 QImage img ( width, height, 32 );
00872
00873 if ( maskColors )
00874 img. setAlphaBuffer ( true );
00875
00876 QPDFDBG( printf ( "IMAGE (%dx%d)\n", width, height ));
00877
00878
00879 ImageStream *imgStr = new ImageStream ( str, width, nComps, nBits );
00880 imgStr-> reset ( );
00881
00882 Guchar pixBuf [gfxColorMaxComps];
00883 GfxRGB rgb;
00884
00885
00886 uchar **scanlines = img. jumpTable ( );
00887
00888 if ( ctm [3] > 0 )
00889 scanlines += ( height - 1 );
00890
00891 for ( int y = 0; y < height; y++ ) {
00892 QRgb *scanline = (QRgb *) *scanlines;
00893
00894 if ( ctm [0] < 0 )
00895 scanline += ( width - 1 );
00896
00897 for ( int x = 0; x < width; x++ ) {
00898 imgStr-> getPixel ( pixBuf );
00899 colorMap-> getRGB ( pixBuf, &rgb );
00900
00901 uint val = ( lrint ( rgb. r * 255 ) & 0xff ) << 16 | ( lrint ( rgb. g * 255 ) & 0xff ) << 8 | ( lrint ( rgb. b * 255 ) & 0xff );
00902
00903 if ( maskColors ) {
00904 for ( int k = 0; k < nComps; ++k ) {
00905 if (( pixBuf [k] < maskColors [2 * k] ) || ( pixBuf [k] > maskColors [2 * k] )) {
00906 val |= 0xff000000;
00907 break;
00908 }
00909 }
00910 }
00911 *scanline = val;
00912
00913 ctm [0] < 0 ? scanline-- : scanline++;
00914 }
00915 ctm [3] > 0 ? scanlines-- : scanlines++;
00916
00917 qApp-> processEvents ( );
00918 }
00919
00920
00921 #ifndef QT_NO_TRANSFORMATIONS
00922 QWMatrix mat ( ctm [0] / width, ctm [1], ctm [2], ctm [3] / height, ctm [4], ctm [5] );
00923
00924 std::cerr << "MATRIX T=" << mat. dx ( ) << "/" << mat. dy ( ) << std::endl
00925 << " - M=" << mat. m11 ( ) << "/" << mat. m12 ( ) << "/" << mat. m21 ( ) << "/" << mat. m22 ( ) << std::endl;
00926
00927 QWMatrix oldmat = m_painter-> worldMatrix ( );
00928 m_painter-> setWorldMatrix ( mat, true );
00929
00930 #ifdef QWS
00931 QPixmap pm;
00932 pm. convertFromImage ( img );
00933 m_painter-> drawPixmap ( 0, 0, pm );
00934 #else
00935 m_painter-> drawImage ( QPoint ( 0, 0 ), img );
00936 #endif
00937
00938 m_painter-> setWorldMatrix ( oldmat );
00939
00940 #else // QT_NO_TRANSFORMATIONS
00941
00942 if (( ctm [1] < -0.1 ) || ( ctm [1] > 0.1 ) || ( ctm [2] < -0.1 ) || ( ctm [2] > 0.1 )) {
00943 QPDFDBG( printf ( "### ROTATED / SHEARED / ETC -- CANNOT DISPLAY THIS IMAGE\n" ));
00944 }
00945 else {
00946 int x = lrint ( ctm [4] );
00947 int y = lrint ( ctm [5] );
00948
00949 int w = lrint ( ctm [0] );
00950 int h = lrint ( ctm [3] );
00951
00952 if ( w < 0 ) {
00953 x += w;
00954 w = -w;
00955 }
00956 if ( h < 0 ) {
00957 y += h;
00958 h = -h;
00959 }
00960
00961 QPDFDBG( printf ( "DRAWING IMAGE: %d/%d - %dx%d\n", x, y, w, h ));
00962
00963 img = img. smoothScale ( w, h );
00964 qApp-> processEvents ( );
00965 m_painter-> drawImage ( x, y, img );
00966 }
00967
00968 #endif
00969
00970
00971 delete imgStr;
00972 qApp-> processEvents ( );
00973 }
00974
00975
00976
00977 bool QOutputDev::findText ( const QString &str, QRect &r, bool top, bool bottom )
00978 {
00979 int l, t, w, h;
00980 r. rect ( &l, &t, &w, &h );
00981
00982 bool res = findText ( str, l, t, w, h, top, bottom );
00983
00984 r. setRect ( l, t, w, h );
00985 return res;
00986 }
00987
00988 bool QOutputDev::findText ( const QString &str, int &l, int &t, int &w, int &h, bool top, bool bottom )
00989 {
00990 bool found = false;
00991 uint len = str. length ( );
00992 Unicode *s = new Unicode [len];
00993
00994 for ( uint i = 0; i < len; i++ )
00995 s [i] = str [i]. unicode ( );
00996
00997 fp_t x1 = (fp_t) l;
00998 fp_t y1 = (fp_t) t;
00999 fp_t x2 = (fp_t) l + w - 1;
01000 fp_t y2 = (fp_t) t + h - 1;
01001
01002 if ( m_text-> findText ( s, len, top, bottom, &x1, &y1, &x2, &y2 )) {
01003 l = lrint ( x1 );
01004 t = lrint ( y1 );
01005 w = lrint ( x2 ) - l + 1;
01006 h = lrint ( y2 ) - t + 1;
01007 found = true;
01008 }
01009 delete [] s;
01010
01011 return found;
01012 }
01013
01014 GBool QOutputDev::findText ( Unicode *s, int len, GBool top, GBool bottom, int *xMin, int *yMin, int *xMax, int *yMax )
01015 {
01016 bool found = false;
01017 fp_t xMin1 = (double) *xMin;
01018 fp_t yMin1 = (double) *yMin;
01019 fp_t xMax1 = (double) *xMax;
01020 fp_t yMax1 = (double) *yMax;
01021
01022 if ( m_text-> findText ( s, len, top, bottom, &xMin1, &yMin1, &xMax1, &yMax1 )) {
01023 *xMin = lrint ( xMin1 );
01024 *xMax = lrint ( xMax1 );
01025 *yMin = lrint ( yMin1 );
01026 *yMax = lrint ( yMax1 );
01027 found = true;
01028 }
01029 return found;
01030 }
01031
01032 QString QOutputDev::getText ( int l, int t, int w, int h )
01033 {
01034 GString *gstr = m_text-> getText ( l, t, l + w - 1, t + h - 1 );
01035 QString str = gstr-> getCString ( );
01036 delete gstr;
01037 return str;
01038 }
01039
01040 QString QOutputDev::getText ( const QRect &r )
01041 {
01042 return getText ( r. left ( ), r. top ( ), r. width ( ), r. height ( ));
01043 }
01044
01045
01046
01047 void QOutputDev::drawContents ( QPainter *p, int clipx, int clipy, int clipw, int cliph )
01048 {
01049 if ( m_pixmap )
01050 p-> drawPixmap ( clipx, clipy, *m_pixmap, clipx, clipy, clipw, cliph );
01051 else
01052 p-> fillRect ( clipx, clipy, clipw, cliph, white );
01053 }