Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

QOutputDev.cpp

Go to the documentation of this file.
00001 
00002 //
00003 // QOutputDev.cc
00004 //
00005 // Copyright 1996 Derek B. Noonburg
00006 // CopyRight 2002 Robert Griebl
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 //#define QPDFDBG(x) x          // special debug mode
00047 #define QPDFDBG(x)              // normal compilation
00048 
00049 
00050 //------------------------------------------------------------------------
00051 // Constants and macros
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 // Font substitutions
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         // build dict for std. fonts on first invocation
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         // compute size and normalized transform matrix
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 ); // type3 fonts misbehave sometimes
00130 
00131         // fast lookup for std. fonts
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                 // common specifiers in font names
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         // Treat x-sheared fonts as italic
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 // QOutputDev
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         // create text object
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 /*pageNum*/, 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 ); // clear window
00212         m_text-> clear ( ); // cleat text object
00213         viewport ( )-> repaint ( );
00214 }
00215 
00216 void QOutputDev::endPage ( )
00217 {
00218         QPDFDBG( printf("End page\n") );
00219         m_text-> coalesce ( );
00220 
00221         /*
00222          * I get stupid crashes after endPage is called and then we do clipping
00223          * and other stuff.....
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 */*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 */*state*/ )
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 */*state*/ )
00263 {
00264         if( ! m_painter )
00265             return;
00266 
00267         m_painter-> restore ( );
00268 
00269 //      m_painter-> setClipRegion ( QRect ( 0, 0, m_pixmap-> width ( ), m_pixmap-> height ( )));
00270 //      m_painter-> setClipping ( false );
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 //      updateFlatness ( state );
00278 //      updateMiterLimit ( state );
00279         updateFillColor ( state );
00280         updateStrokeColor ( state );
00281         updateFont ( state );
00282 }
00283 
00284 void QOutputDev::updateCTM ( GfxState *state, fp_t /*m11*/, fp_t /*m12*/, fp_t /*m21*/, fp_t /*m22*/, fp_t /*m31*/, fp_t /*m32*/ )
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 */*state*/ )
00295 {
00296         // not supported
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 // unimplemented
00311 void QOutputDev::updateMiterLimit ( GfxState */*state*/ )
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                 // Not supported by QT
00365 /*
00366                 char dashList[20];
00367                 if (dashLength > 20)
00368                         dashLength = 20;
00369                 for ( int i = 0; i < dashLength; ++i ) {
00370                         dashList[i] = xoutRound(state->transformWidth(dashPattern[i]));
00371                         if (dashList[i] == 0)
00372                                 dashList[i] = 1;
00373                 }
00374                 XSetDashes(display, strokeGC, xoutRound(dashStart), dashList, dashLength);
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         // transform points
00421         int n = convertPath ( state, points, lengths );
00422 
00423         QPDFDBG( printf ( "DRAWING: %d POLYS\n", n ));
00424 
00425         // draw each subpath
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 //  X doesn't color the pixels on the right-most and bottom-most
00455 //  borders of a polygon.  This means that one-pixel-thick polygons
00456 //  are not colored at all.  I think this is supposed to be a
00457 //  feature, but I can't figure out why.  So after it fills a
00458 //  polygon, it also draws lines around the border.  This is done
00459 //  only for single-component polygons, since it's not very
00460 //  compatible with the compound polygon kludge (see convertPath()).
00461 //
00462 void QOutputDev::doFill ( GfxState *state, bool winding )
00463 {
00464         QPointArray points;
00465         QArray<int> lengths;
00466 
00467         // transform points
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         // draw each subpath
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         // transform points
00511         int n = convertPath ( state, points, lengths );
00512 
00513         QRegion region;
00514 
00515         QPDFDBG( printf ( "CLIPPING: %d POLYS\n", n ));
00516 
00517         // draw each subpath
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 //      m_painter-> setClipRegion ( region );
00541 //      m_painter-> setClipping ( true );
00542 
00543 //      m_painter-> fillRect ( 0, 0, m_pixmap-> width ( ), m_pixmap-> height ( ), red );
00544 //      m_painter-> drawText ( points [0]. x ( ) + 10, points [0]. y ( ) + 10, "Bla bla" );
00545         qApp-> processEvents ( );
00546 }
00547 
00548 //
00549 // Transform points in the path and convert curves to line segments.
00550 // Builds a set of subpaths and returns the number of subpaths.
00551 // If <fillHack> is set, close any unclosed subpaths and activate a
00552 // kludge for polygon fills:  First, it divides up the subpaths into
00553 // non-overlapping polygons by simply comparing bounding rectangles.
00554 // Then it connects subaths within a single compound polygon to a single
00555 // point so that X can fill the polygon (sort of).
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         // do each subpath
00565         for ( int i = 0; i < n; i++ ) {
00566                 // transform the points
00567                 lengths [i] = convertSubpath ( state, path-> getSubpath ( i ), points );
00568         }
00569 
00570         return n;
00571 }
00572 
00573 //
00574 // Transform points in a single subpath and convert curves to line
00575 // segments.
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 */*s*/ )
00623 {
00624         m_text-> beginString ( state );
00625 }
00626 
00627 void QOutputDev::endString ( GfxState */*state*/ )
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         // check for invisible text -- this is used by Acrobat Capture
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                 // some PDF files use CID 0, which is .notdef, so just ignore it
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 */*ref*/, Stream *str, int width, int height, GBool invert, GBool inlineImg )
00732 {
00733         // get CTM, check for singular matrix
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         // initialize the image stream
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 */*ref*/, Stream *str, int width, int height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg )
00846 {
00847         int nComps, nVals, nBits;
00848 
00849         // image parameters
00850         nComps = colorMap->getNumPixelComps ( );
00851         nVals = width * nComps;
00852         nBits = colorMap-> getBits ( );
00853 
00854         // get CTM, check for singular matrix
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         // initialize the image stream
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 }

Generated on Sat Nov 5 16:18:12 2005 for OPIE by  doxygen 1.4.2