summaryrefslogtreecommitdiff
path: root/noncore/unsupported/qpdf/QOutputDev.cpp
Unidiff
Diffstat (limited to 'noncore/unsupported/qpdf/QOutputDev.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/QOutputDev.cpp1043
1 files changed, 1043 insertions, 0 deletions
diff --git a/noncore/unsupported/qpdf/QOutputDev.cpp b/noncore/unsupported/qpdf/QOutputDev.cpp
new file mode 100644
index 0000000..02f269d
--- a/dev/null
+++ b/noncore/unsupported/qpdf/QOutputDev.cpp
@@ -0,0 +1,1043 @@
1///========================================================================
2//
3// QOutputDev.cc
4//
5// Copyright 1996 Derek B. Noonburg
6// CopyRight 2002 Robert Griebl
7//
8//========================================================================
9
10#ifdef __GNUC__
11#pragma implementation
12#endif
13
14#include <aconf.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <stddef.h>
18#include <unistd.h>
19#include <string.h>
20#include <ctype.h>
21#include <math.h>
22#include "GString.h"
23#include "Object.h"
24#include "Stream.h"
25#include "Link.h"
26#include "GfxState.h"
27#include "GfxFont.h"
28#include "UnicodeMap.h"
29#include "CharCodeToUnicode.h"
30#include "FontFile.h"
31#include "Error.h"
32#include "TextOutputDev.h"
33#include "QOutputDev.h"
34
35
36#include <qpixmap.h>
37#include <qimage.h>
38#include <qpainter.h>
39#include <qdict.h>
40#include <qtimer.h>
41#include <qapplication.h>
42#include <qclipboard.h>
43
44
45//------------------------------------------------------------------------
46// Constants and macros
47//------------------------------------------------------------------------
48
49
50static inline int q_rnd ( fp_t d )
51{
52 //qDebug ( "Q_RND: %f -> %d\n", (double) d, (int) ( d >= 0 ? d +0.5 : d - 0.5 ));
53
54 return (int) ( d >= 0 ? d + 0.5 : d - 0.5 );
55}
56
57static inline QColor q_col ( const GfxRGB &rgb )
58{
59 return QColor ( q_rnd ( rgb. r * 255 ), q_rnd ( rgb. g * 255 ), q_rnd ( rgb. b * 255 ));
60}
61
62
63//------------------------------------------------------------------------
64// Font substitutions
65//------------------------------------------------------------------------
66
67struct QOutFontSubst {
68 char * m_name;
69 char * m_sname;
70 bool m_bold;
71 bool m_italic;
72 QFont::StyleHint m_hint;
73};
74
75static QOutFontSubst qStdFonts [] = {
76 { "Helvetica", "Helvetica", false, false, QFont::Helvetica },
77 { "Helvetica-Oblique", "Helvetica", false, true, QFont::Helvetica },
78 { "Helvetica-Bold", "Helvetica", true, false, QFont::Helvetica },
79 { "Helvetica-BoldOblique", "Helvetica", true, true, QFont::Helvetica },
80 { "Times-Roman", "Times", false, false, QFont::Times },
81 { "Times-Italic", "Times", false, true, QFont::Times },
82 { "Times-Bold", "Times", true, false, QFont::Times },
83 { "Times-BoldItalic", "Times", true, true, QFont::Times },
84 { "Courier", "Courier", false, false, QFont::Courier },
85 { "Courier-Oblique", "Courier", false, true, QFont::Courier },
86 { "Courier-Bold", "Courier", true, false, QFont::Courier },
87 { "Courier-BoldOblique", "Courier", true, true, QFont::Courier },
88
89 { "Symbol", 0, false, false, QFont::AnyStyle },
90 { "Zapf-Dingbats", 0, false, false, QFont::AnyStyle },
91
92 { 0, 0, false, false, QFont::AnyStyle }
93};
94
95
96
97
98
99
100
101QFont QOutputDev::matchFont ( GfxFont *gfxFont, fp_t m11, fp_t m12, fp_t m21, fp_t m22 )
102{
103 static QDict<QOutFontSubst> stdfonts;
104
105 // build dict for std. fonts on first invocation
106 if ( stdfonts. isEmpty ( )) {
107 for ( QOutFontSubst *ptr = qStdFonts; ptr-> m_name; ptr++ ) {
108 stdfonts. insert ( QString ( ptr-> m_name ), ptr );
109 }
110 }
111
112 // compute size and normalized transform matrix
113 int size = q_rnd ( sqrt ( m21 * m21 + m22 * m22 ));
114
115 /*qDebug ( "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",
116 (( gfxFont-> getName ( )) ? gfxFont-> getName ( )-> getCString ( ) : "<n/a>" ),
117 size,
118 gfxFont-> isBold ( ),
119 gfxFont-> isItalic ( ),
120 gfxFont-> isFixedWidth ( ),
121 gfxFont-> isSerif ( ),
122 gfxFont-> isSymbolic ( ),
123 gfxFont-> isCIDFont ( ),
124 ( gfxFont-> getEmbeddedFontName ( ) ? gfxFont-> getEmbeddedFontName ( ) : "<n/a>" ),
125 (double) m11, (double) m12, (double) m21, (double) m22 );
126*/
127
128 QString fname (( gfxFont-> getName ( )) ? gfxFont-> getName ( )-> getCString ( ) : "<n/a>" );
129
130 QFont f;
131 f. setPixelSize ( size > 0 ? size : 8 ); // type3 fonts misbehave sometimes
132
133 // fast lookup for std. fonts
134 QOutFontSubst *subst = stdfonts [fname];
135
136 if ( subst ) {
137 if ( subst-> m_sname )
138 f. setFamily ( subst-> m_sname );
139 f. setStyleHint ( subst-> m_hint, (QFont::StyleStrategy) ( QFont::PreferOutline | QFont::PreferQuality ));
140 f. setBold ( subst-> m_bold );
141 f. setItalic ( subst-> m_italic );
142 }
143 else {
144 QFont::StyleHint sty;
145
146 if ( gfxFont-> isSerif ( ))
147 sty = QFont::Serif;
148 else if ( gfxFont-> isFixedWidth ( ))
149 sty = QFont::TypeWriter;
150 else
151 sty = QFont::Helvetica;
152
153 f. setStyleHint ( sty, (QFont::StyleStrategy) ( QFont::PreferOutline | QFont::PreferQuality ));
154 f. setBold ( gfxFont-> isBold ( ) > 0 );
155 f. setItalic ( gfxFont-> isItalic ( ) > 0 );
156 f. setFixedPitch ( gfxFont-> isFixedWidth ( ) > 0 );
157
158 // common specifiers in font names
159 if ( fname. contains ( "Oblique" ) || fname. contains ( "Italic" ))
160 f. setItalic ( true );
161 if ( fname. contains ( "Bold" ))
162 f. setWeight ( QFont::Bold );
163 if ( fname. contains ( "Demi" ))
164 f. setWeight ( QFont::DemiBold );
165 if ( fname. contains ( "Light" ))
166 f. setWeight ( QFont::Light );
167 if ( fname. contains ( "Black" ))
168 f. setWeight ( QFont::Black );
169 }
170 // Treat x-sheared fonts as italic
171 if (( m12 > -0.1 ) && ( m12 < 0.1 ) && ((( m21 > -5.0 ) && ( m21 < -0.1 )) || (( m21 > 0.1 ) && ( m21 < 5.0 )))) {
172 f. setItalic ( true );
173 }
174 return f;
175}
176
177
178
179//------------------------------------------------------------------------
180// QOutputDev
181//------------------------------------------------------------------------
182
183QOutputDev::QOutputDev ( QWidget *parent, const char *name, int flags ) : QScrollView ( parent, name, WRepaintNoErase | WResizeNoErase | flags )
184{
185 m_pixmap = 0;
186 m_painter = 0;
187
188 // create text object
189 m_text = new TextPage ( gFalse );
190}
191
192QOutputDev::~QOutputDev ( )
193{
194 delete m_painter;
195 delete m_pixmap;
196 delete m_text;
197}
198
199
200void QOutputDev::startPage ( int /*pageNum*/, GfxState *state )
201{
202 delete m_pixmap;
203 delete m_painter;
204
205 m_pixmap = new QPixmap ( q_rnd ( state-> getPageWidth ( )), q_rnd ( state-> getPageHeight ( )));
206 m_painter = new QPainter ( m_pixmap );
207
208 //qDebug ( "NEW PIXMAP (%d x %d)\n", q_rnd ( state-> getPageWidth ( )), q_rnd ( state-> getPageHeight ( )));
209
210 resizeContents ( m_pixmap-> width ( ), m_pixmap-> height ( ));
211 setContentsPos ( 0, 0 );
212
213 m_pixmap-> fill ( white ); // clear window
214 m_text-> clear ( ); // cleat text object
215 viewport ( )-> repaint ( );
216}
217
218void QOutputDev::endPage ( )
219{
220 m_text-> coalesce ( );
221
222 delete m_painter;
223 m_painter = 0;
224
225 updateContents ( 0, 0, contentsWidth ( ), contentsHeight ( ));
226}
227
228void QOutputDev::drawLink ( Link *link, Catalog */*catalog*/ )
229{
230 fp_t x1, y1, x2, y2, w;
231
232 link-> getBorder ( &x1, &y1, &x2, &y2, &w );
233
234 if ( w > 0 ) {
235 int x, y, dx, dy;
236
237 cvtUserToDev ( x1, y1, &x, &y );
238 cvtUserToDev ( x2, y2, &dx, &dy );
239
240 QPen oldpen = m_painter-> pen ( );
241 m_painter-> setPen ( blue );
242 m_painter-> drawRect ( x, y, dx, dy );
243 m_painter-> setPen ( oldpen );
244 }
245}
246
247void QOutputDev::saveState ( GfxState */*state*/ )
248{
249 //qDebug ( "SAVE (CLIP=%d/%d)\n", m_painter-> hasClipping ( ), !m_painter-> clipRegion ( ). isEmpty ( ));
250
251 m_painter-> save ( );
252}
253
254void QOutputDev::restoreState ( GfxState */*state*/ )
255{
256 m_painter-> restore ( );
257
258 //m_painter-> setClipRegion ( QRect ( 0, 0, m_pixmap-> width ( ), m_pixmap-> height ( )));
259 //m_painter-> setClipping ( false );
260 //qDebug ( "RESTORE (CLIP=%d/%d)\n", m_painter-> hasClipping ( ), !m_painter-> clipRegion ( ). isEmpty ( ));
261}
262
263void QOutputDev::updateAll ( GfxState *state )
264{
265 updateLineAttrs ( state, gTrue );
266 //updateFlatness ( state );
267 //updateMiterLimit ( state );
268 updateFillColor ( state );
269 updateStrokeColor ( state );
270 updateFont ( state );
271}
272
273void QOutputDev::updateCTM ( GfxState *state, fp_t /*m11*/, fp_t /*m12*/, fp_t /*m21*/, fp_t /*m22*/, fp_t /*m31*/, fp_t /*m32*/ )
274{
275 updateLineAttrs ( state, gTrue );
276}
277
278void QOutputDev::updateLineDash ( GfxState *state )
279{
280 updateLineAttrs ( state, gTrue );
281}
282
283void QOutputDev::updateFlatness ( GfxState */*state*/ )
284{
285 // not supported
286 //qDebug ( "updateFlatness not supported !\n" );
287}
288
289void QOutputDev::updateLineJoin ( GfxState *state )
290{
291 updateLineAttrs ( state, gFalse );
292}
293
294void QOutputDev::updateLineCap ( GfxState *state )
295{
296 updateLineAttrs ( state, gFalse );
297}
298
299// unimplemented
300void QOutputDev::updateMiterLimit ( GfxState */*state*/ )
301{
302 //qDebug ( "updateMiterLimit not supported !\n" );
303}
304
305void QOutputDev::updateLineWidth ( GfxState *state )
306{
307 updateLineAttrs ( state, gFalse );
308}
309
310void QOutputDev::updateLineAttrs ( GfxState *state, GBool updateDash )
311{
312 fp_t *dashPattern;
313 int dashLength;
314 fp_t dashStart;
315
316 Qt::PenCapStyle cap;
317 Qt::PenJoinStyle join;
318 int width;
319
320 width = q_rnd ( state-> getTransformedLineWidth ( ));
321
322 switch ( state-> getLineCap ( )) {
323 case 0: cap = FlatCap; break;
324 case 1: cap = RoundCap; break;
325 case 2: cap = SquareCap; break;
326 default:
327 qWarning ( "Bad line cap style (%d)\n", state-> getLineCap ( ));
328 cap = FlatCap;
329 break;
330 }
331
332 switch (state->getLineJoin()) {
333 case 0: join = MiterJoin; break;
334 case 1: join = RoundJoin; break;
335 case 2: join = BevelJoin; break;
336 default:
337 qWarning ( "Bad line join style (%d)\n", state->getLineJoin ( ));
338 join = MiterJoin;
339 break;
340 }
341
342 state-> getLineDash ( &dashPattern, &dashLength, &dashStart );
343
344 QColor oldcol = m_painter-> pen ( ). color ( );
345 GfxRGB rgb;
346
347 state-> getStrokeRGB ( &rgb );
348 oldcol = q_col ( rgb );
349
350 m_painter-> setPen ( QPen ( oldcol, width, dashLength > 0 ? DashLine : SolidLine, cap, join ));
351
352 if ( updateDash && ( dashLength > 0 )) {
353 // Not supported by QT
354 /*
355 char dashList[20];
356 if (dashLength > 20)
357 dashLength = 20;
358 for ( int i = 0; i < dashLength; ++i ) {
359 dashList[i] = xoutRound(state->transformWidth(dashPattern[i]));
360 if (dashList[i] == 0)
361 dashList[i] = 1;
362 }
363 XSetDashes(display, strokeGC, xoutRound(dashStart), dashList, dashLength);
364*/
365 }
366}
367
368void QOutputDev::updateFillColor ( GfxState *state )
369{
370 GfxRGB rgb;
371 state-> getFillRGB ( &rgb );
372
373 m_painter-> setBrush ( q_col ( rgb ));
374}
375
376void QOutputDev::updateStrokeColor ( GfxState *state )
377{
378 GfxRGB rgb;
379 state-> getStrokeRGB ( &rgb );
380
381 QPen pen = m_painter-> pen ( );
382 pen. setColor ( q_col ( rgb ));
383 m_painter-> setPen ( pen );
384}
385
386void QOutputDev::updateFont ( GfxState *state )
387{
388 fp_t m11, m12, m21, m22;
389 GfxFont *gfxFont = state-> getFont ( );
390
391 if ( !gfxFont )
392 return;
393
394 state-> getFontTransMat ( &m11, &m12, &m21, &m22 );
395 m11 *= state-> getHorizScaling ( );
396 m12 *= state-> getHorizScaling ( );
397
398 QFont font = matchFont ( gfxFont, m11, m12, m21, m22 );
399
400 m_painter-> setFont ( font );
401 m_text-> updateFont ( state );
402}
403
404void QOutputDev::stroke ( GfxState *state )
405{
406 QPointArray points;
407 QArray<int> lengths;
408
409 // transform points
410 int n = convertPath ( state, points, lengths );
411
412 //qDebug ( "DRAWING: %d POLYS\n", n );
413
414 // draw each subpath
415 int j = 0;
416 for ( int i = 0; i < n; i++ ) {
417 int len = lengths [i];
418
419 if ( len >= 2 ) {
420 // qDebug ( " - POLY %d: ", i );
421 // for ( int ii = 0; ii < len; ii++ )
422 // qDebug ( "(%d/%d) ", points [j+ii]. x ( ), points [j+ii]. y ( ));
423 // qDebug ( "\n" );
424
425 m_painter-> drawPolyline ( points, j, len );
426 }
427 j += len;
428 }
429 qApp-> processEvents ( );
430}
431
432void QOutputDev::fill ( GfxState *state )
433{
434 doFill ( state, true );
435}
436
437void QOutputDev::eoFill ( GfxState *state )
438{
439 doFill ( state, false );
440}
441
442//
443// X doesn't color the pixels on the right-most and bottom-most
444// borders of a polygon. This means that one-pixel-thick polygons
445// are not colored at all. I think this is supposed to be a
446// feature, but I can't figure out why. So after it fills a
447// polygon, it also draws lines around the border. This is done
448// only for single-component polygons, since it's not very
449// compatible with the compound polygon kludge (see convertPath()).
450//
451void QOutputDev::doFill ( GfxState *state, bool winding )
452{
453 QPointArray points;
454 QArray<int> lengths;
455
456 // transform points
457 int n = convertPath ( state, points, lengths );
458
459 //qDebug ( "FILLING: %d POLYS\n", n );
460
461 QPen oldpen = m_painter-> pen ( );
462 m_painter-> setPen ( QPen ( NoPen ));
463
464 // draw each subpath
465 int j = 0;
466 for ( int i = 0; i < n; i++ ) {
467 int len = lengths [i];
468
469 if ( len >= 3 ) {
470 // qDebug ( " - POLY %d: ", i );
471 // for ( int ii = 0; ii < len; ii++ )
472 // qDebug ( "(%d/%d) ", points [j+ii]. x ( ), points [j+ii]. y ( ));
473 // qDebug ( "\n" );
474
475 m_painter-> drawPolygon ( points, winding, j, len );
476 }
477 j += len;
478 }
479 m_painter-> setPen ( oldpen );
480
481 qApp-> processEvents ( );
482}
483
484void QOutputDev::clip ( GfxState *state )
485{
486 doClip ( state, true );
487}
488
489void QOutputDev::eoClip ( GfxState *state )
490{
491 doClip ( state, false );
492}
493
494void QOutputDev::doClip ( GfxState *state, bool winding )
495{
496 QPointArray points;
497 QArray<int> lengths;
498
499 // transform points
500 int n = convertPath ( state, points, lengths );
501
502 QRegion region;
503
504 //qDebug ( "CLIPPING: %d POLYS\n", n );
505
506 // draw each subpath
507 int j = 0;
508 for ( int i = 0; i < n; i++ ) {
509 int len = lengths [i];
510
511 if ( len >= 3 ) {
512 QPointArray dummy;
513 dummy. setRawData ( points. data ( ) + j, len );
514
515 // qDebug ( " - POLY %d: ", i );
516 // for ( int ii = 0; ii < len; ii++ )
517 // qDebug ( "(%d/%d) ", points [j+ii]. x ( ), points [j+ii]. y ( ));
518 // qDebug ( "\n" );
519
520 region |= QRegion ( dummy, winding );
521
522 dummy. resetRawData ( points. data ( ) + j, len );
523 }
524 j += len;
525 }
526
527 if ( m_painter-> hasClipping ( ))
528 region &= m_painter-> clipRegion ( );
529
530 //m_painter-> setClipRegion ( region );
531 //m_painter-> setClipping ( true );
532
533 //m_painter-> fillRect ( 0, 0, m_pixmap-> width ( ), m_pixmap-> height ( ), red );
534 //m_painter-> drawText ( points [0]. x ( ) + 10, points [0]. y ( ) + 10, "Bla bla" );
535 qApp-> processEvents ( );
536}
537
538//
539// Transform points in the path and convert curves to line segments.
540// Builds a set of subpaths and returns the number of subpaths.
541// If <fillHack> is set, close any unclosed subpaths and activate a
542// kludge for polygon fills: First, it divides up the subpaths into
543// non-overlapping polygons by simply comparing bounding rectangles.
544// Then it connects subaths within a single compound polygon to a single
545// point so that X can fill the polygon (sort of).
546//
547int QOutputDev::convertPath ( GfxState *state, QPointArray &points, QArray<int> &lengths )
548{
549 GfxPath *path = state-> getPath ( );
550 int n = path-> getNumSubpaths ( );
551
552 lengths. resize ( n );
553
554 // do each subpath
555 for ( int i = 0; i < n; i++ ) {
556 // transform the points
557 lengths [i] = convertSubpath ( state, path-> getSubpath ( i ), points );
558 }
559
560 return n;
561}
562
563//
564// Transform points in a single subpath and convert curves to line
565// segments.
566//
567int QOutputDev::convertSubpath ( GfxState *state, GfxSubpath *subpath, QPointArray &points )
568{
569 int oldcnt = points. count ( );
570
571 fp_t x0, y0, x1, y1, x2, y2, x3, y3;
572
573 int m = subpath-> getNumPoints ( );
574 int i = 0;
575
576 while ( i < m ) {
577 if ( i >= 1 && subpath-> getCurve ( i )) {
578 state-> transform ( subpath-> getX ( i - 1 ), subpath-> getY ( i - 1 ), &x0, &y0 );
579 state-> transform ( subpath-> getX ( i ), subpath-> getY ( i ), &x1, &y1 );
580 state-> transform ( subpath-> getX ( i + 1 ), subpath-> getY ( i + 1 ), &x2, &y2 );
581 state-> transform ( subpath-> getX ( i + 2 ), subpath-> getY ( i + 2 ), &x3, &y3 );
582
583 QPointArray tmp;
584 tmp. setPoints ( 4, q_rnd ( x0 ), q_rnd ( y0 ), q_rnd ( x1 ), q_rnd ( y1 ),
585 q_rnd ( x2 ), q_rnd ( y2 ), q_rnd ( x3 ), q_rnd ( y3 ));
586
587#if QT_VERSION < 300
588 tmp = tmp. quadBezier ( );
589
590 for ( uint loop = 0; loop < tmp. count ( ); loop++ ) {
591 QPoint p = tmp. point ( loop );
592 points. putPoints ( points. count ( ), 1, p. x ( ), p. y ( ));
593 }
594#else
595 tmp = tmp. cubicBezier ( );
596 points. putPoints ( points. count ( ), tmp. count ( ), tmp );
597#endif
598
599 i += 3;
600 }
601 else {
602 state-> transform ( subpath-> getX ( i ), subpath-> getY ( i ), &x1, &y1 );
603
604 points. putPoints ( points. count ( ), 1, q_rnd ( x1 ), q_rnd ( y1 ));
605 ++i;
606 }
607 }
608 return points. count ( ) - oldcnt;
609}
610
611
612void QOutputDev::beginString ( GfxState *state, GString */*s*/ )
613{
614 m_text-> beginString ( state );
615}
616
617void QOutputDev::endString ( GfxState */*state*/ )
618{
619 m_text-> endString ( );
620}
621
622void QOutputDev::drawChar ( GfxState *state, fp_t x, fp_t y,
623 fp_t dx, fp_t dy, fp_t originX, fp_t originY,
624 CharCode code, Unicode *u, int uLen )
625{
626 fp_t x1, y1, dx1, dy1;
627
628 m_text-> addChar ( state, x, y, dx, dy, u, uLen );
629
630
631 // check for invisible text -- this is used by Acrobat Capture
632 if (( state-> getRender ( ) & 3 ) == 3 ) {
633 return;
634 }
635
636 x -= originX;
637 y -= originY;
638 state-> transform ( x, y, &x1, &y1 );
639 state-> transformDelta ( dx, dy, &dx1, &dy1 );
640
641
642 if ( uLen > 0 ) {
643 QString str;
644 QFontMetrics fm = m_painter-> fontMetrics ( );
645
646 for ( int i = 0; i < uLen; i++ ) {
647 QChar c = QChar ( u [i] );
648
649 if ( fm. inFont ( c )) {
650 str [i] = QChar ( u [i] );
651 }
652 else {
653 str [i] = ' ';
654 // qDebug ( "CHARACTER NOT IN FONT: %hx\n", c. unicode ( ));
655 }
656 }
657
658 if (( uLen == 1 ) && ( str [0] == ' ' ))
659 return;
660
661
662 fp_t m11, m12, m21, m22;
663
664 state-> getFontTransMat ( &m11, &m12, &m21, &m22 );
665 m11 *= state-> getHorizScaling ( );
666 m12 *= state-> getHorizScaling ( );
667
668 fp_t fsize = m_painter-> font ( ). pixelSize ( );
669
670#ifndef QT_NO_TRANSFORMATIONS
671 QWMatrix oldmat;
672
673 bool dorot = (( m12 < -0.1 ) || ( m12 > 0.1 )) && (( m21 < -0.1 ) || ( m21 > 0.1 ));
674
675 if ( dorot ) {
676 oldmat = m_painter-> worldMatrix ( );
677
678 cerr << endl << "ROTATED: " << m11 << ", " << m12 << ", " << m21 << ", " << m22 << " / SIZE: " << fsize << " / TEXT: " << str. local8Bit ( ) << endl << endl;
679
680 QWMatrix mat ( q_rnd ( m11 / fsize ), q_rnd ( m12 / fsize ), -q_rnd ( m21 / fsize ), -q_rnd ( m22 / fsize ), q_rnd ( x1 ), q_rnd ( y1 ));
681
682 m_painter-> setWorldMatrix ( mat );
683
684 x1 = 0;
685 y1 = 0;
686 }
687#endif
688
689 QPen oldpen = m_painter-> pen ( );
690
691 if (!( state-> getRender ( ) & 1 )) {
692 QPen fillpen = oldpen;
693
694 fillpen. setColor ( m_painter-> brush ( ). color ( ));
695 m_painter-> setPen ( fillpen );
696 }
697
698 if ( fsize > 5 )
699 m_painter-> drawText ( q_rnd ( x1 ), q_rnd ( y1 ), str );
700 else
701 m_painter-> fillRect ( q_rnd ( x1 ), q_rnd ( y1 ), q_rnd ( QMAX( fp_t(1), dx1 )), q_rnd ( QMAX( fsize, dy1 )), m_painter-> pen ( ). color ( ));
702
703 m_painter-> setPen ( oldpen );
704
705#ifndef QT_NO_TRANSFORMATIONS
706 if ( dorot )
707 m_painter-> setWorldMatrix ( oldmat );
708 #endif
709
710 // qDebug ( "DRAW TEXT: \"%s\" at (%d/%d)\n", str. local8Bit ( ). data ( ), q_rnd ( x1 ), q_rnd ( y1 ));
711 }
712 else if ( code != 0 ) {
713 // some PDF files use CID 0, which is .notdef, so just ignore it
714 qWarning ( "Unknown character (CID=%d Unicode=%hx)\n", code, (unsigned short) ( uLen > 0 ? u [0] : (Unicode) 0 ));
715 }
716 qApp-> processEvents ( );
717}
718
719
720
721void QOutputDev::drawImageMask ( GfxState *state, Object */*ref*/, Stream *str, int width, int height, GBool invert, GBool inlineImg )
722{
723 // get CTM, check for singular matrix
724 fp_t *ctm = state-> getCTM ( );
725
726 if ( fabs ( ctm [0] * ctm [3] - ctm [1] * ctm [2] ) < 0.000001 ) {
727 qWarning ( "Singular CTM in drawImage\n" );
728
729 if ( inlineImg ) {
730 str-> reset ( );
731 int j = height * (( width + 7 ) / 8 );
732 for ( int i = 0; i < j; i++ )
733 str->getChar();
734
735 str->close();
736 }
737 return;
738 }
739
740 GfxRGB rgb;
741 state-> getFillRGB ( &rgb );
742 uint val = ( q_rnd ( rgb. r * 255 ) & 0xff ) << 16 | ( q_rnd ( rgb. g * 255 ) & 0xff ) << 8 | ( q_rnd ( rgb. b * 255 ) & 0xff );
743
744
745 QImage img ( width, height, 32 );
746 img. setAlphaBuffer ( true );
747
748 //qDebug ( "IMAGE MASK (%dx%d)\n", width, height );
749
750 // initialize the image stream
751 ImageStream *imgStr = new ImageStream ( str, width, 1, 1 );
752 imgStr-> reset ( );
753
754 uchar **scanlines = img. jumpTable ( );
755
756 if ( ctm [3] > 0 )
757 scanlines += ( height - 1 );
758
759 for ( int y = 0; y < height; y++ ) {
760 QRgb *scanline = (QRgb *) *scanlines;
761
762 if ( ctm [0] < 0 )
763 scanline += ( width - 1 );
764
765 for ( int x = 0; x < width; x++ ) {
766 Guchar alpha;
767
768 imgStr-> getPixel ( &alpha );
769
770 if ( invert )
771 alpha ^= 1;
772
773 *scanline = ( alpha == 0 ) ? 0xff000000 | val : val;
774
775 ctm [0] < 0 ? scanline-- : scanline++;
776 }
777 ctm [3] > 0 ? scanlines-- : scanlines++;
778
779 qApp-> processEvents ( );
780 }
781
782 #ifndef QT_NO_TRANSFORMATIONS
783 QWMatrix mat ( ctm [0] / width, ctm [1], ctm [2], ctm [3] / height, ctm [4], ctm [5] );
784
785 cerr << "MATRIX T=" << mat. dx ( ) << "/" << mat. dy ( ) << endl
786 << " - M=" << mat. m11 ( ) << "/" << mat. m12 ( ) << "/" << mat. m21 ( ) << "/" << mat. m22 ( ) << endl;
787
788 QWMatrix oldmat = m_painter-> worldMatrix ( );
789 m_painter-> setWorldMatrix ( mat, true );
790
791#ifdef QWS
792 QPixmap pm;
793 pm. convertFromImage ( img );
794 m_painter-> drawPixmap ( 0, 0, pm );
795#else
796 m_painter-> drawImage ( QPoint ( 0, 0 ), img );
797#endif
798
799 m_painter-> setWorldMatrix ( oldmat );
800
801#else
802 if (( ctm [1] < -0.1 ) || ( ctm [1] > 0.1 ) || ( ctm [2] < -0.1 ) || ( ctm [2] > 0.1 )) {
803 qDebug ( "### ROTATED / SHEARED / ETC -- CANNOT DISPLAY THIS IMAGE\n" );
804 }
805 else {
806 int x = q_rnd ( ctm [4] );
807 int y = q_rnd ( ctm [5] );
808
809 int w = q_rnd ( ctm [0] );
810 int h = q_rnd ( ctm [3] );
811
812 if ( w < 0 ) {
813 x += w;
814 w = -w;
815 }
816 if ( h < 0 ) {
817 y += h;
818 h = -h;
819 }
820
821 // qDebug ( "DRAWING IMAGE MASKED: %d/%d - %dx%d\n", x, y, w, h );
822
823 img = img. smoothScale ( w, h );
824 qApp-> processEvents ( );
825 m_painter-> drawImage ( x, y, img );
826 }
827
828#endif
829
830 delete imgStr;
831 qApp-> processEvents ( );
832}
833
834
835void QOutputDev::drawImage(GfxState *state, Object */*ref*/, Stream *str, int width, int height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg )
836{
837 int nComps, nVals, nBits;
838
839 // image parameters
840 nComps = colorMap->getNumPixelComps ( );
841 nVals = width * nComps;
842 nBits = colorMap-> getBits ( );
843
844 // get CTM, check for singular matrix
845 fp_t *ctm = state-> getCTM ( );
846
847 if ( fabs ( ctm [0] * ctm [3] - ctm [1] * ctm [2] ) < 0.000001 ) {
848 qWarning ( "Singular CTM in drawImage\n" );
849
850 if ( inlineImg ) {
851 str-> reset ( );
852 int j = height * (( nVals * nBits + 7 ) / 8 );
853 for ( int i = 0; i < j; i++ )
854 str->getChar();
855
856 str->close();
857 }
858 return;
859 }
860
861 QImage img ( width, height, 32 );
862
863 if ( maskColors )
864 img. setAlphaBuffer ( true );
865
866 //qDebug ( "IMAGE (%dx%d)\n", width, height );
867
868 // initialize the image stream
869 ImageStream *imgStr = new ImageStream ( str, width, nComps, nBits );
870 imgStr-> reset ( );
871
872 Guchar pixBuf [gfxColorMaxComps];
873 GfxRGB rgb;
874
875
876 uchar **scanlines = img. jumpTable ( );
877
878 if ( ctm [3] > 0 )
879 scanlines += ( height - 1 );
880
881 for ( int y = 0; y < height; y++ ) {
882 QRgb *scanline = (QRgb *) *scanlines;
883
884 if ( ctm [0] < 0 )
885 scanline += ( width - 1 );
886
887 for ( int x = 0; x < width; x++ ) {
888 imgStr-> getPixel ( pixBuf );
889 colorMap-> getRGB ( pixBuf, &rgb );
890
891 uint val = ( q_rnd ( rgb. r * 255 ) & 0xff ) << 16 | ( q_rnd ( rgb. g * 255 ) & 0xff ) << 8 | ( q_rnd ( rgb. b * 255 ) & 0xff );
892
893 if ( maskColors ) {
894 for ( int k = 0; k < nComps; ++k ) {
895 if (( pixBuf [k] < maskColors [2 * k] ) || ( pixBuf [k] > maskColors [2 * k] )) {
896 val |= 0xff000000;
897 break;
898 }
899 }
900 }
901 *scanline = val;
902
903 ctm [0] < 0 ? scanline-- : scanline++;
904 }
905 ctm [3] > 0 ? scanlines-- : scanlines++;
906
907 qApp-> processEvents ( );
908 }
909
910
911 #ifndef QT_NO_TRANSFORMATIONS
912 QWMatrix mat ( ctm [0] / width, ctm [1], ctm [2], ctm [3] / height, ctm [4], ctm [5] );
913
914 cerr << "MATRIX T=" << mat. dx ( ) << "/" << mat. dy ( ) << endl
915 << " - M=" << mat. m11 ( ) << "/" << mat. m12 ( ) << "/" << mat. m21 ( ) << "/" << mat. m22 ( ) << endl;
916
917 QWMatrix oldmat = m_painter-> worldMatrix ( );
918 m_painter-> setWorldMatrix ( mat, true );
919
920#ifdef QWS
921 QPixmap pm;
922 pm. convertFromImage ( img );
923 m_painter-> drawPixmap ( 0, 0, pm );
924 #else
925 m_painter-> drawImage ( QPoint ( 0, 0 ), img );
926#endif
927
928 m_painter-> setWorldMatrix ( oldmat );
929
930#else // QT_NO_TRANSFORMATIONS
931
932 if (( ctm [1] < -0.1 ) || ( ctm [1] > 0.1 ) || ( ctm [2] < -0.1 ) || ( ctm [2] > 0.1 )) {
933 qDebug ( "### ROTATED / SHEARED / ETC -- CANNOT DISPLAY THIS IMAGE\n" );
934 }
935 else {
936 int x = q_rnd ( ctm [4] );
937 int y = q_rnd ( ctm [5] );
938
939 int w = q_rnd ( ctm [0] );
940 int h = q_rnd ( ctm [3] );
941
942 if ( w < 0 ) {
943 x += w;
944 w = -w;
945 }
946 if ( h < 0 ) {
947 y += h;
948 h = -h;
949 }
950
951 // qDebug ( "DRAWING IMAGE: %d/%d - %dx%d\n", x, y, w, h );
952
953 img = img. smoothScale ( w, h );
954 qApp-> processEvents ( );
955 m_painter-> drawImage ( x, y, img );
956 }
957
958#endif
959
960
961 delete imgStr;
962 qApp-> processEvents ( );
963}
964
965
966
967bool QOutputDev::findText ( const QString &str, QRect &r, bool top, bool bottom )
968{
969 int l, t, w, h;
970 r. rect ( &l, &t, &w, &h );
971
972 bool res = findText ( str, l, t, w, h, top, bottom );
973
974 r. setRect ( l, t, w, h );
975 return res;
976}
977
978bool QOutputDev::findText ( const QString &str, int &l, int &t, int &w, int &h, bool top, bool bottom )
979{
980 bool found = false;
981 uint len = str. length ( );
982 Unicode *s = new Unicode [len];
983
984 for ( uint i = 0; i < len; i++ )
985 s [i] = str [i]. unicode ( );
986
987 fp_t x1 = (fp_t) l;
988 fp_t y1 = (fp_t) t;
989 fp_t x2 = (fp_t) l + w - 1;
990 fp_t y2 = (fp_t) t + h - 1;
991
992 if ( m_text-> findText ( s, len, top, bottom, &x1, &y1, &x2, &y2 )) {
993 l = q_rnd ( x1 );
994 t = q_rnd ( y1 );
995 w = q_rnd ( x2 ) - l + 1;
996 h = q_rnd ( y2 ) - t + 1;
997 found = true;
998 }
999 delete [] s;
1000
1001 return found;
1002}
1003
1004GBool QOutputDev::findText ( Unicode *s, int len, GBool top, GBool bottom, int *xMin, int *yMin, int *xMax, int *yMax )
1005{
1006 bool found = false;
1007 fp_t xMin1 = (double) *xMin;
1008 fp_t yMin1 = (double) *yMin;
1009 fp_t xMax1 = (double) *xMax;
1010 fp_t yMax1 = (double) *yMax;
1011
1012 if ( m_text-> findText ( s, len, top, bottom, &xMin1, &yMin1, &xMax1, &yMax1 )) {
1013 *xMin = q_rnd ( xMin1 );
1014 *xMax = q_rnd ( xMax1 );
1015 *yMin = q_rnd ( yMin1 );
1016 *yMax = q_rnd ( yMax1 );
1017 found = true;
1018 }
1019 return found;
1020}
1021
1022QString QOutputDev::getText ( int l, int t, int w, int h )
1023{
1024 GString *gstr = m_text-> getText ( l, t, l + w - 1, t + h - 1 );
1025 QString str = gstr-> getCString ( );
1026 delete gstr;
1027 return str;
1028}
1029
1030QString QOutputDev::getText ( const QRect &r )
1031{
1032 return getText ( r. left ( ), r. top ( ), r. width ( ), r. height ( ));
1033}
1034
1035
1036
1037void QOutputDev::drawContents ( QPainter *p, int clipx, int clipy, int clipw, int cliph )
1038{
1039 if ( m_pixmap )
1040 p-> drawPixmap ( clipx, clipy, *m_pixmap, clipx, clipy, clipw, cliph );
1041 else
1042 p-> fillRect ( clipx, clipy, clipw, cliph, white );
1043}