summaryrefslogtreecommitdiff
path: root/noncore/unsupported
authorsandman <sandman>2002-04-13 00:47:20 (UTC)
committer sandman <sandman>2002-04-13 00:47:20 (UTC)
commit98a1e3f36567639344f12932b629e526a8783aa8 (patch) (unidiff)
tree0433d296857faceeafc54f7deabddb621f45a933 /noncore/unsupported
parent7e31b1fba119f69929d6744d7295555ff1727f4f (diff)
downloadopie-98a1e3f36567639344f12932b629e526a8783aa8.zip
opie-98a1e3f36567639344f12932b629e526a8783aa8.tar.gz
opie-98a1e3f36567639344f12932b629e526a8783aa8.tar.bz2
CVS import of QPdf
Diffstat (limited to 'noncore/unsupported') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/QOutputDev.cpp1043
-rw-r--r--noncore/unsupported/qpdf/QOutputDev.h173
-rw-r--r--noncore/unsupported/qpdf/QPEOutputDev.cpp181
-rw-r--r--noncore/unsupported/qpdf/QPEOutputDev.h49
-rw-r--r--noncore/unsupported/qpdf/README89
-rw-r--r--noncore/unsupported/qpdf/UTF8.h24
-rw-r--r--noncore/unsupported/qpdf/aconf.h46
-rw-r--r--noncore/unsupported/qpdf/fixed.h169
-rw-r--r--noncore/unsupported/qpdf/goo/GHash.cc240
-rw-r--r--noncore/unsupported/qpdf/goo/GHash.h67
-rw-r--r--noncore/unsupported/qpdf/goo/GList.cc91
-rw-r--r--noncore/unsupported/qpdf/goo/GList.h89
-rw-r--r--noncore/unsupported/qpdf/goo/GString.cc231
-rw-r--r--noncore/unsupported/qpdf/goo/GString.h98
-rw-r--r--noncore/unsupported/qpdf/goo/gfile.h135
-rw-r--r--noncore/unsupported/qpdf/goo/gmem.h53
-rw-r--r--noncore/unsupported/qpdf/goo/gtypes.h29
-rw-r--r--noncore/unsupported/qpdf/gooStub.cpp60
-rw-r--r--noncore/unsupported/qpdf/opie-qpdf.control9
-rw-r--r--noncore/unsupported/qpdf/qbusybar.cpp132
-rw-r--r--noncore/unsupported/qpdf/qbusybar.h43
-rw-r--r--noncore/unsupported/qpdf/qpdf.cpp529
-rw-r--r--noncore/unsupported/qpdf/qpdf.h94
-rw-r--r--noncore/unsupported/qpdf/qpdf.pro60
-rw-r--r--noncore/unsupported/qpdf/xpdf/Array.cc53
-rw-r--r--noncore/unsupported/qpdf/xpdf/Array.h56
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFont.cc64
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFont.h55
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc3366
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h23
-rw-r--r--noncore/unsupported/qpdf/xpdf/CMap.cc339
-rw-r--r--noncore/unsupported/qpdf/xpdf/CMap.h93
-rw-r--r--noncore/unsupported/qpdf/xpdf/Catalog.cc341
-rw-r--r--noncore/unsupported/qpdf/xpdf/Catalog.h85
-rw-r--r--noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc394
-rw-r--r--noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h89
-rw-r--r--noncore/unsupported/qpdf/xpdf/CharTypes.h24
-rw-r--r--noncore/unsupported/qpdf/xpdf/Decrypt.cc385
-rw-r--r--noncore/unsupported/qpdf/xpdf/Decrypt.h59
-rw-r--r--noncore/unsupported/qpdf/xpdf/Dict.cc90
-rw-r--r--noncore/unsupported/qpdf/xpdf/Dict.h75
-rw-r--r--noncore/unsupported/qpdf/xpdf/DisplayFontTable.h31
-rw-r--r--noncore/unsupported/qpdf/xpdf/Error.cc37
-rw-r--r--noncore/unsupported/qpdf/xpdf/Error.h21
-rw-r--r--noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc1824
-rw-r--r--noncore/unsupported/qpdf/xpdf/FontEncodingTables.h20
-rw-r--r--noncore/unsupported/qpdf/xpdf/FontFile.h10
-rw-r--r--noncore/unsupported/qpdf/xpdf/FormWidget.cc139
-rw-r--r--noncore/unsupported/qpdf/xpdf/FormWidget.h67
-rw-r--r--noncore/unsupported/qpdf/xpdf/Function.cc1511
-rw-r--r--noncore/unsupported/qpdf/xpdf/Function.h181
-rw-r--r--noncore/unsupported/qpdf/xpdf/Gfx.cc2461
-rw-r--r--noncore/unsupported/qpdf/xpdf/Gfx.h240
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxFont.cc1247
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxFont.h286
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxState.cc2097
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxState.h922
-rw-r--r--noncore/unsupported/qpdf/xpdf/GlobalParams.cc916
-rw-r--r--noncore/unsupported/qpdf/xpdf/GlobalParams.h242
-rw-r--r--noncore/unsupported/qpdf/xpdf/Lexer.cc473
-rw-r--r--noncore/unsupported/qpdf/xpdf/Lexer.h74
-rw-r--r--noncore/unsupported/qpdf/xpdf/Link.cc634
-rw-r--r--noncore/unsupported/qpdf/xpdf/Link.h336
-rw-r--r--noncore/unsupported/qpdf/xpdf/NameToCharCode.cc115
-rw-r--r--noncore/unsupported/qpdf/xpdf/NameToCharCode.h40
-rw-r--r--noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h1055
-rw-r--r--noncore/unsupported/qpdf/xpdf/Object.cc223
-rw-r--r--noncore/unsupported/qpdf/xpdf/Object.h299
-rw-r--r--noncore/unsupported/qpdf/xpdf/OutputDev.cc97
-rw-r--r--noncore/unsupported/qpdf/xpdf/OutputDev.h143
-rw-r--r--noncore/unsupported/qpdf/xpdf/PDFDoc.cc251
-rw-r--r--noncore/unsupported/qpdf/xpdf/PDFDoc.h142
-rw-r--r--noncore/unsupported/qpdf/xpdf/Page.cc267
-rw-r--r--noncore/unsupported/qpdf/xpdf/Page.h125
-rw-r--r--noncore/unsupported/qpdf/xpdf/Parser.cc213
-rw-r--r--noncore/unsupported/qpdf/xpdf/Parser.h58
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream-CCITT.h459
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream.cc3467
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream.h723
-rw-r--r--noncore/unsupported/qpdf/xpdf/TextOutputDev.cc686
-rw-r--r--noncore/unsupported/qpdf/xpdf/TextOutputDev.h189
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMap.cc260
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMap.h110
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h303
-rw-r--r--noncore/unsupported/qpdf/xpdf/XRef.cc641
-rw-r--r--noncore/unsupported/qpdf/xpdf/XRef.h111
-rw-r--r--noncore/unsupported/qpdf/xpdf/config.h126
87 files changed, 33197 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}
diff --git a/noncore/unsupported/qpdf/QOutputDev.h b/noncore/unsupported/qpdf/QOutputDev.h
new file mode 100644
index 0000000..2958062
--- a/dev/null
+++ b/noncore/unsupported/qpdf/QOutputDev.h
@@ -0,0 +1,173 @@
1
2//========================================================================
3//
4// XOutputDev.h
5//
6// Copyright 1996 Derek B. Noonburg
7//
8//========================================================================
9
10#ifndef QOUTPUTDEV_H
11#define QOUTPUTDEV_H
12
13#ifdef __GNUC__
14#pragma interface
15#endif
16
17#include "aconf.h"
18#include <stddef.h>
19
20#include <qscrollview.h>
21
22class Object;
23
24#include "config.h"
25#include "CharTypes.h"
26#include "GlobalParams.h"
27#include "OutputDev.h"
28
29class GString;
30class GList;
31struct GfxRGB;
32class GfxFont;
33class GfxSubpath;
34class TextPage;
35class XOutputFontCache;
36class Link;
37class Catalog;
38class DisplayFontParam;
39class UnicodeMap;
40class CharCodeToUnicode;
41
42
43class QPainter;
44class QPixmap;
45class QPointArray;
46
47
48typedef fouble fp_t;
49
50//------------------------------------------------------------------------
51// Constants
52//------------------------------------------------------------------------
53
54
55//------------------------------------------------------------------------
56// Misc types
57//------------------------------------------------------------------------
58
59
60//------------------------------------------------------------------------
61// XOutputDev
62//------------------------------------------------------------------------
63
64class QOutputDev : public QScrollView, public OutputDev {
65public:
66
67 // Constructor.
68 QOutputDev( QWidget *parent = 0, const char *name = 0, int flags = 0 );
69
70 // Destructor.
71 virtual ~QOutputDev();
72
73 //---- get info about output device
74
75 // Does this device use upside-down coordinates?
76 // (Upside-down means (0,0) is the top left corner of the page.)
77 virtual GBool upsideDown() { return gTrue; }
78
79 // Does this device use drawChar() or drawString()?
80 virtual GBool useDrawChar() { return gTrue; }
81
82 //----- initialization and control
83
84 // Start a page.
85 virtual void startPage(int pageNum, GfxState *state);
86
87 // End a page.
88 virtual void endPage();
89
90 //----- link borders
91 virtual void drawLink(Link *link, Catalog *catalog);
92
93 //----- save/restore graphics state
94 virtual void saveState(GfxState *state);
95 virtual void restoreState(GfxState *state);
96
97 //----- update graphics state
98 virtual void updateAll(GfxState *state);
99 virtual void updateCTM(GfxState *state, fp_t m11, fp_t m12,
100 fp_t m21, fp_t m22, fp_t m31, fp_t m32);
101 virtual void updateLineDash(GfxState *state);
102 virtual void updateFlatness(GfxState *state);
103 virtual void updateLineJoin(GfxState *state);
104 virtual void updateLineCap(GfxState *state);
105 virtual void updateMiterLimit(GfxState *state);
106 virtual void updateLineWidth(GfxState *state);
107 virtual void updateFillColor(GfxState *state);
108 virtual void updateStrokeColor(GfxState *state);
109
110 //----- update text state
111 virtual void updateFont(GfxState *state);
112
113 //----- path painting
114 virtual void stroke(GfxState *state);
115 virtual void fill(GfxState *state);
116 virtual void eoFill(GfxState *state);
117
118 //----- path clipping
119 virtual void clip(GfxState *state);
120 virtual void eoClip(GfxState *state);
121
122 //----- text drawing
123 virtual void beginString(GfxState *state, GString *s);
124 virtual void endString(GfxState *state);
125 virtual void drawChar(GfxState *state, fp_t x, fp_t y,
126 fp_t dx, fp_t dy,
127 fp_t originX, fp_t originY,
128 CharCode code, Unicode *u, int uLen);
129
130 //----- image drawing
131 virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
132 int width, int height, GBool invert,
133 GBool inlineImg);
134 virtual void drawImage(GfxState *state, Object *ref, Stream *str,
135 int width, int height, GfxImageColorMap *colorMap,
136 int *maskColors, GBool inlineImg);
137
138 // Find a string. If <top> is true, starts looking at <l>,<t>;
139 // otherwise starts looking at top of page. If <bottom> is true,
140 // stops looking at <l+w-1>,<t+h-1>; otherwise stops looking at bottom
141 // of page. If found, sets the text bounding rectange and returns
142 // true; otherwise returns false.
143 GBool findText ( Unicode *s, int len, GBool top, GBool bottom, int *xMin, int *yMin, int *xMax, int *yMax );
144
145 //----- special QT access
146
147 bool findText ( const QString &str, int &l, int &t, int &w, int &h, bool top = 0, bool bottom = 0 );
148 bool findText ( const QString &str, QRect &r, bool top = 0, bool bottom = 0 );
149
150 // Get the text which is inside the specified rectangle.
151 QString getText ( int left, int top, int width, int height );
152 QString getText ( const QRect &r );
153
154protected:
155 virtual void drawContents ( QPainter *p, int, int, int, int );
156
157private:
158 QPixmap *m_pixmap; // pixmap to draw into
159 QPainter *m_painter;
160
161 TextPage *m_text; // text from the current page
162
163 private:
164 QFont matchFont ( GfxFont *, fp_t m11, fp_t m12, fp_t m21, fp_t m22 );
165
166 void updateLineAttrs ( GfxState *state, GBool updateDash );
167 void doFill ( GfxState *state, bool winding );
168 void doClip ( GfxState *state, bool winding );
169 int convertPath ( GfxState *state, QPointArray &points, QArray<int> &lengths );
170 int convertSubpath ( GfxState *state, GfxSubpath *subpath, QPointArray &points );
171};
172
173#endif
diff --git a/noncore/unsupported/qpdf/QPEOutputDev.cpp b/noncore/unsupported/qpdf/QPEOutputDev.cpp
new file mode 100644
index 0000000..8d4e68e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/QPEOutputDev.cpp
@@ -0,0 +1,181 @@
1#include <aconf.h>
2
3#include "QPEOutputDev.h"
4
5#include <qapplication.h>
6#include <qlabel.h>
7#include "qbusybar.h"
8
9
10QPEOutputDev::QPEOutputDev ( QWidget *parent, const char *name ) : QOutputDev ( parent, name )
11{
12 m_counter = new QLabel ( this );
13 m_counter-> setAlignment ( AlignCenter | SingleLine );
14
15 m_busybar = new QBusyBar ( this );
16 m_busybar-> setParameters ( 12, 8, 200 );
17 m_busybar-> hide ( );
18
19 setHScrollBarMode ( AlwaysOn );
20
21 m_isbusy = false;
22
23 m_selectiondrag = false;
24
25 setFocusPolicy ( WheelFocus );
26}
27
28void QPEOutputDev::startPage ( int pn, GfxState *st )
29{
30 m_selection = QRect ( );
31 m_selectiondrag = false;
32
33 QOutputDev::startPage ( pn, st );
34}
35
36
37void QPEOutputDev::setPageCount ( int actp, int maxp )
38{
39 m_counter-> setText ( QString ( "%1 / %2" ). arg ( actp ). arg ( maxp ));
40}
41
42void QPEOutputDev::setBusy ( bool b )
43{
44 if ( b != m_isbusy ) {
45 if ( b ) {
46 m_busybar-> beginBusy ( );
47 m_busybar-> show ( );
48 m_counter-> hide ( );
49 }
50 else {
51 m_counter-> show ( );
52 m_busybar-> hide ( );
53 m_busybar-> endBusy ( );
54 }
55 m_isbusy = b;
56 }
57}
58
59bool QPEOutputDev::isBusy ( ) const
60{
61 return m_isbusy;
62}
63
64void QPEOutputDev::setHBarGeometry ( QScrollBar &hbar, int x, int y, int w, int h )
65{
66 int delta = w * 3 / 10;
67
68 m_counter-> setGeometry ( x, y, delta, h );
69 m_busybar-> setGeometry ( x, y, delta, h );
70 hbar. setGeometry ( x + delta, y, w - delta, h );
71}
72
73
74void QPEOutputDev::keyPressEvent ( QKeyEvent *e )
75{
76 switch ( e-> key ( )) {
77 case Key_Left:
78 scrollBy ( -10, 0 );
79 break;
80 case Key_Right:
81 scrollBy ( 10, 0 );
82 break;
83 case Key_Up:
84 scrollBy ( 0, -10 );
85 break;
86 case Key_Down:
87 scrollBy ( 0, 10 );
88 break;
89
90 default:
91 QOutputDev::keyPressEvent ( e );
92 }
93}
94
95
96void QPEOutputDev::drawContents ( QPainter *p, int clipx, int clipy, int clipw, int cliph )
97{
98 QOutputDev::drawContents ( p, clipx, clipy, clipw, cliph );
99
100 if ( m_selection. isValid ( )) {
101 QRect clip ( clipx, clipy, clipw, cliph );
102
103 if ( m_selection. intersects ( clip )) {
104 RasterOp rop = p-> rasterOp ( );
105
106 p-> setRasterOp ( XorROP );
107 p-> fillRect ( m_selection & clip, white );
108 p-> setRasterOp ( rop );
109 }
110 }
111}
112
113
114QRect QPEOutputDev::selection ( ) const
115{
116 return m_selection;
117}
118
119
120void QPEOutputDev::setSelection ( const QRect &r, bool scrollto )
121{
122 QRect oldsel = m_selection;
123 m_selection = r;
124
125 QArray<QRect> urects = ( QRegion ( oldsel ) ^ QRegion ( m_selection )). rects ( );
126
127 for ( uint i = 0; i < urects. count ( ); i++ )
128 repaintContents ( urects [i] );
129
130 if ( scrollto ) {
131 QPoint c = r. center ( );
132
133 ensureVisible ( c. x ( ), c. y ( ), r. width ( ) / 2 + 5, r. height ( ) / 2 + 5 );
134 }
135
136 if ( !m_selectiondrag )
137 emit selectionChanged ( m_selection );
138}
139
140
141void QPEOutputDev::viewportMousePressEvent ( QMouseEvent *e )
142{
143 if ( e-> button ( ) == LeftButton ) {
144 m_selectionstart = e-> pos ( ) + QPoint ( contentsX ( ), contentsY ( ));
145 m_selectioncursor = m_selectionstart;
146 m_selectiondrag = true;
147
148 setSelection ( QRect ( m_selectionstart, QSize ( 0, 0 )), true );
149 }
150}
151
152void QPEOutputDev::viewportMouseMoveEvent ( QMouseEvent *e )
153{
154 if ( e-> state ( ) & LeftButton ) {
155 if ( m_selectiondrag ) {
156 QPoint to ( e-> pos ( ) + QPoint ( contentsX ( ), contentsY ( )));
157
158 if ( to != m_selectioncursor ) {
159 setSelection ( QRect ( m_selectionstart, to ). normalize ( ), false );
160 m_selectioncursor = to;
161 }
162 ensureVisible ( m_selectioncursor. x ( ), m_selectioncursor. y ( ), 5, 5 );
163 }
164 }
165}
166
167
168void QPEOutputDev::viewportMouseReleaseEvent ( QMouseEvent *e )
169{
170 if ( e-> button ( ) == LeftButton ) {
171 if ( m_selectiondrag ) {
172 m_selectiondrag = false;
173
174 setSelection ( selection ( ), false ); // emit signal
175 }
176 else {
177 setSelection ( QRect ( 0, 0, 0, 0 ), false );
178 }
179 }
180}
181
diff --git a/noncore/unsupported/qpdf/QPEOutputDev.h b/noncore/unsupported/qpdf/QPEOutputDev.h
new file mode 100644
index 0000000..7f1e527
--- a/dev/null
+++ b/noncore/unsupported/qpdf/QPEOutputDev.h
@@ -0,0 +1,49 @@
1#ifndef __QPE_OUTPUTDEV_H__
2#define __QPE_OUTPUTDEV_H__
3
4#include "QOutputDev.h"
5
6class QLabel;
7class QBusyBar;
8
9class QPEOutputDev : public QOutputDev {
10 Q_OBJECT
11
12public:
13 QPEOutputDev ( QWidget *parent = 0, const char *name = 0 );
14
15 void setPageCount ( int actp, int maxp );
16
17 virtual void setBusy ( bool b = true );
18 virtual bool isBusy ( ) const;
19
20 QRect selection ( ) const;
21 void setSelection ( const QRect &r, bool scrollto = false );
22
23 virtual void startPage ( int pn, GfxState *gs );
24
25signals:
26 void selectionChanged ( const QRect &sel );
27
28protected:
29 virtual void setHBarGeometry ( QScrollBar &hbar, int x, int y, int w, int h );
30
31 virtual void keyPressEvent ( QKeyEvent *e );
32 virtual void viewportMousePressEvent ( QMouseEvent *e );
33 virtual void viewportMouseMoveEvent ( QMouseEvent *e );
34 virtual void viewportMouseReleaseEvent ( QMouseEvent *e );
35
36 virtual void drawContents ( QPainter *p, int, int, int, int );
37
38private:
39 QLabel *m_counter;
40 QBusyBar *m_busybar;
41 bool m_isbusy;
42
43 QRect m_selection;
44 QPoint m_selectionstart;
45 QPoint m_selectioncursor;
46 bool m_selectiondrag;
47};
48
49#endif \ No newline at end of file
diff --git a/noncore/unsupported/qpdf/README b/noncore/unsupported/qpdf/README
new file mode 100644
index 0000000..36ce6bc
--- a/dev/null
+++ b/noncore/unsupported/qpdf/README
@@ -0,0 +1,89 @@
1
2QPDF - a PDF viewer for the Qtopia environment
3
4This tool is based on xpdf (currently 1.00). It uses the (mostly unmodified -
5see below) xpdf PDF rendering engine. The Qtopia adaption was done with a new
6OutputDev which renders directly to a QPixmap via QPainter calls.
7
8Changes in 20020406:
9 - Font substitution handling improved.
10 - Unknown characters are simply ignored now.
11 - Fullscreen view added.
12
13Changes in 20020407:
14 - Crash with FontName == 0 fixed
15 - Cleanup
16 - Prepare for CVS import
17
18Changes in 20020408:
19 - Progress indicator added
20 - Problems with type 3 fonts (not fully supported by XPDF) solved
21 - Heavy optimizations in the image rendering code
22
23Changed in 20020413:
24 - Fixed crash in find routine
25 - Stylus selection reworked
26 - Cursor-key navigation added
27 - Various crashes related to recursive calling of XPDF fixed
28
29
30Changes to xpdf:
31 - xpdf calculates nearly everything with doubles. Since ARMs are not equipped
32 with a FPU, all doubles have been replaced with a C++ class "fouble" (fixed
33 double), which operates on 32bit integers with fixed point arithmetic.
34 This gave a speedup of up to 800% for image rendering.
35
36 - No Font handling anymore - This means no embedded, no true-type, no type1-
37 fonts. The task to choose the right font is up to the Qt QFont class.
38 This works pretty well -- only Symbol fonts give problems.
39
40 - Everything that should be rotated (fonts, images) is simply ignored, because
41 a) the Qtopia Qt/E config has QPainter transformations disabled
42 b) the transformation is awful slow
43 c) do you really need rotated images on your iPaq ? ;)
44
45
46ToDo:
47 - Clipping has been deactivated, because Qt/E had problems with QPainter
48 save/restore's with active clipping regions. I need to investigate this
49 in detail.
50
51 - Links are currently simply ignored.
52
53
54Install:
55 - xpdf-1.00
56 Get the tarball for xpdf, version 1.0, untar it and ./configure it.
57 (No special flags are needed for ./configure - it simply has to run)
58
59 - qpdf
60 Make sure your QPEDIR / TMAKEPATH variables are correctly !
61
62 cd into the xpdf directory (xpdf-1.00) and untar the qpdf tarball. This
63 should create a subdirectory qpdf.
64 cd into this directory and start the script "./setup-qpdf". This
65 incorporates the above mentioned patches into xpdf.
66
67 Now do a make.
68
69 Copy the files qpdf, qpdf_icon.png and qpdf.desktop to the appropriate
70 directories on your iPaq or:
71 If you want a ipk, just run ./mkipkg
72
73 - compress / uncompress
74 If you run a normal familiar installation, it the standard gzip (I tested
75 1.2.4-33 ipkg) can handle the compression format used in PDF files, when
76 called as uncompress. The BusyBox version of gzip can _not_ handle this
77 old format.
78
79 If you do not have a working uncompress installed on your iPaq, you can
80 simply use the one in the contrib directory of the tarball (make uncompress
81 a link to compress).
82 [I could not find an official tarball for compress -- this is the SuSE
83 version cross-compiled for ARM]
84
85
86Have fun ;)
87
88Robert (griebl@gmx.de)
89 \ No newline at end of file
diff --git a/noncore/unsupported/qpdf/UTF8.h b/noncore/unsupported/qpdf/UTF8.h
new file mode 100644
index 0000000..aacf663
--- a/dev/null
+++ b/noncore/unsupported/qpdf/UTF8.h
@@ -0,0 +1,24 @@
1//========================================================================
2//
3// UTF8.h
4//
5// Copyright 2001 Derek B. Noonburg
6// Modified for QPE by Robert Griebl
7//
8//========================================================================
9
10#include <qstring.h>
11#include <string.h>
12
13static int mapUTF8 ( Unicode u, char *buf, int bufSize )
14{
15 QCString utf = QString ( QChar ( u )). utf8 ( );
16 int len = utf. length ( );
17
18 if ( len <= bufSize ) {
19 ::memcpy ( buf, utf. data ( ), len );
20 return len;
21 }
22 else
23 return 0;
24}
diff --git a/noncore/unsupported/qpdf/aconf.h b/noncore/unsupported/qpdf/aconf.h
new file mode 100644
index 0000000..3cd8fca
--- a/dev/null
+++ b/noncore/unsupported/qpdf/aconf.h
@@ -0,0 +1,46 @@
1/* aconf.h. Generated automatically by configure. */
2/*
3 * aconf.h
4 *
5 * Copyright 2002 Derek B. Noonburg
6 */
7
8/*
9 * Manually edited for QPDF (Robert Griebl)
10 */
11
12#ifndef ACONF_H
13#define ACONF_H
14
15// vv QPDF specific
16
17#include "fixed.h"
18
19//template <> class fixed<10>;
20
21typedef fixed<10> fouble;
22
23// ^^ QPDF specific
24
25
26/*
27 * Full path for the system-wide xpdfrc file.
28 */
29#define SYSTEM_XPDFRC "/etc/xpdfrc"
30
31/*
32 * Various include files and functions.
33 */
34#define HAVE_DIRENT_H 1
35/* #undef HAVE_SYS_NDIR_H */
36/* #undef HAVE_SYS_DIR_H */
37/* #undef HAVE_NDIR_H */
38/* #undef HAVE_SYS_SELECT_H */
39/* #undef HAVE_SYS_BSDTYPES_H */
40/* #undef HAVE_STRINGS_H */
41/* #undef HAVE_BSTRING_H */
42#define HAVE_POPEN 1
43#define HAVE_MKSTEMP 1
44/* #undef SELECT_TAKES_INT */
45
46#endif
diff --git a/noncore/unsupported/qpdf/fixed.h b/noncore/unsupported/qpdf/fixed.h
new file mode 100644
index 0000000..111b95e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/fixed.h
@@ -0,0 +1,169 @@
1#ifndef __FIXED_H__
2#define __FIXED_H__
3
4#include <iostream>
5
6#define _GCC_TEMPLATE_BUG_ 1
7
8template <unsigned int SH> class fixed {
9public:
10 inline fixed ( int i = 0 ) : m_f ( i2f( i ) ) { }
11 inline fixed ( double d ) : m_f ( d2f( d )) { }
12 inline fixed ( const fixed &f ) : m_f ( f. m_f ) { }
13
14 inline operator bool ( ) const { return m_f != 0; }
15 inline operator double ( ) const { return f2d( m_f ); }
16 inline operator float ( ) const { return (float) f2d( m_f ); }
17 inline operator int ( ) const { return (int) f2i( m_f ); }
18
19 inline fixed &operator = ( const fixed &f ) { m_f = f. m_f; return *this; }
20 inline fixed &operator = ( double d ) { m_f = d2f( d ); return *this; }
21 inline fixed &operator = ( float f ) { m_f = d2f( f ); return *this; }
22 inline fixed &operator = ( int i ) { m_f = i2f( i ); return *this; }
23
24 inline fixed &operator += ( const fixed &f ) { m_f += f. m_f; return *this; }
25 inline fixed &operator -= ( const fixed &f ) { m_f -= f. m_f; return *this; }
26 inline fixed &operator *= ( const fixed &f ) { m_f = mul ( m_f, f. m_f ); return *this; }
27 inline fixed &operator /= ( const fixed &f ) { m_f = div ( m_f, f. m_f ); return *this; }
28
29 inline fixed &operator += ( int i ) { m_f += i2f( i ); return *this; }
30 inline fixed &operator -= ( int i ) { m_f -= i2f( i ); return *this; }
31 inline fixed &operator *= ( int i ) { m_f *= i; return *this; }
32 inline fixed &operator /= ( int i ) { m_f /= i; return *this; }
33
34 inline fixed &operator += ( double d ) { m_f += d2f( d ); return *this; }
35 inline fixed &operator -= ( double d ) { m_f -= d2f( d ); return *this; }
36 inline fixed &operator *= ( double d ) { m_f = mul ( m_f, d2f( d )); return *this; }
37 inline fixed &operator /= ( double d ) { m_f = div ( m_f, d2f( d )); return *this; }
38
39 inline fixed operator - ( ) const { return fixed ( -m_f, true ); }
40
41 inline fixed operator + ( const fixed &f ) const { return fixed ( m_f + f. m_f, true ); }
42 inline fixed operator - ( const fixed &f ) const { return fixed ( m_f - f. m_f, true ); }
43 inline fixed operator * ( const fixed &f ) const { return fixed ( mul ( m_f, f. m_f ), true ); }
44 inline fixed operator / ( const fixed &f ) const { return fixed ( div ( m_f, f. m_f ), true ); }
45
46 inline fixed operator + ( double d ) const { return fixed ( m_f + d2f( d ), true ); }
47 inline fixed operator - ( double d ) const { return fixed ( m_f - d2f( d ), true ); }
48 inline fixed operator * ( double d ) const { return fixed ( mul ( m_f, d2f( d )), true ); }
49 inline fixed operator / ( double d ) const { return fixed ( div ( m_f, d2f( d )), true ); }
50
51 inline fixed operator + ( int i ) const { return fixed ( m_f + i2f( i ), true ); }
52 inline fixed operator - ( int i ) const { return fixed ( m_f - i2f( i ), true ); }
53 inline fixed operator * ( int i ) const { return fixed ( m_f * i, true ); }
54 inline fixed operator / ( int i ) const { return fixed ( m_f / i, true ); }
55
56 inline bool operator < ( const fixed &f ) const { return m_f < f. m_f; }
57 inline bool operator > ( const fixed &f ) const { return m_f > f. m_f; }
58 inline bool operator <= ( const fixed &f ) const { return m_f <= f. m_f; }
59 inline bool operator >= ( const fixed &f ) const { return m_f >= f. m_f; }
60 inline bool operator == ( const fixed &f ) const { return m_f == f. m_f; }
61 inline bool operator != ( const fixed &f ) const { return m_f != f. m_f; }
62
63 inline bool operator < ( double d ) const { return m_f < d2f( d ); }
64 inline bool operator > ( double d ) const { return m_f > d2f( d ); }
65 inline bool operator <= ( double d ) const { return m_f <= d2f( d ); }
66 inline bool operator >= ( double d ) const { return m_f >= d2f( d ); }
67 inline bool operator == ( double d ) const { return m_f == d2f( d ); }
68 inline bool operator != ( double d ) const { return m_f != d2f( d ); }
69
70 inline bool operator < ( int i ) const { return m_f < i2f( i ); }
71 inline bool operator > ( int i ) const { return m_f > i2f( i ); }
72 inline bool operator <= ( int i ) const { return m_f <= i2f( i ); }
73 inline bool operator >= ( int i ) const { return m_f >= i2f( i ); }
74 inline bool operator == ( int i ) const { return m_f == i2f( i ); }
75 inline bool operator != ( int i ) const { return m_f != i2f( i ); }
76
77#if _GCC_TEMPLATE_BUG_
78public:
79#else
80private:
81#endif
82 typedef int fix_t;
83
84 inline static double f2d ( fix_t f ) { return ((double) f ) / ((double) ( 1 << SH )); }
85 inline static fix_t d2f ( double d ) { return (fix_t) ( d * ((double) ( 1 << SH ))); }
86
87 inline static int f2i ( fix_t f ) { return (int) ( f >> SH ); }
88 inline static fix_t i2f ( int i ) { return (fix_t) ( i << SH ); }
89
90 inline static fix_t mul ( fix_t m1, fix_t m2 ) { return (fix_t) ((((long long int) m1 ) * m2 ) >> SH ); }
91 inline static fix_t div ( fix_t d1, fix_t d2 ){ return (fix_t) ((((long long int) d1 ) << SH ) / d2 ); }
92
93 fixed ( fix_t f, bool /*dummy*/ ) : m_f ( f ) { }
94
95 //data
96 fix_t m_f;
97
98 // friends:
99#if !_GCC_TEMPLATE_BUG_
100 friend fixed operator + <> ( int i, const fixed &f );
101 friend fixed operator - <> ( int i, const fixed &f );
102 friend fixed operator * <> ( int i, const fixed &f );
103 friend fixed operator / <> ( int i, const fixed &f );
104
105 friend fixed operator + <> ( double d, const fixed &f );
106 friend fixed operator - <> ( double d, const fixed &f );
107 friend fixed operator * <> ( double d, const fixed &f );
108 friend fixed &operator / <> ( double d, const fixed<SH> &f );
109
110 friend bool operator < <> ( double d, const fixed &f );
111 friend bool operator > <> ( double d, const fixed &f );
112 friend bool operator <= <> ( double d, const fixed &f );
113 friend bool operator >= <> ( double d, const fixed &f );
114 friend bool operator == <> ( double d, const fixed &f );
115 friend bool operator != <> ( double d, const fixed &f );
116
117 friend bool operator < <> ( int i, const fixed &f );
118 friend bool operator > <> ( int i, const fixed &f );
119 friend bool operator <= <> ( int i, const fixed &f );
120 friend bool operator >= <> ( int i, const fixed &f );
121 friend bool operator == <> ( int i, const fixed &f );
122 friend bool operator != <> ( int i, const fixed &f );
123#endif
124};
125
126
127template <unsigned int SH> inline fixed<SH> operator + ( int i, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::i2f( i ) + f. m_f, true ); }
128template <unsigned int SH> inline fixed<SH> operator - ( int i, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::i2f( i ) - f. m_f, true ); }
129template <unsigned int SH> inline fixed<SH> operator * ( int i, const fixed<SH> &f ) { return fixed<SH> ( i * f. m_f, true ); }
130template <unsigned int SH> inline fixed<SH> operator / ( int i, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::div ( fixed<SH>::i2f( i ), f. m_f ), true ); }
131//template <unsigned int SH> inline fixed<SH> operator / ( int i, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::i2f ( i / fixed<SH>::f2i ( f. m_f )), true ); }
132
133template <unsigned int SH> inline fixed<SH> operator + ( double d, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::d2f( d ) + f. m_f, true ); }
134template <unsigned int SH> inline fixed<SH> operator - ( double d, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::d2f( d ) - f. m_f, true ); }
135template <unsigned int SH> inline fixed<SH> operator * ( double d, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::mul ( fixed<SH>::d2f( d ), f. m_f ), true ); }
136template <unsigned int SH> inline fixed<SH> operator / ( double d, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::mul ( fixed<SH>::d2f( d ), f. m_f ), true ); }
137
138template <unsigned int SH> inline bool operator < ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) < f. m_f; }
139template <unsigned int SH> inline bool operator > ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) > f. m_f; }
140template <unsigned int SH> inline bool operator <= ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) <= f. m_f; }
141template <unsigned int SH> inline bool operator >= ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) >= f. m_f; }
142template <unsigned int SH> inline bool operator == ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) == f. m_f; }
143template <unsigned int SH> inline bool operator != ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) != f. m_f; }
144
145template <unsigned int SH> inline bool operator < ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) < f. m_f; }
146template <unsigned int SH> inline bool operator > ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) > f. m_f; }
147template <unsigned int SH> inline bool operator <= ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) <= f. m_f; }
148template <unsigned int SH> inline bool operator >= ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) >= f. m_f; }
149template <unsigned int SH> inline bool operator == ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) == f. m_f; }
150template <unsigned int SH> inline bool operator != ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) != f. m_f; }
151
152
153template <unsigned int SH> inline fixed<SH> sqrt ( const fixed<SH> &f )
154{
155 return fixed<SH> ( double( sqrt ( double( f ))));
156}
157
158template <unsigned int SH> inline fixed<SH> fabs ( const fixed<SH> &f )
159{
160 return ( f < 0 ) ? -f : f;
161}
162
163template <unsigned int SH> inline ostream &operator << ( ostream &o, const fixed<SH> &f )
164{
165 o << double( f );
166 return o;
167}
168
169#endif
diff --git a/noncore/unsupported/qpdf/goo/GHash.cc b/noncore/unsupported/qpdf/goo/GHash.cc
new file mode 100644
index 0000000..9ef6bb1
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/GHash.cc
@@ -0,0 +1,240 @@
1//========================================================================
2//
3// GHash.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include "gmem.h"
15#include "GString.h"
16#include "GHash.h"
17
18//------------------------------------------------------------------------
19
20struct GHashBucket {
21 GString *key;
22 void *val;
23 GHashBucket *next;
24};
25
26struct GHashIter {
27 int h;
28 GHashBucket *p;
29};
30
31//------------------------------------------------------------------------
32
33GHash::GHash(GBool deleteKeysA) {
34 int h;
35
36 deleteKeys = deleteKeysA;
37 size = 7;
38 tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
39 for (h = 0; h < size; ++h) {
40 tab[h] = NULL;
41 }
42 len = 0;
43}
44
45GHash::~GHash() {
46 GHashBucket *p;
47 int h;
48
49 for (h = 0; h < size; ++h) {
50 while (tab[h]) {
51 p = tab[h];
52 tab[h] = p->next;
53 if (deleteKeys) {
54 delete p->key;
55 }
56 delete p;
57 }
58 }
59 gfree(tab);
60}
61
62void GHash::add(GString *key, void *val) {
63 GHashBucket **oldTab;
64 GHashBucket *p;
65 int oldSize, i, h;
66
67 // expand the table if necessary
68 if (len >= size) {
69 oldSize = size;
70 oldTab = tab;
71 size = 2*size + 1;
72 tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
73 for (h = 0; h < size; ++h) {
74 tab[h] = NULL;
75 }
76 for (i = 0; i < oldSize; ++i) {
77 while (oldTab[i]) {
78 p = oldTab[i];
79 oldTab[i] = oldTab[i]->next;
80 h = hash(p->key);
81 p->next = tab[h];
82 tab[h] = p;
83 }
84 }
85 gfree(oldTab);
86 }
87
88 // add the new symbol
89 p = new GHashBucket;
90 p->key = key;
91 p->val = val;
92 h = hash(key);
93 p->next = tab[h];
94 tab[h] = p;
95 ++len;
96}
97
98void *GHash::lookup(GString *key) {
99 GHashBucket *p;
100 int h;
101
102 if (!(p = find(key, &h))) {
103 return NULL;
104 }
105 return p->val;
106}
107
108void *GHash::lookup(char *key) {
109 GHashBucket *p;
110 int h;
111
112 if (!(p = find(key, &h))) {
113 return NULL;
114 }
115 return p->val;
116}
117
118void *GHash::remove(GString *key) {
119 GHashBucket *p;
120 GHashBucket **q;
121 void *val;
122 int h;
123
124 if (!(p = find(key, &h))) {
125 return NULL;
126 }
127 q = &tab[h];
128 while (*q != p) {
129 q = &((*q)->next);
130 }
131 *q = p->next;
132 if (deleteKeys) {
133 delete p->key;
134 }
135 val = p->val;
136 delete p;
137 --len;
138 return val;
139}
140
141void *GHash::remove(char *key) {
142 GHashBucket *p;
143 GHashBucket **q;
144 void *val;
145 int h;
146
147 if (!(p = find(key, &h))) {
148 return NULL;
149 }
150 q = &tab[h];
151 while (*q != p) {
152 q = &((*q)->next);
153 }
154 *q = p->next;
155 if (deleteKeys) {
156 delete p->key;
157 }
158 val = p->val;
159 delete p;
160 --len;
161 return val;
162}
163
164void GHash::startIter(GHashIter **iter) {
165 *iter = new GHashIter;
166 (*iter)->h = -1;
167 (*iter)->p = NULL;
168}
169
170GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
171 if (!*iter) {
172 return gFalse;
173 }
174 if ((*iter)->p) {
175 (*iter)->p = (*iter)->p->next;
176 }
177 while (!(*iter)->p) {
178 if (++(*iter)->h == size) {
179 delete *iter;
180 *iter = NULL;
181 return gFalse;
182 }
183 (*iter)->p = tab[(*iter)->h];
184 }
185 *key = (*iter)->p->key;
186 *val = (*iter)->p->val;
187 return gTrue;
188}
189
190void GHash::killIter(GHashIter **iter) {
191 delete *iter;
192 *iter = NULL;
193}
194
195GHashBucket *GHash::find(GString *key, int *h) {
196 GHashBucket *p;
197
198 *h = hash(key);
199 for (p = tab[*h]; p; p = p->next) {
200 if (!p->key->cmp(key)) {
201 return p;
202 }
203 }
204 return NULL;
205}
206
207GHashBucket *GHash::find(char *key, int *h) {
208 GHashBucket *p;
209
210 *h = hash(key);
211 for (p = tab[*h]; p; p = p->next) {
212 if (!p->key->cmp(key)) {
213 return p;
214 }
215 }
216 return NULL;
217}
218
219int GHash::hash(GString *key) {
220 char *p;
221 unsigned int h;
222 int i;
223
224 h = 0;
225 for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
226 h = 17 * h + (int)(*p & 0xff);
227 }
228 return (int)(h % size);
229}
230
231int GHash::hash(char *key) {
232 char *p;
233 unsigned int h;
234
235 h = 0;
236 for (p = key; *p; ++p) {
237 h = 17 * h + (int)(*p & 0xff);
238 }
239 return (int)(h % size);
240}
diff --git a/noncore/unsupported/qpdf/goo/GHash.h b/noncore/unsupported/qpdf/goo/GHash.h
new file mode 100644
index 0000000..be1e573
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/GHash.h
@@ -0,0 +1,67 @@
1//========================================================================
2//
3// GHash.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef GHASH_H
10#define GHASH_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17
18class GString;
19struct GHashBucket;
20struct GHashIter;
21
22//------------------------------------------------------------------------
23
24class GHash {
25public:
26
27 GHash(GBool deleteKeysA = gFalse);
28 ~GHash();
29 void add(GString *key, void *val);
30 void *lookup(GString *key);
31 void *lookup(char *key);
32 void *remove(GString *key);
33 void *remove(char *key);
34 int getLength() { return len; }
35 void startIter(GHashIter **iter);
36 GBool getNext(GHashIter **iter, GString **key, void **val);
37 void killIter(GHashIter **iter);
38
39private:
40
41 GHashBucket *find(GString *key, int *h);
42 GHashBucket *find(char *key, int *h);
43 int hash(GString *key);
44 int hash(char *key);
45
46 GBool deleteKeys; // set if key strings should be deleted
47 int size; // number of buckets
48 int len; // number of entries
49 GHashBucket **tab;
50};
51
52#define deleteGHash(hash, T) \
53 do { \
54 GHash *_hash = (hash); \
55 { \
56 GHashIter *_iter; \
57 GString *_key; \
58 void *_p; \
59 _hash->startIter(&_iter); \
60 while (_hash->getNext(&_iter, &_key, &_p)) { \
61 delete (T*)_p; \
62 } \
63 delete _hash; \
64 } \
65 } while(0)
66
67#endif
diff --git a/noncore/unsupported/qpdf/goo/GList.cc b/noncore/unsupported/qpdf/goo/GList.cc
new file mode 100644
index 0000000..cfe0a25
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/GList.cc
@@ -0,0 +1,91 @@
1//========================================================================
2//
3// GList.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <string.h>
15#include "gmem.h"
16#include "GList.h"
17
18//------------------------------------------------------------------------
19// GList
20//------------------------------------------------------------------------
21
22GList::GList() {
23 size = 8;
24 data = (void **)gmalloc(size * sizeof(void*));
25 length = 0;
26 inc = 0;
27}
28
29GList::GList(int sizeA) {
30 size = sizeA;
31 data = (void **)gmalloc(size * sizeof(void*));
32 length = 0;
33 inc = 0;
34}
35
36GList::~GList() {
37 gfree(data);
38}
39
40void GList::append(void *p) {
41 if (length >= size) {
42 expand();
43 }
44 data[length++] = p;
45}
46
47void GList::append(GList *list) {
48 int i;
49
50 while (length + list->length > size) {
51 expand();
52 }
53 for (i = 0; i < list->length; ++i) {
54 data[length++] = list->data[i];
55 }
56}
57
58void GList::insert(int i, void *p) {
59 if (length >= size) {
60 expand();
61 }
62 if (i < length) {
63 memmove(data+i+1, data+i, (length - i) * sizeof(void *));
64 }
65 data[i] = p;
66 ++length;
67}
68
69void *GList::del(int i) {
70 void *p;
71
72 p = data[i];
73 if (i < length - 1) {
74 memmove(data+i, data+i+1, (length - i - 1) * sizeof(void *));
75 }
76 --length;
77 if (size - length >= ((inc > 0) ? inc : size/2)) {
78 shrink();
79 }
80 return p;
81}
82
83void GList::expand() {
84 size += (inc > 0) ? inc : size;
85 data = (void **)grealloc(data, size * sizeof(void*));
86}
87
88void GList::shrink() {
89 size -= (inc > 0) ? inc : size/2;
90 data = (void **)grealloc(data, size * sizeof(void*));
91}
diff --git a/noncore/unsupported/qpdf/goo/GList.h b/noncore/unsupported/qpdf/goo/GList.h
new file mode 100644
index 0000000..cc23731
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/GList.h
@@ -0,0 +1,89 @@
1//========================================================================
2//
3// GList.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef GLIST_H
10#define GLIST_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17
18//------------------------------------------------------------------------
19// GList
20//------------------------------------------------------------------------
21
22class GList {
23public:
24
25 // Create an empty list.
26 GList();
27
28 // Create an empty list with space for <size1> elements.
29 GList(int sizeA);
30
31 // Destructor - does not free pointed-to objects.
32 ~GList();
33
34 //----- general
35
36 // Get the number of elements.
37 int getLength() { return length; }
38
39 //----- ordered list support
40
41 // Return the <i>th element.
42 // Assumes 0 <= i < length.
43 void *get(int i) { return data[i]; }
44
45 // Append an element to the end of the list.
46 void append(void *p);
47
48 // Append another list to the end of this one.
49 void append(GList *list);
50
51 // Insert an element at index <i>.
52 // Assumes 0 <= i <= length.
53 void insert(int i, void *p);
54
55 // Deletes and returns the element at index <i>.
56 // Assumes 0 <= i < length.
57 void *del(int i);
58
59 //----- control
60
61 // Set allocation increment to <inc>. If inc > 0, that many
62 // elements will be allocated every time the list is expanded.
63 // If inc <= 0, the list will be doubled in size.
64 void setAllocIncr(int incA) { inc = incA; }
65
66private:
67
68 void expand();
69 void shrink();
70
71 void **data; // the list elements
72 int size; // size of data array
73 int length; // number of elements on list
74 int inc; // allocation increment
75};
76
77#define deleteGList(list, T) \
78 do { \
79 GList *_list = (list); \
80 { \
81 int _i; \
82 for (_i = 0; _i < _list->getLength(); ++_i) { \
83 delete (T*)_list->get(_i); \
84 } \
85 delete _list; \
86 } \
87 } while (0)
88
89#endif
diff --git a/noncore/unsupported/qpdf/goo/GString.cc b/noncore/unsupported/qpdf/goo/GString.cc
new file mode 100644
index 0000000..414c490
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/GString.cc
@@ -0,0 +1,231 @@
1//========================================================================
2//
3// GString.cc
4//
5// Simple variable-length string type.
6//
7// Copyright 1996 Derek B. Noonburg
8//
9//========================================================================
10
11#ifdef __GNUC__
12#pragma implementation
13#endif
14
15#include <aconf.h>
16#include <stdlib.h>
17#include <stddef.h>
18#include <string.h>
19#include <ctype.h>
20#include "gtypes.h"
21#include "GString.h"
22
23static inline int size(int len) {
24 int delta;
25
26 delta = len < 256 ? 7 : 255;
27 return ((len + 1) + delta) & ~delta;
28}
29
30inline void GString::resize(int length1) {
31 char *s1;
32
33 if (!s) {
34 s = new char[size(length1)];
35 } else if (size(length1) != size(length)) {
36 s1 = new char[size(length1)];
37 memcpy(s1, s, length + 1);
38 delete[] s;
39 s = s1;
40 }
41}
42
43GString::GString() {
44 s = NULL;
45 resize(length = 0);
46 s[0] = '\0';
47}
48
49GString::GString(const char *sA) {
50 int n = strlen(sA);
51
52 s = NULL;
53 resize(length = n);
54 memcpy(s, sA, n + 1);
55}
56
57GString::GString(const char *sA, int lengthA) {
58 s = NULL;
59 resize(length = lengthA);
60 memcpy(s, sA, length * sizeof(char));
61 s[length] = '\0';
62}
63
64GString::GString(GString *str, int idx, int lengthA) {
65 s = NULL;
66 resize(length = lengthA);
67 memcpy(s, str->getCString() + idx, length);
68 s[length] = '\0';
69}
70
71GString::GString(GString *str) {
72 s = NULL;
73 resize(length = str->getLength());
74 memcpy(s, str->getCString(), length + 1);
75}
76
77GString::GString(GString *str1, GString *str2) {
78 int n1 = str1->getLength();
79 int n2 = str2->getLength();
80
81 s = NULL;
82 resize(length = n1 + n2);
83 memcpy(s, str1->getCString(), n1);
84 memcpy(s + n1, str2->getCString(), n2 + 1);
85}
86
87GString *GString::fromInt(int x) {
88 char buf[24]; // enough space for 64-bit ints plus a little extra
89 GBool neg;
90 Guint y;
91 int i;
92
93 i = 24;
94 if (x == 0) {
95 buf[--i] = '0';
96 } else {
97 if ((neg = x < 0)) {
98 y = (Guint)-x;
99 } else {
100 y = (Guint)x;
101 }
102 while (i > 0 && y > 0) {
103 buf[--i] = '0' + y % 10;
104 y /= 10;
105 }
106 if (neg && i > 0) {
107 buf[--i] = '-';
108 }
109 }
110 return new GString(buf + i, 24 - i);
111}
112
113GString::~GString() {
114 delete[] s;
115}
116
117GString *GString::clear() {
118 s[length = 0] = '\0';
119 resize(0);
120 return this;
121}
122
123GString *GString::append(char c) {
124 resize(length + 1);
125 s[length++] = c;
126 s[length] = '\0';
127 return this;
128}
129
130GString *GString::append(GString *str) {
131 int n = str->getLength();
132
133 resize(length + n);
134 memcpy(s + length, str->getCString(), n + 1);
135 length += n;
136 return this;
137}
138
139GString *GString::append(const char *str) {
140 int n = strlen(str);
141
142 resize(length + n);
143 memcpy(s + length, str, n + 1);
144 length += n;
145 return this;
146}
147
148GString *GString::append(const char *str, int lengthA) {
149 resize(length + lengthA);
150 memcpy(s + length, str, lengthA);
151 length += lengthA;
152 s[length] = '\0';
153 return this;
154}
155
156GString *GString::insert(int i, char c) {
157 int j;
158
159 resize(length + 1);
160 for (j = length + 1; j > i; --j)
161 s[j] = s[j-1];
162 s[i] = c;
163 ++length;
164 return this;
165}
166
167GString *GString::insert(int i, GString *str) {
168 int n = str->getLength();
169 int j;
170
171 resize(length + n);
172 for (j = length; j >= i; --j)
173 s[j+n] = s[j];
174 memcpy(s+i, str->getCString(), n);
175 length += n;
176 return this;
177}
178
179GString *GString::insert(int i, const char *str) {
180 int n = strlen(str);
181 int j;
182
183 resize(length + n);
184 for (j = length; j >= i; --j)
185 s[j+n] = s[j];
186 memcpy(s+i, str, n);
187 length += n;
188 return this;
189}
190
191GString *GString::insert(int i, const char *str, int lengthA) {
192 int j;
193
194 resize(length + lengthA);
195 for (j = length; j >= i; --j)
196 s[j+lengthA] = s[j];
197 memcpy(s+i, str, lengthA);
198 length += lengthA;
199 return this;
200}
201
202GString *GString::del(int i, int n) {
203 int j;
204
205 if (n > 0) {
206 for (j = i; j <= length - n; ++j)
207 s[j] = s[j + n];
208 resize(length -= n);
209 }
210 return this;
211}
212
213GString *GString::upperCase() {
214 int i;
215
216 for (i = 0; i < length; ++i) {
217 if (islower(s[i]))
218 s[i] = toupper(s[i]);
219 }
220 return this;
221}
222
223GString *GString::lowerCase() {
224 int i;
225
226 for (i = 0; i < length; ++i) {
227 if (isupper(s[i]))
228 s[i] = tolower(s[i]);
229 }
230 return this;
231}
diff --git a/noncore/unsupported/qpdf/goo/GString.h b/noncore/unsupported/qpdf/goo/GString.h
new file mode 100644
index 0000000..3ced1c4
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/GString.h
@@ -0,0 +1,98 @@
1//========================================================================
2//
3// GString.h
4//
5// Simple variable-length string type.
6//
7// Copyright 1996 Derek B. Noonburg
8//
9//========================================================================
10
11#ifndef GSTRING_H
12#define GSTRING_H
13
14#ifdef __GNUC__
15#pragma interface
16#endif
17
18#include <string.h>
19
20class GString {
21public:
22
23 // Create an empty string.
24 GString();
25
26 // Create a string from a C string.
27 GString(const char *sA);
28
29 // Create a string from <lengthA> chars at <sA>. This string
30 // can contain null characters.
31 GString(const char *sA, int lengthA);
32
33 // Create a string from <lengthA> chars at <idx> in <str>.
34 GString(GString *str, int idx, int lengthA);
35
36 // Copy a string.
37 GString(GString *str);
38 GString *copy() { return new GString(this); }
39
40 // Concatenate two strings.
41 GString(GString *str1, GString *str2);
42
43 // Convert an integer to a string.
44 static GString *fromInt(int x);
45
46 // Destructor.
47 ~GString();
48
49 // Get length.
50 int getLength() { return length; }
51
52 // Get C string.
53 char *getCString() { return s; }
54
55 // Get <i>th character.
56 char getChar(int i) { return s[i]; }
57
58 // Change <i>th character.
59 void setChar(int i, char c) { s[i] = c; }
60
61 // Clear string to zero length.
62 GString *clear();
63
64 // Append a character or string.
65 GString *append(char c);
66 GString *append(GString *str);
67 GString *append(const char *str);
68 GString *append(const char *str, int lengthA);
69
70 // Insert a character or string.
71 GString *insert(int i, char c);
72 GString *insert(int i, GString *str);
73 GString *insert(int i, const char *str);
74 GString *insert(int i, const char *str, int lengthA);
75
76 // Delete a character or range of characters.
77 GString *del(int i, int n = 1);
78
79 // Convert string to all-upper/all-lower case.
80 GString *upperCase();
81 GString *lowerCase();
82
83 // Compare two strings: -1:< 0:= +1:>
84 // These functions assume the strings do not contain null characters.
85 int cmp(GString *str) { return strcmp(s, str->getCString()); }
86 int cmpN(GString *str, int n) { return strncmp(s, str->getCString(), n); }
87 int cmp(const char *sA) { return strcmp(s, sA); }
88 int cmpN(const char *sA, int n) { return strncmp(s, sA, n); }
89
90private:
91
92 int length;
93 char *s;
94
95 void resize(int length1);
96};
97
98#endif
diff --git a/noncore/unsupported/qpdf/goo/gfile.h b/noncore/unsupported/qpdf/goo/gfile.h
new file mode 100644
index 0000000..16cbca0
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/gfile.h
@@ -0,0 +1,135 @@
1//========================================================================
2//
3// gfile.h
4//
5// Miscellaneous file and directory name manipulation.
6//
7// Copyright 1996 Derek B. Noonburg
8//
9//========================================================================
10
11#ifndef GFILE_H
12#define GFILE_H
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <stddef.h>
17#if defined(WIN32)
18# include <sys/stat.h>
19# ifdef FPTEX
20# include <win32lib.h>
21# else
22# include <windows.h>
23# endif
24#elif defined(ACORN)
25#elif defined(MACOS)
26# include <ctime.h>
27#else
28# include <unistd.h>
29# include <sys/types.h>
30# ifdef VMS
31# include "vms_dirent.h"
32# elif HAVE_DIRENT_H
33# include <dirent.h>
34# define NAMLEN(d) strlen((d)->d_name)
35# else
36# define dirent direct
37# define NAMLEN(d) (d)->d_namlen
38# if HAVE_SYS_NDIR_H
39# include <sys/ndir.h>
40# endif
41# if HAVE_SYS_DIR_H
42# include <sys/dir.h>
43# endif
44# if HAVE_NDIR_H
45# include <ndir.h>
46# endif
47# endif
48#endif
49#include "gtypes.h"
50
51class GString;
52
53//------------------------------------------------------------------------
54
55// Get home directory path.
56extern GString *getHomeDir();
57
58// Get current directory.
59extern GString *getCurrentDir();
60
61// Append a file name to a path string. <path> may be an empty
62// string, denoting the current directory). Returns <path>.
63extern GString *appendToPath(GString *path, char *fileName);
64
65// Grab the path from the front of the file name. If there is no
66// directory component in <fileName>, returns an empty string.
67extern GString *grabPath(char *fileName);
68
69// Is this an absolute path or file name?
70extern GBool isAbsolutePath(char *path);
71
72// Make this path absolute by prepending current directory (if path is
73// relative) or prepending user's directory (if path starts with '~').
74extern GString *makePathAbsolute(GString *path);
75
76// Get the modification time for <fileName>. Returns 0 if there is an
77// error.
78extern time_t getModTime(char *fileName);
79
80// Create a temporary file and open it for writing. If <ext> is not
81// NULL, it will be used as the file name extension. Returns both the
82// name and the file pointer. For security reasons, all writing
83// should be done to the returned file pointer; the file may be
84// reopened later for reading, but not for writing. The <mode> string
85// should be "w" or "wb". Returns true on success.
86extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
87
88// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line
89// conventions.
90extern char *getLine(char *buf, int size, FILE *f);
91
92//------------------------------------------------------------------------
93// GDir and GDirEntry
94//------------------------------------------------------------------------
95
96class GDirEntry {
97public:
98
99 GDirEntry(char *dirPath, char *nameA, GBool doStat);
100 ~GDirEntry();
101 GString *getName() { return name; }
102 GBool isDir() { return dir; }
103
104private:
105
106 GString *name; // dir/file name
107 GBool dir; // is it a directory?
108};
109
110class GDir {
111public:
112
113 GDir(char *name, GBool doStatA = gTrue);
114 ~GDir();
115 GDirEntry *getNextEntry();
116 void rewind();
117
118private:
119
120 GString *path; // directory path
121 GBool doStat; // call stat() for each entry?
122#if defined(WIN32)
123 WIN32_FIND_DATA ffd;
124 HANDLE hnd;
125#elif defined(ACORN)
126#elif defined(MACOS)
127#else
128 DIR *dir; // the DIR structure from opendir()
129#ifdef VMS
130 GBool needParent; // need to return an entry for [-]
131#endif
132#endif
133};
134
135#endif
diff --git a/noncore/unsupported/qpdf/goo/gmem.h b/noncore/unsupported/qpdf/goo/gmem.h
new file mode 100644
index 0000000..7ab5ddb
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/gmem.h
@@ -0,0 +1,53 @@
1/*
2 * gmem.h
3 *
4 * Memory routines with out-of-memory checking.
5 *
6 * Copyright 1996 Derek B. Noonburg
7 */
8
9#ifndef GMEM_H
10#define GMEM_H
11
12#include <stdio.h>
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
18/*
19 * Same as malloc, but prints error message and exits if malloc()
20 * returns NULL.
21 */
22extern void *gmalloc(int size);
23
24/*
25 * Same as realloc, but prints error message and exits if realloc()
26 * returns NULL. If <p> is NULL, calls malloc instead of realloc().
27 */
28extern void *grealloc(void *p, int size);
29
30/*
31 * Same as free, but checks for and ignores NULL pointers.
32 */
33extern void gfree(void *p);
34
35#ifdef DEBUG_MEM
36/*
37 * Report on unfreed memory.
38 */
39extern void gMemReport(FILE *f);
40#else
41#define gMemReport(f)
42#endif
43
44/*
45 * Allocate memory and copy a string into it.
46 */
47extern char *copyString(char *s);
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/noncore/unsupported/qpdf/goo/gtypes.h b/noncore/unsupported/qpdf/goo/gtypes.h
new file mode 100644
index 0000000..6593267
--- a/dev/null
+++ b/noncore/unsupported/qpdf/goo/gtypes.h
@@ -0,0 +1,29 @@
1/*
2 * gtypes.h
3 *
4 * Some useful simple types.
5 *
6 * Copyright 1996 Derek B. Noonburg
7 */
8
9#ifndef GTYPES_H
10#define GTYPES_H
11
12/*
13 * These have stupid names to avoid conflicts with some (but not all)
14 * C++ compilers which define them.
15 */
16typedef int GBool;
17#define gTrue 1
18#define gFalse 0
19
20/*
21 * These have stupid names to avoid conflicts with <sys/types.h>,
22 * which on various systems defines some random subset of these.
23 */
24typedef unsigned char Guchar;
25typedef unsigned short Gushort;
26typedef unsigned int Guint;
27typedef unsigned long Gulong;
28
29#endif
diff --git a/noncore/unsupported/qpdf/gooStub.cpp b/noncore/unsupported/qpdf/gooStub.cpp
new file mode 100644
index 0000000..cc29685
--- a/dev/null
+++ b/noncore/unsupported/qpdf/gooStub.cpp
@@ -0,0 +1,60 @@
1
2extern "C" {
3
4#include <stdlib.h>
5#include <string.h>
6#include <unistd.h>
7#include <stdio.h>
8#include <dirent.h>
9#include <fcntl.h>
10
11#include <gmem.h>
12}
13
14#include <gfile.h>
15#include <GString.h>
16
17#include <qdir.h>
18
19
20// replacement stubs to simplify (and speed up) operations
21
22void *gmalloc ( int size ) { return malloc ( size ); }
23void *grealloc ( void *p, int size ) { return realloc ( p, size ); }
24void gfree ( void *p ) { free ( p ); }
25char *copyString ( char *str ) { return strdup ( str ); }
26char *getLine(char *buf, int size, FILE *f) { return fgets ( buf, size, f ); }
27GString *getHomeDir ( ) { return new GString ( QDir::home ( ). absPath ( ). local8Bit ( )); }
28GString *appendToPath ( GString *path, char *fileName ) { return new GString ( QDir ( path-> getCString ( )). absFilePath ( fileName ). local8Bit ( )); }
29
30// mostly taken from XPDF, but simplified...
31
32GBool openTempFile ( GString **name, FILE **f, char *mode, char *ext )
33{
34 char *s, *p;
35 int fd;
36
37 if ( !ext )
38 ext = ".tmp";
39
40 if (!( s = tmpnam ( 0 )))
41 return gFalse;
42
43 *name = new GString ( "qpdf_" );
44 (*name)-> append ( s );
45
46 s = (*name)-> getCString ( );
47 if (( p = strrchr ( s, '.' )))
48 (*name)-> del ( p - s, (*name)-> getLength ( ) - ( p - s ));
49
50 (*name)-> append ( ext );
51
52 fd = open ((*name)-> getCString ( ), O_WRONLY | O_CREAT | O_EXCL, 0600 );
53
54 if ( fd < 0 || !( *f = fdopen ( fd, mode ))) {
55 delete *name;
56 return gFalse;
57 }
58
59 return gTrue;
60}
diff --git a/noncore/unsupported/qpdf/opie-qpdf.control b/noncore/unsupported/qpdf/opie-qpdf.control
new file mode 100644
index 0000000..77faa95
--- a/dev/null
+++ b/noncore/unsupported/qpdf/opie-qpdf.control
@@ -0,0 +1,9 @@
1Files: bin/qpdf apps/Applications/qpdf.desktop pics/qpdf_icon.png
2Package: opie-qpdf
3Priority: optional
4Section: opie/applications
5Maintainer: Robert Griebl <sandman@handhelds.org>
6Architecture: arm
7Version: $QPE_VERSION-$SUB_VERSION
8Depends: opie-base ($QPE_VERSION), gzip
9Description: A PDF viewer for OPIE.
diff --git a/noncore/unsupported/qpdf/qbusybar.cpp b/noncore/unsupported/qpdf/qbusybar.cpp
new file mode 100644
index 0000000..f5c62fa
--- a/dev/null
+++ b/noncore/unsupported/qpdf/qbusybar.cpp
@@ -0,0 +1,132 @@
1#include <qapplication.h>
2#include <qtimer.h>
3#include <qpainter.h>
4
5#include "qbusybar.h"
6
7
8
9QBusyBar::QBusyBar ( QWidget *parent, const char *name, int flags ) : QWidget ( parent, name, flags | WRepaintNoErase )
10{
11 m_busy = 0;
12
13 m_div = 0;
14 m_pos = 0;
15 m_fade = 0;
16 m_fadecols = 0;
17 m_speed = 500;
18
19 m_timer = new QTimer ( this );
20 connect ( m_timer, SIGNAL( timeout ( )), this, SLOT( slotTimeout ( )));
21
22 setParameters ( 12, 8, 200 );
23}
24
25 void QBusyBar::setParameters ( int d, int s, int v )
26 {
27 bool running = m_timer-> isActive ( );
28
29 if ( running )
30 m_timer-> stop ( );
31
32 m_div = d;
33 m_speed = v;
34
35 delete [] m_fadecols;
36 m_fade = s;
37 m_fadecols = new QColor [m_fade];
38
39 int rt, gt, bt;
40 int rf, gf, bf;
41
42 colorGroup ( ). color ( QColorGroup::Highlight ). rgb ( &rf, &gf, &bf );
43 colorGroup ( ). color ( QColorGroup::Background ). rgb ( &rt, &gt, &bt );
44
45 for ( int i = 0; i < s; i++ )
46 m_fadecols [i]. setRgb ( rf + ( rt - rf ) * i / s, gf + ( gt - gf ) * i / s, bf + ( bt - bf ) * i / s );
47
48 if ( running ) {
49 m_pos = 0;
50 m_timer-> start ( m_speed );
51 }
52}
53
54QBusyBar::~QBusyBar ( )
55{
56}
57
58bool QBusyBar::isBusy ( ) const
59{
60 return m_busy;
61}
62
63void QBusyBar::beginBusy ( )
64{
65 setBusy ( true );
66}
67
68void QBusyBar::endBusy ( )
69{
70 setBusy ( false );
71}
72
73void QBusyBar::setBusy ( bool b )
74{
75 int busy = m_busy + ( b ? 1 : -1 );
76
77 if ( busy < 0 )
78 busy = 0;
79
80 if (( m_busy == 0 ) && ( busy > 0 )) { // Changed stateto on
81 m_pos = 0;
82 m_timer-> start ( m_speed );
83 update ( );
84 }
85 else if (( m_busy > 0 ) && ( busy == 0 )) { // Changed state to off
86 m_timer-> stop ( );
87 update ( );
88 }
89
90 m_busy = busy;
91}
92
93void QBusyBar::slotTimeout ( )
94{
95 m_pos++;
96 m_pos %= ( 2 * ( m_fade + m_div ));
97
98 update ( );
99}
100
101void QBusyBar::paintEvent ( QPaintEvent *e )
102{
103 QPainter p ( this );
104
105 QRect clip = e-> rect ( );
106
107 int x = 0;
108 int dx = width ( ) / m_div;
109 int y = clip. top ( );
110 int dy = clip. height ( );
111
112 if ( m_busy ) {
113 int dir = ( m_pos < ( m_fade + m_div )) ? 1 : -1;
114 int pos = ( dir > 0 ) ? m_pos : ( 2 * ( m_div + m_fade )) - m_pos - m_fade - 1;
115
116 for ( int i = 0; i < m_div; i++ ) {
117 int ind = ( pos - i ) * dir;
118 if (( ind < 0 ) || ( ind >= m_fade ))
119 ind = m_fade - 1;
120
121 if ((( x + dx ) > clip. left ( )) || ( x < clip. right ( )))
122 p. fillRect ( x, y, ( i < ( m_div - 1 )) ? dx : width ( ) - x, dy, m_fadecols [ind] );
123 x += dx;
124 }
125 }
126 else {
127 p. fillRect ( e-> rect ( ), m_fadecols [m_fade - 1] );
128 }
129}
130
131
132
diff --git a/noncore/unsupported/qpdf/qbusybar.h b/noncore/unsupported/qpdf/qbusybar.h
new file mode 100644
index 0000000..a52094a
--- a/dev/null
+++ b/noncore/unsupported/qpdf/qbusybar.h
@@ -0,0 +1,43 @@
1#ifndef __QBUSYBAR_H__
2#define __QBUSYBAR_H__
3
4#include <qwidget.h>
5
6class QColor;
7class QTimer;
8
9class QBusyBar : public QWidget {
10 Q_OBJECT
11
12public:
13 QBusyBar ( QWidget *parent = 0, const char *name = 0, int flags = 0 );
14 virtual ~QBusyBar ( );
15
16 bool isBusy ( ) const;
17
18 void setParameters ( int div, int fade, int speed );
19
20public slots:
21 void beginBusy ( );
22 void endBusy ( );
23
24 void setBusy ( bool b );
25
26protected:
27 virtual void paintEvent ( QPaintEvent *e );
28
29private slots:
30 void slotTimeout ( );
31
32private:
33 QTimer *m_timer;
34 int m_busy;
35
36 int m_div;
37 int m_pos; // 0 .. 2 * m_div - 1
38 int m_fade; // 0 .. m_div - 1
39 int m_speed;
40 QColor *m_fadecols;
41};
42
43#endif
diff --git a/noncore/unsupported/qpdf/qpdf.cpp b/noncore/unsupported/qpdf/qpdf.cpp
new file mode 100644
index 0000000..6c268ec
--- a/dev/null
+++ b/noncore/unsupported/qpdf/qpdf.cpp
@@ -0,0 +1,529 @@
1//========================================================================
2//
3// qpdf.cc
4//
5// Copyright 2001 Robert Griebl
6//
7//========================================================================
8
9#include "aconf.h"
10#include "GString.h"
11#include "PDFDoc.h"
12#include "TextOutputDev.h"
13
14#include "QPEOutputDev.h"
15
16#include <qpe/qpeapplication.h>
17#include <qpe/resource.h>
18#include <qpe/applnk.h>
19#include <qpe/fileselector.h>
20#include <qpe/qcopenvelope_qws.h>
21
22
23#include <qclipboard.h>
24#include <qtoolbar.h>
25#include <qmenubar.h>
26#include <qpopupmenu.h>
27#include <qwidgetstack.h>
28#include <qtimer.h>
29#include <qfileinfo.h>
30#include <qstring.h>
31#include <qlineedit.h>
32#include <qspinbox.h>
33#include <qlayout.h>
34#include <qdialog.h>
35#include <qlabel.h>
36#include <qmessagebox.h>
37
38#include "qpdf.h"
39
40
41int main ( int argc, char **argv )
42{
43 QPEApplication app ( argc, argv );
44
45 // read config file
46 globalParams = new GlobalParams ( "" );
47 globalParams-> setErrQuiet ( true );
48
49 QPdfDlg *dlg = new QPdfDlg ( );
50 app. showMainDocumentWidget ( dlg );
51
52 if (( app. argc ( ) == 3 ) && ( app. argv ( ) [1] == QCString ( "-f" )))
53 dlg-> openFile ( app. argv ( ) [2] );
54
55 return app. exec ( );
56}
57
58
59QPdfDlg::QPdfDlg ( ) : QMainWindow ( )
60{
61 setCaption ( tr( "QPdf" ));
62 setIcon ( Resource::loadPixmap ( "qpdf_icon" ));
63
64 m_busy = false;
65
66 m_doc = 0;
67 m_pages = 0;
68 m_zoom = 72;
69 m_currentpage = 0;
70
71 m_fullscreen = false;
72 m_renderok = false;
73
74
75 setToolBarsMovable ( false );
76
77 m_stack = new QWidgetStack ( this );
78 m_stack-> setSizePolicy ( QSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding ));
79 setCentralWidget ( m_stack );
80
81 m_outdev = new QPEOutputDev ( m_stack );
82 connect ( m_outdev, SIGNAL( selectionChanged ( const QRect & )), this, SLOT( copyToClipboard ( const QRect & )));
83
84 m_filesel = new FileSelector ( "application/pdf", m_stack, "fs", false, true );
85 connect ( m_filesel, SIGNAL( closeMe ( )), this, SLOT( closeFileSelector ( )));
86 connect ( m_filesel, SIGNAL( fileSelected ( const DocLnk & )), this, SLOT( openFile ( const DocLnk & )));
87
88 m_tb_menu = new QToolBar ( this );
89 m_tb_menu-> setHorizontalStretchable ( true );
90
91 QMenuBar *mb = new QMenuBar ( m_tb_menu );
92
93 m_pm_zoom = new QPopupMenu ( mb );
94 m_pm_zoom-> setCheckable ( true );
95
96 mb-> insertItem ( tr( "Zoom" ), m_pm_zoom );
97
98 m_pm_zoom-> insertItem ( tr( "Fit to width" ), 1 );
99 m_pm_zoom-> insertItem ( tr( "Fit to page" ), 2 );
100 m_pm_zoom-> insertSeparator ( );
101 m_pm_zoom-> insertItem ( tr( "50%" ), 50 );
102 m_pm_zoom-> insertItem ( tr( "75%" ), 75 );
103 m_pm_zoom-> insertItem ( tr( "100%" ), 100 );
104 m_pm_zoom-> insertItem ( tr( "125%" ), 125 );
105 m_pm_zoom-> insertItem ( tr( "150%" ), 150 );
106 m_pm_zoom-> insertItem ( tr( "200%" ), 200 );
107
108 connect ( m_pm_zoom, SIGNAL( activated ( int )), this, SLOT( setZoom ( int )));
109
110 m_tb_tool = new QToolBar ( this );
111
112 new QToolButton ( Resource::loadIconSet ( "fileopen" ), tr( "Open..." ), QString::null, this, SLOT( openFile ( )), m_tb_tool, "open" );
113 m_tb_tool-> addSeparator ( );
114 m_to_find = new QToolButton ( Resource::loadIconSet ( "find" ), tr( "Find..." ), QString::null, this, SLOT( toggleFindBar ( )), m_tb_tool, "find" );
115 m_to_find-> setToggleButton ( true );
116 m_tb_tool-> addSeparator ( );
117 m_to_full = new QToolButton ( Resource::loadIconSet ( "fullscreen" ), tr( "Fullscreen" ), QString::null, this, SLOT( toggleFullscreen ( )), m_tb_tool, "fullscreen" );
118 m_to_full-> setToggleButton ( true );
119 m_tb_tool-> addSeparator ( );
120 new QToolButton ( Resource::loadIconSet ( "fastback" ), tr( "First page" ), QString::null, this, SLOT( firstPage ( )), m_tb_tool, "first" );
121 new QToolButton ( Resource::loadIconSet ( "back" ), tr( "Previous page" ), QString::null, this, SLOT( prevPage ( )), m_tb_tool, "prev" );
122 new QToolButton ( Resource::loadIconSet ( "down" ), tr( "Goto page..." ), QString::null, this, SLOT( gotoPageDialog ( )), m_tb_tool, "goto" );
123 new QToolButton ( Resource::loadIconSet ( "forward" ), tr( "Next page" ), QString::null, this, SLOT( nextPage ( )), m_tb_tool, "next" );
124 new QToolButton ( Resource::loadIconSet ( "fastforward" ), tr( "Last page" ), QString::null, this, SLOT( lastPage ( )), m_tb_tool, "last" );
125
126 m_tb_find = new QToolBar ( this );
127 addToolBar ( m_tb_find, "Search", QMainWindow::Top, true );
128 m_tb_find-> setHorizontalStretchable ( true );
129 m_tb_find-> hide ( );
130
131 m_findedit = new QLineEdit ( m_tb_find, "findedit" );
132 m_tb_find-> setStretchableWidget ( m_findedit );
133 connect ( m_findedit, SIGNAL( textChanged ( const QString & )), this, SLOT( findText ( const QString & )));
134
135 new QToolButton ( Resource::loadIconSet ( "next" ), tr( "Next" ), QString::null, this, SLOT( findText ( )), m_tb_find, "findnext" );
136
137 openFile ( );
138}
139
140QPdfDlg::~QPdfDlg ( )
141{
142 delete m_doc;
143}
144
145// vv Fullscreen handling (for broken QT-lib) [David Hedbor, www.eongames.com]
146
147void QPdfDlg::resizeEvent ( QResizeEvent * )
148{
149 if ( m_fullscreen && ( size ( ) != qApp-> desktop ( )-> size ( )))
150 setFullscreen ( true );
151}
152
153void QPdfDlg::focusInEvent ( QFocusEvent * )
154{
155 if ( m_fullscreen )
156 setFullscreen ( true );
157}
158
159void QPdfDlg::toggleFullscreen ( )
160{
161 if ( m_to_full-> isOn ( ) == m_fullscreen )
162 m_to_full-> setOn ( !m_fullscreen );
163
164 m_fullscreen = !m_fullscreen;
165 setFullscreen ( m_fullscreen );
166}
167
168void QPdfDlg::setFullscreen ( bool b )
169{
170 static QSize normalsize;
171
172 if ( b ) {
173 if ( !normalsize. isValid ( ))
174 normalsize = size ( );
175
176 setFixedSize ( qApp-> desktop ( )-> size ( ));
177 showNormal ( );
178 reparent ( 0, WStyle_Customize | WStyle_NoBorder, QPoint ( 0, 0 ));
179 showFullScreen ( );
180 }
181 else {
182 showNormal ( );
183 reparent ( 0, 0, QPoint ( 0, 0 ));
184 resize ( normalsize );
185 showMaximized ( );
186 normalsize = QSize ( );
187 }
188}
189
190// ^^ Fullscreen handling (for broken QT-lib)
191
192void QPdfDlg::setBusy ( bool b )
193{
194 if ( b != m_busy ) {
195 m_busy = b;
196
197 m_outdev-> setBusy ( m_busy );
198 setEnabled ( !m_busy );
199 }
200}
201
202bool QPdfDlg::busy ( ) const
203{
204 return m_busy;
205}
206
207
208void QPdfDlg::updateCaption ( )
209{
210 QString cap = "";
211
212 if ( !m_currentdoc. isEmpty ( ))
213 cap = QString ( "%1 - " ). arg ( m_currentdoc );
214 cap += "QPdf";
215
216 setCaption ( cap );
217}
218
219
220void QPdfDlg::setZoom ( int id )
221{
222 int dpi = 0;
223
224 switch ( id ) {
225 case 1:
226 if ( m_doc && m_doc-> isOk ( ))
227 dpi = m_outdev-> visibleWidth ( ) * 72 / m_doc-> getPageWidth ( m_currentpage );
228 break;
229
230 case 2:
231 if ( m_doc && m_doc-> isOk ( ))
232 dpi = QMIN( m_outdev-> visibleWidth ( ) * 72 / m_doc-> getPageWidth ( m_currentpage ), \
233 m_outdev-> visibleHeight ( ) * 72 / m_doc-> getPageHeight ( m_currentpage ));
234 break;
235
236 default:
237 dpi = id * 72 / 100;
238 break;
239 }
240
241 if ( dpi < 18 )
242 dpi = 18;
243 if ( dpi > 216 )
244 dpi = 216;
245
246 for ( uint i = 0; i < m_pm_zoom-> count ( ); i++ ) {
247 int xid = m_pm_zoom-> idAt ( i );
248 m_pm_zoom-> setItemChecked ( xid, xid == id );
249 }
250
251 if ( dpi != m_zoom ) {
252 m_zoom = dpi;
253
254 renderPage ( );
255 }
256}
257
258
259void QPdfDlg::gotoPageDialog ( )
260{
261 QDialog *d = new QDialog ( this, "gotodlg", true );
262 d-> setCaption ( tr( "Goto page" ));
263
264 QBoxLayout *lay = new QVBoxLayout ( d, 4, 4 );
265
266 QLabel *l = new QLabel ( tr( "Select from 1 .. %1:" ). arg ( m_pages ), d );
267 lay-> addWidget ( l );
268
269 QSpinBox *spin = new QSpinBox ( 1, m_pages, 1, d );
270 spin-> setValue ( m_currentpage );
271 spin-> setWrapping ( true );
272 spin-> setButtonSymbols ( QSpinBox::PlusMinus );
273 lay-> addWidget ( spin );
274
275 if ( d-> exec ( ) == QDialog::Accepted ) {
276 gotoPage ( spin-> value ( ));
277 }
278
279 delete d;
280}
281
282void QPdfDlg::toggleFindBar ( )
283{
284 if ( m_to_find-> isOn ( ) == m_tb_find-> isVisible ( ))
285 m_to_find-> setOn ( !m_tb_find-> isVisible ( ));
286
287 if ( m_tb_find-> isVisible ( )) {
288 m_tb_find-> hide ( );
289 m_outdev-> setFocus ( );
290 }
291 else {
292 m_tb_find-> show ( );
293 m_findedit-> setFocus ( );
294 }
295}
296
297void QPdfDlg::findText ( const QString &str )
298{
299 if ( !m_doc || !m_doc-> isOk ( ) || str. isEmpty ( ))
300 return;
301
302 TextOutputDev *textOut = 0;
303 int pg = 0;
304
305 setBusy ( true );
306
307 int len = str. length ( );
308 Unicode *u = new Unicode [len];
309 for ( int i = 0; i < len; i++ )
310 u [i] = str [i]. unicode ( );
311
312 int xMin = 0, yMin = 0, xMax = 0, yMax = 0;
313 QRect selr = m_outdev-> selection ( );
314 bool fromtop = true;
315
316 if ( selr. isValid ( )) {
317 xMin = selr. right ( );
318 yMin = selr. top ( ) + selr. height ( ) / 2;
319 fromtop = false;
320 }
321
322 if ( m_outdev-> findText ( u, len, fromtop, true, &xMin, &yMin, &xMax, &yMax ))
323 goto found;
324
325 qApp-> processEvents ( );
326
327 // search following pages
328 textOut = new TextOutputDev ( 0, gFalse, gFalse );
329 if ( !textOut-> isOk ( ))
330 goto done;
331
332 qApp-> processEvents ( );
333
334 for ( pg = ( m_currentpage % m_pages ) + 1; pg != m_currentpage; pg = ( pg % m_pages ) + 1 ) {
335 m_doc-> displayPage ( textOut, pg, 72, 0, gFalse );
336
337 fp_t xMin1, yMin1, xMax1, yMax1;
338
339 qApp-> processEvents ( );
340
341 if ( textOut-> findText ( u, len, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1 ))
342 goto foundPage;
343
344 qApp-> processEvents ( );
345 }
346
347 // search current page ending at current selection
348 if ( selr. isValid ( )) {
349 xMax = selr. left ( );
350 yMax = selr. top ( ) + selr. height ( ) / 2;
351
352 if ( m_outdev-> findText ( u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax ))
353 goto found;
354 }
355
356 // not found
357 QMessageBox::information ( this, tr( "Find..." ), tr( "'%1' could not be found." ). arg ( str ));
358 goto done;
359
360foundPage:
361 qApp-> processEvents ( );
362
363 gotoPage ( pg );
364
365 if ( !m_outdev-> findText ( u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax )) {
366 // this can happen if coalescing is bad
367 goto done;
368 }
369
370found:
371 selr. setCoords ( xMin, yMin, xMax, yMax );
372 m_outdev-> setSelection ( selr, true ); // this will emit QPEOutputDev::selectionChanged ( ) -> copyToClipboard ( )
373
374 done:
375
376 delete [] u;
377 delete textOut;
378
379 setBusy ( false );
380}
381
382
383void QPdfDlg::findText ( )
384{
385 findText ( m_findedit-> text ( ));
386}
387
388void QPdfDlg::copyToClipboard ( const QRect &r )
389{
390 if ( m_doc && m_doc-> isOk ( ) && m_doc-> okToCopy ( ))
391 qApp-> clipboard ( )-> setText ( m_outdev-> getText ( r ));
392}
393
394void QPdfDlg::firstPage ( )
395{
396 gotoPage ( 1 );
397}
398
399void QPdfDlg::prevPage ( )
400{
401 gotoPage ( m_currentpage - 1 );
402}
403
404void QPdfDlg::nextPage ( )
405{
406 gotoPage ( m_currentpage + 1 );
407}
408
409void QPdfDlg::lastPage ( )
410{
411 gotoPage ( m_pages );
412}
413
414void QPdfDlg::gotoPage ( int n )
415{
416 if ( n < 1 )
417 n = 1;
418 if ( n > m_pages )
419 n = m_pages;
420
421 if ( n != m_currentpage ) {
422 m_currentpage = n;
423
424 renderPage ( );
425 }
426}
427
428void QPdfDlg::renderPage ( )
429{
430 if ( m_renderok && m_doc && m_doc-> isOk ( )) {
431 m_renderok = false;
432
433 setBusy ( true );
434 m_doc-> displayPage ( m_outdev, m_currentpage, m_zoom, 0, true );
435 setBusy ( false );
436
437 m_outdev-> setPageCount ( m_currentpage, m_pages );
438
439 m_renderok = true;
440 }
441}
442
443void QPdfDlg::closeFileSelector ( )
444{
445 m_tb_menu-> show ( );
446 m_tb_tool-> show ( );
447 m_stack-> raiseWidget ( m_outdev );
448}
449
450void QPdfDlg::openFile ( )
451{
452 m_tb_menu-> hide ( );
453 m_tb_tool-> hide ( );
454 m_tb_find-> hide ( );
455 m_stack-> raiseWidget ( m_filesel );
456}
457
458void QPdfDlg::openFile ( const QString &f )
459{
460 DocLnk nf;
461 nf. setType ( "application/pdf" );
462 nf. setFile ( f );
463 QFileInfo fi ( f );
464 nf. setName ( fi. baseName ( ));
465 openFile ( nf );
466}
467
468void QPdfDlg::openFile ( const DocLnk &f )
469{
470 QString fn = f. file ( );
471 QFileInfo fi ( fn );
472
473 if ( fi. exists ( )) {
474 delete m_doc;
475
476 m_doc = new PDFDoc ( new GString ( fn. local8Bit ( )), 0, 0 );
477
478 if ( m_doc-> isOk ( )) {
479 m_currentdoc = f. name ( );
480 int sep = m_currentdoc. findRev ( '/' );
481 if ( sep > 0 )
482 m_currentdoc = m_currentdoc. mid ( sep + 1 );
483
484 m_pages = m_doc-> getNumPages ( );
485 m_currentpage = 0;
486
487 QTimer::singleShot ( 0, this, SLOT( delayedInit ( )));
488 }
489 else {
490 delete m_doc;
491 m_doc = 0;
492
493 m_currentdoc = QString::null;
494 }
495
496 updateCaption ( );
497 }
498 else
499 QMessageBox::warning ( this, tr( "Error" ), tr( "File does not exist !" ));
500}
501
502void QPdfDlg::setDocument ( const QString &f )
503{
504 if ( f. find ( ".desktop", 0, true ) == -1 )
505 openFile ( f );
506 else
507 openFile ( DocLnk ( f ));
508
509 closeFileSelector ( );
510}
511
512void QPdfDlg::delayedInit ( )
513 {
514 closeFileSelector ( );
515
516 m_currentpage = 0;
517 m_zoom = 0;
518 m_renderok = false;
519
520 setZoom ( 100 );
521 gotoPage ( 1 );
522
523 m_renderok = true;
524
525 renderPage ( );
526
527 m_outdev-> setFocus ( );
528}
529
diff --git a/noncore/unsupported/qpdf/qpdf.h b/noncore/unsupported/qpdf/qpdf.h
new file mode 100644
index 0000000..b4ce554
--- a/dev/null
+++ b/noncore/unsupported/qpdf/qpdf.h
@@ -0,0 +1,94 @@
1#ifndef __QPDF_H__
2#define __QPDF_H__
3
4#include "aconf.h"
5
6#include <qmainwindow.h>
7
8
9class QPEOutputDev;
10class PDFDoc;
11
12class DocLnk;
13class FileSelector;
14class QWidgetStack;
15class QLineEdit;
16
17
18class QPdfDlg : public QMainWindow {
19 Q_OBJECT
20
21public:
22 QPdfDlg ( );
23 virtual ~QPdfDlg ( );
24
25public slots:
26 void firstPage ( );
27 void prevPage ( );
28 void nextPage ( );
29 void lastPage ( );
30
31 void gotoPage ( int n );
32
33 void setZoom ( int z );
34
35 void gotoPageDialog ( );
36
37 void toggleFullscreen ( );
38 void toggleFindBar ( );
39
40 void findText ( const QString & );
41 void findText ( );
42
43 void openFile ( );
44 void openFile ( const QString & );
45 void openFile ( const DocLnk & );
46
47 void setDocument ( const QString & );
48
49private slots:
50 void delayedInit ( );
51 void closeFileSelector ( );
52
53 void updateCaption ( );
54
55 void copyToClipboard ( const QRect & );
56
57protected:
58 void setFullscreen ( bool b = true );
59
60 void setBusy ( bool b = true );
61 bool busy ( ) const;
62
63 void renderPage ( );
64
65 virtual void resizeEvent ( QResizeEvent *e );
66 virtual void focusInEvent ( QFocusEvent *e );
67
68private:
69 QWidgetStack *m_stack;
70 QPEOutputDev *m_outdev;
71 FileSelector *m_filesel;
72
73 QToolBar *m_tb_menu, *m_tb_tool, *m_tb_find;
74 QLineEdit *m_findedit;
75 QPopupMenu *m_pm_zoom;
76
77 QToolButton *m_to_find, *m_to_full;
78
79 bool m_fullscreen;
80
81 bool m_busy;
82 bool m_renderok;
83
84 int m_currentpage;
85 int m_pages;
86 int m_zoom;
87
88 PDFDoc *m_doc;
89
90 QString m_currentdoc;
91};
92
93
94#endif
diff --git a/noncore/unsupported/qpdf/qpdf.pro b/noncore/unsupported/qpdf/qpdf.pro
new file mode 100644
index 0000000..6ba4f49
--- a/dev/null
+++ b/noncore/unsupported/qpdf/qpdf.pro
@@ -0,0 +1,60 @@
1TEMPLATE = app
2
3CONFIG *= qt embedded release warn_off
4CONFIG -= warn_on
5
6SOURCES = xpdf/Array.cc \
7 xpdf/BuiltinFont.cc \
8 xpdf/BuiltinFontTables.cc \
9 xpdf/CMap.cc \
10 xpdf/Catalog.cc \
11 xpdf/CharCodeToUnicode.cc \
12 xpdf/Decrypt.cc \
13 xpdf/Dict.cc \
14 xpdf/Error.cc \
15 xpdf/FontEncodingTables.cc \
16 xpdf/FormWidget.cc \
17 xpdf/Function.cc \
18 xpdf/Gfx.cc \
19 xpdf/GfxFont.cc \
20 xpdf/GfxState.cc \
21 xpdf/GlobalParams.cc \
22 xpdf/Lexer.cc \
23 xpdf/Link.cc \
24 xpdf/NameToCharCode.cc \
25 xpdf/Object.cc \
26 xpdf/OutputDev.cc \
27 xpdf/PDFDoc.cc \
28 xpdf/Page.cc \
29 xpdf/Parser.cc \
30 xpdf/Stream.cc \
31 xpdf/TextOutputDev.cc \
32 xpdf/UnicodeMap.cc \
33 xpdf/XRef.cc \
34 goo/GHash.cc \
35 goo/GString.cc \
36 goo/GList.cc \
37 QOutputDev.cpp \
38 QPEOutputDev.cpp \
39 qpdf.cpp \
40 qbusybar.cpp \
41 gooStub.cpp
42
43HEADERS = QOutputDev.h \
44 QPEOutputDev.h \
45 qbusybar.h \
46 qpdf.h
47
48INCLUDEPATH += . \
49 .. \
50 xpdf \
51 $(OPIEDIR)/include \
52 ../goo \
53 goo
54
55LIBS += -L $(OPIEDIR)/lib -lqpe -lstdc++
56
57DESTDIR = $(OPIEDIR)/bin
58TARGET = qpdf
59
60TRANSLATIONS = ../../i18n/de/qpdf.ts
diff --git a/noncore/unsupported/qpdf/xpdf/Array.cc b/noncore/unsupported/qpdf/xpdf/Array.cc
new file mode 100644
index 0000000..5743fe6
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Array.cc
@@ -0,0 +1,53 @@
1//========================================================================
2//
3// Array.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include "gmem.h"
16#include "Object.h"
17#include "Array.h"
18
19//------------------------------------------------------------------------
20// Array
21//------------------------------------------------------------------------
22
23Array::Array(XRef *xrefA) {
24 xref = xrefA;
25 elems = NULL;
26 size = length = 0;
27 ref = 1;
28}
29
30Array::~Array() {
31 int i;
32
33 for (i = 0; i < length; ++i)
34 elems[i].free();
35 gfree(elems);
36}
37
38void Array::add(Object *elem) {
39 if (length + 1 > size) {
40 size += 8;
41 elems = (Object *)grealloc(elems, size * sizeof(Object));
42 }
43 elems[length] = *elem;
44 ++length;
45}
46
47Object *Array::get(int i, Object *obj) {
48 return elems[i].fetch(xref, obj);
49}
50
51Object *Array::getNF(int i, Object *obj) {
52 return elems[i].copy(obj);
53}
diff --git a/noncore/unsupported/qpdf/xpdf/Array.h b/noncore/unsupported/qpdf/xpdf/Array.h
new file mode 100644
index 0000000..1616fc3
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Array.h
@@ -0,0 +1,56 @@
1//========================================================================
2//
3// Array.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef ARRAY_H
10#define ARRAY_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "Object.h"
17
18class XRef;
19
20//------------------------------------------------------------------------
21// Array
22//------------------------------------------------------------------------
23
24class Array {
25public:
26
27 // Constructor.
28 Array(XRef *xrefA);
29
30 // Destructor.
31 ~Array();
32
33 // Reference counting.
34 int incRef() { return ++ref; }
35 int decRef() { return --ref; }
36
37 // Get number of elements.
38 int getLength() { return length; }
39
40 // Add an element.
41 void add(Object *elem);
42
43 // Accessors.
44 Object *get(int i, Object *obj);
45 Object *getNF(int i, Object *obj);
46
47private:
48
49 XRef *xref; // the xref table for this PDF file
50 Object *elems; // array of elements
51 int size; // size of <elems> array
52 int length; // number of elements in array
53 int ref; // reference count
54};
55
56#endif
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFont.cc b/noncore/unsupported/qpdf/xpdf/BuiltinFont.cc
new file mode 100644
index 0000000..a8cef7b
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFont.cc
@@ -0,0 +1,64 @@
1//========================================================================
2//
3// BuiltinFont.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdlib.h>
15#include <string.h>
16#include "gmem.h"
17#include "FontEncodingTables.h"
18#include "BuiltinFont.h"
19
20//------------------------------------------------------------------------
21
22BuiltinFontWidths::BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA) {
23 int i, h;
24
25 size = sizeA;
26 tab = (BuiltinFontWidth **)gmalloc(size * sizeof(BuiltinFontWidth *));
27 for (i = 0; i < size; ++i) {
28 tab[i] = NULL;
29 }
30 for (i = 0; i < sizeA; ++i) {
31 h = hash(widths[i].name);
32 widths[i].next = tab[h];
33 tab[h] = &widths[i];
34 }
35}
36
37BuiltinFontWidths::~BuiltinFontWidths() {
38 gfree(tab);
39}
40
41GBool BuiltinFontWidths::getWidth(char *name, Gushort *width) {
42 int h;
43 BuiltinFontWidth *p;
44
45 h = hash(name);
46 for (p = tab[h]; p; p = p->next) {
47 if (!strcmp(p->name, name)) {
48 *width = p->width;
49 return gTrue;
50 }
51 }
52 return gFalse;
53}
54
55int BuiltinFontWidths::hash(char *name) {
56 char *p;
57 unsigned int h;
58
59 h = 0;
60 for (p = name; *p; ++p) {
61 h = 17 * h + (int)(*p & 0xff);
62 }
63 return (int)(h % size);
64}
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFont.h b/noncore/unsupported/qpdf/xpdf/BuiltinFont.h
new file mode 100644
index 0000000..b4fa24c
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFont.h
@@ -0,0 +1,55 @@
1//========================================================================
2//
3// BuiltinFont.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef BUILTINFONT_H
10#define BUILTINFONT_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17
18struct BuiltinFont;
19class BuiltinFontWidths;
20
21//------------------------------------------------------------------------
22
23struct BuiltinFont {
24 char *name;
25 char **defaultBaseEnc;
26 short ascent;
27 short descent;
28 short bbox[4];
29 BuiltinFontWidths *widths;
30};
31
32//------------------------------------------------------------------------
33
34struct BuiltinFontWidth {
35 char *name;
36 Gushort width;
37 BuiltinFontWidth *next;
38};
39
40class BuiltinFontWidths {
41public:
42
43 BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA);
44 ~BuiltinFontWidths();
45 GBool getWidth(char *name, Gushort *width);
46
47private:
48
49 int hash(char *name);
50
51 BuiltinFontWidth **tab;
52 int size;
53};
54
55#endif
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc
new file mode 100644
index 0000000..6833972
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc
@@ -0,0 +1,3366 @@
1//========================================================================
2//
3// BuiltinFontTables.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#include <aconf.h>
10#include <stdlib.h>
11#include "FontEncodingTables.h"
12#include "BuiltinFontTables.h"
13
14static BuiltinFontWidth courierWidthsTab[] = {
15 { "Ntilde", 600, NULL },
16 { "comma", 600, NULL },
17 { "cedilla", 600, NULL },
18 { "plusminus", 600, NULL },
19 { "arrowup", 600, NULL },
20 { "circumflex", 600, NULL },
21 { "dotaccent", 600, NULL },
22 { "LL", 600, NULL },
23 { "asciitilde", 600, NULL },
24 { "colon", 600, NULL },
25 { "onehalf", 600, NULL },
26 { "dollar", 600, NULL },
27 { "ntilde", 600, NULL },
28 { "left", 600, NULL },
29 { "minus", 600, NULL },
30 { "yen", 600, NULL },
31 { "space", 600, NULL },
32 { "questiondown", 600, NULL },
33 { "emdash", 600, NULL },
34 { "Agrave", 600, NULL },
35 { "three", 600, NULL },
36 { "numbersign", 600, NULL },
37 { "A", 600, NULL },
38 { "B", 600, NULL },
39 { "C", 600, NULL },
40 { "D", 600, NULL },
41 { "E", 600, NULL },
42 { "onequarter", 600, NULL },
43 { "F", 600, NULL },
44 { "G", 600, NULL },
45 { "H", 600, NULL },
46 { "I", 600, NULL },
47 { "J", 600, NULL },
48 { "K", 600, NULL },
49 { "L", 600, NULL },
50 { "backslash", 600, NULL },
51 { "periodcentered", 600, NULL },
52 { "M", 600, NULL },
53 { "N", 600, NULL },
54 { "O", 600, NULL },
55 { "P", 600, NULL },
56 { "Q", 600, NULL },
57 { "R", 600, NULL },
58 { "Aacute", 600, NULL },
59 { "caron", 600, NULL },
60 { "S", 600, NULL },
61 { "T", 600, NULL },
62 { "U", 600, NULL },
63 { "agrave", 600, NULL },
64 { "V", 600, NULL },
65 { "tab", 600, NULL },
66 { "W", 600, NULL },
67 { "ll", 600, NULL },
68 { "equal", 600, NULL },
69 { "question", 600, NULL },
70 { "X", 600, NULL },
71 { "Y", 600, NULL },
72 { "Z", 600, NULL },
73 { "four", 600, NULL },
74 { "a", 600, NULL },
75 { "b", 600, NULL },
76 { "c", 600, NULL },
77 { "d", 600, NULL },
78 { "e", 600, NULL },
79 { "f", 600, NULL },
80 { "g", 600, NULL },
81 { "bullet", 600, NULL },
82 { "h", 600, NULL },
83 { "i", 600, NULL },
84 { "Oslash", 600, NULL },
85 { "dagger", 600, NULL },
86 { "j", 600, NULL },
87 { "k", 600, NULL },
88 { "l", 600, NULL },
89 { "m", 600, NULL },
90 { "n", 600, NULL },
91 { "o", 600, NULL },
92 { "ordfeminine", 600, NULL },
93 { "ring", 600, NULL },
94 { "p", 600, NULL },
95 { "q", 600, NULL },
96 { "r", 600, NULL },
97 { "twosuperior", 600, NULL },
98 { "largebullet", 600, NULL },
99 { "aacute", 600, NULL },
100 { "s", 600, NULL },
101 { "OE", 600, NULL },
102 { "t", 600, NULL },
103 { "divide", 600, NULL },
104 { "u", 600, NULL },
105 { "v", 600, NULL },
106 { "w", 600, NULL },
107 { "x", 600, NULL },
108 { "y", 600, NULL },
109 { "z", 600, NULL },
110 { "hungarumlaut", 600, NULL },
111 { "quotedbl", 600, NULL },
112 { "mu", 600, NULL },
113 { "Scaron", 600, NULL },
114 { "Lslash", 600, NULL },
115 { "semicolon", 600, NULL },
116 { "oslash", 600, NULL },
117 { "parenright", 600, NULL },
118 { "Ecircumflex", 600, NULL },
119 { "trademark", 600, NULL },
120 { "daggerdbl", 600, NULL },
121 { "macron", 600, NULL },
122 { "Otilde", 600, NULL },
123 { "ellipsis", 600, NULL },
124 { "scaron", 600, NULL },
125 { "AE", 600, NULL },
126 { "Ucircumflex", 600, NULL },
127 { "lslash", 600, NULL },
128 { "lira", 600, NULL },
129 { "quotedblleft", 600, NULL },
130 { "hyphen", 600, NULL },
131 { "guilsinglright", 600, NULL },
132 { "quotesingle", 600, NULL },
133 { "eight", 600, NULL },
134 { "exclamdown", 600, NULL },
135 { "endash", 600, NULL },
136 { "oe", 600, NULL },
137 { "ecircumflex", 600, NULL },
138 { "copyright", 600, NULL },
139 { "Adieresis", 600, NULL },
140 { "Egrave", 600, NULL },
141 { "slash", 600, NULL },
142 { "Edieresis", 600, NULL },
143 { "otilde", 600, NULL },
144 { "Idieresis", 600, NULL },
145 { "parenleft", 600, NULL },
146 { "one", 600, NULL },
147 { "ucircumflex", 600, NULL },
148 { "Odieresis", 600, NULL },
149 { "bracketleft", 600, NULL },
150 { "Ugrave", 600, NULL },
151 { "quoteright", 600, NULL },
152 { "Udieresis", 600, NULL },
153 { "perthousand", 600, NULL },
154 { "Ydieresis", 600, NULL },
155 { "Eacute", 600, NULL },
156 { "adieresis", 600, NULL },
157 { "egrave", 600, NULL },
158 { "edieresis", 600, NULL },
159 { "idieresis", 600, NULL },
160 { "Eth", 600, NULL },
161 { "ae", 600, NULL },
162 { "asterisk", 600, NULL },
163 { "odieresis", 600, NULL },
164 { "Uacute", 600, NULL },
165 { "ugrave", 600, NULL },
166 { "five", 600, NULL },
167 { "nine", 600, NULL },
168 { "udieresis", 600, NULL },
169 { "Zcaron", 600, NULL },
170 { "threequarters", 600, NULL },
171 { "guillemotright", 600, NULL },
172 { "ydieresis", 600, NULL },
173 { "Ccedilla", 600, NULL },
174 { "tilde", 600, NULL },
175 { "at", 600, NULL },
176 { "eacute", 600, NULL },
177 { "Gcaron", 600, NULL },
178 { "underscore", 600, NULL },
179 { "zero", 600, NULL },
180 { "multiply", 600, NULL },
181 { "Scedilla", 600, NULL },
182 { "eth", 600, NULL },
183 { "Ograve", 600, NULL },
184 { "uacute", 600, NULL },
185 { "braceleft", 600, NULL },
186 { "Thorn", 600, NULL },
187 { "zcaron", 600, NULL },
188 { "ccedilla", 600, NULL },
189 { "gcaron", 600, NULL },
190 { "Oacute", 600, NULL },
191 { "Ocircumflex", 600, NULL },
192 { "scedilla", 600, NULL },
193 { "ogonek", 600, NULL },
194 { "arrowdown", 600, NULL },
195 { "ograve", 600, NULL },
196 { "thorn", 600, NULL },
197 { "degree", 600, NULL },
198 { "registered", 600, NULL },
199 { "percent", 600, NULL },
200 { "Aring", 600, NULL },
201 { "six", 600, NULL },
202 { "paragraph", 600, NULL },
203 { "two", 600, NULL },
204 { "Igrave", 600, NULL },
205 { "oacute", 600, NULL },
206 { "ocircumflex", 600, NULL },
207 { "asciicircum", 600, NULL },
208 { "aring", 600, NULL },
209 { "square", 600, NULL },
210 { "grave", 600, NULL },
211 { "bracketright", 600, NULL },
212 { "ampersand", 600, NULL },
213 { "Iacute", 600, NULL },
214 { "igrave", 600, NULL },
215 { "return", 600, NULL },
216 { "plus", 600, NULL },
217 { "quotesinglbase", 600, NULL },
218 { "Yacute", 600, NULL },
219 { "threesuperior", 600, NULL },
220 { "acute", 600, NULL },
221 { "notegraphic", 600, NULL },
222 { "section", 600, NULL },
223 { "arrowleft", 600, NULL },
224 { "dieresis", 600, NULL },
225 { "quotedblbase", 600, NULL },
226 { "iacute", 600, NULL },
227 { "up", 600, NULL },
228 { "florin", 600, NULL },
229 { "yacute", 600, NULL },
230 { "fi", 600, NULL },
231 { "fl", 600, NULL },
232 { "Acircumflex", 600, NULL },
233 { "Icircumflex", 600, NULL },
234 { "guillemotleft", 600, NULL },
235 { "germandbls", 600, NULL },
236 { "seven", 600, NULL },
237 { "indent", 600, NULL },
238 { "prescription", 600, NULL },
239 { "dectab", 600, NULL },
240 { "ordmasculine", 600, NULL },
241 { "dotlessi", 600, NULL },
242 { "sterling", 600, NULL },
243 { "IJ", 600, NULL },
244 { "acircumflex", 600, NULL },
245 { "overscore", 600, NULL },
246 { "braceright", 600, NULL },
247 { "icircumflex", 600, NULL },
248 { "graybox", 600, NULL },
249 { "quotedblright", 600, NULL },
250 { "center", 600, NULL },
251 { "stop", 600, NULL },
252 { "cent", 600, NULL },
253 { "currency", 600, NULL },
254 { "logicalnot", 600, NULL },
255 { "Idot", 600, NULL },
256 { "merge", 600, NULL },
257 { "Atilde", 600, NULL },
258 { "breve", 600, NULL },
259 { "bar", 600, NULL },
260 { "fraction", 600, NULL },
261 { "less", 600, NULL },
262 { "down", 600, NULL },
263 { "guilsinglleft", 600, NULL },
264 { "exclam", 600, NULL },
265 { "period", 600, NULL },
266 { "arrowright", 600, NULL },
267 { "format", 600, NULL },
268 { "greater", 600, NULL },
269 { "atilde", 600, NULL },
270 { "ij", 600, NULL },
271 { "brokenbar", 600, NULL },
272 { "arrowboth", 600, NULL },
273 { "quoteleft", 600, NULL },
274 { "onesuperior", 600, NULL }
275};
276
277static BuiltinFontWidth courierBoldWidthsTab[] = {
278 { "Ntilde", 600, NULL },
279 { "comma", 600, NULL },
280 { "cedilla", 600, NULL },
281 { "plusminus", 600, NULL },
282 { "arrowup", 600, NULL },
283 { "circumflex", 600, NULL },
284 { "dotaccent", 600, NULL },
285 { "LL", 600, NULL },
286 { "asciitilde", 600, NULL },
287 { "colon", 600, NULL },
288 { "onehalf", 600, NULL },
289 { "dollar", 600, NULL },
290 { "ntilde", 600, NULL },
291 { "left", 600, NULL },
292 { "minus", 600, NULL },
293 { "yen", 600, NULL },
294 { "space", 600, NULL },
295 { "questiondown", 600, NULL },
296 { "emdash", 600, NULL },
297 { "Agrave", 600, NULL },
298 { "three", 600, NULL },
299 { "numbersign", 600, NULL },
300 { "A", 600, NULL },
301 { "B", 600, NULL },
302 { "C", 600, NULL },
303 { "D", 600, NULL },
304 { "E", 600, NULL },
305 { "onequarter", 600, NULL },
306 { "F", 600, NULL },
307 { "G", 600, NULL },
308 { "H", 600, NULL },
309 { "I", 600, NULL },
310 { "J", 600, NULL },
311 { "K", 600, NULL },
312 { "backslash", 600, NULL },
313 { "L", 600, NULL },
314 { "periodcentered", 600, NULL },
315 { "M", 600, NULL },
316 { "N", 600, NULL },
317 { "O", 600, NULL },
318 { "P", 600, NULL },
319 { "Q", 600, NULL },
320 { "R", 600, NULL },
321 { "Aacute", 600, NULL },
322 { "caron", 600, NULL },
323 { "S", 600, NULL },
324 { "T", 600, NULL },
325 { "U", 600, NULL },
326 { "agrave", 600, NULL },
327 { "V", 600, NULL },
328 { "tab", 600, NULL },
329 { "W", 600, NULL },
330 { "ll", 600, NULL },
331 { "X", 600, NULL },
332 { "question", 600, NULL },
333 { "equal", 600, NULL },
334 { "Y", 600, NULL },
335 { "Z", 600, NULL },
336 { "four", 600, NULL },
337 { "a", 600, NULL },
338 { "b", 600, NULL },
339 { "c", 600, NULL },
340 { "d", 600, NULL },
341 { "e", 600, NULL },
342 { "f", 600, NULL },
343 { "g", 600, NULL },
344 { "bullet", 600, NULL },
345 { "h", 600, NULL },
346 { "i", 600, NULL },
347 { "Oslash", 600, NULL },
348 { "dagger", 600, NULL },
349 { "j", 600, NULL },
350 { "k", 600, NULL },
351 { "l", 600, NULL },
352 { "m", 600, NULL },
353 { "n", 600, NULL },
354 { "o", 600, NULL },
355 { "ordfeminine", 600, NULL },
356 { "ring", 600, NULL },
357 { "p", 600, NULL },
358 { "q", 600, NULL },
359 { "r", 600, NULL },
360 { "twosuperior", 600, NULL },
361 { "largebullet", 600, NULL },
362 { "aacute", 600, NULL },
363 { "s", 600, NULL },
364 { "OE", 600, NULL },
365 { "t", 600, NULL },
366 { "divide", 600, NULL },
367 { "u", 600, NULL },
368 { "v", 600, NULL },
369 { "w", 600, NULL },
370 { "x", 600, NULL },
371 { "y", 600, NULL },
372 { "z", 600, NULL },
373 { "hungarumlaut", 600, NULL },
374 { "quotedbl", 600, NULL },
375 { "mu", 600, NULL },
376 { "Scaron", 600, NULL },
377 { "Lslash", 600, NULL },
378 { "semicolon", 600, NULL },
379 { "oslash", 600, NULL },
380 { "parenright", 600, NULL },
381 { "Ecircumflex", 600, NULL },
382 { "trademark", 600, NULL },
383 { "daggerdbl", 600, NULL },
384 { "macron", 600, NULL },
385 { "Otilde", 600, NULL },
386 { "ellipsis", 600, NULL },
387 { "scaron", 600, NULL },
388 { "AE", 600, NULL },
389 { "Ucircumflex", 600, NULL },
390 { "lslash", 600, NULL },
391 { "lira", 600, NULL },
392 { "quotedblleft", 600, NULL },
393 { "guilsinglright", 600, NULL },
394 { "hyphen", 600, NULL },
395 { "quotesingle", 600, NULL },
396 { "eight", 600, NULL },
397 { "exclamdown", 600, NULL },
398 { "endash", 600, NULL },
399 { "oe", 600, NULL },
400 { "ecircumflex", 600, NULL },
401 { "copyright", 600, NULL },
402 { "Adieresis", 600, NULL },
403 { "Egrave", 600, NULL },
404 { "slash", 600, NULL },
405 { "Edieresis", 600, NULL },
406 { "otilde", 600, NULL },
407 { "Idieresis", 600, NULL },
408 { "parenleft", 600, NULL },
409 { "one", 600, NULL },
410 { "ucircumflex", 600, NULL },
411 { "Odieresis", 600, NULL },
412 { "bracketleft", 600, NULL },
413 { "Ugrave", 600, NULL },
414 { "quoteright", 600, NULL },
415 { "Udieresis", 600, NULL },
416 { "perthousand", 600, NULL },
417 { "Ydieresis", 600, NULL },
418 { "Eacute", 600, NULL },
419 { "adieresis", 600, NULL },
420 { "egrave", 600, NULL },
421 { "edieresis", 600, NULL },
422 { "idieresis", 600, NULL },
423 { "Eth", 600, NULL },
424 { "ae", 600, NULL },
425 { "asterisk", 600, NULL },
426 { "odieresis", 600, NULL },
427 { "Uacute", 600, NULL },
428 { "ugrave", 600, NULL },
429 { "nine", 600, NULL },
430 { "five", 600, NULL },
431 { "udieresis", 600, NULL },
432 { "Zcaron", 600, NULL },
433 { "threequarters", 600, NULL },
434 { "guillemotright", 600, NULL },
435 { "ydieresis", 600, NULL },
436 { "Ccedilla", 600, NULL },
437 { "tilde", 600, NULL },
438 { "at", 600, NULL },
439 { "eacute", 600, NULL },
440 { "Gcaron", 600, NULL },
441 { "underscore", 600, NULL },
442 { "multiply", 600, NULL },
443 { "zero", 600, NULL },
444 { "eth", 600, NULL },
445 { "Scedilla", 600, NULL },
446 { "Ograve", 600, NULL },
447 { "uacute", 600, NULL },
448 { "braceleft", 600, NULL },
449 { "Thorn", 600, NULL },
450 { "zcaron", 600, NULL },
451 { "ccedilla", 600, NULL },
452 { "gcaron", 600, NULL },
453 { "scedilla", 600, NULL },
454 { "Ocircumflex", 600, NULL },
455 { "Oacute", 600, NULL },
456 { "arrowdown", 600, NULL },
457 { "ogonek", 600, NULL },
458 { "ograve", 600, NULL },
459 { "thorn", 600, NULL },
460 { "degree", 600, NULL },
461 { "registered", 600, NULL },
462 { "Aring", 600, NULL },
463 { "percent", 600, NULL },
464 { "six", 600, NULL },
465 { "paragraph", 600, NULL },
466 { "two", 600, NULL },
467 { "Igrave", 600, NULL },
468 { "ocircumflex", 600, NULL },
469 { "oacute", 600, NULL },
470 { "asciicircum", 600, NULL },
471 { "square", 600, NULL },
472 { "aring", 600, NULL },
473 { "grave", 600, NULL },
474 { "bracketright", 600, NULL },
475 { "Iacute", 600, NULL },
476 { "ampersand", 600, NULL },
477 { "igrave", 600, NULL },
478 { "return", 600, NULL },
479 { "plus", 600, NULL },
480 { "quotesinglbase", 600, NULL },
481 { "Yacute", 600, NULL },
482 { "threesuperior", 600, NULL },
483 { "acute", 600, NULL },
484 { "notegraphic", 600, NULL },
485 { "section", 600, NULL },
486 { "arrowleft", 600, NULL },
487 { "dieresis", 600, NULL },
488 { "iacute", 600, NULL },
489 { "quotedblbase", 600, NULL },
490 { "up", 600, NULL },
491 { "florin", 600, NULL },
492 { "yacute", 600, NULL },
493 { "fi", 600, NULL },
494 { "fl", 600, NULL },
495 { "Acircumflex", 600, NULL },
496 { "Icircumflex", 600, NULL },
497 { "guillemotleft", 600, NULL },
498 { "germandbls", 600, NULL },
499 { "seven", 600, NULL },
500 { "prescription", 600, NULL },
501 { "indent", 600, NULL },
502 { "dectab", 600, NULL },
503 { "ordmasculine", 600, NULL },
504 { "dotlessi", 600, NULL },
505 { "sterling", 600, NULL },
506 { "acircumflex", 600, NULL },
507 { "IJ", 600, NULL },
508 { "overscore", 600, NULL },
509 { "icircumflex", 600, NULL },
510 { "braceright", 600, NULL },
511 { "graybox", 600, NULL },
512 { "quotedblright", 600, NULL },
513 { "center", 600, NULL },
514 { "stop", 600, NULL },
515 { "cent", 600, NULL },
516 { "currency", 600, NULL },
517 { "logicalnot", 600, NULL },
518 { "merge", 600, NULL },
519 { "Idot", 600, NULL },
520 { "Atilde", 600, NULL },
521 { "breve", 600, NULL },
522 { "bar", 600, NULL },
523 { "fraction", 600, NULL },
524 { "less", 600, NULL },
525 { "down", 600, NULL },
526 { "guilsinglleft", 600, NULL },
527 { "exclam", 600, NULL },
528 { "period", 600, NULL },
529 { "format", 600, NULL },
530 { "arrowright", 600, NULL },
531 { "greater", 600, NULL },
532 { "ij", 600, NULL },
533 { "atilde", 600, NULL },
534 { "brokenbar", 600, NULL },
535 { "arrowboth", 600, NULL },
536 { "quoteleft", 600, NULL },
537 { "onesuperior", 600, NULL }
538};
539
540static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
541 { "Ntilde", 600, NULL },
542 { "comma", 600, NULL },
543 { "cedilla", 600, NULL },
544 { "plusminus", 600, NULL },
545 { "arrowup", 600, NULL },
546 { "circumflex", 600, NULL },
547 { "dotaccent", 600, NULL },
548 { "LL", 600, NULL },
549 { "asciitilde", 600, NULL },
550 { "colon", 600, NULL },
551 { "onehalf", 600, NULL },
552 { "dollar", 600, NULL },
553 { "ntilde", 600, NULL },
554 { "left", 600, NULL },
555 { "minus", 600, NULL },
556 { "yen", 600, NULL },
557 { "space", 600, NULL },
558 { "questiondown", 600, NULL },
559 { "emdash", 600, NULL },
560 { "Agrave", 600, NULL },
561 { "three", 600, NULL },
562 { "numbersign", 600, NULL },
563 { "A", 600, NULL },
564 { "B", 600, NULL },
565 { "C", 600, NULL },
566 { "D", 600, NULL },
567 { "E", 600, NULL },
568 { "onequarter", 600, NULL },
569 { "F", 600, NULL },
570 { "G", 600, NULL },
571 { "H", 600, NULL },
572 { "I", 600, NULL },
573 { "J", 600, NULL },
574 { "K", 600, NULL },
575 { "backslash", 600, NULL },
576 { "L", 600, NULL },
577 { "periodcentered", 600, NULL },
578 { "M", 600, NULL },
579 { "N", 600, NULL },
580 { "O", 600, NULL },
581 { "P", 600, NULL },
582 { "Q", 600, NULL },
583 { "R", 600, NULL },
584 { "Aacute", 600, NULL },
585 { "caron", 600, NULL },
586 { "S", 600, NULL },
587 { "T", 600, NULL },
588 { "U", 600, NULL },
589 { "agrave", 600, NULL },
590 { "V", 600, NULL },
591 { "tab", 600, NULL },
592 { "W", 600, NULL },
593 { "ll", 600, NULL },
594 { "X", 600, NULL },
595 { "question", 600, NULL },
596 { "equal", 600, NULL },
597 { "Y", 600, NULL },
598 { "Z", 600, NULL },
599 { "four", 600, NULL },
600 { "a", 600, NULL },
601 { "b", 600, NULL },
602 { "c", 600, NULL },
603 { "d", 600, NULL },
604 { "e", 600, NULL },
605 { "f", 600, NULL },
606 { "g", 600, NULL },
607 { "bullet", 600, NULL },
608 { "h", 600, NULL },
609 { "i", 600, NULL },
610 { "Oslash", 600, NULL },
611 { "dagger", 600, NULL },
612 { "j", 600, NULL },
613 { "k", 600, NULL },
614 { "l", 600, NULL },
615 { "m", 600, NULL },
616 { "n", 600, NULL },
617 { "o", 600, NULL },
618 { "ordfeminine", 600, NULL },
619 { "ring", 600, NULL },
620 { "p", 600, NULL },
621 { "q", 600, NULL },
622 { "r", 600, NULL },
623 { "twosuperior", 600, NULL },
624 { "largebullet", 600, NULL },
625 { "aacute", 600, NULL },
626 { "s", 600, NULL },
627 { "OE", 600, NULL },
628 { "t", 600, NULL },
629 { "divide", 600, NULL },
630 { "u", 600, NULL },
631 { "v", 600, NULL },
632 { "w", 600, NULL },
633 { "x", 600, NULL },
634 { "y", 600, NULL },
635 { "z", 600, NULL },
636 { "hungarumlaut", 600, NULL },
637 { "quotedbl", 600, NULL },
638 { "mu", 600, NULL },
639 { "Scaron", 600, NULL },
640 { "Lslash", 600, NULL },
641 { "semicolon", 600, NULL },
642 { "oslash", 600, NULL },
643 { "parenright", 600, NULL },
644 { "Ecircumflex", 600, NULL },
645 { "trademark", 600, NULL },
646 { "daggerdbl", 600, NULL },
647 { "macron", 600, NULL },
648 { "Otilde", 600, NULL },
649 { "ellipsis", 600, NULL },
650 { "scaron", 600, NULL },
651 { "AE", 600, NULL },
652 { "Ucircumflex", 600, NULL },
653 { "lslash", 600, NULL },
654 { "lira", 600, NULL },
655 { "quotedblleft", 600, NULL },
656 { "guilsinglright", 600, NULL },
657 { "hyphen", 600, NULL },
658 { "quotesingle", 600, NULL },
659 { "eight", 600, NULL },
660 { "exclamdown", 600, NULL },
661 { "endash", 600, NULL },
662 { "oe", 600, NULL },
663 { "ecircumflex", 600, NULL },
664 { "copyright", 600, NULL },
665 { "Adieresis", 600, NULL },
666 { "Egrave", 600, NULL },
667 { "slash", 600, NULL },
668 { "Edieresis", 600, NULL },
669 { "otilde", 600, NULL },
670 { "Idieresis", 600, NULL },
671 { "parenleft", 600, NULL },
672 { "one", 600, NULL },
673 { "ucircumflex", 600, NULL },
674 { "Odieresis", 600, NULL },
675 { "bracketleft", 600, NULL },
676 { "Ugrave", 600, NULL },
677 { "quoteright", 600, NULL },
678 { "Udieresis", 600, NULL },
679 { "perthousand", 600, NULL },
680 { "Ydieresis", 600, NULL },
681 { "Eacute", 600, NULL },
682 { "adieresis", 600, NULL },
683 { "egrave", 600, NULL },
684 { "edieresis", 600, NULL },
685 { "idieresis", 600, NULL },
686 { "Eth", 600, NULL },
687 { "ae", 600, NULL },
688 { "asterisk", 600, NULL },
689 { "odieresis", 600, NULL },
690 { "Uacute", 600, NULL },
691 { "ugrave", 600, NULL },
692 { "nine", 600, NULL },
693 { "five", 600, NULL },
694 { "udieresis", 600, NULL },
695 { "Zcaron", 600, NULL },
696 { "threequarters", 600, NULL },
697 { "guillemotright", 600, NULL },
698 { "ydieresis", 600, NULL },
699 { "Ccedilla", 600, NULL },
700 { "tilde", 600, NULL },
701 { "at", 600, NULL },
702 { "eacute", 600, NULL },
703 { "Gcaron", 600, NULL },
704 { "underscore", 600, NULL },
705 { "multiply", 600, NULL },
706 { "zero", 600, NULL },
707 { "eth", 600, NULL },
708 { "Scedilla", 600, NULL },
709 { "Ograve", 600, NULL },
710 { "uacute", 600, NULL },
711 { "braceleft", 600, NULL },
712 { "Thorn", 600, NULL },
713 { "zcaron", 600, NULL },
714 { "ccedilla", 600, NULL },
715 { "gcaron", 600, NULL },
716 { "scedilla", 600, NULL },
717 { "Ocircumflex", 600, NULL },
718 { "Oacute", 600, NULL },
719 { "arrowdown", 600, NULL },
720 { "ogonek", 600, NULL },
721 { "ograve", 600, NULL },
722 { "thorn", 600, NULL },
723 { "degree", 600, NULL },
724 { "registered", 600, NULL },
725 { "Aring", 600, NULL },
726 { "percent", 600, NULL },
727 { "six", 600, NULL },
728 { "paragraph", 600, NULL },
729 { "two", 600, NULL },
730 { "Igrave", 600, NULL },
731 { "ocircumflex", 600, NULL },
732 { "oacute", 600, NULL },
733 { "asciicircum", 600, NULL },
734 { "square", 600, NULL },
735 { "aring", 600, NULL },
736 { "grave", 600, NULL },
737 { "bracketright", 600, NULL },
738 { "Iacute", 600, NULL },
739 { "ampersand", 600, NULL },
740 { "igrave", 600, NULL },
741 { "return", 600, NULL },
742 { "plus", 600, NULL },
743 { "quotesinglbase", 600, NULL },
744 { "Yacute", 600, NULL },
745 { "threesuperior", 600, NULL },
746 { "acute", 600, NULL },
747 { "notegraphic", 600, NULL },
748 { "section", 600, NULL },
749 { "arrowleft", 600, NULL },
750 { "dieresis", 600, NULL },
751 { "iacute", 600, NULL },
752 { "quotedblbase", 600, NULL },
753 { "up", 600, NULL },
754 { "florin", 600, NULL },
755 { "yacute", 600, NULL },
756 { "fi", 600, NULL },
757 { "fl", 600, NULL },
758 { "Acircumflex", 600, NULL },
759 { "Icircumflex", 600, NULL },
760 { "guillemotleft", 600, NULL },
761 { "germandbls", 600, NULL },
762 { "seven", 600, NULL },
763 { "prescription", 600, NULL },
764 { "indent", 600, NULL },
765 { "dectab", 600, NULL },
766 { "ordmasculine", 600, NULL },
767 { "dotlessi", 600, NULL },
768 { "sterling", 600, NULL },
769 { "acircumflex", 600, NULL },
770 { "IJ", 600, NULL },
771 { "overscore", 600, NULL },
772 { "icircumflex", 600, NULL },
773 { "braceright", 600, NULL },
774 { "graybox", 600, NULL },
775 { "quotedblright", 600, NULL },
776 { "center", 600, NULL },
777 { "stop", 600, NULL },
778 { "cent", 600, NULL },
779 { "currency", 600, NULL },
780 { "logicalnot", 600, NULL },
781 { "merge", 600, NULL },
782 { "Idot", 600, NULL },
783 { "Atilde", 600, NULL },
784 { "breve", 600, NULL },
785 { "bar", 600, NULL },
786 { "fraction", 600, NULL },
787 { "less", 600, NULL },
788 { "down", 600, NULL },
789 { "guilsinglleft", 600, NULL },
790 { "exclam", 600, NULL },
791 { "period", 600, NULL },
792 { "format", 600, NULL },
793 { "arrowright", 600, NULL },
794 { "greater", 600, NULL },
795 { "ij", 600, NULL },
796 { "atilde", 600, NULL },
797 { "brokenbar", 600, NULL },
798 { "arrowboth", 600, NULL },
799 { "quoteleft", 600, NULL },
800 { "onesuperior", 600, NULL }
801};
802
803static BuiltinFontWidth courierObliqueWidthsTab[] = {
804 { "Ntilde", 600, NULL },
805 { "comma", 600, NULL },
806 { "cedilla", 600, NULL },
807 { "plusminus", 600, NULL },
808 { "arrowup", 600, NULL },
809 { "circumflex", 600, NULL },
810 { "dotaccent", 600, NULL },
811 { "LL", 600, NULL },
812 { "asciitilde", 600, NULL },
813 { "colon", 600, NULL },
814 { "onehalf", 600, NULL },
815 { "dollar", 600, NULL },
816 { "ntilde", 600, NULL },
817 { "left", 600, NULL },
818 { "minus", 600, NULL },
819 { "yen", 600, NULL },
820 { "space", 600, NULL },
821 { "questiondown", 600, NULL },
822 { "emdash", 600, NULL },
823 { "Agrave", 600, NULL },
824 { "three", 600, NULL },
825 { "numbersign", 600, NULL },
826 { "A", 600, NULL },
827 { "B", 600, NULL },
828 { "C", 600, NULL },
829 { "D", 600, NULL },
830 { "E", 600, NULL },
831 { "onequarter", 600, NULL },
832 { "F", 600, NULL },
833 { "G", 600, NULL },
834 { "H", 600, NULL },
835 { "I", 600, NULL },
836 { "J", 600, NULL },
837 { "K", 600, NULL },
838 { "backslash", 600, NULL },
839 { "L", 600, NULL },
840 { "periodcentered", 600, NULL },
841 { "M", 600, NULL },
842 { "N", 600, NULL },
843 { "O", 600, NULL },
844 { "P", 600, NULL },
845 { "Q", 600, NULL },
846 { "R", 600, NULL },
847 { "Aacute", 600, NULL },
848 { "caron", 600, NULL },
849 { "S", 600, NULL },
850 { "T", 600, NULL },
851 { "U", 600, NULL },
852 { "agrave", 600, NULL },
853 { "V", 600, NULL },
854 { "tab", 600, NULL },
855 { "W", 600, NULL },
856 { "ll", 600, NULL },
857 { "X", 600, NULL },
858 { "question", 600, NULL },
859 { "equal", 600, NULL },
860 { "Y", 600, NULL },
861 { "Z", 600, NULL },
862 { "four", 600, NULL },
863 { "a", 600, NULL },
864 { "b", 600, NULL },
865 { "c", 600, NULL },
866 { "d", 600, NULL },
867 { "e", 600, NULL },
868 { "f", 600, NULL },
869 { "g", 600, NULL },
870 { "bullet", 600, NULL },
871 { "h", 600, NULL },
872 { "i", 600, NULL },
873 { "Oslash", 600, NULL },
874 { "dagger", 600, NULL },
875 { "j", 600, NULL },
876 { "k", 600, NULL },
877 { "l", 600, NULL },
878 { "m", 600, NULL },
879 { "n", 600, NULL },
880 { "o", 600, NULL },
881 { "ordfeminine", 600, NULL },
882 { "ring", 600, NULL },
883 { "p", 600, NULL },
884 { "q", 600, NULL },
885 { "r", 600, NULL },
886 { "twosuperior", 600, NULL },
887 { "largebullet", 600, NULL },
888 { "aacute", 600, NULL },
889 { "s", 600, NULL },
890 { "OE", 600, NULL },
891 { "t", 600, NULL },
892 { "divide", 600, NULL },
893 { "u", 600, NULL },
894 { "v", 600, NULL },
895 { "w", 600, NULL },
896 { "x", 600, NULL },
897 { "y", 600, NULL },
898 { "z", 600, NULL },
899 { "hungarumlaut", 600, NULL },
900 { "quotedbl", 600, NULL },
901 { "mu", 600, NULL },
902 { "Scaron", 600, NULL },
903 { "Lslash", 600, NULL },
904 { "semicolon", 600, NULL },
905 { "oslash", 600, NULL },
906 { "parenright", 600, NULL },
907 { "Ecircumflex", 600, NULL },
908 { "trademark", 600, NULL },
909 { "daggerdbl", 600, NULL },
910 { "macron", 600, NULL },
911 { "Otilde", 600, NULL },
912 { "ellipsis", 600, NULL },
913 { "scaron", 600, NULL },
914 { "AE", 600, NULL },
915 { "Ucircumflex", 600, NULL },
916 { "lslash", 600, NULL },
917 { "lira", 600, NULL },
918 { "quotedblleft", 600, NULL },
919 { "guilsinglright", 600, NULL },
920 { "hyphen", 600, NULL },
921 { "quotesingle", 600, NULL },
922 { "eight", 600, NULL },
923 { "exclamdown", 600, NULL },
924 { "endash", 600, NULL },
925 { "oe", 600, NULL },
926 { "ecircumflex", 600, NULL },
927 { "copyright", 600, NULL },
928 { "Adieresis", 600, NULL },
929 { "Egrave", 600, NULL },
930 { "slash", 600, NULL },
931 { "Edieresis", 600, NULL },
932 { "otilde", 600, NULL },
933 { "Idieresis", 600, NULL },
934 { "parenleft", 600, NULL },
935 { "one", 600, NULL },
936 { "ucircumflex", 600, NULL },
937 { "Odieresis", 600, NULL },
938 { "bracketleft", 600, NULL },
939 { "Ugrave", 600, NULL },
940 { "quoteright", 600, NULL },
941 { "Udieresis", 600, NULL },
942 { "perthousand", 600, NULL },
943 { "Ydieresis", 600, NULL },
944 { "Eacute", 600, NULL },
945 { "adieresis", 600, NULL },
946 { "egrave", 600, NULL },
947 { "edieresis", 600, NULL },
948 { "idieresis", 600, NULL },
949 { "Eth", 600, NULL },
950 { "ae", 600, NULL },
951 { "asterisk", 600, NULL },
952 { "odieresis", 600, NULL },
953 { "Uacute", 600, NULL },
954 { "ugrave", 600, NULL },
955 { "nine", 600, NULL },
956 { "five", 600, NULL },
957 { "udieresis", 600, NULL },
958 { "Zcaron", 600, NULL },
959 { "threequarters", 600, NULL },
960 { "guillemotright", 600, NULL },
961 { "ydieresis", 600, NULL },
962 { "Ccedilla", 600, NULL },
963 { "tilde", 600, NULL },
964 { "at", 600, NULL },
965 { "eacute", 600, NULL },
966 { "Gcaron", 600, NULL },
967 { "underscore", 600, NULL },
968 { "multiply", 600, NULL },
969 { "zero", 600, NULL },
970 { "eth", 600, NULL },
971 { "Scedilla", 600, NULL },
972 { "Ograve", 600, NULL },
973 { "uacute", 600, NULL },
974 { "braceleft", 600, NULL },
975 { "Thorn", 600, NULL },
976 { "zcaron", 600, NULL },
977 { "ccedilla", 600, NULL },
978 { "gcaron", 600, NULL },
979 { "scedilla", 600, NULL },
980 { "Ocircumflex", 600, NULL },
981 { "Oacute", 600, NULL },
982 { "arrowdown", 600, NULL },
983 { "ogonek", 600, NULL },
984 { "ograve", 600, NULL },
985 { "thorn", 600, NULL },
986 { "degree", 600, NULL },
987 { "registered", 600, NULL },
988 { "Aring", 600, NULL },
989 { "percent", 600, NULL },
990 { "six", 600, NULL },
991 { "paragraph", 600, NULL },
992 { "two", 600, NULL },
993 { "Igrave", 600, NULL },
994 { "ocircumflex", 600, NULL },
995 { "oacute", 600, NULL },
996 { "asciicircum", 600, NULL },
997 { "square", 600, NULL },
998 { "aring", 600, NULL },
999 { "grave", 600, NULL },
1000 { "bracketright", 600, NULL },
1001 { "Iacute", 600, NULL },
1002 { "ampersand", 600, NULL },
1003 { "igrave", 600, NULL },
1004 { "return", 600, NULL },
1005 { "plus", 600, NULL },
1006 { "quotesinglbase", 600, NULL },
1007 { "Yacute", 600, NULL },
1008 { "threesuperior", 600, NULL },
1009 { "acute", 600, NULL },
1010 { "notegraphic", 600, NULL },
1011 { "section", 600, NULL },
1012 { "arrowleft", 600, NULL },
1013 { "dieresis", 600, NULL },
1014 { "iacute", 600, NULL },
1015 { "quotedblbase", 600, NULL },
1016 { "up", 600, NULL },
1017 { "florin", 600, NULL },
1018 { "yacute", 600, NULL },
1019 { "fi", 600, NULL },
1020 { "fl", 600, NULL },
1021 { "Acircumflex", 600, NULL },
1022 { "Icircumflex", 600, NULL },
1023 { "guillemotleft", 600, NULL },
1024 { "germandbls", 600, NULL },
1025 { "seven", 600, NULL },
1026 { "prescription", 600, NULL },
1027 { "indent", 600, NULL },
1028 { "dectab", 600, NULL },
1029 { "ordmasculine", 600, NULL },
1030 { "dotlessi", 600, NULL },
1031 { "sterling", 600, NULL },
1032 { "acircumflex", 600, NULL },
1033 { "IJ", 600, NULL },
1034 { "overscore", 600, NULL },
1035 { "icircumflex", 600, NULL },
1036 { "braceright", 600, NULL },
1037 { "graybox", 600, NULL },
1038 { "quotedblright", 600, NULL },
1039 { "center", 600, NULL },
1040 { "stop", 600, NULL },
1041 { "cent", 600, NULL },
1042 { "currency", 600, NULL },
1043 { "logicalnot", 600, NULL },
1044 { "merge", 600, NULL },
1045 { "Idot", 600, NULL },
1046 { "Atilde", 600, NULL },
1047 { "breve", 600, NULL },
1048 { "bar", 600, NULL },
1049 { "fraction", 600, NULL },
1050 { "less", 600, NULL },
1051 { "down", 600, NULL },
1052 { "guilsinglleft", 600, NULL },
1053 { "exclam", 600, NULL },
1054 { "period", 600, NULL },
1055 { "format", 600, NULL },
1056 { "arrowright", 600, NULL },
1057 { "greater", 600, NULL },
1058 { "ij", 600, NULL },
1059 { "atilde", 600, NULL },
1060 { "brokenbar", 600, NULL },
1061 { "arrowboth", 600, NULL },
1062 { "quoteleft", 600, NULL },
1063 { "onesuperior", 600, NULL }
1064};
1065
1066static BuiltinFontWidth helveticaWidthsTab[] = {
1067 { "Ntilde", 722, NULL },
1068 { "comma", 278, NULL },
1069 { "cedilla", 333, NULL },
1070 { "plusminus", 584, NULL },
1071 { "circumflex", 333, NULL },
1072 { "dotaccent", 333, NULL },
1073 { "asciitilde", 584, NULL },
1074 { "colon", 278, NULL },
1075 { "onehalf", 834, NULL },
1076 { "dollar", 556, NULL },
1077 { "ntilde", 556, NULL },
1078 { "minus", 584, NULL },
1079 { "yen", 556, NULL },
1080 { "space", 278, NULL },
1081 { "questiondown", 611, NULL },
1082 { "emdash", 1000, NULL },
1083 { "Agrave", 667, NULL },
1084 { "three", 556, NULL },
1085 { "numbersign", 556, NULL },
1086 { "A", 667, NULL },
1087 { "B", 667, NULL },
1088 { "C", 722, NULL },
1089 { "D", 722, NULL },
1090 { "E", 667, NULL },
1091 { "onequarter", 834, NULL },
1092 { "F", 611, NULL },
1093 { "G", 778, NULL },
1094 { "H", 722, NULL },
1095 { "I", 278, NULL },
1096 { "J", 500, NULL },
1097 { "K", 667, NULL },
1098 { "backslash", 278, NULL },
1099 { "L", 556, NULL },
1100 { "periodcentered", 278, NULL },
1101 { "M", 833, NULL },
1102 { "N", 722, NULL },
1103 { "O", 778, NULL },
1104 { "P", 667, NULL },
1105 { "Q", 778, NULL },
1106 { "R", 722, NULL },
1107 { "Aacute", 667, NULL },
1108 { "caron", 333, NULL },
1109 { "S", 667, NULL },
1110 { "T", 611, NULL },
1111 { "U", 722, NULL },
1112 { "agrave", 556, NULL },
1113 { "V", 667, NULL },
1114 { "W", 944, NULL },
1115 { "X", 667, NULL },
1116 { "question", 556, NULL },
1117 { "equal", 584, NULL },
1118 { "Y", 667, NULL },
1119 { "Z", 611, NULL },
1120 { "four", 556, NULL },
1121 { "a", 556, NULL },
1122 { "b", 556, NULL },
1123 { "c", 500, NULL },
1124 { "d", 556, NULL },
1125 { "e", 556, NULL },
1126 { "f", 278, NULL },
1127 { "g", 556, NULL },
1128 { "bullet", 350, NULL },
1129 { "h", 556, NULL },
1130 { "i", 222, NULL },
1131 { "Oslash", 778, NULL },
1132 { "dagger", 556, NULL },
1133 { "j", 222, NULL },
1134 { "k", 500, NULL },
1135 { "l", 222, NULL },
1136 { "m", 833, NULL },
1137 { "n", 556, NULL },
1138 { "o", 556, NULL },
1139 { "ordfeminine", 370, NULL },
1140 { "ring", 333, NULL },
1141 { "p", 556, NULL },
1142 { "q", 556, NULL },
1143 { "r", 333, NULL },
1144 { "twosuperior", 333, NULL },
1145 { "aacute", 556, NULL },
1146 { "s", 500, NULL },
1147 { "OE", 1000, NULL },
1148 { "t", 278, NULL },
1149 { "divide", 584, NULL },
1150 { "u", 556, NULL },
1151 { "v", 500, NULL },
1152 { "w", 722, NULL },
1153 { "x", 500, NULL },
1154 { "y", 500, NULL },
1155 { "z", 500, NULL },
1156 { "hungarumlaut", 333, NULL },
1157 { "quotedbl", 355, NULL },
1158 { "mu", 556, NULL },
1159 { "Scaron", 667, NULL },
1160 { "Lslash", 556, NULL },
1161 { "semicolon", 278, NULL },
1162 { "oslash", 611, NULL },
1163 { "parenright", 333, NULL },
1164 { "Ecircumflex", 667, NULL },
1165 { "trademark", 1000, NULL },
1166 { "daggerdbl", 556, NULL },
1167 { "macron", 333, NULL },
1168 { "Otilde", 778, NULL },
1169 { "ellipsis", 1000, NULL },
1170 { "scaron", 500, NULL },
1171 { "AE", 1000, NULL },
1172 { "Ucircumflex", 722, NULL },
1173 { "lslash", 222, NULL },
1174 { "quotedblleft", 333, NULL },
1175 { "guilsinglright", 333, NULL },
1176 { "hyphen", 333, NULL },
1177 { "quotesingle", 191, NULL },
1178 { "eight", 556, NULL },
1179 { "exclamdown", 333, NULL },
1180 { "endash", 556, NULL },
1181 { "oe", 944, NULL },
1182 { "ecircumflex", 556, NULL },
1183 { "copyright", 737, NULL },
1184 { "Adieresis", 667, NULL },
1185 { "Egrave", 667, NULL },
1186 { "slash", 278, NULL },
1187 { "Edieresis", 667, NULL },
1188 { "otilde", 556, NULL },
1189 { "Idieresis", 278, NULL },
1190 { "parenleft", 333, NULL },
1191 { "one", 556, NULL },
1192 { "ucircumflex", 556, NULL },
1193 { "Odieresis", 778, NULL },
1194 { "bracketleft", 278, NULL },
1195 { "Ugrave", 722, NULL },
1196 { "quoteright", 222, NULL },
1197 { "Udieresis", 722, NULL },
1198 { "perthousand", 1000, NULL },
1199 { "Ydieresis", 667, NULL },
1200 { "Eacute", 667, NULL },
1201 { "adieresis", 556, NULL },
1202 { "egrave", 556, NULL },
1203 { "edieresis", 556, NULL },
1204 { "idieresis", 278, NULL },
1205 { "Eth", 722, NULL },
1206 { "ae", 889, NULL },
1207 { "asterisk", 389, NULL },
1208 { "odieresis", 556, NULL },
1209 { "Uacute", 722, NULL },
1210 { "ugrave", 556, NULL },
1211 { "nine", 556, NULL },
1212 { "five", 556, NULL },
1213 { "udieresis", 556, NULL },
1214 { "Zcaron", 611, NULL },
1215 { "threequarters", 834, NULL },
1216 { "guillemotright", 556, NULL },
1217 { "ydieresis", 500, NULL },
1218 { "Ccedilla", 722, NULL },
1219 { "tilde", 333, NULL },
1220 { "at", 1015, NULL },
1221 { "eacute", 556, NULL },
1222 { "underscore", 556, NULL },
1223 { "multiply", 584, NULL },
1224 { "zero", 556, NULL },
1225 { "eth", 556, NULL },
1226 { "Ograve", 778, NULL },
1227 { "uacute", 556, NULL },
1228 { "braceleft", 334, NULL },
1229 { "Thorn", 667, NULL },
1230 { "zcaron", 500, NULL },
1231 { "ccedilla", 500, NULL },
1232 { "Ocircumflex", 778, NULL },
1233 { "Oacute", 778, NULL },
1234 { "ogonek", 333, NULL },
1235 { "ograve", 556, NULL },
1236 { "thorn", 556, NULL },
1237 { "degree", 400, NULL },
1238 { "registered", 737, NULL },
1239 { "Aring", 667, NULL },
1240 { "percent", 889, NULL },
1241 { "six", 556, NULL },
1242 { "paragraph", 537, NULL },
1243 { "two", 556, NULL },
1244 { "Igrave", 278, NULL },
1245 { "ocircumflex", 556, NULL },
1246 { "oacute", 556, NULL },
1247 { "asciicircum", 469, NULL },
1248 { "aring", 556, NULL },
1249 { "grave", 333, NULL },
1250 { "bracketright", 278, NULL },
1251 { "Iacute", 278, NULL },
1252 { "ampersand", 667, NULL },
1253 { "igrave", 278, NULL },
1254 { "plus", 584, NULL },
1255 { "quotesinglbase", 222, NULL },
1256 { "Yacute", 667, NULL },
1257 { "threesuperior", 333, NULL },
1258 { "acute", 333, NULL },
1259 { "section", 556, NULL },
1260 { "dieresis", 333, NULL },
1261 { "iacute", 278, NULL },
1262 { "quotedblbase", 333, NULL },
1263 { "florin", 556, NULL },
1264 { "yacute", 500, NULL },
1265 { "fi", 500, NULL },
1266 { "fl", 500, NULL },
1267 { "Acircumflex", 667, NULL },
1268 { "Icircumflex", 278, NULL },
1269 { "guillemotleft", 556, NULL },
1270 { "germandbls", 611, NULL },
1271 { "seven", 556, NULL },
1272 { "ordmasculine", 365, NULL },
1273 { "dotlessi", 278, NULL },
1274 { "sterling", 556, NULL },
1275 { "acircumflex", 556, NULL },
1276 { "icircumflex", 278, NULL },
1277 { "braceright", 334, NULL },
1278 { "quotedblright", 333, NULL },
1279 { "cent", 556, NULL },
1280 { "currency", 556, NULL },
1281 { "logicalnot", 584, NULL },
1282 { "Atilde", 667, NULL },
1283 { "breve", 333, NULL },
1284 { "bar", 260, NULL },
1285 { "fraction", 167, NULL },
1286 { "less", 584, NULL },
1287 { "guilsinglleft", 333, NULL },
1288 { "exclam", 278, NULL },
1289 { "period", 278, NULL },
1290 { "greater", 584, NULL },
1291 { "atilde", 556, NULL },
1292 { "brokenbar", 260, NULL },
1293 { "quoteleft", 222, NULL },
1294 { "onesuperior", 333, NULL }
1295};
1296
1297static BuiltinFontWidth helveticaBoldWidthsTab[] = {
1298 { "Ntilde", 722, NULL },
1299 { "comma", 278, NULL },
1300 { "cedilla", 333, NULL },
1301 { "plusminus", 584, NULL },
1302 { "circumflex", 333, NULL },
1303 { "dotaccent", 333, NULL },
1304 { "asciitilde", 584, NULL },
1305 { "colon", 333, NULL },
1306 { "onehalf", 834, NULL },
1307 { "dollar", 556, NULL },
1308 { "ntilde", 611, NULL },
1309 { "minus", 584, NULL },
1310 { "yen", 556, NULL },
1311 { "space", 278, NULL },
1312 { "questiondown", 611, NULL },
1313 { "emdash", 1000, NULL },
1314 { "Agrave", 722, NULL },
1315 { "three", 556, NULL },
1316 { "numbersign", 556, NULL },
1317 { "A", 722, NULL },
1318 { "B", 722, NULL },
1319 { "C", 722, NULL },
1320 { "D", 722, NULL },
1321 { "E", 667, NULL },
1322 { "onequarter", 834, NULL },
1323 { "F", 611, NULL },
1324 { "G", 778, NULL },
1325 { "H", 722, NULL },
1326 { "I", 278, NULL },
1327 { "J", 556, NULL },
1328 { "K", 722, NULL },
1329 { "backslash", 278, NULL },
1330 { "L", 611, NULL },
1331 { "periodcentered", 278, NULL },
1332 { "M", 833, NULL },
1333 { "N", 722, NULL },
1334 { "O", 778, NULL },
1335 { "P", 667, NULL },
1336 { "Q", 778, NULL },
1337 { "R", 722, NULL },
1338 { "Aacute", 722, NULL },
1339 { "caron", 333, NULL },
1340 { "S", 667, NULL },
1341 { "T", 611, NULL },
1342 { "U", 722, NULL },
1343 { "agrave", 556, NULL },
1344 { "V", 667, NULL },
1345 { "W", 944, NULL },
1346 { "X", 667, NULL },
1347 { "question", 611, NULL },
1348 { "equal", 584, NULL },
1349 { "Y", 667, NULL },
1350 { "Z", 611, NULL },
1351 { "four", 556, NULL },
1352 { "a", 556, NULL },
1353 { "b", 611, NULL },
1354 { "c", 556, NULL },
1355 { "d", 611, NULL },
1356 { "e", 556, NULL },
1357 { "f", 333, NULL },
1358 { "g", 611, NULL },
1359 { "bullet", 350, NULL },
1360 { "h", 611, NULL },
1361 { "i", 278, NULL },
1362 { "Oslash", 778, NULL },
1363 { "dagger", 556, NULL },
1364 { "j", 278, NULL },
1365 { "k", 556, NULL },
1366 { "l", 278, NULL },
1367 { "m", 889, NULL },
1368 { "n", 611, NULL },
1369 { "o", 611, NULL },
1370 { "ordfeminine", 370, NULL },
1371 { "ring", 333, NULL },
1372 { "p", 611, NULL },
1373 { "q", 611, NULL },
1374 { "r", 389, NULL },
1375 { "twosuperior", 333, NULL },
1376 { "aacute", 556, NULL },
1377 { "s", 556, NULL },
1378 { "OE", 1000, NULL },
1379 { "t", 333, NULL },
1380 { "divide", 584, NULL },
1381 { "u", 611, NULL },
1382 { "v", 556, NULL },
1383 { "w", 778, NULL },
1384 { "x", 556, NULL },
1385 { "y", 556, NULL },
1386 { "z", 500, NULL },
1387 { "hungarumlaut", 333, NULL },
1388 { "quotedbl", 474, NULL },
1389 { "mu", 611, NULL },
1390 { "Scaron", 667, NULL },
1391 { "Lslash", 611, NULL },
1392 { "semicolon", 333, NULL },
1393 { "oslash", 611, NULL },
1394 { "parenright", 333, NULL },
1395 { "Ecircumflex", 667, NULL },
1396 { "trademark", 1000, NULL },
1397 { "daggerdbl", 556, NULL },
1398 { "macron", 333, NULL },
1399 { "Otilde", 778, NULL },
1400 { "ellipsis", 1000, NULL },
1401 { "scaron", 556, NULL },
1402 { "AE", 1000, NULL },
1403 { "Ucircumflex", 722, NULL },
1404 { "lslash", 278, NULL },
1405 { "quotedblleft", 500, NULL },
1406 { "guilsinglright", 333, NULL },
1407 { "hyphen", 333, NULL },
1408 { "quotesingle", 238, NULL },
1409 { "eight", 556, NULL },
1410 { "exclamdown", 333, NULL },
1411 { "endash", 556, NULL },
1412 { "oe", 944, NULL },
1413 { "ecircumflex", 556, NULL },
1414 { "copyright", 737, NULL },
1415 { "Adieresis", 722, NULL },
1416 { "Egrave", 667, NULL },
1417 { "slash", 278, NULL },
1418 { "Edieresis", 667, NULL },
1419 { "otilde", 611, NULL },
1420 { "Idieresis", 278, NULL },
1421 { "parenleft", 333, NULL },
1422 { "one", 556, NULL },
1423 { "ucircumflex", 611, NULL },
1424 { "Odieresis", 778, NULL },
1425 { "bracketleft", 333, NULL },
1426 { "Ugrave", 722, NULL },
1427 { "quoteright", 278, NULL },
1428 { "Udieresis", 722, NULL },
1429 { "perthousand", 1000, NULL },
1430 { "Ydieresis", 667, NULL },
1431 { "Eacute", 667, NULL },
1432 { "adieresis", 556, NULL },
1433 { "egrave", 556, NULL },
1434 { "edieresis", 556, NULL },
1435 { "idieresis", 278, NULL },
1436 { "Eth", 722, NULL },
1437 { "ae", 889, NULL },
1438 { "asterisk", 389, NULL },
1439 { "odieresis", 611, NULL },
1440 { "Uacute", 722, NULL },
1441 { "ugrave", 611, NULL },
1442 { "nine", 556, NULL },
1443 { "five", 556, NULL },
1444 { "udieresis", 611, NULL },
1445 { "Zcaron", 611, NULL },
1446 { "threequarters", 834, NULL },
1447 { "guillemotright", 556, NULL },
1448 { "ydieresis", 556, NULL },
1449 { "Ccedilla", 722, NULL },
1450 { "tilde", 333, NULL },
1451 { "at", 975, NULL },
1452 { "eacute", 556, NULL },
1453 { "underscore", 556, NULL },
1454 { "multiply", 584, NULL },
1455 { "zero", 556, NULL },
1456 { "eth", 611, NULL },
1457 { "Ograve", 778, NULL },
1458 { "uacute", 611, NULL },
1459 { "braceleft", 389, NULL },
1460 { "Thorn", 667, NULL },
1461 { "zcaron", 500, NULL },
1462 { "ccedilla", 556, NULL },
1463 { "Ocircumflex", 778, NULL },
1464 { "Oacute", 778, NULL },
1465 { "ogonek", 333, NULL },
1466 { "ograve", 611, NULL },
1467 { "thorn", 611, NULL },
1468 { "degree", 400, NULL },
1469 { "registered", 737, NULL },
1470 { "Aring", 722, NULL },
1471 { "percent", 889, NULL },
1472 { "six", 556, NULL },
1473 { "paragraph", 556, NULL },
1474 { "two", 556, NULL },
1475 { "Igrave", 278, NULL },
1476 { "ocircumflex", 611, NULL },
1477 { "oacute", 611, NULL },
1478 { "asciicircum", 584, NULL },
1479 { "aring", 556, NULL },
1480 { "grave", 333, NULL },
1481 { "bracketright", 333, NULL },
1482 { "Iacute", 278, NULL },
1483 { "ampersand", 722, NULL },
1484 { "igrave", 278, NULL },
1485 { "plus", 584, NULL },
1486 { "quotesinglbase", 278, NULL },
1487 { "Yacute", 667, NULL },
1488 { "threesuperior", 333, NULL },
1489 { "acute", 333, NULL },
1490 { "section", 556, NULL },
1491 { "dieresis", 333, NULL },
1492 { "iacute", 278, NULL },
1493 { "quotedblbase", 500, NULL },
1494 { "florin", 556, NULL },
1495 { "yacute", 556, NULL },
1496 { "fi", 611, NULL },
1497 { "fl", 611, NULL },
1498 { "Acircumflex", 722, NULL },
1499 { "Icircumflex", 278, NULL },
1500 { "guillemotleft", 556, NULL },
1501 { "germandbls", 611, NULL },
1502 { "seven", 556, NULL },
1503 { "ordmasculine", 365, NULL },
1504 { "dotlessi", 278, NULL },
1505 { "sterling", 556, NULL },
1506 { "acircumflex", 556, NULL },
1507 { "icircumflex", 278, NULL },
1508 { "braceright", 389, NULL },
1509 { "quotedblright", 500, NULL },
1510 { "cent", 556, NULL },
1511 { "currency", 556, NULL },
1512 { "logicalnot", 584, NULL },
1513 { "Atilde", 722, NULL },
1514 { "breve", 333, NULL },
1515 { "bar", 280, NULL },
1516 { "fraction", 167, NULL },
1517 { "less", 584, NULL },
1518 { "guilsinglleft", 333, NULL },
1519 { "exclam", 333, NULL },
1520 { "period", 278, NULL },
1521 { "greater", 584, NULL },
1522 { "atilde", 556, NULL },
1523 { "brokenbar", 280, NULL },
1524 { "quoteleft", 278, NULL },
1525 { "onesuperior", 333, NULL }
1526};
1527
1528static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
1529 { "Ntilde", 722, NULL },
1530 { "comma", 278, NULL },
1531 { "cedilla", 333, NULL },
1532 { "plusminus", 584, NULL },
1533 { "circumflex", 333, NULL },
1534 { "dotaccent", 333, NULL },
1535 { "asciitilde", 584, NULL },
1536 { "colon", 333, NULL },
1537 { "onehalf", 834, NULL },
1538 { "dollar", 556, NULL },
1539 { "ntilde", 611, NULL },
1540 { "minus", 584, NULL },
1541 { "yen", 556, NULL },
1542 { "space", 278, NULL },
1543 { "questiondown", 611, NULL },
1544 { "emdash", 1000, NULL },
1545 { "Agrave", 722, NULL },
1546 { "three", 556, NULL },
1547 { "numbersign", 556, NULL },
1548 { "A", 722, NULL },
1549 { "B", 722, NULL },
1550 { "C", 722, NULL },
1551 { "D", 722, NULL },
1552 { "E", 667, NULL },
1553 { "onequarter", 834, NULL },
1554 { "F", 611, NULL },
1555 { "G", 778, NULL },
1556 { "H", 722, NULL },
1557 { "I", 278, NULL },
1558 { "J", 556, NULL },
1559 { "K", 722, NULL },
1560 { "backslash", 278, NULL },
1561 { "L", 611, NULL },
1562 { "periodcentered", 278, NULL },
1563 { "M", 833, NULL },
1564 { "N", 722, NULL },
1565 { "O", 778, NULL },
1566 { "P", 667, NULL },
1567 { "Q", 778, NULL },
1568 { "R", 722, NULL },
1569 { "Aacute", 722, NULL },
1570 { "caron", 333, NULL },
1571 { "S", 667, NULL },
1572 { "T", 611, NULL },
1573 { "U", 722, NULL },
1574 { "agrave", 556, NULL },
1575 { "V", 667, NULL },
1576 { "W", 944, NULL },
1577 { "X", 667, NULL },
1578 { "question", 611, NULL },
1579 { "equal", 584, NULL },
1580 { "Y", 667, NULL },
1581 { "Z", 611, NULL },
1582 { "four", 556, NULL },
1583 { "a", 556, NULL },
1584 { "b", 611, NULL },
1585 { "c", 556, NULL },
1586 { "d", 611, NULL },
1587 { "e", 556, NULL },
1588 { "f", 333, NULL },
1589 { "g", 611, NULL },
1590 { "bullet", 350, NULL },
1591 { "h", 611, NULL },
1592 { "i", 278, NULL },
1593 { "Oslash", 778, NULL },
1594 { "dagger", 556, NULL },
1595 { "j", 278, NULL },
1596 { "k", 556, NULL },
1597 { "l", 278, NULL },
1598 { "m", 889, NULL },
1599 { "n", 611, NULL },
1600 { "o", 611, NULL },
1601 { "ordfeminine", 370, NULL },
1602 { "ring", 333, NULL },
1603 { "p", 611, NULL },
1604 { "q", 611, NULL },
1605 { "r", 389, NULL },
1606 { "twosuperior", 333, NULL },
1607 { "aacute", 556, NULL },
1608 { "s", 556, NULL },
1609 { "OE", 1000, NULL },
1610 { "t", 333, NULL },
1611 { "divide", 584, NULL },
1612 { "u", 611, NULL },
1613 { "v", 556, NULL },
1614 { "w", 778, NULL },
1615 { "x", 556, NULL },
1616 { "y", 556, NULL },
1617 { "z", 500, NULL },
1618 { "hungarumlaut", 333, NULL },
1619 { "quotedbl", 474, NULL },
1620 { "mu", 611, NULL },
1621 { "Scaron", 667, NULL },
1622 { "Lslash", 611, NULL },
1623 { "semicolon", 333, NULL },
1624 { "oslash", 611, NULL },
1625 { "parenright", 333, NULL },
1626 { "Ecircumflex", 667, NULL },
1627 { "trademark", 1000, NULL },
1628 { "daggerdbl", 556, NULL },
1629 { "macron", 333, NULL },
1630 { "Otilde", 778, NULL },
1631 { "ellipsis", 1000, NULL },
1632 { "scaron", 556, NULL },
1633 { "AE", 1000, NULL },
1634 { "Ucircumflex", 722, NULL },
1635 { "lslash", 278, NULL },
1636 { "quotedblleft", 500, NULL },
1637 { "guilsinglright", 333, NULL },
1638 { "hyphen", 333, NULL },
1639 { "quotesingle", 238, NULL },
1640 { "eight", 556, NULL },
1641 { "exclamdown", 333, NULL },
1642 { "endash", 556, NULL },
1643 { "oe", 944, NULL },
1644 { "ecircumflex", 556, NULL },
1645 { "copyright", 737, NULL },
1646 { "Adieresis", 722, NULL },
1647 { "Egrave", 667, NULL },
1648 { "slash", 278, NULL },
1649 { "Edieresis", 667, NULL },
1650 { "otilde", 611, NULL },
1651 { "Idieresis", 278, NULL },
1652 { "parenleft", 333, NULL },
1653 { "one", 556, NULL },
1654 { "ucircumflex", 611, NULL },
1655 { "Odieresis", 778, NULL },
1656 { "bracketleft", 333, NULL },
1657 { "Ugrave", 722, NULL },
1658 { "quoteright", 278, NULL },
1659 { "Udieresis", 722, NULL },
1660 { "perthousand", 1000, NULL },
1661 { "Ydieresis", 667, NULL },
1662 { "Eacute", 667, NULL },
1663 { "adieresis", 556, NULL },
1664 { "egrave", 556, NULL },
1665 { "edieresis", 556, NULL },
1666 { "idieresis", 278, NULL },
1667 { "Eth", 722, NULL },
1668 { "ae", 889, NULL },
1669 { "asterisk", 389, NULL },
1670 { "odieresis", 611, NULL },
1671 { "Uacute", 722, NULL },
1672 { "ugrave", 611, NULL },
1673 { "nine", 556, NULL },
1674 { "five", 556, NULL },
1675 { "udieresis", 611, NULL },
1676 { "Zcaron", 611, NULL },
1677 { "threequarters", 834, NULL },
1678 { "guillemotright", 556, NULL },
1679 { "ydieresis", 556, NULL },
1680 { "Ccedilla", 722, NULL },
1681 { "tilde", 333, NULL },
1682 { "at", 975, NULL },
1683 { "eacute", 556, NULL },
1684 { "underscore", 556, NULL },
1685 { "multiply", 584, NULL },
1686 { "zero", 556, NULL },
1687 { "eth", 611, NULL },
1688 { "Ograve", 778, NULL },
1689 { "uacute", 611, NULL },
1690 { "braceleft", 389, NULL },
1691 { "Thorn", 667, NULL },
1692 { "zcaron", 500, NULL },
1693 { "ccedilla", 556, NULL },
1694 { "Ocircumflex", 778, NULL },
1695 { "Oacute", 778, NULL },
1696 { "ogonek", 333, NULL },
1697 { "ograve", 611, NULL },
1698 { "thorn", 611, NULL },
1699 { "degree", 400, NULL },
1700 { "registered", 737, NULL },
1701 { "Aring", 722, NULL },
1702 { "percent", 889, NULL },
1703 { "six", 556, NULL },
1704 { "paragraph", 556, NULL },
1705 { "two", 556, NULL },
1706 { "Igrave", 278, NULL },
1707 { "ocircumflex", 611, NULL },
1708 { "oacute", 611, NULL },
1709 { "asciicircum", 584, NULL },
1710 { "aring", 556, NULL },
1711 { "grave", 333, NULL },
1712 { "bracketright", 333, NULL },
1713 { "Iacute", 278, NULL },
1714 { "ampersand", 722, NULL },
1715 { "igrave", 278, NULL },
1716 { "plus", 584, NULL },
1717 { "quotesinglbase", 278, NULL },
1718 { "Yacute", 667, NULL },
1719 { "threesuperior", 333, NULL },
1720 { "acute", 333, NULL },
1721 { "section", 556, NULL },
1722 { "dieresis", 333, NULL },
1723 { "iacute", 278, NULL },
1724 { "quotedblbase", 500, NULL },
1725 { "florin", 556, NULL },
1726 { "yacute", 556, NULL },
1727 { "fi", 611, NULL },
1728 { "fl", 611, NULL },
1729 { "Acircumflex", 722, NULL },
1730 { "Icircumflex", 278, NULL },
1731 { "guillemotleft", 556, NULL },
1732 { "germandbls", 611, NULL },
1733 { "seven", 556, NULL },
1734 { "ordmasculine", 365, NULL },
1735 { "dotlessi", 278, NULL },
1736 { "sterling", 556, NULL },
1737 { "acircumflex", 556, NULL },
1738 { "icircumflex", 278, NULL },
1739 { "braceright", 389, NULL },
1740 { "quotedblright", 500, NULL },
1741 { "cent", 556, NULL },
1742 { "currency", 556, NULL },
1743 { "logicalnot", 584, NULL },
1744 { "Atilde", 722, NULL },
1745 { "breve", 333, NULL },
1746 { "bar", 280, NULL },
1747 { "fraction", 167, NULL },
1748 { "less", 584, NULL },
1749 { "guilsinglleft", 333, NULL },
1750 { "exclam", 333, NULL },
1751 { "period", 278, NULL },
1752 { "greater", 584, NULL },
1753 { "atilde", 556, NULL },
1754 { "brokenbar", 280, NULL },
1755 { "quoteleft", 278, NULL },
1756 { "onesuperior", 333, NULL }
1757};
1758
1759static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
1760 { "Ntilde", 722, NULL },
1761 { "comma", 278, NULL },
1762 { "cedilla", 333, NULL },
1763 { "plusminus", 584, NULL },
1764 { "circumflex", 333, NULL },
1765 { "dotaccent", 333, NULL },
1766 { "asciitilde", 584, NULL },
1767 { "colon", 278, NULL },
1768 { "onehalf", 834, NULL },
1769 { "dollar", 556, NULL },
1770 { "ntilde", 556, NULL },
1771 { "minus", 584, NULL },
1772 { "yen", 556, NULL },
1773 { "space", 278, NULL },
1774 { "questiondown", 611, NULL },
1775 { "emdash", 1000, NULL },
1776 { "Agrave", 667, NULL },
1777 { "three", 556, NULL },
1778 { "numbersign", 556, NULL },
1779 { "A", 667, NULL },
1780 { "B", 667, NULL },
1781 { "C", 722, NULL },
1782 { "D", 722, NULL },
1783 { "E", 667, NULL },
1784 { "onequarter", 834, NULL },
1785 { "F", 611, NULL },
1786 { "G", 778, NULL },
1787 { "H", 722, NULL },
1788 { "I", 278, NULL },
1789 { "J", 500, NULL },
1790 { "K", 667, NULL },
1791 { "backslash", 278, NULL },
1792 { "L", 556, NULL },
1793 { "periodcentered", 278, NULL },
1794 { "M", 833, NULL },
1795 { "N", 722, NULL },
1796 { "O", 778, NULL },
1797 { "P", 667, NULL },
1798 { "Q", 778, NULL },
1799 { "R", 722, NULL },
1800 { "Aacute", 667, NULL },
1801 { "caron", 333, NULL },
1802 { "S", 667, NULL },
1803 { "T", 611, NULL },
1804 { "U", 722, NULL },
1805 { "agrave", 556, NULL },
1806 { "V", 667, NULL },
1807 { "W", 944, NULL },
1808 { "X", 667, NULL },
1809 { "question", 556, NULL },
1810 { "equal", 584, NULL },
1811 { "Y", 667, NULL },
1812 { "Z", 611, NULL },
1813 { "four", 556, NULL },
1814 { "a", 556, NULL },
1815 { "b", 556, NULL },
1816 { "c", 500, NULL },
1817 { "d", 556, NULL },
1818 { "e", 556, NULL },
1819 { "f", 278, NULL },
1820 { "g", 556, NULL },
1821 { "bullet", 350, NULL },
1822 { "h", 556, NULL },
1823 { "i", 222, NULL },
1824 { "Oslash", 778, NULL },
1825 { "dagger", 556, NULL },
1826 { "j", 222, NULL },
1827 { "k", 500, NULL },
1828 { "l", 222, NULL },
1829 { "m", 833, NULL },
1830 { "n", 556, NULL },
1831 { "o", 556, NULL },
1832 { "ordfeminine", 370, NULL },
1833 { "ring", 333, NULL },
1834 { "p", 556, NULL },
1835 { "q", 556, NULL },
1836 { "r", 333, NULL },
1837 { "twosuperior", 333, NULL },
1838 { "aacute", 556, NULL },
1839 { "s", 500, NULL },
1840 { "OE", 1000, NULL },
1841 { "t", 278, NULL },
1842 { "divide", 584, NULL },
1843 { "u", 556, NULL },
1844 { "v", 500, NULL },
1845 { "w", 722, NULL },
1846 { "x", 500, NULL },
1847 { "y", 500, NULL },
1848 { "z", 500, NULL },
1849 { "hungarumlaut", 333, NULL },
1850 { "quotedbl", 355, NULL },
1851 { "mu", 556, NULL },
1852 { "Scaron", 667, NULL },
1853 { "Lslash", 556, NULL },
1854 { "semicolon", 278, NULL },
1855 { "oslash", 611, NULL },
1856 { "parenright", 333, NULL },
1857 { "Ecircumflex", 667, NULL },
1858 { "trademark", 1000, NULL },
1859 { "daggerdbl", 556, NULL },
1860 { "macron", 333, NULL },
1861 { "Otilde", 778, NULL },
1862 { "ellipsis", 1000, NULL },
1863 { "scaron", 500, NULL },
1864 { "AE", 1000, NULL },
1865 { "Ucircumflex", 722, NULL },
1866 { "lslash", 222, NULL },
1867 { "quotedblleft", 333, NULL },
1868 { "guilsinglright", 333, NULL },
1869 { "hyphen", 333, NULL },
1870 { "quotesingle", 191, NULL },
1871 { "eight", 556, NULL },
1872 { "exclamdown", 333, NULL },
1873 { "endash", 556, NULL },
1874 { "oe", 944, NULL },
1875 { "ecircumflex", 556, NULL },
1876 { "copyright", 737, NULL },
1877 { "Adieresis", 667, NULL },
1878 { "Egrave", 667, NULL },
1879 { "slash", 278, NULL },
1880 { "Edieresis", 667, NULL },
1881 { "otilde", 556, NULL },
1882 { "Idieresis", 278, NULL },
1883 { "parenleft", 333, NULL },
1884 { "one", 556, NULL },
1885 { "ucircumflex", 556, NULL },
1886 { "Odieresis", 778, NULL },
1887 { "bracketleft", 278, NULL },
1888 { "Ugrave", 722, NULL },
1889 { "quoteright", 222, NULL },
1890 { "Udieresis", 722, NULL },
1891 { "perthousand", 1000, NULL },
1892 { "Ydieresis", 667, NULL },
1893 { "Eacute", 667, NULL },
1894 { "adieresis", 556, NULL },
1895 { "egrave", 556, NULL },
1896 { "edieresis", 556, NULL },
1897 { "idieresis", 278, NULL },
1898 { "Eth", 722, NULL },
1899 { "ae", 889, NULL },
1900 { "asterisk", 389, NULL },
1901 { "odieresis", 556, NULL },
1902 { "Uacute", 722, NULL },
1903 { "ugrave", 556, NULL },
1904 { "nine", 556, NULL },
1905 { "five", 556, NULL },
1906 { "udieresis", 556, NULL },
1907 { "Zcaron", 611, NULL },
1908 { "threequarters", 834, NULL },
1909 { "guillemotright", 556, NULL },
1910 { "ydieresis", 500, NULL },
1911 { "Ccedilla", 722, NULL },
1912 { "tilde", 333, NULL },
1913 { "at", 1015, NULL },
1914 { "eacute", 556, NULL },
1915 { "underscore", 556, NULL },
1916 { "multiply", 584, NULL },
1917 { "zero", 556, NULL },
1918 { "eth", 556, NULL },
1919 { "Ograve", 778, NULL },
1920 { "uacute", 556, NULL },
1921 { "braceleft", 334, NULL },
1922 { "Thorn", 667, NULL },
1923 { "zcaron", 500, NULL },
1924 { "ccedilla", 500, NULL },
1925 { "Ocircumflex", 778, NULL },
1926 { "Oacute", 778, NULL },
1927 { "ogonek", 333, NULL },
1928 { "ograve", 556, NULL },
1929 { "thorn", 556, NULL },
1930 { "degree", 400, NULL },
1931 { "registered", 737, NULL },
1932 { "Aring", 667, NULL },
1933 { "percent", 889, NULL },
1934 { "six", 556, NULL },
1935 { "paragraph", 537, NULL },
1936 { "two", 556, NULL },
1937 { "Igrave", 278, NULL },
1938 { "ocircumflex", 556, NULL },
1939 { "oacute", 556, NULL },
1940 { "asciicircum", 469, NULL },
1941 { "aring", 556, NULL },
1942 { "grave", 333, NULL },
1943 { "bracketright", 278, NULL },
1944 { "Iacute", 278, NULL },
1945 { "ampersand", 667, NULL },
1946 { "igrave", 278, NULL },
1947 { "plus", 584, NULL },
1948 { "quotesinglbase", 222, NULL },
1949 { "Yacute", 667, NULL },
1950 { "threesuperior", 333, NULL },
1951 { "acute", 333, NULL },
1952 { "section", 556, NULL },
1953 { "dieresis", 333, NULL },
1954 { "iacute", 278, NULL },
1955 { "quotedblbase", 333, NULL },
1956 { "florin", 556, NULL },
1957 { "yacute", 500, NULL },
1958 { "fi", 500, NULL },
1959 { "fl", 500, NULL },
1960 { "Acircumflex", 667, NULL },
1961 { "Icircumflex", 278, NULL },
1962 { "guillemotleft", 556, NULL },
1963 { "germandbls", 611, NULL },
1964 { "seven", 556, NULL },
1965 { "ordmasculine", 365, NULL },
1966 { "dotlessi", 278, NULL },
1967 { "sterling", 556, NULL },
1968 { "acircumflex", 556, NULL },
1969 { "icircumflex", 278, NULL },
1970 { "braceright", 334, NULL },
1971 { "quotedblright", 333, NULL },
1972 { "cent", 556, NULL },
1973 { "currency", 556, NULL },
1974 { "logicalnot", 584, NULL },
1975 { "Atilde", 667, NULL },
1976 { "breve", 333, NULL },
1977 { "bar", 260, NULL },
1978 { "fraction", 167, NULL },
1979 { "less", 584, NULL },
1980 { "guilsinglleft", 333, NULL },
1981 { "exclam", 278, NULL },
1982 { "period", 278, NULL },
1983 { "greater", 584, NULL },
1984 { "atilde", 556, NULL },
1985 { "brokenbar", 260, NULL },
1986 { "quoteleft", 222, NULL },
1987 { "onesuperior", 333, NULL }
1988};
1989
1990static BuiltinFontWidth symbolWidthsTab[] = {
1991 { "bracketleftex", 384, NULL },
1992 { "alpha", 631, NULL },
1993 { "union", 768, NULL },
1994 { "infinity", 713, NULL },
1995 { "comma", 250, NULL },
1996 { "copyrightsans", 790, NULL },
1997 { "plusminus", 549, NULL },
1998 { "arrowup", 603, NULL },
1999 { "apple", 790, NULL },
2000 { "parenleftbt", 384, NULL },
2001 { "notelement", 713, NULL },
2002 { "colon", 278, NULL },
2003 { "beta", 549, NULL },
2004 { "braceleftbt", 494, NULL },
2005 { "Lambda", 686, NULL },
2006 { "Phi", 763, NULL },
2007 { "minus", 549, NULL },
2008 { "space", 250, NULL },
2009 { "Sigma", 592, NULL },
2010 { "approxequal", 549, NULL },
2011 { "minute", 247, NULL },
2012 { "circleplus", 768, NULL },
2013 { "Omicron", 722, NULL },
2014 { "three", 500, NULL },
2015 { "numbersign", 500, NULL },
2016 { "lambda", 549, NULL },
2017 { "phi", 521, NULL },
2018 { "aleph", 823, NULL },
2019 { "Tau", 611, NULL },
2020 { "spade", 753, NULL },
2021 { "logicaland", 603, NULL },
2022 { "sigma", 603, NULL },
2023 { "propersuperset", 713, NULL },
2024 { "omicron", 549, NULL },
2025 { "question", 444, NULL },
2026 { "equal", 549, NULL },
2027 { "Epsilon", 611, NULL },
2028 { "emptyset", 823, NULL },
2029 { "diamond", 753, NULL },
2030 { "four", 500, NULL },
2031 { "Mu", 889, NULL },
2032 { "parenlefttp", 384, NULL },
2033 { "club", 753, NULL },
2034 { "bullet", 460, NULL },
2035 { "Omega", 768, NULL },
2036 { "tau", 439, NULL },
2037 { "Upsilon", 690, NULL },
2038 { "bracelefttp", 494, NULL },
2039 { "heart", 753, NULL },
2040 { "divide", 549, NULL },
2041 { "epsilon", 439, NULL },
2042 { "logicalor", 603, NULL },
2043 { "parenleftex", 384, NULL },
2044 { "greaterequal", 549, NULL },
2045 { "mu", 576, NULL },
2046 { "Nu", 722, NULL },
2047 { "therefore", 863, NULL },
2048 { "notsubset", 713, NULL },
2049 { "omega", 686, NULL },
2050 { "semicolon", 278, NULL },
2051 { "element", 713, NULL },
2052 { "upsilon", 576, NULL },
2053 { "existential", 549, NULL },
2054 { "integralbt", 686, NULL },
2055 { "lessequal", 549, NULL },
2056 { "phi1", 603, NULL },
2057 { "lozenge", 494, NULL },
2058 { "trademarkserif", 890, NULL },
2059 { "parenright", 333, NULL },
2060 { "reflexsuperset", 713, NULL },
2061 { "sigma1", 439, NULL },
2062 { "nu", 521, NULL },
2063 { "Gamma", 603, NULL },
2064 { "angleright", 329, NULL },
2065 { "ellipsis", 1000, NULL },
2066 { "Rho", 556, NULL },
2067 { "parenrightbt", 384, NULL },
2068 { "radicalex", 500, NULL },
2069 { "eight", 500, NULL },
2070 { "angleleft", 329, NULL },
2071 { "arrowdbldown", 603, NULL },
2072 { "congruent", 549, NULL },
2073 { "Theta", 741, NULL },
2074 { "intersection", 768, NULL },
2075 { "Pi", 768, NULL },
2076 { "slash", 278, NULL },
2077 { "registerserif", 790, NULL },
2078 { "parenleft", 333, NULL },
2079 { "one", 500, NULL },
2080 { "gamma", 411, NULL },
2081 { "bracketleft", 333, NULL },
2082 { "rho", 549, NULL },
2083 { "circlemultiply", 768, NULL },
2084 { "Chi", 722, NULL },
2085 { "theta", 521, NULL },
2086 { "pi", 549, NULL },
2087 { "integraltp", 686, NULL },
2088 { "Eta", 722, NULL },
2089 { "product", 823, NULL },
2090 { "nine", 500, NULL },
2091 { "five", 500, NULL },
2092 { "propersubset", 713, NULL },
2093 { "bracketrightbt", 384, NULL },
2094 { "trademarksans", 786, NULL },
2095 { "dotmath", 250, NULL },
2096 { "integralex", 686, NULL },
2097 { "chi", 549, NULL },
2098 { "parenrighttp", 384, NULL },
2099 { "eta", 603, NULL },
2100 { "underscore", 500, NULL },
2101 { "multiply", 549, NULL },
2102 { "zero", 500, NULL },
2103 { "partialdiff", 494, NULL },
2104 { "angle", 768, NULL },
2105 { "arrowdblleft", 987, NULL },
2106 { "braceleft", 480, NULL },
2107 { "parenrightex", 384, NULL },
2108 { "Rfraktur", 795, NULL },
2109 { "Zeta", 611, NULL },
2110 { "braceex", 494, NULL },
2111 { "arrowdblup", 603, NULL },
2112 { "arrowdown", 603, NULL },
2113 { "Ifraktur", 686, NULL },
2114 { "degree", 400, NULL },
2115 { "Iota", 333, NULL },
2116 { "perpendicular", 658, NULL },
2117 { "radical", 549, NULL },
2118 { "asteriskmath", 500, NULL },
2119 { "percent", 833, NULL },
2120 { "zeta", 494, NULL },
2121 { "six", 500, NULL },
2122 { "two", 500, NULL },
2123 { "weierstrass", 987, NULL },
2124 { "summation", 713, NULL },
2125 { "bracketrighttp", 384, NULL },
2126 { "carriagereturn", 658, NULL },
2127 { "suchthat", 439, NULL },
2128 { "arrowvertex", 603, NULL },
2129 { "Delta", 612, NULL },
2130 { "iota", 329, NULL },
2131 { "arrowhorizex", 1000, NULL },
2132 { "bracketrightex", 384, NULL },
2133 { "bracketright", 333, NULL },
2134 { "ampersand", 778, NULL },
2135 { "plus", 549, NULL },
2136 { "proportional", 713, NULL },
2137 { "delta", 494, NULL },
2138 { "copyrightserif", 790, NULL },
2139 { "bracerightmid", 494, NULL },
2140 { "arrowleft", 987, NULL },
2141 { "second", 411, NULL },
2142 { "arrowdblboth", 1042, NULL },
2143 { "florin", 500, NULL },
2144 { "Psi", 795, NULL },
2145 { "bracerightbt", 494, NULL },
2146 { "bracketleftbt", 384, NULL },
2147 { "seven", 500, NULL },
2148 { "braceleftmid", 494, NULL },
2149 { "notequal", 549, NULL },
2150 { "psi", 686, NULL },
2151 { "equivalence", 549, NULL },
2152 { "universal", 713, NULL },
2153 { "arrowdblright", 987, NULL },
2154 { "braceright", 480, NULL },
2155 { "reflexsubset", 713, NULL },
2156 { "Xi", 645, NULL },
2157 { "theta1", 631, NULL },
2158 { "logicalnot", 713, NULL },
2159 { "Kappa", 722, NULL },
2160 { "similar", 549, NULL },
2161 { "bar", 200, NULL },
2162 { "fraction", 167, NULL },
2163 { "less", 549, NULL },
2164 { "registersans", 790, NULL },
2165 { "omega1", 713, NULL },
2166 { "exclam", 333, NULL },
2167 { "Upsilon1", 620, NULL },
2168 { "bracerighttp", 494, NULL },
2169 { "xi", 493, NULL },
2170 { "period", 250, NULL },
2171 { "Alpha", 722, NULL },
2172 { "arrowright", 987, NULL },
2173 { "greater", 549, NULL },
2174 { "bracketlefttp", 384, NULL },
2175 { "kappa", 549, NULL },
2176 { "gradient", 713, NULL },
2177 { "integral", 274, NULL },
2178 { "arrowboth", 1042, NULL },
2179 { "Beta", 667, NULL }
2180};
2181
2182static BuiltinFontWidth timesBoldWidthsTab[] = {
2183 { "Ntilde", 722, NULL },
2184 { "comma", 250, NULL },
2185 { "cedilla", 333, NULL },
2186 { "plusminus", 570, NULL },
2187 { "circumflex", 333, NULL },
2188 { "dotaccent", 333, NULL },
2189 { "asciitilde", 520, NULL },
2190 { "colon", 333, NULL },
2191 { "onehalf", 750, NULL },
2192 { "dollar", 500, NULL },
2193 { "ntilde", 556, NULL },
2194 { "minus", 570, NULL },
2195 { "yen", 500, NULL },
2196 { "space", 250, NULL },
2197 { "questiondown", 500, NULL },
2198 { "emdash", 1000, NULL },
2199 { "Agrave", 722, NULL },
2200 { "three", 500, NULL },
2201 { "numbersign", 500, NULL },
2202 { "A", 722, NULL },
2203 { "B", 667, NULL },
2204 { "C", 722, NULL },
2205 { "D", 722, NULL },
2206 { "E", 667, NULL },
2207 { "onequarter", 750, NULL },
2208 { "F", 611, NULL },
2209 { "G", 778, NULL },
2210 { "H", 778, NULL },
2211 { "I", 389, NULL },
2212 { "J", 500, NULL },
2213 { "K", 778, NULL },
2214 { "backslash", 278, NULL },
2215 { "L", 667, NULL },
2216 { "periodcentered", 250, NULL },
2217 { "M", 944, NULL },
2218 { "N", 722, NULL },
2219 { "O", 778, NULL },
2220 { "P", 611, NULL },
2221 { "Q", 778, NULL },
2222 { "R", 722, NULL },
2223 { "Aacute", 722, NULL },
2224 { "caron", 333, NULL },
2225 { "S", 556, NULL },
2226 { "T", 667, NULL },
2227 { "U", 722, NULL },
2228 { "agrave", 500, NULL },
2229 { "V", 722, NULL },
2230 { "W", 1000, NULL },
2231 { "X", 722, NULL },
2232 { "question", 500, NULL },
2233 { "equal", 570, NULL },
2234 { "Y", 722, NULL },
2235 { "Z", 667, NULL },
2236 { "four", 500, NULL },
2237 { "a", 500, NULL },
2238 { "b", 556, NULL },
2239 { "c", 444, NULL },
2240 { "d", 556, NULL },
2241 { "e", 444, NULL },
2242 { "f", 333, NULL },
2243 { "g", 500, NULL },
2244 { "bullet", 350, NULL },
2245 { "h", 556, NULL },
2246 { "i", 278, NULL },
2247 { "Oslash", 778, NULL },
2248 { "dagger", 500, NULL },
2249 { "j", 333, NULL },
2250 { "k", 556, NULL },
2251 { "l", 278, NULL },
2252 { "m", 833, NULL },
2253 { "n", 556, NULL },
2254 { "o", 500, NULL },
2255 { "ordfeminine", 300, NULL },
2256 { "ring", 333, NULL },
2257 { "p", 556, NULL },
2258 { "q", 556, NULL },
2259 { "r", 444, NULL },
2260 { "twosuperior", 300, NULL },
2261 { "aacute", 500, NULL },
2262 { "s", 389, NULL },
2263 { "OE", 1000, NULL },
2264 { "t", 333, NULL },
2265 { "divide", 570, NULL },
2266 { "u", 556, NULL },
2267 { "v", 500, NULL },
2268 { "w", 722, NULL },
2269 { "x", 500, NULL },
2270 { "y", 500, NULL },
2271 { "z", 444, NULL },
2272 { "hungarumlaut", 333, NULL },
2273 { "quotedbl", 555, NULL },
2274 { "mu", 556, NULL },
2275 { "Scaron", 556, NULL },
2276 { "Lslash", 667, NULL },
2277 { "semicolon", 333, NULL },
2278 { "oslash", 500, NULL },
2279 { "parenright", 333, NULL },
2280 { "Ecircumflex", 667, NULL },
2281 { "trademark", 1000, NULL },
2282 { "daggerdbl", 500, NULL },
2283 { "macron", 333, NULL },
2284 { "Otilde", 778, NULL },
2285 { "ellipsis", 1000, NULL },
2286 { "scaron", 389, NULL },
2287 { "AE", 1000, NULL },
2288 { "Ucircumflex", 722, NULL },
2289 { "lslash", 278, NULL },
2290 { "quotedblleft", 500, NULL },
2291 { "guilsinglright", 333, NULL },
2292 { "hyphen", 333, NULL },
2293 { "quotesingle", 278, NULL },
2294 { "eight", 500, NULL },
2295 { "exclamdown", 333, NULL },
2296 { "endash", 500, NULL },
2297 { "oe", 722, NULL },
2298 { "ecircumflex", 444, NULL },
2299 { "copyright", 747, NULL },
2300 { "Adieresis", 722, NULL },
2301 { "Egrave", 667, NULL },
2302 { "slash", 278, NULL },
2303 { "Edieresis", 667, NULL },
2304 { "otilde", 500, NULL },
2305 { "Idieresis", 389, NULL },
2306 { "parenleft", 333, NULL },
2307 { "one", 500, NULL },
2308 { "ucircumflex", 556, NULL },
2309 { "Odieresis", 778, NULL },
2310 { "bracketleft", 333, NULL },
2311 { "Ugrave", 722, NULL },
2312 { "quoteright", 333, NULL },
2313 { "Udieresis", 722, NULL },
2314 { "perthousand", 1000, NULL },
2315 { "Ydieresis", 722, NULL },
2316 { "Eacute", 667, NULL },
2317 { "adieresis", 500, NULL },
2318 { "egrave", 444, NULL },
2319 { "edieresis", 444, NULL },
2320 { "idieresis", 278, NULL },
2321 { "Eth", 722, NULL },
2322 { "ae", 722, NULL },
2323 { "asterisk", 500, NULL },
2324 { "odieresis", 500, NULL },
2325 { "Uacute", 722, NULL },
2326 { "ugrave", 556, NULL },
2327 { "nine", 500, NULL },
2328 { "five", 500, NULL },
2329 { "udieresis", 556, NULL },
2330 { "Zcaron", 667, NULL },
2331 { "threequarters", 750, NULL },
2332 { "guillemotright", 500, NULL },
2333 { "ydieresis", 500, NULL },
2334 { "Ccedilla", 722, NULL },
2335 { "tilde", 333, NULL },
2336 { "at", 930, NULL },
2337 { "eacute", 444, NULL },
2338 { "underscore", 500, NULL },
2339 { "multiply", 570, NULL },
2340 { "zero", 500, NULL },
2341 { "eth", 500, NULL },
2342 { "Ograve", 778, NULL },
2343 { "uacute", 556, NULL },
2344 { "braceleft", 394, NULL },
2345 { "Thorn", 611, NULL },
2346 { "zcaron", 444, NULL },
2347 { "ccedilla", 444, NULL },
2348 { "Ocircumflex", 778, NULL },
2349 { "Oacute", 778, NULL },
2350 { "ogonek", 333, NULL },
2351 { "ograve", 500, NULL },
2352 { "thorn", 556, NULL },
2353 { "degree", 400, NULL },
2354 { "registered", 747, NULL },
2355 { "Aring", 722, NULL },
2356 { "percent", 1000, NULL },
2357 { "six", 500, NULL },
2358 { "paragraph", 540, NULL },
2359 { "two", 500, NULL },
2360 { "Igrave", 389, NULL },
2361 { "ocircumflex", 500, NULL },
2362 { "oacute", 500, NULL },
2363 { "asciicircum", 581, NULL },
2364 { "aring", 500, NULL },
2365 { "grave", 333, NULL },
2366 { "bracketright", 333, NULL },
2367 { "Iacute", 389, NULL },
2368 { "ampersand", 833, NULL },
2369 { "igrave", 278, NULL },
2370 { "plus", 570, NULL },
2371 { "quotesinglbase", 333, NULL },
2372 { "Yacute", 722, NULL },
2373 { "threesuperior", 300, NULL },
2374 { "acute", 333, NULL },
2375 { "section", 500, NULL },
2376 { "dieresis", 333, NULL },
2377 { "iacute", 278, NULL },
2378 { "quotedblbase", 500, NULL },
2379 { "florin", 500, NULL },
2380 { "yacute", 500, NULL },
2381 { "fi", 556, NULL },
2382 { "fl", 556, NULL },
2383 { "Acircumflex", 722, NULL },
2384 { "Icircumflex", 389, NULL },
2385 { "guillemotleft", 500, NULL },
2386 { "germandbls", 556, NULL },
2387 { "seven", 500, NULL },
2388 { "ordmasculine", 330, NULL },
2389 { "dotlessi", 278, NULL },
2390 { "sterling", 500, NULL },
2391 { "acircumflex", 500, NULL },
2392 { "icircumflex", 278, NULL },
2393 { "braceright", 394, NULL },
2394 { "quotedblright", 500, NULL },
2395 { "cent", 500, NULL },
2396 { "currency", 500, NULL },
2397 { "logicalnot", 570, NULL },
2398 { "Atilde", 722, NULL },
2399 { "breve", 333, NULL },
2400 { "bar", 220, NULL },
2401 { "fraction", 167, NULL },
2402 { "less", 570, NULL },
2403 { "guilsinglleft", 333, NULL },
2404 { "exclam", 333, NULL },
2405 { "period", 250, NULL },
2406 { "greater", 570, NULL },
2407 { "atilde", 500, NULL },
2408 { "brokenbar", 220, NULL },
2409 { "quoteleft", 333, NULL },
2410 { "onesuperior", 300, NULL }
2411};
2412
2413static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
2414 { "Ntilde", 722, NULL },
2415 { "comma", 250, NULL },
2416 { "cedilla", 333, NULL },
2417 { "plusminus", 570, NULL },
2418 { "circumflex", 333, NULL },
2419 { "dotaccent", 333, NULL },
2420 { "asciitilde", 570, NULL },
2421 { "colon", 333, NULL },
2422 { "onehalf", 750, NULL },
2423 { "dollar", 500, NULL },
2424 { "ntilde", 556, NULL },
2425 { "minus", 606, NULL },
2426 { "yen", 500, NULL },
2427 { "space", 250, NULL },
2428 { "questiondown", 500, NULL },
2429 { "emdash", 1000, NULL },
2430 { "Agrave", 667, NULL },
2431 { "three", 500, NULL },
2432 { "numbersign", 500, NULL },
2433 { "A", 667, NULL },
2434 { "B", 667, NULL },
2435 { "C", 667, NULL },
2436 { "D", 722, NULL },
2437 { "E", 667, NULL },
2438 { "onequarter", 750, NULL },
2439 { "F", 667, NULL },
2440 { "G", 722, NULL },
2441 { "H", 778, NULL },
2442 { "I", 389, NULL },
2443 { "J", 500, NULL },
2444 { "K", 667, NULL },
2445 { "backslash", 278, NULL },
2446 { "L", 611, NULL },
2447 { "periodcentered", 250, NULL },
2448 { "M", 889, NULL },
2449 { "N", 722, NULL },
2450 { "O", 722, NULL },
2451 { "P", 611, NULL },
2452 { "Q", 722, NULL },
2453 { "R", 667, NULL },
2454 { "Aacute", 667, NULL },
2455 { "caron", 333, NULL },
2456 { "S", 556, NULL },
2457 { "T", 611, NULL },
2458 { "U", 722, NULL },
2459 { "agrave", 500, NULL },
2460 { "V", 667, NULL },
2461 { "W", 889, NULL },
2462 { "X", 667, NULL },
2463 { "question", 500, NULL },
2464 { "equal", 570, NULL },
2465 { "Y", 611, NULL },
2466 { "Z", 611, NULL },
2467 { "four", 500, NULL },
2468 { "a", 500, NULL },
2469 { "b", 500, NULL },
2470 { "c", 444, NULL },
2471 { "d", 500, NULL },
2472 { "e", 444, NULL },
2473 { "f", 333, NULL },
2474 { "g", 500, NULL },
2475 { "bullet", 350, NULL },
2476 { "h", 556, NULL },
2477 { "i", 278, NULL },
2478 { "Oslash", 722, NULL },
2479 { "dagger", 500, NULL },
2480 { "j", 278, NULL },
2481 { "k", 500, NULL },
2482 { "l", 278, NULL },
2483 { "m", 778, NULL },
2484 { "n", 556, NULL },
2485 { "o", 500, NULL },
2486 { "ordfeminine", 266, NULL },
2487 { "ring", 333, NULL },
2488 { "p", 500, NULL },
2489 { "q", 500, NULL },
2490 { "r", 389, NULL },
2491 { "twosuperior", 300, NULL },
2492 { "aacute", 500, NULL },
2493 { "s", 389, NULL },
2494 { "OE", 944, NULL },
2495 { "t", 278, NULL },
2496 { "divide", 570, NULL },
2497 { "u", 556, NULL },
2498 { "v", 444, NULL },
2499 { "w", 667, NULL },
2500 { "x", 500, NULL },
2501 { "y", 444, NULL },
2502 { "z", 389, NULL },
2503 { "hungarumlaut", 333, NULL },
2504 { "quotedbl", 555, NULL },
2505 { "mu", 576, NULL },
2506 { "Scaron", 556, NULL },
2507 { "Lslash", 611, NULL },
2508 { "semicolon", 333, NULL },
2509 { "oslash", 500, NULL },
2510 { "parenright", 333, NULL },
2511 { "Ecircumflex", 667, NULL },
2512 { "trademark", 1000, NULL },
2513 { "daggerdbl", 500, NULL },
2514 { "macron", 333, NULL },
2515 { "Otilde", 722, NULL },
2516 { "ellipsis", 1000, NULL },
2517 { "scaron", 389, NULL },
2518 { "AE", 944, NULL },
2519 { "Ucircumflex", 722, NULL },
2520 { "lslash", 278, NULL },
2521 { "quotedblleft", 500, NULL },
2522 { "guilsinglright", 333, NULL },
2523 { "hyphen", 333, NULL },
2524 { "quotesingle", 278, NULL },
2525 { "eight", 500, NULL },
2526 { "exclamdown", 389, NULL },
2527 { "endash", 500, NULL },
2528 { "oe", 722, NULL },
2529 { "ecircumflex", 444, NULL },
2530 { "copyright", 747, NULL },
2531 { "Adieresis", 667, NULL },
2532 { "Egrave", 667, NULL },
2533 { "slash", 278, NULL },
2534 { "Edieresis", 667, NULL },
2535 { "otilde", 500, NULL },
2536 { "Idieresis", 389, NULL },
2537 { "parenleft", 333, NULL },
2538 { "one", 500, NULL },
2539 { "ucircumflex", 556, NULL },
2540 { "Odieresis", 722, NULL },
2541 { "bracketleft", 333, NULL },
2542 { "Ugrave", 722, NULL },
2543 { "quoteright", 333, NULL },
2544 { "Udieresis", 722, NULL },
2545 { "perthousand", 1000, NULL },
2546 { "Ydieresis", 611, NULL },
2547 { "Eacute", 667, NULL },
2548 { "adieresis", 500, NULL },
2549 { "egrave", 444, NULL },
2550 { "edieresis", 444, NULL },
2551 { "idieresis", 278, NULL },
2552 { "Eth", 722, NULL },
2553 { "ae", 722, NULL },
2554 { "asterisk", 500, NULL },
2555 { "odieresis", 500, NULL },
2556 { "Uacute", 722, NULL },
2557 { "ugrave", 556, NULL },
2558 { "nine", 500, NULL },
2559 { "five", 500, NULL },
2560 { "udieresis", 556, NULL },
2561 { "Zcaron", 611, NULL },
2562 { "threequarters", 750, NULL },
2563 { "guillemotright", 500, NULL },
2564 { "ydieresis", 444, NULL },
2565 { "Ccedilla", 667, NULL },
2566 { "tilde", 333, NULL },
2567 { "at", 832, NULL },
2568 { "eacute", 444, NULL },
2569 { "underscore", 500, NULL },
2570 { "multiply", 570, NULL },
2571 { "zero", 500, NULL },
2572 { "eth", 500, NULL },
2573 { "Ograve", 722, NULL },
2574 { "uacute", 556, NULL },
2575 { "braceleft", 348, NULL },
2576 { "Thorn", 611, NULL },
2577 { "zcaron", 389, NULL },
2578 { "ccedilla", 444, NULL },
2579 { "Ocircumflex", 722, NULL },
2580 { "Oacute", 722, NULL },
2581 { "ogonek", 333, NULL },
2582 { "ograve", 500, NULL },
2583 { "thorn", 500, NULL },
2584 { "degree", 400, NULL },
2585 { "registered", 747, NULL },
2586 { "Aring", 667, NULL },
2587 { "percent", 833, NULL },
2588 { "six", 500, NULL },
2589 { "paragraph", 500, NULL },
2590 { "two", 500, NULL },
2591 { "Igrave", 389, NULL },
2592 { "ocircumflex", 500, NULL },
2593 { "oacute", 500, NULL },
2594 { "asciicircum", 570, NULL },
2595 { "aring", 500, NULL },
2596 { "grave", 333, NULL },
2597 { "bracketright", 333, NULL },
2598 { "Iacute", 389, NULL },
2599 { "ampersand", 778, NULL },
2600 { "igrave", 278, NULL },
2601 { "plus", 570, NULL },
2602 { "quotesinglbase", 333, NULL },
2603 { "Yacute", 611, NULL },
2604 { "threesuperior", 300, NULL },
2605 { "acute", 333, NULL },
2606 { "section", 500, NULL },
2607 { "dieresis", 333, NULL },
2608 { "iacute", 278, NULL },
2609 { "quotedblbase", 500, NULL },
2610 { "florin", 500, NULL },
2611 { "yacute", 444, NULL },
2612 { "fi", 556, NULL },
2613 { "fl", 556, NULL },
2614 { "Acircumflex", 667, NULL },
2615 { "Icircumflex", 389, NULL },
2616 { "guillemotleft", 500, NULL },
2617 { "germandbls", 500, NULL },
2618 { "seven", 500, NULL },
2619 { "ordmasculine", 300, NULL },
2620 { "dotlessi", 278, NULL },
2621 { "sterling", 500, NULL },
2622 { "acircumflex", 500, NULL },
2623 { "icircumflex", 278, NULL },
2624 { "braceright", 348, NULL },
2625 { "quotedblright", 500, NULL },
2626 { "cent", 500, NULL },
2627 { "currency", 500, NULL },
2628 { "logicalnot", 606, NULL },
2629 { "Atilde", 667, NULL },
2630 { "breve", 333, NULL },
2631 { "bar", 220, NULL },
2632 { "fraction", 167, NULL },
2633 { "less", 570, NULL },
2634 { "guilsinglleft", 333, NULL },
2635 { "exclam", 389, NULL },
2636 { "period", 250, NULL },
2637 { "greater", 570, NULL },
2638 { "atilde", 500, NULL },
2639 { "brokenbar", 220, NULL },
2640 { "quoteleft", 333, NULL },
2641 { "onesuperior", 300, NULL }
2642};
2643
2644static BuiltinFontWidth timesItalicWidthsTab[] = {
2645 { "Ntilde", 667, NULL },
2646 { "comma", 250, NULL },
2647 { "cedilla", 333, NULL },
2648 { "plusminus", 675, NULL },
2649 { "circumflex", 333, NULL },
2650 { "dotaccent", 333, NULL },
2651 { "asciitilde", 541, NULL },
2652 { "colon", 333, NULL },
2653 { "onehalf", 750, NULL },
2654 { "dollar", 500, NULL },
2655 { "ntilde", 500, NULL },
2656 { "minus", 675, NULL },
2657 { "yen", 500, NULL },
2658 { "space", 250, NULL },
2659 { "questiondown", 500, NULL },
2660 { "emdash", 889, NULL },
2661 { "Agrave", 611, NULL },
2662 { "three", 500, NULL },
2663 { "numbersign", 500, NULL },
2664 { "A", 611, NULL },
2665 { "B", 611, NULL },
2666 { "C", 667, NULL },
2667 { "D", 722, NULL },
2668 { "E", 611, NULL },
2669 { "onequarter", 750, NULL },
2670 { "F", 611, NULL },
2671 { "G", 722, NULL },
2672 { "H", 722, NULL },
2673 { "I", 333, NULL },
2674 { "J", 444, NULL },
2675 { "K", 667, NULL },
2676 { "backslash", 278, NULL },
2677 { "L", 556, NULL },
2678 { "periodcentered", 250, NULL },
2679 { "M", 833, NULL },
2680 { "N", 667, NULL },
2681 { "O", 722, NULL },
2682 { "P", 611, NULL },
2683 { "Q", 722, NULL },
2684 { "R", 611, NULL },
2685 { "Aacute", 611, NULL },
2686 { "caron", 333, NULL },
2687 { "S", 500, NULL },
2688 { "T", 556, NULL },
2689 { "U", 722, NULL },
2690 { "agrave", 500, NULL },
2691 { "V", 611, NULL },
2692 { "W", 833, NULL },
2693 { "X", 611, NULL },
2694 { "question", 500, NULL },
2695 { "equal", 675, NULL },
2696 { "Y", 556, NULL },
2697 { "Z", 556, NULL },
2698 { "four", 500, NULL },
2699 { "a", 500, NULL },
2700 { "b", 500, NULL },
2701 { "c", 444, NULL },
2702 { "d", 500, NULL },
2703 { "e", 444, NULL },
2704 { "f", 278, NULL },
2705 { "g", 500, NULL },
2706 { "bullet", 350, NULL },
2707 { "h", 500, NULL },
2708 { "i", 278, NULL },
2709 { "Oslash", 722, NULL },
2710 { "dagger", 500, NULL },
2711 { "j", 278, NULL },
2712 { "k", 444, NULL },
2713 { "l", 278, NULL },
2714 { "m", 722, NULL },
2715 { "n", 500, NULL },
2716 { "o", 500, NULL },
2717 { "ordfeminine", 276, NULL },
2718 { "ring", 333, NULL },
2719 { "p", 500, NULL },
2720 { "q", 500, NULL },
2721 { "r", 389, NULL },
2722 { "twosuperior", 300, NULL },
2723 { "aacute", 500, NULL },
2724 { "s", 389, NULL },
2725 { "OE", 944, NULL },
2726 { "t", 278, NULL },
2727 { "divide", 675, NULL },
2728 { "u", 500, NULL },
2729 { "v", 444, NULL },
2730 { "w", 667, NULL },
2731 { "x", 444, NULL },
2732 { "y", 444, NULL },
2733 { "z", 389, NULL },
2734 { "hungarumlaut", 333, NULL },
2735 { "quotedbl", 420, NULL },
2736 { "mu", 500, NULL },
2737 { "Scaron", 500, NULL },
2738 { "Lslash", 556, NULL },
2739 { "semicolon", 333, NULL },
2740 { "oslash", 500, NULL },
2741 { "parenright", 333, NULL },
2742 { "Ecircumflex", 611, NULL },
2743 { "trademark", 980, NULL },
2744 { "daggerdbl", 500, NULL },
2745 { "macron", 333, NULL },
2746 { "Otilde", 722, NULL },
2747 { "ellipsis", 889, NULL },
2748 { "scaron", 389, NULL },
2749 { "AE", 889, NULL },
2750 { "Ucircumflex", 722, NULL },
2751 { "lslash", 278, NULL },
2752 { "quotedblleft", 556, NULL },
2753 { "guilsinglright", 333, NULL },
2754 { "hyphen", 333, NULL },
2755 { "quotesingle", 214, NULL },
2756 { "eight", 500, NULL },
2757 { "exclamdown", 389, NULL },
2758 { "endash", 500, NULL },
2759 { "oe", 667, NULL },
2760 { "ecircumflex", 444, NULL },
2761 { "copyright", 760, NULL },
2762 { "Adieresis", 611, NULL },
2763 { "Egrave", 611, NULL },
2764 { "slash", 278, NULL },
2765 { "Edieresis", 611, NULL },
2766 { "otilde", 500, NULL },
2767 { "Idieresis", 333, NULL },
2768 { "parenleft", 333, NULL },
2769 { "one", 500, NULL },
2770 { "ucircumflex", 500, NULL },
2771 { "Odieresis", 722, NULL },
2772 { "bracketleft", 389, NULL },
2773 { "Ugrave", 722, NULL },
2774 { "quoteright", 333, NULL },
2775 { "Udieresis", 722, NULL },
2776 { "perthousand", 1000, NULL },
2777 { "Ydieresis", 556, NULL },
2778 { "Eacute", 611, NULL },
2779 { "adieresis", 500, NULL },
2780 { "egrave", 444, NULL },
2781 { "edieresis", 444, NULL },
2782 { "idieresis", 278, NULL },
2783 { "Eth", 722, NULL },
2784 { "ae", 667, NULL },
2785 { "asterisk", 500, NULL },
2786 { "odieresis", 500, NULL },
2787 { "Uacute", 722, NULL },
2788 { "ugrave", 500, NULL },
2789 { "nine", 500, NULL },
2790 { "five", 500, NULL },
2791 { "udieresis", 500, NULL },
2792 { "Zcaron", 556, NULL },
2793 { "threequarters", 750, NULL },
2794 { "guillemotright", 500, NULL },
2795 { "ydieresis", 444, NULL },
2796 { "Ccedilla", 667, NULL },
2797 { "tilde", 333, NULL },
2798 { "at", 920, NULL },
2799 { "eacute", 444, NULL },
2800 { "underscore", 500, NULL },
2801 { "multiply", 675, NULL },
2802 { "zero", 500, NULL },
2803 { "eth", 500, NULL },
2804 { "Ograve", 722, NULL },
2805 { "uacute", 500, NULL },
2806 { "braceleft", 400, NULL },
2807 { "Thorn", 611, NULL },
2808 { "zcaron", 389, NULL },
2809 { "ccedilla", 444, NULL },
2810 { "Ocircumflex", 722, NULL },
2811 { "Oacute", 722, NULL },
2812 { "ogonek", 333, NULL },
2813 { "ograve", 500, NULL },
2814 { "thorn", 500, NULL },
2815 { "degree", 400, NULL },
2816 { "registered", 760, NULL },
2817 { "Aring", 611, NULL },
2818 { "percent", 833, NULL },
2819 { "six", 500, NULL },
2820 { "paragraph", 523, NULL },
2821 { "two", 500, NULL },
2822 { "Igrave", 333, NULL },
2823 { "ocircumflex", 500, NULL },
2824 { "oacute", 500, NULL },
2825 { "asciicircum", 422, NULL },
2826 { "aring", 500, NULL },
2827 { "grave", 333, NULL },
2828 { "bracketright", 389, NULL },
2829 { "Iacute", 333, NULL },
2830 { "ampersand", 778, NULL },
2831 { "igrave", 278, NULL },
2832 { "plus", 675, NULL },
2833 { "quotesinglbase", 333, NULL },
2834 { "Yacute", 556, NULL },
2835 { "threesuperior", 300, NULL },
2836 { "acute", 333, NULL },
2837 { "section", 500, NULL },
2838 { "dieresis", 333, NULL },
2839 { "iacute", 278, NULL },
2840 { "quotedblbase", 556, NULL },
2841 { "florin", 500, NULL },
2842 { "yacute", 444, NULL },
2843 { "fi", 500, NULL },
2844 { "fl", 500, NULL },
2845 { "Acircumflex", 611, NULL },
2846 { "Icircumflex", 333, NULL },
2847 { "guillemotleft", 500, NULL },
2848 { "germandbls", 500, NULL },
2849 { "seven", 500, NULL },
2850 { "ordmasculine", 310, NULL },
2851 { "dotlessi", 278, NULL },
2852 { "sterling", 500, NULL },
2853 { "acircumflex", 500, NULL },
2854 { "icircumflex", 278, NULL },
2855 { "braceright", 400, NULL },
2856 { "quotedblright", 556, NULL },
2857 { "cent", 500, NULL },
2858 { "currency", 500, NULL },
2859 { "logicalnot", 675, NULL },
2860 { "Atilde", 611, NULL },
2861 { "breve", 333, NULL },
2862 { "bar", 275, NULL },
2863 { "fraction", 167, NULL },
2864 { "less", 675, NULL },
2865 { "guilsinglleft", 333, NULL },
2866 { "exclam", 333, NULL },
2867 { "period", 250, NULL },
2868 { "greater", 675, NULL },
2869 { "atilde", 500, NULL },
2870 { "brokenbar", 275, NULL },
2871 { "quoteleft", 333, NULL },
2872 { "onesuperior", 300, NULL }
2873};
2874
2875static BuiltinFontWidth timesRomanWidthsTab[] = {
2876 { "Ntilde", 722, NULL },
2877 { "comma", 250, NULL },
2878 { "cedilla", 333, NULL },
2879 { "plusminus", 564, NULL },
2880 { "circumflex", 333, NULL },
2881 { "dotaccent", 333, NULL },
2882 { "asciitilde", 541, NULL },
2883 { "colon", 278, NULL },
2884 { "onehalf", 750, NULL },
2885 { "dollar", 500, NULL },
2886 { "ntilde", 500, NULL },
2887 { "minus", 564, NULL },
2888 { "yen", 500, NULL },
2889 { "space", 250, NULL },
2890 { "questiondown", 444, NULL },
2891 { "emdash", 1000, NULL },
2892 { "Agrave", 722, NULL },
2893 { "three", 500, NULL },
2894 { "numbersign", 500, NULL },
2895 { "A", 722, NULL },
2896 { "B", 667, NULL },
2897 { "C", 667, NULL },
2898 { "D", 722, NULL },
2899 { "E", 611, NULL },
2900 { "onequarter", 750, NULL },
2901 { "F", 556, NULL },
2902 { "G", 722, NULL },
2903 { "H", 722, NULL },
2904 { "I", 333, NULL },
2905 { "J", 389, NULL },
2906 { "K", 722, NULL },
2907 { "backslash", 278, NULL },
2908 { "L", 611, NULL },
2909 { "periodcentered", 250, NULL },
2910 { "M", 889, NULL },
2911 { "N", 722, NULL },
2912 { "O", 722, NULL },
2913 { "P", 556, NULL },
2914 { "Q", 722, NULL },
2915 { "R", 667, NULL },
2916 { "Aacute", 722, NULL },
2917 { "caron", 333, NULL },
2918 { "S", 556, NULL },
2919 { "T", 611, NULL },
2920 { "U", 722, NULL },
2921 { "agrave", 444, NULL },
2922 { "V", 722, NULL },
2923 { "W", 944, NULL },
2924 { "X", 722, NULL },
2925 { "question", 444, NULL },
2926 { "equal", 564, NULL },
2927 { "Y", 722, NULL },
2928 { "Z", 611, NULL },
2929 { "four", 500, NULL },
2930 { "a", 444, NULL },
2931 { "b", 500, NULL },
2932 { "c", 444, NULL },
2933 { "d", 500, NULL },
2934 { "e", 444, NULL },
2935 { "f", 333, NULL },
2936 { "g", 500, NULL },
2937 { "bullet", 350, NULL },
2938 { "h", 500, NULL },
2939 { "i", 278, NULL },
2940 { "Oslash", 722, NULL },
2941 { "dagger", 500, NULL },
2942 { "j", 278, NULL },
2943 { "k", 500, NULL },
2944 { "l", 278, NULL },
2945 { "m", 778, NULL },
2946 { "n", 500, NULL },
2947 { "o", 500, NULL },
2948 { "ordfeminine", 276, NULL },
2949 { "ring", 333, NULL },
2950 { "p", 500, NULL },
2951 { "q", 500, NULL },
2952 { "r", 333, NULL },
2953 { "twosuperior", 300, NULL },
2954 { "aacute", 444, NULL },
2955 { "s", 389, NULL },
2956 { "OE", 889, NULL },
2957 { "t", 278, NULL },
2958 { "divide", 564, NULL },
2959 { "u", 500, NULL },
2960 { "v", 500, NULL },
2961 { "w", 722, NULL },
2962 { "x", 500, NULL },
2963 { "y", 500, NULL },
2964 { "z", 444, NULL },
2965 { "hungarumlaut", 333, NULL },
2966 { "quotedbl", 408, NULL },
2967 { "mu", 500, NULL },
2968 { "Scaron", 556, NULL },
2969 { "Lslash", 611, NULL },
2970 { "semicolon", 278, NULL },
2971 { "oslash", 500, NULL },
2972 { "parenright", 333, NULL },
2973 { "Ecircumflex", 611, NULL },
2974 { "trademark", 980, NULL },
2975 { "daggerdbl", 500, NULL },
2976 { "macron", 333, NULL },
2977 { "Otilde", 722, NULL },
2978 { "ellipsis", 1000, NULL },
2979 { "scaron", 389, NULL },
2980 { "AE", 889, NULL },
2981 { "Ucircumflex", 722, NULL },
2982 { "lslash", 278, NULL },
2983 { "quotedblleft", 444, NULL },
2984 { "guilsinglright", 333, NULL },
2985 { "hyphen", 333, NULL },
2986 { "quotesingle", 180, NULL },
2987 { "eight", 500, NULL },
2988 { "exclamdown", 333, NULL },
2989 { "endash", 500, NULL },
2990 { "oe", 722, NULL },
2991 { "ecircumflex", 444, NULL },
2992 { "copyright", 760, NULL },
2993 { "Adieresis", 722, NULL },
2994 { "Egrave", 611, NULL },
2995 { "slash", 278, NULL },
2996 { "Edieresis", 611, NULL },
2997 { "otilde", 500, NULL },
2998 { "Idieresis", 333, NULL },
2999 { "parenleft", 333, NULL },
3000 { "one", 500, NULL },
3001 { "ucircumflex", 500, NULL },
3002 { "Odieresis", 722, NULL },
3003 { "bracketleft", 333, NULL },
3004 { "Ugrave", 722, NULL },
3005 { "quoteright", 333, NULL },
3006 { "Udieresis", 722, NULL },
3007 { "perthousand", 1000, NULL },
3008 { "Ydieresis", 722, NULL },
3009 { "Eacute", 611, NULL },
3010 { "adieresis", 444, NULL },
3011 { "egrave", 444, NULL },
3012 { "edieresis", 444, NULL },
3013 { "idieresis", 278, NULL },
3014 { "Eth", 722, NULL },
3015 { "ae", 667, NULL },
3016 { "asterisk", 500, NULL },
3017 { "odieresis", 500, NULL },
3018 { "Uacute", 722, NULL },
3019 { "ugrave", 500, NULL },
3020 { "nine", 500, NULL },
3021 { "five", 500, NULL },
3022 { "udieresis", 500, NULL },
3023 { "Zcaron", 611, NULL },
3024 { "threequarters", 750, NULL },
3025 { "guillemotright", 500, NULL },
3026 { "ydieresis", 500, NULL },
3027 { "Ccedilla", 667, NULL },
3028 { "tilde", 333, NULL },
3029 { "at", 921, NULL },
3030 { "eacute", 444, NULL },
3031 { "underscore", 500, NULL },
3032 { "multiply", 564, NULL },
3033 { "zero", 500, NULL },
3034 { "eth", 500, NULL },
3035 { "Ograve", 722, NULL },
3036 { "uacute", 500, NULL },
3037 { "braceleft", 480, NULL },
3038 { "Thorn", 556, NULL },
3039 { "zcaron", 444, NULL },
3040 { "ccedilla", 444, NULL },
3041 { "Ocircumflex", 722, NULL },
3042 { "Oacute", 722, NULL },
3043 { "ogonek", 333, NULL },
3044 { "ograve", 500, NULL },
3045 { "thorn", 500, NULL },
3046 { "degree", 400, NULL },
3047 { "registered", 760, NULL },
3048 { "Aring", 722, NULL },
3049 { "percent", 833, NULL },
3050 { "six", 500, NULL },
3051 { "paragraph", 453, NULL },
3052 { "two", 500, NULL },
3053 { "Igrave", 333, NULL },
3054 { "ocircumflex", 500, NULL },
3055 { "oacute", 500, NULL },
3056 { "asciicircum", 469, NULL },
3057 { "aring", 444, NULL },
3058 { "grave", 333, NULL },
3059 { "bracketright", 333, NULL },
3060 { "Iacute", 333, NULL },
3061 { "ampersand", 778, NULL },
3062 { "igrave", 278, NULL },
3063 { "plus", 564, NULL },
3064 { "quotesinglbase", 333, NULL },
3065 { "Yacute", 722, NULL },
3066 { "threesuperior", 300, NULL },
3067 { "acute", 333, NULL },
3068 { "section", 500, NULL },
3069 { "dieresis", 333, NULL },
3070 { "iacute", 278, NULL },
3071 { "quotedblbase", 444, NULL },
3072 { "florin", 500, NULL },
3073 { "yacute", 500, NULL },
3074 { "fi", 556, NULL },
3075 { "fl", 556, NULL },
3076 { "Acircumflex", 722, NULL },
3077 { "Icircumflex", 333, NULL },
3078 { "guillemotleft", 500, NULL },
3079 { "germandbls", 500, NULL },
3080 { "seven", 500, NULL },
3081 { "ordmasculine", 310, NULL },
3082 { "dotlessi", 278, NULL },
3083 { "sterling", 500, NULL },
3084 { "acircumflex", 444, NULL },
3085 { "icircumflex", 278, NULL },
3086 { "braceright", 480, NULL },
3087 { "quotedblright", 444, NULL },
3088 { "cent", 500, NULL },
3089 { "currency", 500, NULL },
3090 { "logicalnot", 564, NULL },
3091 { "Atilde", 722, NULL },
3092 { "breve", 333, NULL },
3093 { "bar", 200, NULL },
3094 { "fraction", 167, NULL },
3095 { "less", 564, NULL },
3096 { "guilsinglleft", 333, NULL },
3097 { "exclam", 333, NULL },
3098 { "period", 250, NULL },
3099 { "greater", 564, NULL },
3100 { "atilde", 444, NULL },
3101 { "brokenbar", 200, NULL },
3102 { "quoteleft", 333, NULL },
3103 { "onesuperior", 300, NULL }
3104};
3105
3106static BuiltinFontWidth zapfDingbatsWidthsTab[] = {
3107 { "a81", 438, NULL },
3108 { "a82", 138, NULL },
3109 { "a83", 277, NULL },
3110 { "a84", 415, NULL },
3111 { "a85", 509, NULL },
3112 { "a86", 410, NULL },
3113 { "a87", 234, NULL },
3114 { "a88", 234, NULL },
3115 { "a89", 390, NULL },
3116 { "a140", 788, NULL },
3117 { "a141", 788, NULL },
3118 { "a142", 788, NULL },
3119 { "a143", 788, NULL },
3120 { "a144", 788, NULL },
3121 { "a145", 788, NULL },
3122 { "a146", 788, NULL },
3123 { "a147", 788, NULL },
3124 { "a148", 788, NULL },
3125 { "a149", 788, NULL },
3126 { "a90", 390, NULL },
3127 { "a91", 276, NULL },
3128 { "a92", 276, NULL },
3129 { "space", 278, NULL },
3130 { "a93", 317, NULL },
3131 { "a94", 317, NULL },
3132 { "a95", 334, NULL },
3133 { "a96", 334, NULL },
3134 { "a97", 392, NULL },
3135 { "a98", 392, NULL },
3136 { "a99", 668, NULL },
3137 { "a150", 788, NULL },
3138 { "a151", 788, NULL },
3139 { "a152", 788, NULL },
3140 { "a153", 788, NULL },
3141 { "a154", 788, NULL },
3142 { "a155", 788, NULL },
3143 { "a156", 788, NULL },
3144 { "a157", 788, NULL },
3145 { "a158", 788, NULL },
3146 { "a159", 788, NULL },
3147 { "a160", 894, NULL },
3148 { "a161", 838, NULL },
3149 { "a162", 924, NULL },
3150 { "a163", 1016, NULL },
3151 { "a164", 458, NULL },
3152 { "a165", 924, NULL },
3153 { "a166", 918, NULL },
3154 { "a167", 927, NULL },
3155 { "a168", 928, NULL },
3156 { "a169", 928, NULL },
3157 { "a170", 834, NULL },
3158 { "a171", 873, NULL },
3159 { "a172", 828, NULL },
3160 { "a173", 924, NULL },
3161 { "a174", 917, NULL },
3162 { "a175", 930, NULL },
3163 { "a176", 931, NULL },
3164 { "a177", 463, NULL },
3165 { "a178", 883, NULL },
3166 { "a179", 836, NULL },
3167 { "a180", 867, NULL },
3168 { "a181", 696, NULL },
3169 { "a182", 874, NULL },
3170 { "a183", 760, NULL },
3171 { "a184", 946, NULL },
3172 { "a185", 865, NULL },
3173 { "a186", 967, NULL },
3174 { "a187", 831, NULL },
3175 { "a188", 873, NULL },
3176 { "a189", 927, NULL },
3177 { "a1", 974, NULL },
3178 { "a2", 961, NULL },
3179 { "a3", 980, NULL },
3180 { "a4", 719, NULL },
3181 { "a5", 789, NULL },
3182 { "a6", 494, NULL },
3183 { "a7", 552, NULL },
3184 { "a8", 537, NULL },
3185 { "a9", 577, NULL },
3186 { "a190", 970, NULL },
3187 { "a191", 918, NULL },
3188 { "a192", 748, NULL },
3189 { "a193", 836, NULL },
3190 { "a194", 771, NULL },
3191 { "a195", 888, NULL },
3192 { "a196", 748, NULL },
3193 { "a197", 771, NULL },
3194 { "a198", 888, NULL },
3195 { "a199", 867, NULL },
3196 { "a10", 692, NULL },
3197 { "a11", 960, NULL },
3198 { "a12", 939, NULL },
3199 { "a13", 549, NULL },
3200 { "a14", 855, NULL },
3201 { "a15", 911, NULL },
3202 { "a16", 933, NULL },
3203 { "a17", 945, NULL },
3204 { "a18", 974, NULL },
3205 { "a19", 755, NULL },
3206 { "a20", 846, NULL },
3207 { "a21", 762, NULL },
3208 { "a22", 761, NULL },
3209 { "a23", 571, NULL },
3210 { "a24", 677, NULL },
3211 { "a25", 763, NULL },
3212 { "a26", 760, NULL },
3213 { "a27", 759, NULL },
3214 { "a28", 754, NULL },
3215 { "a29", 786, NULL },
3216 { "a30", 788, NULL },
3217 { "a31", 788, NULL },
3218 { "a32", 790, NULL },
3219 { "a33", 793, NULL },
3220 { "a34", 794, NULL },
3221 { "a35", 816, NULL },
3222 { "a36", 823, NULL },
3223 { "a37", 789, NULL },
3224 { "a38", 841, NULL },
3225 { "a39", 823, NULL },
3226 { "a40", 833, NULL },
3227 { "a41", 816, NULL },
3228 { "a42", 831, NULL },
3229 { "a43", 923, NULL },
3230 { "a44", 744, NULL },
3231 { "a45", 723, NULL },
3232 { "a46", 749, NULL },
3233 { "a47", 790, NULL },
3234 { "a48", 792, NULL },
3235 { "a49", 695, NULL },
3236 { "a100", 668, NULL },
3237 { "a101", 732, NULL },
3238 { "a102", 544, NULL },
3239 { "a103", 544, NULL },
3240 { "a104", 910, NULL },
3241 { "a105", 911, NULL },
3242 { "a106", 667, NULL },
3243 { "a107", 760, NULL },
3244 { "a108", 760, NULL },
3245 { "a109", 626, NULL },
3246 { "a50", 776, NULL },
3247 { "a51", 768, NULL },
3248 { "a52", 792, NULL },
3249 { "a53", 759, NULL },
3250 { "a54", 707, NULL },
3251 { "a55", 708, NULL },
3252 { "a56", 682, NULL },
3253 { "a57", 701, NULL },
3254 { "a58", 826, NULL },
3255 { "a59", 815, NULL },
3256 { "a110", 694, NULL },
3257 { "a111", 595, NULL },
3258 { "a112", 776, NULL },
3259 { "a117", 690, NULL },
3260 { "a118", 791, NULL },
3261 { "a119", 790, NULL },
3262 { "a60", 789, NULL },
3263 { "a61", 789, NULL },
3264 { "a62", 707, NULL },
3265 { "a63", 687, NULL },
3266 { "a64", 696, NULL },
3267 { "a65", 689, NULL },
3268 { "a66", 786, NULL },
3269 { "a67", 787, NULL },
3270 { "a68", 713, NULL },
3271 { "a69", 791, NULL },
3272 { "a200", 696, NULL },
3273 { "a201", 874, NULL },
3274 { "a120", 788, NULL },
3275 { "a121", 788, NULL },
3276 { "a202", 974, NULL },
3277 { "a122", 788, NULL },
3278 { "a203", 762, NULL },
3279 { "a123", 788, NULL },
3280 { "a204", 759, NULL },
3281 { "a205", 509, NULL },
3282 { "a124", 788, NULL },
3283 { "a206", 410, NULL },
3284 { "a125", 788, NULL },
3285 { "a126", 788, NULL },
3286 { "a127", 788, NULL },
3287 { "a128", 788, NULL },
3288 { "a129", 788, NULL },
3289 { "a70", 785, NULL },
3290 { "a71", 791, NULL },
3291 { "a72", 873, NULL },
3292 { "a73", 761, NULL },
3293 { "a74", 762, NULL },
3294 { "a75", 759, NULL },
3295 { "a76", 892, NULL },
3296 { "a77", 892, NULL },
3297 { "a78", 788, NULL },
3298 { "a79", 784, NULL },
3299 { "a130", 788, NULL },
3300 { "a131", 788, NULL },
3301 { "a132", 788, NULL },
3302 { "a133", 788, NULL },
3303 { "a134", 788, NULL },
3304 { "a135", 788, NULL },
3305 { "a136", 788, NULL },
3306 { "a137", 788, NULL },
3307 { "a138", 788, NULL },
3308 { "a139", 788, NULL }
3309};
3310
3311BuiltinFont builtinFonts[] = {
3312 { "Courier", standardEncoding, 624, -207, { -40, -290, 640, 795}, NULL },
3313 { "Courier-Bold", standardEncoding, 674, -257, {-100, -350, 700, 855}, NULL },
3314 { "Courier-BoldOblique", standardEncoding, 674, -257, {-145, -350, 817, 855}, NULL },
3315 { "Courier-Oblique", standardEncoding, 624, -207, { -85, -290, 759, 795}, NULL },
3316 { "Helvetica", standardEncoding, 729, -219, {-174, -220, 1001, 944}, NULL },
3317 { "Helvetica-Bold", standardEncoding, 729, -219, {-173, -221, 1003, 936}, NULL },
3318 { "Helvetica-BoldOblique", standardEncoding, 729, -219, {-177, -221, 1107, 936}, NULL },
3319 { "Helvetica-Oblique", standardEncoding, 729, -219, {-178, -220, 1108, 944}, NULL },
3320 { "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL },
3321 { "Times-Bold", standardEncoding, 670, -210, {-172, -256, 1008, 965}, NULL },
3322 { "Times-BoldItalic", standardEncoding, 682, -203, {-168, -232, 1014, 894}, NULL },
3323 { "Times-Italic", standardEncoding, 684, -206, {-176, -252, 990, 930}, NULL },
3324 { "Times-Roman", standardEncoding, 682, -217, {-170, -223, 1024, 896}, NULL },
3325 { "ZapfDingbats", zapfDingbatsEncoding, 820, -143, { -1, -143, 981, 820}, NULL }
3326};
3327
3328BuiltinFont *builtinFontSubst[] = {
3329 &builtinFonts[0],
3330 &builtinFonts[3],
3331 &builtinFonts[1],
3332 &builtinFonts[2],
3333 &builtinFonts[4],
3334 &builtinFonts[7],
3335 &builtinFonts[5],
3336 &builtinFonts[6],
3337 &builtinFonts[12],
3338 &builtinFonts[11],
3339 &builtinFonts[9],
3340 &builtinFonts[10]
3341};
3342
3343void initBuiltinFontTables() {
3344 builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 260);
3345 builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 260);
3346 builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 260);
3347 builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 260);
3348 builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 228);
3349 builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 228);
3350 builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 228);
3351 builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 228);
3352 builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 189);
3353 builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 228);
3354 builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 228);
3355 builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 228);
3356 builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 228);
3357 builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202);
3358}
3359
3360void freeBuiltinFontTables() {
3361 int i;
3362
3363 for (i = 0; i < 14; ++i) {
3364 delete builtinFonts[i].widths;
3365 }
3366}
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h
new file mode 100644
index 0000000..9a17ce9
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h
@@ -0,0 +1,23 @@
1//========================================================================
2//
3// BuiltinFontTables.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef BUILTINFONTTABLES_H
10#define BUILTINFONTTABLES_H
11
12#include "BuiltinFont.h"
13
14#define nBuiltinFonts 14
15#define nBuiltinFontSubsts 12
16
17extern BuiltinFont builtinFonts[nBuiltinFonts];
18extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts];
19
20extern void initBuiltinFontTables();
21extern void freeBuiltinFontTables();
22
23#endif
diff --git a/noncore/unsupported/qpdf/xpdf/CMap.cc b/noncore/unsupported/qpdf/xpdf/CMap.cc
new file mode 100644
index 0000000..57809f0
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/CMap.cc
@@ -0,0 +1,339 @@
1//========================================================================
2//
3// CMap.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <ctype.h>
18#include "gmem.h"
19#include "gfile.h"
20#include "GString.h"
21#include "Error.h"
22#include "GlobalParams.h"
23#include "CMap.h"
24
25//------------------------------------------------------------------------
26
27struct CMapVectorEntry {
28 GBool isVector;
29 union {
30 CMapVectorEntry *vector;
31 CID cid;
32 };
33};
34
35//------------------------------------------------------------------------
36
37CMap *CMap::parse(CMapCache *cache, GString *collectionA,
38 GString *cMapNameA) {
39 FILE *f;
40 CMap *cmap;
41 char buf[256];
42 GBool inCodeSpace, inCIDRange;
43 char *tok1, *tok2, *tok3;
44 Guint start, end;
45 Guint n;
46
47 if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
48
49 // Check for an identity CMap.
50 if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
51 return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
52 }
53 if (!cMapNameA->cmp("Identity-V")) {
54 return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
55 }
56
57 error(-1, "Couldn't find '%s' CMap file for '%s' collection",
58 cMapNameA->getCString(), collectionA->getCString());
59 return NULL;
60 }
61
62 cmap = new CMap(collectionA->copy(), cMapNameA->copy());
63
64 inCodeSpace = inCIDRange = gFalse;
65 while (getLine(buf, sizeof(buf), f)) {
66 tok1 = strtok(buf, " \t\r\n");
67 if (!tok1 || tok1[0] == '%') {
68 continue;
69 }
70 tok2 = strtok(NULL, " \t\r\n");
71 tok3 = strtok(NULL, " \t\r\n");
72 if (inCodeSpace) {
73 if (!strcmp(tok1, "endcodespacerange")) {
74 inCodeSpace = gFalse;
75 } else if (tok2 && tok1[0] == '<' && tok2[0] == '<' &&
76 (n = strlen(tok1)) == strlen(tok2) &&
77 n >= 4 && (n & 1) == 0) {
78 tok1[n - 1] = tok2[n - 1] = '\0';
79 sscanf(tok1 + 1, "%x", &start);
80 sscanf(tok2 + 1, "%x", &end);
81 n = (n - 2) / 2;
82 cmap->addCodeSpace(cmap->vector, start, end, n);
83 }
84 } else if (inCIDRange) {
85 if (!strcmp(tok1, "endcidrange")) {
86 inCIDRange = gFalse;
87 } else if (tok2 && tok3 && tok1[0] == '<' && tok2[0] == '<' &&
88 (n = strlen(tok1)) == strlen(tok2) &&
89 n >= 4 && (n & 1) == 0) {
90 tok1[n - 1] = tok2[n - 1] = '\0';
91 sscanf(tok1 + 1, "%x", &start);
92 sscanf(tok2 + 1, "%x", &end);
93 n = (n - 2) / 2;
94 cmap->addCIDs(start, end, n, (CID)atoi(tok3));
95 }
96 } else if (tok2 && !strcmp(tok2, "usecmap")) {
97 if (tok1[0] == '/') {
98 cmap->useCMap(cache, tok1 + 1);
99 }
100 } else if (!strcmp(tok1, "/WMode")) {
101 cmap->wMode = atoi(tok2);
102 } else if (tok2 && !strcmp(tok2, "begincodespacerange")) {
103 inCodeSpace = gTrue;
104 } else if (tok2 && !strcmp(tok2, "begincidrange")) {
105 inCIDRange = gTrue;
106 }
107 }
108
109 fclose(f);
110
111 return cmap;
112}
113
114CMap::CMap(GString *collectionA, GString *cMapNameA) {
115 int i;
116
117 collection = collectionA;
118 cMapName = cMapNameA;
119 wMode = 0;
120 vector = (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
121 for (i = 0; i < 256; ++i) {
122 vector[i].isVector = gFalse;
123 vector[i].cid = 0;
124 }
125 refCnt = 1;
126}
127
128CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
129 collection = collectionA;
130 cMapName = cMapNameA;
131 wMode = wModeA;
132 vector = NULL;
133 refCnt = 1;
134}
135
136void CMap::useCMap(CMapCache *cache, char *useName) {
137 GString *useNameStr;
138 CMap *subCMap;
139
140 useNameStr = new GString(useName);
141 subCMap = cache->getCMap(collection, useNameStr);
142 delete useNameStr;
143 if (!subCMap) {
144 return;
145 }
146 copyVector(vector, subCMap->vector);
147 subCMap->decRefCnt();
148}
149
150void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
151 int i, j;
152
153 for (i = 0; i < 256; ++i) {
154 if (src[i].isVector) {
155 if (!dest[i].isVector) {
156 dest[i].isVector = gTrue;
157 dest[i].vector =
158 (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
159 for (j = 0; j < 256; ++j) {
160 dest[i].vector[j].isVector = gFalse;
161 dest[i].vector[j].cid = 0;
162 }
163 }
164 copyVector(dest[i].vector, src[i].vector);
165 } else {
166 if (dest[i].isVector) {
167 error(-1, "Collision in usecmap");
168 } else {
169 dest[i].cid = src[i].cid;
170 }
171 }
172 }
173}
174
175void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
176 Guint nBytes) {
177 Guint start2, end2;
178 int startByte, endByte, i, j;
179
180 if (nBytes > 1) {
181 startByte = (start >> (8 * (nBytes - 1))) & 0xff;
182 endByte = (end >> (8 * (nBytes - 1))) & 0xff;
183 start2 = start & ((1 << (8 * (nBytes - 1))) - 1);
184 end2 = end & ((1 << (8 * (nBytes - 1))) - 1);
185 for (i = startByte; i <= endByte; ++i) {
186 if (!vec[i].isVector) {
187 vec[i].isVector = gTrue;
188 vec[i].vector =
189 (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
190 for (j = 0; j < 256; ++j) {
191 vec[i].vector[j].isVector = gFalse;
192 vec[i].vector[j].cid = 0;
193 }
194 }
195 addCodeSpace(vec[i].vector, start2, end2, nBytes - 1);
196 }
197 }
198}
199
200void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
201 CMapVectorEntry *vec;
202 CID cid;
203 int byte;
204 Guint i;
205
206 vec = vector;
207 for (i = nBytes - 1; i >= 1; --i) {
208 byte = (start >> (8 * i)) & 0xff;
209 if (!vec[byte].isVector) {
210 error(-1, "Invalid CID (%*x - %*x) in CMap",
211 2*nBytes, start, 2*nBytes, end);
212 return;
213 }
214 vec = vec[byte].vector;
215 }
216 cid = firstCID;
217 for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) {
218 if (vec[byte].isVector) {
219 error(-1, "Invalid CID (%*x - %*x) in CMap",
220 2*nBytes, start, 2*nBytes, end);
221 } else {
222 vec[byte].cid = cid;
223 }
224 ++cid;
225 }
226}
227
228CMap::~CMap() {
229 delete collection;
230 delete cMapName;
231 if (vector) {
232 freeCMapVector(vector);
233 }
234}
235
236void CMap::freeCMapVector(CMapVectorEntry *vec) {
237 int i;
238
239 for (i = 0; i < 256; ++i) {
240 if (vec[i].isVector) {
241 freeCMapVector(vec[i].vector);
242 }
243 }
244 gfree(vec);
245}
246
247void CMap::incRefCnt() {
248 ++refCnt;
249}
250
251void CMap::decRefCnt() {
252 if (--refCnt == 0) {
253 delete this;
254 }
255}
256
257GBool CMap::match(GString *collectionA, GString *cMapNameA) {
258 return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA);
259}
260
261CID CMap::getCID(char *s, int len, int *nUsed) {
262 CMapVectorEntry *vec;
263 int n, i;
264
265 if (!(vec = vector)) {
266 // identity CMap
267 *nUsed = 2;
268 if (len < 2) {
269 return 0;
270 }
271 return ((s[0] & 0xff) << 8) + (s[1] & 0xff);
272 }
273 n = 0;
274 while (1) {
275 if (n >= len) {
276 *nUsed = n;
277 return 0;
278 }
279 i = s[n++] & 0xff;
280 if (!vec[i].isVector) {
281 *nUsed = n;
282 return vec[i].cid;
283 }
284 vec = vec[i].vector;
285 }
286}
287
288//------------------------------------------------------------------------
289
290CMapCache::CMapCache() {
291 int i;
292
293 for (i = 0; i < cMapCacheSize; ++i) {
294 cache[i] = NULL;
295 }
296}
297
298CMapCache::~CMapCache() {
299 int i;
300
301 for (i = 0; i < cMapCacheSize; ++i) {
302 if (cache[i]) {
303 cache[i]->decRefCnt();
304 }
305 }
306}
307
308CMap *CMapCache::getCMap(GString *collection, GString *cMapName) {
309 CMap *cmap;
310 int i, j;
311
312 if (cache[0] && cache[0]->match(collection, cMapName)) {
313 cache[0]->incRefCnt();
314 return cache[0];
315 }
316 for (i = 1; i < cMapCacheSize; ++i) {
317 if (cache[i] && cache[i]->match(collection, cMapName)) {
318 cmap = cache[i];
319 for (j = i; j >= 1; --j) {
320 cache[j] = cache[j - 1];
321 }
322 cache[0] = cmap;
323 cmap->incRefCnt();
324 return cmap;
325 }
326 }
327 if ((cmap = CMap::parse(this, collection, cMapName))) {
328 if (cache[cMapCacheSize - 1]) {
329 cache[cMapCacheSize - 1]->decRefCnt();
330 }
331 for (j = cMapCacheSize - 1; j >= 1; --j) {
332 cache[j] = cache[j - 1];
333 }
334 cache[0] = cmap;
335 cmap->incRefCnt();
336 return cmap;
337 }
338 return NULL;
339}
diff --git a/noncore/unsupported/qpdf/xpdf/CMap.h b/noncore/unsupported/qpdf/xpdf/CMap.h
new file mode 100644
index 0000000..8b29ef7
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/CMap.h
@@ -0,0 +1,93 @@
1//========================================================================
2//
3// CMap.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef CMAP_H
10#define CMAP_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "CharTypes.h"
18
19class GString;
20struct CMapVectorEntry;
21class CMapCache;
22
23//------------------------------------------------------------------------
24
25class CMap {
26public:
27
28 // Create the CMap specified by <collection> and <cMapName>. Sets
29 // the initial reference count to 1. Returns NULL on failure.
30 static CMap *parse(CMapCache *cache, GString *collectionA,
31 GString *cMapNameA);
32
33 ~CMap();
34
35 void incRefCnt();
36 void decRefCnt();
37
38 // Return collection name (<registry>-<ordering>).
39 GString *getCollection() { return collection; }
40
41 // Return true if this CMap matches the specified <collectionA>, and
42 // <cMapNameA>.
43 GBool match(GString *collectionA, GString *cMapNameA);
44
45 // Return the CID corresponding to the character code starting at
46 // <s>, which contains <len> bytes. Sets *<nUsed> to the number of
47 // bytes used by the char code.
48 CID getCID(char *s, int len, int *nUsed);
49
50 // Return the writing mode (0=horizontal, 1=vertical).
51 int getWMode() { return wMode; }
52
53private:
54
55 CMap(GString *collectionA, GString *cMapNameA);
56 CMap(GString *collectionA, GString *cMapNameA, int wModeA);
57 void useCMap(CMapCache *cache, char *useName);
58 void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
59 void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
60 Guint nBytes);
61 void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
62 void freeCMapVector(CMapVectorEntry *vec);
63
64 GString *collection;
65 GString *cMapName;
66 int wMode; // writing mode (0=horizontal, 1=vertical)
67 CMapVectorEntry *vector;// vector for first byte (NULL for
68 // identity CMap)
69 int refCnt;
70};
71
72//------------------------------------------------------------------------
73
74#define cMapCacheSize 4
75
76class CMapCache {
77public:
78
79 CMapCache();
80 ~CMapCache();
81
82 // Get the <cMapName> CMap for the specified character collection.
83 // Increments its reference count; there will be one reference for
84 // the cache plus one for the caller of this function. Returns NULL
85 // on failure.
86 CMap *getCMap(GString *collection, GString *cMapName);
87
88private:
89
90 CMap *cache[cMapCacheSize];
91};
92
93#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Catalog.cc b/noncore/unsupported/qpdf/xpdf/Catalog.cc
new file mode 100644
index 0000000..6a0c2d5
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Catalog.cc
@@ -0,0 +1,341 @@
1//========================================================================
2//
3// Catalog.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include "gmem.h"
16#include "Object.h"
17#include "XRef.h"
18#include "Array.h"
19#include "Dict.h"
20#include "Page.h"
21#include "Error.h"
22#include "Link.h"
23#include "Catalog.h"
24
25//------------------------------------------------------------------------
26// Catalog
27//------------------------------------------------------------------------
28
29Catalog::Catalog(XRef *xrefA, GBool printCommands) {
30 Object catDict, pagesDict;
31 Object obj, obj2;
32 int numPages0;
33 int i;
34
35 ok = gTrue;
36 xref = xrefA;
37 pages = NULL;
38 pageRefs = NULL;
39 numPages = pagesSize = 0;
40 baseURI = NULL;
41
42 xref->getCatalog(&catDict);
43 if (!catDict.isDict()) {
44 error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
45 goto err1;
46 }
47
48 // read page tree
49 catDict.dictLookup("Pages", &pagesDict);
50 // This should really be isDict("Pages"), but I've seen at least one
51 // PDF file where the /Type entry is missing.
52 if (!pagesDict.isDict()) {
53 error(-1, "Top-level pages object is wrong type (%s)",
54 pagesDict.getTypeName());
55 goto err2;
56 }
57 pagesDict.dictLookup("Count", &obj);
58 if (!obj.isInt()) {
59 error(-1, "Page count in top-level pages object is wrong type (%s)",
60 obj.getTypeName());
61 goto err3;
62 }
63 pagesSize = numPages0 = obj.getInt();
64 obj.free();
65 pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
66 pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
67 for (i = 0; i < pagesSize; ++i) {
68 pages[i] = NULL;
69 pageRefs[i].num = -1;
70 pageRefs[i].gen = -1;
71 }
72 numPages = readPageTree(pagesDict.getDict(), NULL, 0, printCommands);
73 if (numPages != numPages0) {
74 error(-1, "Page count in top-level pages object is incorrect");
75 }
76 pagesDict.free();
77
78 // read named destination dictionary
79 catDict.dictLookup("Dests", &dests);
80
81 // read root of named destination tree
82 if (catDict.dictLookup("Names", &obj)->isDict())
83 obj.dictLookup("Dests", &nameTree);
84 else
85 nameTree.initNull();
86 obj.free();
87
88 // read base URI
89 if (catDict.dictLookup("URI", &obj)->isDict()) {
90 if (obj.dictLookup("Base", &obj2)->isString()) {
91 baseURI = obj2.getString()->copy();
92 }
93 obj2.free();
94 }
95 obj.free();
96
97 // get the metadata stream
98 catDict.dictLookup("Metadata", &metadata);
99
100 // get the structure tree root
101 catDict.dictLookup("StructTreeRoot", &structTreeRoot);
102
103 catDict.free();
104 return;
105
106 err3:
107 obj.free();
108 err2:
109 pagesDict.free();
110 err1:
111 catDict.free();
112 dests.initNull();
113 nameTree.initNull();
114 ok = gFalse;
115}
116
117Catalog::~Catalog() {
118 int i;
119
120 if (pages) {
121 for (i = 0; i < pagesSize; ++i) {
122 if (pages[i]) {
123 delete pages[i];
124 }
125 }
126 gfree(pages);
127 gfree(pageRefs);
128 }
129 dests.free();
130 nameTree.free();
131 if (baseURI) {
132 delete baseURI;
133 }
134 metadata.free();
135 structTreeRoot.free();
136}
137
138GString *Catalog::readMetadata() {
139 GString *s;
140 Dict *dict;
141 Object obj;
142 int c;
143
144 if (!metadata.isStream()) {
145 return NULL;
146 }
147 dict = metadata.streamGetDict();
148 if (!dict->lookup("Subtype", &obj)->isName("XML")) {
149 error(-1, "Unknown Metadata type: '%s'\n",
150 obj.isName() ? obj.getName() : "???");
151 }
152 obj.free();
153 s = new GString();
154 metadata.streamReset();
155 while ((c = metadata.streamGetChar()) != EOF) {
156 s->append(c);
157 }
158 metadata.streamClose();
159 return s;
160}
161
162int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
163 GBool printCommands) {
164 Object kids;
165 Object kid;
166 Object kidRef;
167 PageAttrs *attrs1, *attrs2;
168 Page *page;
169 int i, j;
170
171 attrs1 = new PageAttrs(attrs, pagesDict);
172 pagesDict->lookup("Kids", &kids);
173 if (!kids.isArray()) {
174 error(-1, "Kids object (page %d) is wrong type (%s)",
175 start+1, kids.getTypeName());
176 goto err1;
177 }
178 for (i = 0; i < kids.arrayGetLength(); ++i) {
179 kids.arrayGet(i, &kid);
180 if (kid.isDict("Page")) {
181 attrs2 = new PageAttrs(attrs1, kid.getDict());
182 page = new Page(xref, start+1, kid.getDict(), attrs2, printCommands);
183 if (!page->isOk()) {
184 ++start;
185 goto err3;
186 }
187 if (start >= pagesSize) {
188 pagesSize += 32;
189 pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *));
190 pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref));
191 for (j = pagesSize - 32; j < pagesSize; ++j) {
192 pages[j] = NULL;
193 pageRefs[j].num = -1;
194 pageRefs[j].gen = -1;
195 }
196 }
197 pages[start] = page;
198 kids.arrayGetNF(i, &kidRef);
199 if (kidRef.isRef()) {
200 pageRefs[start].num = kidRef.getRefNum();
201 pageRefs[start].gen = kidRef.getRefGen();
202 }
203 kidRef.free();
204 ++start;
205 // This should really be isDict("Pages"), but I've seen at least one
206 // PDF file where the /Type entry is missing.
207 } else if (kid.isDict()) {
208 if ((start = readPageTree(kid.getDict(), attrs1, start, printCommands))
209 < 0)
210 goto err2;
211 } else {
212 error(-1, "Kid object (page %d) is wrong type (%s)",
213 start+1, kid.getTypeName());
214 goto err2;
215 }
216 kid.free();
217 }
218 delete attrs1;
219 kids.free();
220 return start;
221
222 err3:
223 delete page;
224 err2:
225 kid.free();
226 err1:
227 kids.free();
228 delete attrs1;
229 ok = gFalse;
230 return -1;
231}
232
233int Catalog::findPage(int num, int gen) {
234 int i;
235
236 for (i = 0; i < numPages; ++i) {
237 if (pageRefs[i].num == num && pageRefs[i].gen == gen)
238 return i + 1;
239 }
240 return 0;
241}
242
243LinkDest *Catalog::findDest(GString *name) {
244 LinkDest *dest;
245 Object obj1, obj2;
246 GBool found;
247
248 // try named destination dictionary then name tree
249 found = gFalse;
250 if (dests.isDict()) {
251 if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
252 found = gTrue;
253 else
254 obj1.free();
255 }
256 if (!found && nameTree.isDict()) {
257 if (!findDestInTree(&nameTree, name, &obj1)->isNull())
258 found = gTrue;
259 else
260 obj1.free();
261 }
262 if (!found)
263 return NULL;
264
265 // construct LinkDest
266 dest = NULL;
267 if (obj1.isArray()) {
268 dest = new LinkDest(obj1.getArray(), gTrue);
269 } else if (obj1.isDict()) {
270 if (obj1.dictLookup("D", &obj2)->isArray())
271 dest = new LinkDest(obj2.getArray(), gTrue);
272 else
273 error(-1, "Bad named destination value");
274 obj2.free();
275 } else {
276 error(-1, "Bad named destination value");
277 }
278 obj1.free();
279
280 return dest;
281}
282
283Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
284 Object names, name1;
285 Object kids, kid, limits, low, high;
286 GBool done, found;
287 int cmp, i;
288
289 // leaf node
290 if (tree->dictLookup("Names", &names)->isArray()) {
291 done = found = gFalse;
292 for (i = 0; !done && i < names.arrayGetLength(); i += 2) {
293 if (names.arrayGet(i, &name1)->isString()) {
294 cmp = name->cmp(name1.getString());
295 if (cmp == 0) {
296 names.arrayGet(i+1, obj);
297 found = gTrue;
298 done = gTrue;
299 } else if (cmp < 0) {
300 done = gTrue;
301 }
302 name1.free();
303 }
304 }
305 names.free();
306 if (!found)
307 obj->initNull();
308 return obj;
309 }
310 names.free();
311
312 // root or intermediate node
313 done = gFalse;
314 if (tree->dictLookup("Kids", &kids)->isArray()) {
315 for (i = 0; !done && i < kids.arrayGetLength(); ++i) {
316 if (kids.arrayGet(i, &kid)->isDict()) {
317 if (kid.dictLookup("Limits", &limits)->isArray()) {
318 if (limits.arrayGet(0, &low)->isString() &&
319 name->cmp(low.getString()) >= 0) {
320 if (limits.arrayGet(1, &high)->isString() &&
321 name->cmp(high.getString()) <= 0) {
322 findDestInTree(&kid, name, obj);
323 done = gTrue;
324 }
325 high.free();
326 }
327 low.free();
328 }
329 limits.free();
330 }
331 kid.free();
332 }
333 }
334 kids.free();
335
336 // name was outside of ranges of all kids
337 if (!done)
338 obj->initNull();
339
340 return obj;
341}
diff --git a/noncore/unsupported/qpdf/xpdf/Catalog.h b/noncore/unsupported/qpdf/xpdf/Catalog.h
new file mode 100644
index 0000000..197f5b8
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Catalog.h
@@ -0,0 +1,85 @@
1//========================================================================
2//
3// Catalog.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef CATALOG_H
10#define CATALOG_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16class XRef;
17class Object;
18class Page;
19class PageAttrs;
20struct Ref;
21class LinkDest;
22
23//------------------------------------------------------------------------
24// Catalog
25//------------------------------------------------------------------------
26
27class Catalog {
28public:
29
30 // Constructor.
31 Catalog(XRef *xrefA, GBool printCommands = gFalse);
32
33 // Destructor.
34 ~Catalog();
35
36 // Is catalog valid?
37 GBool isOk() { return ok; }
38
39 // Get number of pages.
40 int getNumPages() { return numPages; }
41
42 // Get a page.
43 Page *getPage(int i) { return pages[i-1]; }
44
45 // Get the reference for a page object.
46 Ref *getPageRef(int i) { return &pageRefs[i-1]; }
47
48 // Return base URI, or NULL if none.
49 GString *getBaseURI() { return baseURI; }
50
51 // Return the contents of the metadata stream, or NULL if there is
52 // no metadata.
53 GString *readMetadata();
54
55 // Return the structure tree root object.
56 Object *getStructTreeRoot() { return &structTreeRoot; }
57
58 // Find a page, given its object ID. Returns page number, or 0 if
59 // not found.
60 int findPage(int num, int gen);
61
62 // Find a named destination. Returns the link destination, or
63 // NULL if <name> is not a destination.
64 LinkDest *findDest(GString *name);
65
66private:
67
68 XRef *xref; // the xref table for this PDF file
69 Page **pages; // array of pages
70 Ref *pageRefs; // object ID for each page
71 int numPages; // number of pages
72 int pagesSize; // size of pages array
73 Object dests; // named destination dictionary
74 Object nameTree; // name tree
75 GString *baseURI; // base URI for URI-type links
76 Object metadata; // metadata stream
77 Object structTreeRoot;// structure tree root dictionary
78 GBool ok; // true if catalog is valid
79
80 int readPageTree(Dict *pages, PageAttrs *attrs, int start,
81 GBool printCommands);
82 Object *findDestInTree(Object *tree, GString *name, Object *obj);
83};
84
85#endif
diff --git a/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc
new file mode 100644
index 0000000..6793398
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc
@@ -0,0 +1,394 @@
1//========================================================================
2//
3// CharCodeToUnicode.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <string.h>
16#include "gmem.h"
17#include "gfile.h"
18#include "GString.h"
19#include "Error.h"
20#include "GlobalParams.h"
21#include "CharCodeToUnicode.h"
22
23//------------------------------------------------------------------------
24
25#define maxUnicodeString 8
26
27struct CharCodeToUnicodeString {
28 CharCode c;
29 Unicode u[maxUnicodeString];
30 int len;
31};
32
33//------------------------------------------------------------------------
34
35CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *collectionA) {
36 FILE *f;
37 Unicode *mapA;
38 CharCode size, mapLenA;
39 char buf[64];
40 Unicode u;
41 CharCodeToUnicode *ctu;
42
43 if (!(f = globalParams->getCIDToUnicodeFile(collectionA))) {
44 error(-1, "Couldn't find cidToUnicode file for the '%s' collection",
45 collectionA->getCString());
46 return NULL;
47 }
48
49 size = 32768;
50 mapA = (Unicode *)gmalloc(size * sizeof(Unicode));
51 mapLenA = 0;
52
53 while (getLine(buf, sizeof(buf), f)) {
54 if (mapLenA == size) {
55 size *= 2;
56 mapA = (Unicode *)grealloc(mapA, size * sizeof(Unicode));
57 }
58 if (sscanf(buf, "%x", &u) == 1) {
59 mapA[mapLenA] = u;
60 } else {
61 error(-1, "Bad line (%d) in cidToUnicode file for the '%s' collection",
62 (int)(mapLenA + 1), collectionA->getCString());
63 mapA[mapLenA] = 0;
64 }
65 ++mapLenA;
66 }
67
68 ctu = new CharCodeToUnicode(collectionA->copy(), mapA, mapLenA, gTrue,
69 NULL, 0);
70 gfree(mapA);
71 return ctu;
72}
73
74CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) {
75 return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0);
76}
77
78static char *getLineFromString(char *buf, int size, char **s) {
79 char c;
80 int i;
81
82 i = 0;
83 while (i < size - 1 && **s) {
84 buf[i++] = c = *(*s)++;
85 if (c == '\x0a') {
86 break;
87 }
88 if (c == '\x0d') {
89 if (**s == '\x0a' && i < size - 1) {
90 buf[i++] = '\x0a';
91 ++*s;
92 }
93 break;
94 }
95 }
96 buf[i] = '\0';
97 if (i == 0) {
98 return NULL;
99 }
100 return buf;
101}
102
103CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) {
104 CharCodeToUnicode *ctu;
105 char *p;
106
107 ctu = new CharCodeToUnicode(NULL);
108 p = buf->getCString();
109 ctu->parseCMap1((char *(*)(char *, int, void *))&getLineFromString,
110 &p, nBits);
111 return ctu;
112}
113
114void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *),
115 void *data, int nBits) {
116 char buf[256];
117 GBool inBFChar, inBFRange;
118 char *tok1, *tok2, *tok3;
119 int nDigits, n1, n2, n3;
120 CharCode oldLen, i;
121 CharCode code1, code2;
122 Unicode u;
123 char uHex[5];
124 int j;
125 GString *name;
126 FILE *f;
127
128 nDigits = nBits / 4;
129 inBFChar = inBFRange = gFalse;
130 while ((*getLineFunc)(buf, sizeof(buf), data)) {
131 tok1 = strtok(buf, " \t\r\n");
132 if (!tok1 || tok1[0] == '%') {
133 continue;
134 }
135 tok2 = strtok(NULL, " \t\r\n");
136 tok3 = strtok(NULL, " \t\r\n");
137 if (inBFChar) {
138 if (!strcmp(tok1, "endbfchar")) {
139 inBFChar = gFalse;
140 } else if (tok2) {
141 n1 = strlen(tok1);
142 n2 = strlen(tok2);
143 if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
144 tok2[0] == '<' && tok2[n2 - 1] == '>')) {
145 error(-1, "Illegal line in bfchar block in ToUnicode CMap");
146 continue;
147 }
148 tok1[n1 - 1] = tok2[n2 - 1] = '\0';
149 if (sscanf(tok1 + 1, "%x", &code1) != 1) {
150 error(-1, "Illegal line in bfchar block in ToUnicode CMap");
151 continue;
152 }
153 if (code1 >= mapLen) {
154 oldLen = mapLen;
155 mapLen = (code1 + 256) & ~255;
156 map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
157 for (i = oldLen; i < mapLen; ++i) {
158 map[i] = 0;
159 }
160 }
161 if (n2 == 6) {
162 if (sscanf(tok2 + 1, "%x", &u) != 1) {
163 error(-1, "Illegal line in bfchar block in ToUnicode CMap");
164 continue;
165 }
166 map[code1] = u;
167 } else {
168 map[code1] = 0;
169 if (sMapLen == sMapSize) {
170 sMapSize += 8;
171 sMap = (CharCodeToUnicodeString *)
172 grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
173 }
174 sMap[sMapLen].c = code1;
175 sMap[sMapLen].len = (n2 - 2) / 4;
176 for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
177 strncpy(uHex, tok2 + 1 + j*4, 4);
178 uHex[4] = '\0';
179 if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
180 error(-1, "Illegal line in bfchar block in ToUnicode CMap");
181 }
182 }
183 ++sMapLen;
184 }
185 } else {
186 error(-1, "Illegal bfchar block in ToUnicode CMap");
187 }
188 } else if (inBFRange) {
189 if (!strcmp(tok1, "endbfrange")) {
190 inBFRange = gFalse;
191 } else if (tok2 && tok3) {
192 n1 = strlen(tok1);
193 n2 = strlen(tok2);
194 n3 = strlen(tok3);
195 if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
196 n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>' &&
197 tok3[0] == '<' && tok3[n3 - 1] == '>')) {
198 error(-1, "Illegal line in bfrange block in ToUnicode CMap");
199 continue;
200 }
201 tok1[n1 - 1] = tok2[n2 - 1] = tok3[n3 - 1] = '\0';
202 if (sscanf(tok1 + 1, "%x", &code1) != 1 ||
203 sscanf(tok2 + 1, "%x", &code2) != 1) {
204 error(-1, "Illegal line in bfrange block in ToUnicode CMap");
205 continue;
206 }
207 if (code2 >= mapLen) {
208 oldLen = mapLen;
209 mapLen = (code2 + 256) & ~255;
210 map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
211 for (i = oldLen; i < mapLen; ++i) {
212 map[i] = 0;
213 }
214 }
215 if (n3 == 6) {
216 if (sscanf(tok3 + 1, "%x", &u) != 1) {
217 error(-1, "Illegal line in bfrange block in ToUnicode CMap");
218 continue;
219 }
220 for (; code1 <= code2; ++code1) {
221 map[code1] = u++;
222 }
223 } else {
224 if (sMapLen + (int)(code2 - code1 + 1) > sMapSize) {
225 sMapSize = (sMapSize + (code2 - code1 + 1) + 7) & ~7;
226 sMap = (CharCodeToUnicodeString *)
227 grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
228 }
229 for (i = 0; code1 <= code2; ++code1, ++i) {
230 map[code1] = 0;
231 sMap[sMapLen].c = code1;
232 sMap[sMapLen].len = (n3 - 2) / 4;
233 for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
234 strncpy(uHex, tok3 + 1 + j*4, 4);
235 uHex[4] = '\0';
236 if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
237 error(-1, "Illegal line in bfrange block in ToUnicode CMap");
238 }
239 }
240 sMap[sMapLen].u[sMap[sMapLen].len - 1] += i;
241 ++sMapLen;
242 }
243 }
244 } else {
245 error(-1, "Illegal bfrange block in ToUnicode CMap");
246 }
247 } else if (tok2 && !strcmp(tok2, "usecmap")) {
248 if (tok1[0] == '/') {
249 name = new GString(tok1 + 1);
250 if ((f = globalParams->findToUnicodeFile(name))) {
251 parseCMap1((char *(*)(char *, int, void *))&getLine, f, nBits);
252 fclose(f);
253 } else {
254 error(-1, "Couldn't find ToUnicode CMap file for '%s'",
255 name->getCString());
256 }
257 delete name;
258 }
259 } else if (tok2 && !strcmp(tok2, "beginbfchar")) {
260 inBFChar = gTrue;
261 } else if (tok2 && !strcmp(tok2, "beginbfrange")) {
262 inBFRange = gTrue;
263 }
264 }
265}
266
267CharCodeToUnicode::CharCodeToUnicode(GString *collectionA) {
268 CharCode i;
269
270 collection = collectionA;
271 mapLen = 256;
272 map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
273 for (i = 0; i < mapLen; ++i) {
274 map[i] = 0;
275 }
276 sMap = NULL;
277 sMapLen = sMapSize = 0;
278 refCnt = 1;
279}
280
281CharCodeToUnicode::CharCodeToUnicode(GString *collectionA, Unicode *mapA,
282 CharCode mapLenA, GBool copyMap,
283 CharCodeToUnicodeString *sMapA,
284 int sMapLenA) {
285 collection = collectionA;
286 mapLen = mapLenA;
287 if (copyMap) {
288 map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
289 memcpy(map, mapA, mapLen * sizeof(Unicode));
290 } else {
291 map = mapA;
292 }
293 sMap = sMapA;
294 sMapLen = sMapSize = sMapLenA;
295 refCnt = 1;
296}
297
298CharCodeToUnicode::~CharCodeToUnicode() {
299 if (collection) {
300 delete collection;
301 }
302 gfree(map);
303 if (sMap) {
304 gfree(sMap);
305 }
306}
307
308void CharCodeToUnicode::incRefCnt() {
309 ++refCnt;
310}
311
312void CharCodeToUnicode::decRefCnt() {
313 if (--refCnt == 0) {
314 delete this;
315 }
316}
317
318GBool CharCodeToUnicode::match(GString *collectionA) {
319 return collection && !collection->cmp(collectionA);
320}
321
322int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
323 int i, j;
324
325 if (c >= mapLen) {
326 return 0;
327 }
328 if (map[c]) {
329 u[0] = map[c];
330 return 1;
331 }
332 for (i = 0; i < sMapLen; ++i) {
333 if (sMap[i].c == c) {
334 for (j = 0; j < sMap[i].len && j < size; ++j) {
335 u[j] = sMap[i].u[j];
336 }
337 return j;
338 }
339 }
340 return 0;
341}
342
343//------------------------------------------------------------------------
344
345CIDToUnicodeCache::CIDToUnicodeCache() {
346 int i;
347
348 for (i = 0; i < cidToUnicodeCacheSize; ++i) {
349 cache[i] = NULL;
350 }
351}
352
353CIDToUnicodeCache::~CIDToUnicodeCache() {
354 int i;
355
356 for (i = 0; i < cidToUnicodeCacheSize; ++i) {
357 if (cache[i]) {
358 cache[i]->decRefCnt();
359 }
360 }
361}
362
363CharCodeToUnicode *CIDToUnicodeCache::getCIDToUnicode(GString *collection) {
364 CharCodeToUnicode *ctu;
365 int i, j;
366
367 if (cache[0] && cache[0]->match(collection)) {
368 cache[0]->incRefCnt();
369 return cache[0];
370 }
371 for (i = 1; i < cidToUnicodeCacheSize; ++i) {
372 if (cache[i] && cache[i]->match(collection)) {
373 ctu = cache[i];
374 for (j = i; j >= 1; --j) {
375 cache[j] = cache[j - 1];
376 }
377 cache[0] = ctu;
378 ctu->incRefCnt();
379 return ctu;
380 }
381 }
382 if ((ctu = CharCodeToUnicode::parseCIDToUnicode(collection))) {
383 if (cache[cidToUnicodeCacheSize - 1]) {
384 cache[cidToUnicodeCacheSize - 1]->decRefCnt();
385 }
386 for (j = cidToUnicodeCacheSize - 1; j >= 1; --j) {
387 cache[j] = cache[j - 1];
388 }
389 cache[0] = ctu;
390 ctu->incRefCnt();
391 return ctu;
392 }
393 return NULL;
394}
diff --git a/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h
new file mode 100644
index 0000000..c811d72
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h
@@ -0,0 +1,89 @@
1//========================================================================
2//
3// CharCodeToUnicode.h
4//
5// Mapping from character codes to Unicode.
6//
7// Copyright 2001 Derek B. Noonburg
8//
9//========================================================================
10
11#ifndef CHARCODETOUNICODE_H
12#define CHARCODETOUNICODE_H
13
14#ifdef __GNUC__
15#pragma interface
16#endif
17
18#include "CharTypes.h"
19
20struct CharCodeToUnicodeString;
21
22//------------------------------------------------------------------------
23
24class CharCodeToUnicode {
25public:
26
27 // Create the CID-to-Unicode mapping specified by <collection>.
28 // This reads a .cidToUnicode file from disk. Sets the initial
29 // reference count to 1. Returns NULL on failure.
30 static CharCodeToUnicode *parseCIDToUnicode(GString *collectionA);
31
32 // Create the CharCode-to-Unicode mapping for an 8-bit font.
33 // <toUnicode> is an array of 256 Unicode indexes. Sets the initial
34 // reference count to 1.
35 static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode);
36
37 // Parse a ToUnicode CMap for an 8- or 16-bit font.
38 static CharCodeToUnicode *parseCMap(GString *buf, int nBits);
39
40 ~CharCodeToUnicode();
41
42 void incRefCnt();
43 void decRefCnt();
44
45 // Return true if this mapping matches the specified <collectionA>.
46 GBool match(GString *collectionA);
47
48 // Map a CharCode to Unicode.
49 int mapToUnicode(CharCode c, Unicode *u, int size);
50
51private:
52
53 void parseCMap1(char *(*getLineFunc)(char *, int, void *),
54 void *data, int nBits);
55 CharCodeToUnicode(GString *collectionA);
56 CharCodeToUnicode(GString *collectionA, Unicode *mapA,
57 CharCode mapLenA, GBool copyMap,
58 CharCodeToUnicodeString *sMapA, int sMapLenA);
59
60 GString *collection;
61 Unicode *map;
62 CharCode mapLen;
63 CharCodeToUnicodeString *sMap;
64 int sMapLen, sMapSize;
65 int refCnt;
66};
67
68//------------------------------------------------------------------------
69
70#define cidToUnicodeCacheSize 4
71
72class CIDToUnicodeCache {
73public:
74
75 CIDToUnicodeCache();
76 ~CIDToUnicodeCache();
77
78 // Get the CharCodeToUnicode object for <collection>. Increments
79 // its reference count; there will be one reference for the cache
80 // plus one for the caller of this function. Returns NULL on
81 // failure.
82 CharCodeToUnicode *getCIDToUnicode(GString *collection);
83
84private:
85
86 CharCodeToUnicode *cache[cidToUnicodeCacheSize];
87};
88
89#endif
diff --git a/noncore/unsupported/qpdf/xpdf/CharTypes.h b/noncore/unsupported/qpdf/xpdf/CharTypes.h
new file mode 100644
index 0000000..8938be5
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/CharTypes.h
@@ -0,0 +1,24 @@
1//========================================================================
2//
3// CharTypes.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef CHARTYPES_H
10#define CHARTYPES_H
11
12// Unicode character.
13typedef unsigned int Unicode;
14
15// Character ID for CID character collections.
16typedef unsigned int CID;
17
18// This is large enough to hold any of the following:
19// - 8-bit char code
20// - 16-bit CID
21// - Unicode
22typedef unsigned int CharCode;
23
24#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Decrypt.cc b/noncore/unsupported/qpdf/xpdf/Decrypt.cc
new file mode 100644
index 0000000..2def802
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Decrypt.cc
@@ -0,0 +1,385 @@
1//========================================================================
2//
3// Decrypt.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include "gmem.h"
15#include "Decrypt.h"
16
17static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
18static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
19static void md5(Guchar *msg, int msgLen, Guchar *digest);
20
21static Guchar passwordPad[32] = {
22 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
23 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
24 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
25 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
26};
27
28//------------------------------------------------------------------------
29// Decrypt
30//------------------------------------------------------------------------
31
32Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
33 int i;
34
35 // construct object key
36 for (i = 0; i < keyLength; ++i) {
37 objKey[i] = fileKey[i];
38 }
39 objKey[keyLength] = objNum & 0xff;
40 objKey[keyLength + 1] = (objNum >> 8) & 0xff;
41 objKey[keyLength + 2] = (objNum >> 16) & 0xff;
42 objKey[keyLength + 3] = objGen & 0xff;
43 objKey[keyLength + 4] = (objGen >> 8) & 0xff;
44 md5(objKey, keyLength + 5, objKey);
45
46 // set up for decryption
47 x = y = 0;
48 if ((objKeyLength = keyLength + 5) > 16) {
49 objKeyLength = 16;
50 }
51 rc4InitKey(objKey, objKeyLength, state);
52}
53
54void Decrypt::reset() {
55 x = y = 0;
56 rc4InitKey(objKey, objKeyLength, state);
57}
58
59Guchar Decrypt::decryptByte(Guchar c) {
60 return rc4DecryptByte(state, &x, &y, c);
61}
62
63GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
64 GString *ownerKey, GString *userKey,
65 int permissions, GString *fileID,
66 GString *ownerPassword, GString *userPassword,
67 Guchar *fileKey, GBool *ownerPasswordOk) {
68 Guchar test[32];
69 GString *userPassword2;
70 Guchar fState[256];
71 Guchar fx, fy;
72 int len, i;
73
74 // try using the supplied owner password to generate the user password
75 if (ownerPassword) {
76 len = ownerPassword->getLength();
77 if (len < 32) {
78 memcpy(test, ownerPassword->getCString(), len);
79 memcpy(test + len, passwordPad, 32 - len);
80 } else {
81 memcpy(test, ownerPassword->getCString(), 32);
82 }
83 } else {
84 memcpy(test, passwordPad, 32);
85 }
86 md5(test, 32, test);
87 if (encRevision == 3) {
88 for (i = 0; i < 50; ++i) {
89 md5(test, 16, test);
90 }
91 }
92 rc4InitKey(test, keyLength, fState);
93 fx = fy = 0;
94 for (i = 0; i < 32; ++i) {
95 test[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
96 }
97 userPassword2 = new GString((char *)test, 32);
98 if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
99 permissions, fileID, userPassword2, fileKey)) {
100 *ownerPasswordOk = gTrue;
101 delete userPassword2;
102 return gTrue;
103 }
104 *ownerPasswordOk = gFalse;
105 delete userPassword2;
106
107 // try using the supplied user password
108 return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
109 permissions, fileID, userPassword, fileKey);
110}
111
112GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
113 GString *ownerKey, GString *userKey,
114 int permissions, GString *fileID,
115 GString *userPassword, Guchar *fileKey) {
116 Guchar *buf;
117 Guchar test[32];
118 Guchar fState[256];
119 Guchar tmpKey[16];
120 Guchar fx, fy;
121 int len, i, j;
122 GBool ok;
123
124 // generate file key
125 buf = (Guchar *)gmalloc(68 + fileID->getLength());
126 if (userPassword) {
127 len = userPassword->getLength();
128 if (len < 32) {
129 memcpy(buf, userPassword->getCString(), len);
130 memcpy(buf + len, passwordPad, 32 - len);
131 } else {
132 memcpy(buf, userPassword->getCString(), 32);
133 }
134 } else {
135 memcpy(buf, passwordPad, 32);
136 }
137 memcpy(buf + 32, ownerKey->getCString(), 32);
138 buf[64] = permissions & 0xff;
139 buf[65] = (permissions >> 8) & 0xff;
140 buf[66] = (permissions >> 16) & 0xff;
141 buf[67] = (permissions >> 24) & 0xff;
142 memcpy(buf + 68, fileID->getCString(), fileID->getLength());
143 md5(buf, 68 + fileID->getLength(), fileKey);
144 if (encRevision == 3) {
145 for (i = 0; i < 50; ++i) {
146 md5(fileKey, 16, fileKey);
147 }
148 }
149
150 // test user password
151 if (encRevision == 2) {
152 rc4InitKey(fileKey, keyLength, fState);
153 fx = fy = 0;
154 for (i = 0; i < 32; ++i) {
155 test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
156 }
157 ok = memcmp(test, passwordPad, 32) == 0;
158 } else if (encRevision == 3) {
159 memcpy(test, userKey->getCString(), 32);
160 for (i = 19; i >= 0; --i) {
161 for (j = 0; j < keyLength; ++j) {
162 tmpKey[j] = fileKey[j] ^ i;
163 }
164 rc4InitKey(tmpKey, keyLength, fState);
165 fx = fy = 0;
166 for (j = 0; j < 32; ++j) {
167 test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
168 }
169 }
170 memcpy(buf, passwordPad, 32);
171 memcpy(buf + 32, fileID->getCString(), fileID->getLength());
172 md5(buf, 32 + fileID->getLength(), buf);
173 ok = memcmp(test, buf, 16) == 0;
174 } else {
175 ok = gFalse;
176 }
177
178 gfree(buf);
179 return ok;
180}
181
182//------------------------------------------------------------------------
183// RC4-compatible decryption
184//------------------------------------------------------------------------
185
186static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
187 Guchar index1, index2;
188 Guchar t;
189 int i;
190
191 for (i = 0; i < 256; ++i)
192 state[i] = i;
193 index1 = index2 = 0;
194 for (i = 0; i < 256; ++i) {
195 index2 = (key[index1] + state[i] + index2) % 256;
196 t = state[i];
197 state[i] = state[index2];
198 state[index2] = t;
199 index1 = (index1 + 1) % keyLen;
200 }
201}
202
203static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
204 Guchar x1, y1, tx, ty;
205
206 x1 = *x = (*x + 1) % 256;
207 y1 = *y = (state[*x] + *y) % 256;
208 tx = state[x1];
209 ty = state[y1];
210 state[x1] = ty;
211 state[y1] = tx;
212 return c ^ state[(tx + ty) % 256];
213}
214
215//------------------------------------------------------------------------
216// MD5 message digest
217//------------------------------------------------------------------------
218
219// this works around a bug in older Sun compilers
220static inline Gulong rotateLeft(Gulong x, int r) {
221 x &= 0xffffffff;
222 return ((x << r) | (x >> (32 - r))) & 0xffffffff;
223}
224
225static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
226 Gulong Xk, Gulong s, Gulong Ti) {
227 return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
228}
229
230static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
231 Gulong Xk, Gulong s, Gulong Ti) {
232 return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
233}
234
235static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
236 Gulong Xk, Gulong s, Gulong Ti) {
237 return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
238}
239
240static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
241 Gulong Xk, Gulong s, Gulong Ti) {
242 return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
243}
244
245static void md5(Guchar *msg, int msgLen, Guchar *digest) {
246 Gulong x[16];
247 Gulong a, b, c, d, aa, bb, cc, dd;
248 int n64;
249 int i, j, k;
250
251 // compute number of 64-byte blocks
252 // (length + pad byte (0x80) + 8 bytes for length)
253 n64 = (msgLen + 1 + 8 + 63) / 64;
254
255 // initialize a, b, c, d
256 a = 0x67452301;
257 b = 0xefcdab89;
258 c = 0x98badcfe;
259 d = 0x10325476;
260
261 // loop through blocks
262 k = 0;
263 for (i = 0; i < n64; ++i) {
264
265 // grab a 64-byte block
266 for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
267 x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
268 if (i == n64 - 1) {
269 if (k == msgLen - 3)
270 x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
271 else if (k == msgLen - 2)
272 x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
273 else if (k == msgLen - 1)
274 x[j] = 0x8000 + msg[k];
275 else
276 x[j] = 0x80;
277 ++j;
278 while (j < 16)
279 x[j++] = 0;
280 x[14] = msgLen << 3;
281 }
282
283 // save a, b, c, d
284 aa = a;
285 bb = b;
286 cc = c;
287 dd = d;
288
289 // round 1
290 a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478);
291 d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756);
292 c = md5Round1(c, d, a, b, x[2], 17, 0x242070db);
293 b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee);
294 a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf);
295 d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a);
296 c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613);
297 b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501);
298 a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8);
299 d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af);
300 c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
301 b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
302 a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122);
303 d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
304 c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
305 b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
306
307 // round 2
308 a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562);
309 d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340);
310 c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
311 b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa);
312 a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d);
313 d = md5Round2(d, a, b, c, x[10], 9, 0x02441453);
314 c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
315 b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8);
316 a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6);
317 d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6);
318 c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87);
319 b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed);
320 a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905);
321 d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8);
322 c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9);
323 b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
324
325 // round 3
326 a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942);
327 d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681);
328 c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
329 b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
330 a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44);
331 d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9);
332 c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60);
333 b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
334 a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6);
335 d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa);
336 c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085);
337 b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05);
338 a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039);
339 d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
340 c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
341 b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665);
342
343 // round 4
344 a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244);
345 d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97);
346 c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
347 b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039);
348 a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3);
349 d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92);
350 c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
351 b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1);
352 a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f);
353 d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
354 c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314);
355 b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
356 a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82);
357 d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
358 c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb);
359 b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391);
360
361 // increment a, b, c, d
362 a += aa;
363 b += bb;
364 c += cc;
365 d += dd;
366 }
367
368 // break digest into bytes
369 digest[0] = a & 0xff;
370 digest[1] = (a >>= 8) & 0xff;
371 digest[2] = (a >>= 8) & 0xff;
372 digest[3] = (a >>= 8) & 0xff;
373 digest[4] = b & 0xff;
374 digest[5] = (b >>= 8) & 0xff;
375 digest[6] = (b >>= 8) & 0xff;
376 digest[7] = (b >>= 8) & 0xff;
377 digest[8] = c & 0xff;
378 digest[9] = (c >>= 8) & 0xff;
379 digest[10] = (c >>= 8) & 0xff;
380 digest[11] = (c >>= 8) & 0xff;
381 digest[12] = d & 0xff;
382 digest[13] = (d >>= 8) & 0xff;
383 digest[14] = (d >>= 8) & 0xff;
384 digest[15] = (d >>= 8) & 0xff;
385}
diff --git a/noncore/unsupported/qpdf/xpdf/Decrypt.h b/noncore/unsupported/qpdf/xpdf/Decrypt.h
new file mode 100644
index 0000000..1bdb2b7
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Decrypt.h
@@ -0,0 +1,59 @@
1//========================================================================
2//
3// Decrypt.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef DECRYPT_H
10#define DECRYPT_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "GString.h"
18
19//------------------------------------------------------------------------
20// Decrypt
21//------------------------------------------------------------------------
22
23class Decrypt {
24public:
25
26 // Initialize the decryptor object.
27 Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
28
29 // Reset decryption.
30 void reset();
31
32 // Decrypt one byte.
33 Guchar decryptByte(Guchar c);
34
35 // Generate a file key. The <fileKey> buffer must have space for at
36 // least 16 bytes. Checks <ownerPassword> and then <userPassword>
37 // and returns true if either is correct. Sets <ownerPasswordOk> if
38 // the owner password was correct. Either or both of the passwords
39 // may be NULL, which is treated as an empty string.
40 static GBool makeFileKey(int encVersion, int encRevision, int keyLength,
41 GString *ownerKey, GString *userKey,
42 int permissions, GString *fileID,
43 GString *ownerPassword, GString *userPassword,
44 Guchar *fileKey, GBool *ownerPasswordOk);
45
46private:
47
48 static GBool makeFileKey2(int encVersion, int encRevision, int keyLength,
49 GString *ownerKey, GString *userKey,
50 int permissions, GString *fileID,
51 GString *userPassword, Guchar *fileKey);
52
53 int objKeyLength;
54 Guchar objKey[21];
55 Guchar state[256];
56 Guchar x, y;
57};
58
59#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Dict.cc b/noncore/unsupported/qpdf/xpdf/Dict.cc
new file mode 100644
index 0000000..1a49ca5
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Dict.cc
@@ -0,0 +1,90 @@
1//========================================================================
2//
3// Dict.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include <string.h>
16#include "gmem.h"
17#include "Object.h"
18#include "XRef.h"
19#include "Dict.h"
20
21//------------------------------------------------------------------------
22// Dict
23//------------------------------------------------------------------------
24
25Dict::Dict(XRef *xrefA) {
26 xref = xrefA;
27 entries = NULL;
28 size = length = 0;
29 ref = 1;
30}
31
32Dict::~Dict() {
33 int i;
34
35 for (i = 0; i < length; ++i) {
36 gfree(entries[i].key);
37 entries[i].val.free();
38 }
39 gfree(entries);
40}
41
42void Dict::add(char *key, Object *val) {
43 if (length + 1 > size) {
44 size += 8;
45 entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
46 }
47 entries[length].key = key;
48 entries[length].val = *val;
49 ++length;
50}
51
52inline DictEntry *Dict::find(char *key) {
53 int i;
54
55 for (i = 0; i < length; ++i) {
56 if (!strcmp(key, entries[i].key))
57 return &entries[i];
58 }
59 return NULL;
60}
61
62GBool Dict::is(char *type) {
63 DictEntry *e;
64
65 return (e = find("Type")) && e->val.isName(type);
66}
67
68Object *Dict::lookup(char *key, Object *obj) {
69 DictEntry *e;
70
71 return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
72}
73
74Object *Dict::lookupNF(char *key, Object *obj) {
75 DictEntry *e;
76
77 return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
78}
79
80char *Dict::getKey(int i) {
81 return entries[i].key;
82}
83
84Object *Dict::getVal(int i, Object *obj) {
85 return entries[i].val.fetch(xref, obj);
86}
87
88Object *Dict::getValNF(int i, Object *obj) {
89 return entries[i].val.copy(obj);
90}
diff --git a/noncore/unsupported/qpdf/xpdf/Dict.h b/noncore/unsupported/qpdf/xpdf/Dict.h
new file mode 100644
index 0000000..c4f1ea5
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Dict.h
@@ -0,0 +1,75 @@
1//========================================================================
2//
3// Dict.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef DICT_H
10#define DICT_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "Object.h"
17
18//------------------------------------------------------------------------
19// Dict
20//------------------------------------------------------------------------
21
22struct DictEntry {
23 char *key;
24 Object val;
25};
26
27class Dict {
28public:
29
30 // Constructor.
31 Dict(XRef *xrefA);
32
33 // Destructor.
34 ~Dict();
35
36 // Reference counting.
37 int incRef() { return ++ref; }
38 int decRef() { return --ref; }
39
40 // Get number of entries.
41 int getLength() { return length; }
42
43 // Add an entry. NB: does not copy key.
44 void add(char *key, Object *val);
45
46 // Check if dictionary is of specified type.
47 GBool is(char *type);
48
49 // Look up an entry and return the value. Returns a null object
50 // if <key> is not in the dictionary.
51 Object *lookup(char *key, Object *obj);
52 Object *lookupNF(char *key, Object *obj);
53
54 // Iterative accessors.
55 char *getKey(int i);
56 Object *getVal(int i, Object *obj);
57 Object *getValNF(int i, Object *obj);
58
59 // Set the xref pointer. This is only used in one special case: the
60 // trailer dictionary, which is read before the xref table is
61 // parsed.
62 void setXRef(XRef *xrefA) { xref = xrefA; }
63
64private:
65
66 XRef *xref; // the xref table for this PDF file
67 DictEntry *entries; // array of entries
68 int size; // size of <entries> array
69 int length; // number of entries in dictionary
70 int ref; // reference count
71
72 DictEntry *find(char *key);
73};
74
75#endif
diff --git a/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h b/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h
new file mode 100644
index 0000000..048e25d
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h
@@ -0,0 +1,31 @@
1//========================================================================
2//
3// DisplayFontTable.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9static struct {
10 char *name;
11 char *xlfd;
12 char *encoding;
13} displayFontTab[] = {
14#if _NO_USE_FOR_QPE
15 {"Courier", "-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
16 {"Courier-Bold", "-*-courier-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
17 {"Courier-BoldOblique", "-*-courier-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
18 {"Courier-Oblique", "-*-courier-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
19 {"Helvetica", "-*-helvetica-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
20 {"Helvetica-Bold", "-*-helvetica-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
21 {"Helvetica-BoldOblique", "-*-helvetica-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
22 {"Helvetica-Oblique", "-*-helvetica-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
23 {"Symbol", "-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", "Symbol"},
24 {"Times-Bold", "-*-times-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
25 {"Times-BoldItalic", "-*-times-bold-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
26 {"Times-Italic", "-*-times-medium-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
27 {"Times-Roman", "-*-times-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
28 {"ZapfDingbats", "-*-zapfdingbats-medium-r-normal-*-%s-*-*-*-*-*-*-*", "ZapfDingbats"},
29#endif
30 {NULL}
31};
diff --git a/noncore/unsupported/qpdf/xpdf/Error.cc b/noncore/unsupported/qpdf/xpdf/Error.cc
new file mode 100644
index 0000000..8763846
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Error.cc
@@ -0,0 +1,37 @@
1//========================================================================
2//
3// Error.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stddef.h>
16#include <stdarg.h>
17#include "GlobalParams.h"
18#include "Error.h"
19
20void CDECL error(int pos, char *msg, ...) {
21 va_list args;
22
23 // NB: this can be called before the globalParams object is created
24 if (globalParams && globalParams->getErrQuiet()) {
25 return;
26 }
27 if (pos >= 0) {
28 fprintf(stderr, "Error (%d): ", pos);
29 } else {
30 fprintf(stderr, "Error: ");
31 }
32 va_start(args, msg);
33 vfprintf(stderr, msg, args);
34 va_end(args);
35 fprintf(stderr, "\n");
36 fflush(stderr);
37}
diff --git a/noncore/unsupported/qpdf/xpdf/Error.h b/noncore/unsupported/qpdf/xpdf/Error.h
new file mode 100644
index 0000000..151e961
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Error.h
@@ -0,0 +1,21 @@
1//========================================================================
2//
3// Error.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef ERROR_H
10#define ERROR_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include <stdio.h>
17#include "config.h"
18
19extern void CDECL error(int pos, char *msg, ...);
20
21#endif
diff --git a/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc
new file mode 100644
index 0000000..12a1a27
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc
@@ -0,0 +1,1824 @@
1//========================================================================
2//
3// FontEncodingTables.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#include <aconf.h>
10#include <stdlib.h>
11#include "FontEncodingTables.h"
12
13char *macRomanEncoding[256] = {
14 NULL,
15 NULL,
16 NULL,
17 NULL,
18 NULL,
19 NULL,
20 NULL,
21 NULL,
22 NULL,
23 NULL,
24 NULL,
25 NULL,
26 NULL,
27 NULL,
28 NULL,
29 NULL,
30 NULL,
31 NULL,
32 NULL,
33 NULL,
34 NULL,
35 NULL,
36 NULL,
37 NULL,
38 NULL,
39 NULL,
40 NULL,
41 NULL,
42 NULL,
43 NULL,
44 NULL,
45 NULL,
46 "space",
47 "exclam",
48 "quotedbl",
49 "numbersign",
50 "dollar",
51 "percent",
52 "ampersand",
53 "quotesingle",
54 "parenleft",
55 "parenright",
56 "asterisk",
57 "plus",
58 "comma",
59 "hyphen",
60 "period",
61 "slash",
62 "zero",
63 "one",
64 "two",
65 "three",
66 "four",
67 "five",
68 "six",
69 "seven",
70 "eight",
71 "nine",
72 "colon",
73 "semicolon",
74 "less",
75 "equal",
76 "greater",
77 "question",
78 "at",
79 "A",
80 "B",
81 "C",
82 "D",
83 "E",
84 "F",
85 "G",
86 "H",
87 "I",
88 "J",
89 "K",
90 "L",
91 "M",
92 "N",
93 "O",
94 "P",
95 "Q",
96 "R",
97 "S",
98 "T",
99 "U",
100 "V",
101 "W",
102 "X",
103 "Y",
104 "Z",
105 "bracketleft",
106 "backslash",
107 "bracketright",
108 "asciicircum",
109 "underscore",
110 "grave",
111 "a",
112 "b",
113 "c",
114 "d",
115 "e",
116 "f",
117 "g",
118 "h",
119 "i",
120 "j",
121 "k",
122 "l",
123 "m",
124 "n",
125 "o",
126 "p",
127 "q",
128 "r",
129 "s",
130 "t",
131 "u",
132 "v",
133 "w",
134 "x",
135 "y",
136 "z",
137 "braceleft",
138 "bar",
139 "braceright",
140 "asciitilde",
141 NULL,
142 "Adieresis",
143 "Aring",
144 "Ccedilla",
145 "Eacute",
146 "Ntilde",
147 "Odieresis",
148 "Udieresis",
149 "aacute",
150 "agrave",
151 "acircumflex",
152 "adieresis",
153 "atilde",
154 "aring",
155 "ccedilla",
156 "eacute",
157 "egrave",
158 "ecircumflex",
159 "edieresis",
160 "iacute",
161 "igrave",
162 "icircumflex",
163 "idieresis",
164 "ntilde",
165 "oacute",
166 "ograve",
167 "ocircumflex",
168 "odieresis",
169 "otilde",
170 "uacute",
171 "ugrave",
172 "ucircumflex",
173 "udieresis",
174 "dagger",
175 "degree",
176 "cent",
177 "sterling",
178 "section",
179 "bullet",
180 "paragraph",
181 "germandbls",
182 "registered",
183 "copyright",
184 "trademark",
185 "acute",
186 "dieresis",
187 NULL,
188 "AE",
189 "Oslash",
190 NULL,
191 "plusminus",
192 NULL,
193 NULL,
194 "yen",
195 "mu",
196 NULL,
197 NULL,
198 NULL,
199 NULL,
200 NULL,
201 "ordfeminine",
202 "ordmasculine",
203 NULL,
204 "ae",
205 "oslash",
206 "questiondown",
207 "exclamdown",
208 "logicalnot",
209 NULL,
210 "florin",
211 NULL,
212 NULL,
213 "guillemotleft",
214 "guillemotright",
215 "ellipsis",
216 "space",
217 "Agrave",
218 "Atilde",
219 "Otilde",
220 "OE",
221 "oe",
222 "endash",
223 "emdash",
224 "quotedblleft",
225 "quotedblright",
226 "quoteleft",
227 "quoteright",
228 "divide",
229 NULL,
230 "ydieresis",
231 "Ydieresis",
232 "fraction",
233 "currency",
234 "guilsinglleft",
235 "guilsinglright",
236 "fi",
237 "fl",
238 "daggerdbl",
239 "periodcentered",
240 "quotesinglbase",
241 "quotedblbase",
242 "perthousand",
243 "Acircumflex",
244 "Ecircumflex",
245 "Aacute",
246 "Edieresis",
247 "Egrave",
248 "Iacute",
249 "Icircumflex",
250 "Idieresis",
251 "Igrave",
252 "Oacute",
253 "Ocircumflex",
254 NULL,
255 "Ograve",
256 "Uacute",
257 "Ucircumflex",
258 "Ugrave",
259 "dotlessi",
260 "circumflex",
261 "tilde",
262 "macron",
263 "breve",
264 "dotaccent",
265 "ring",
266 "cedilla",
267 "hungarumlaut",
268 "ogonek",
269 "caron"
270};
271
272char *macExpertEncoding[256] = {
273 NULL,
274 NULL,
275 NULL,
276 NULL,
277 NULL,
278 NULL,
279 NULL,
280 NULL,
281 NULL,
282 NULL,
283 NULL,
284 NULL,
285 NULL,
286 NULL,
287 NULL,
288 NULL,
289 NULL,
290 NULL,
291 NULL,
292 NULL,
293 NULL,
294 NULL,
295 NULL,
296 NULL,
297 NULL,
298 NULL,
299 NULL,
300 NULL,
301 NULL,
302 NULL,
303 NULL,
304 NULL,
305 "space",
306 "exclamsmall",
307 "Hungarumlautsmall",
308 "centoldstyle",
309 "dollaroldstyle",
310 "dollarsuperior",
311 "ampersandsmall",
312 "Acutesmall",
313 "parenleftsuperior",
314 "parenrightsuperior",
315 "twodotenleader",
316 "onedotenleader",
317 "comma",
318 "hyphen",
319 "period",
320 "fraction",
321 "zerooldstyle",
322 "oneoldstyle",
323 "twooldstyle",
324 "threeoldstyle",
325 "fouroldstyle",
326 "fiveoldstyle",
327 "sixoldstyle",
328 "sevenoldstyle",
329 "eightoldstyle",
330 "nineoldstyle",
331 "colon",
332 "semicolon",
333 NULL,
334 "threequartersemdash",
335 NULL,
336 "questionsmall",
337 NULL,
338 NULL,
339 NULL,
340 NULL,
341 "Ethsmall",
342 NULL,
343 NULL,
344 "onequarter",
345 "onehalf",
346 "threequarters",
347 "oneeighth",
348 "threeeighths",
349 "fiveeighths",
350 "seveneighths",
351 "onethird",
352 "twothirds",
353 NULL,
354 NULL,
355 NULL,
356 NULL,
357 NULL,
358 NULL,
359 "ff",
360 "fi",
361 "fl",
362 "ffi",
363 "ffl",
364 "parenleftinferior",
365 NULL,
366 "parenrightinferior",
367 "Circumflexsmall",
368 "hypheninferior",
369 "Gravesmall",
370 "Asmall",
371 "Bsmall",
372 "Csmall",
373 "Dsmall",
374 "Esmall",
375 "Fsmall",
376 "Gsmall",
377 "Hsmall",
378 "Ismall",
379 "Jsmall",
380 "Ksmall",
381 "Lsmall",
382 "Msmall",
383 "Nsmall",
384 "Osmall",
385 "Psmall",
386 "Qsmall",
387 "Rsmall",
388 "Ssmall",
389 "Tsmall",
390 "Usmall",
391 "Vsmall",
392 "Wsmall",
393 "Xsmall",
394 "Ysmall",
395 "Zsmall",
396 "colonmonetary",
397 "onefitted",
398 "rupiah",
399 "Tildesmall",
400 NULL,
401 NULL,
402 "asuperior",
403 "centsuperior",
404 NULL,
405 NULL,
406 NULL,
407 NULL,
408 "Aacutesmall",
409 "Agravesmall",
410 "Acircumflexsmall",
411 "Adieresissmall",
412 "Atildesmall",
413 "Aringsmall",
414 "Ccedillasmall",
415 "Eacutesmall",
416 "Egravesmall",
417 "Ecircumflexsmall",
418 "Edieresissmall",
419 "Iacutesmall",
420 "Igravesmall",
421 "Icircumflexsmall",
422 "Idieresissmall",
423 "Ntildesmall",
424 "Oacutesmall",
425 "Ogravesmall",
426 "Ocircumflexsmall",
427 "Odieresissmall",
428 "Otildesmall",
429 "Uacutesmall",
430 "Ugravesmall",
431 "Ucircumflexsmall",
432 "Udieresissmall",
433 NULL,
434 "eightsuperior",
435 "fourinferior",
436 "threeinferior",
437 "sixinferior",
438 "eightinferior",
439 "seveninferior",
440 "Scaronsmall",
441 NULL,
442 "centinferior",
443 "twoinferior",
444 NULL,
445 "Dieresissmall",
446 NULL,
447 "Caronsmall",
448 "osuperior",
449 "fiveinferior",
450 NULL,
451 "commainferior",
452 "periodinferior",
453 "Yacutesmall",
454 NULL,
455 "dollarinferior",
456 NULL,
457 NULL,
458 "Thornsmall",
459 NULL,
460 "nineinferior",
461 "zeroinferior",
462 "Zcaronsmall",
463 "AEsmall",
464 "Oslashsmall",
465 "questiondownsmall",
466 "oneinferior",
467 "Lslashsmall",
468 NULL,
469 NULL,
470 NULL,
471 NULL,
472 NULL,
473 NULL,
474 "Cedillasmall",
475 NULL,
476 NULL,
477 NULL,
478 NULL,
479 NULL,
480 "OEsmall",
481 "figuredash",
482 "hyphensuperior",
483 NULL,
484 NULL,
485 NULL,
486 NULL,
487 "exclamdownsmall",
488 NULL,
489 "Ydieresissmall",
490 NULL,
491 "onesuperior",
492 "twosuperior",
493 "threesuperior",
494 "foursuperior",
495 "fivesuperior",
496 "sixsuperior",
497 "sevensuperior",
498 "ninesuperior",
499 "zerosuperior",
500 NULL,
501 "esuperior",
502 "rsuperior",
503 "tsuperior",
504 NULL,
505 NULL,
506 "isuperior",
507 "ssuperior",
508 "dsuperior",
509 NULL,
510 NULL,
511 NULL,
512 NULL,
513 NULL,
514 "lsuperior",
515 "Ogoneksmall",
516 "Brevesmall",
517 "Macronsmall",
518 "bsuperior",
519 "nsuperior",
520 "msuperior",
521 "commasuperior",
522 "periodsuperior",
523 "Dotaccentsmall",
524 "Ringsmall",
525 NULL,
526 NULL,
527 NULL,
528 NULL
529};
530
531char *winAnsiEncoding[256] = {
532 NULL,
533 NULL,
534 NULL,
535 NULL,
536 NULL,
537 NULL,
538 NULL,
539 NULL,
540 NULL,
541 NULL,
542 NULL,
543 NULL,
544 NULL,
545 NULL,
546 NULL,
547 NULL,
548 NULL,
549 NULL,
550 NULL,
551 NULL,
552 NULL,
553 NULL,
554 NULL,
555 NULL,
556 NULL,
557 NULL,
558 NULL,
559 NULL,
560 NULL,
561 NULL,
562 NULL,
563 NULL,
564 "space",
565 "exclam",
566 "quotedbl",
567 "numbersign",
568 "dollar",
569 "percent",
570 "ampersand",
571 "quotesingle",
572 "parenleft",
573 "parenright",
574 "asterisk",
575 "plus",
576 "comma",
577 "hyphen",
578 "period",
579 "slash",
580 "zero",
581 "one",
582 "two",
583 "three",
584 "four",
585 "five",
586 "six",
587 "seven",
588 "eight",
589 "nine",
590 "colon",
591 "semicolon",
592 "less",
593 "equal",
594 "greater",
595 "question",
596 "at",
597 "A",
598 "B",
599 "C",
600 "D",
601 "E",
602 "F",
603 "G",
604 "H",
605 "I",
606 "J",
607 "K",
608 "L",
609 "M",
610 "N",
611 "O",
612 "P",
613 "Q",
614 "R",
615 "S",
616 "T",
617 "U",
618 "V",
619 "W",
620 "X",
621 "Y",
622 "Z",
623 "bracketleft",
624 "backslash",
625 "bracketright",
626 "asciicircum",
627 "underscore",
628 "grave",
629 "a",
630 "b",
631 "c",
632 "d",
633 "e",
634 "f",
635 "g",
636 "h",
637 "i",
638 "j",
639 "k",
640 "l",
641 "m",
642 "n",
643 "o",
644 "p",
645 "q",
646 "r",
647 "s",
648 "t",
649 "u",
650 "v",
651 "w",
652 "x",
653 "y",
654 "z",
655 "braceleft",
656 "bar",
657 "braceright",
658 "asciitilde",
659 "bullet",
660 "Euro",
661 "bullet",
662 "quotesinglbase",
663 "florin",
664 "quotedblbase",
665 "ellipsis",
666 "dagger",
667 "daggerdbl",
668 "circumflex",
669 "perthousand",
670 "Scaron",
671 "guilsinglleft",
672 "OE",
673 "bullet",
674 "Zcaron",
675 "bullet",
676 "bullet",
677 "quoteleft",
678 "quoteright",
679 "quotedblleft",
680 "quotedblright",
681 "bullet",
682 "endash",
683 "emdash",
684 "tilde",
685 "trademark",
686 "scaron",
687 "guilsinglright",
688 "oe",
689 "bullet",
690 "zcaron",
691 "Ydieresis",
692 "space",
693 "exclamdown",
694 "cent",
695 "sterling",
696 "currency",
697 "yen",
698 "brokenbar",
699 "section",
700 "dieresis",
701 "copyright",
702 "ordfeminine",
703 "guillemotleft",
704 "logicalnot",
705 "hyphen",
706 "registered",
707 "macron",
708 "degree",
709 "plusminus",
710 "twosuperior",
711 "threesuperior",
712 "acute",
713 "mu",
714 "paragraph",
715 "periodcentered",
716 "cedilla",
717 "onesuperior",
718 "ordmasculine",
719 "guillemotright",
720 "onequarter",
721 "onehalf",
722 "threequarters",
723 "questiondown",
724 "Agrave",
725 "Aacute",
726 "Acircumflex",
727 "Atilde",
728 "Adieresis",
729 "Aring",
730 "AE",
731 "Ccedilla",
732 "Egrave",
733 "Eacute",
734 "Ecircumflex",
735 "Edieresis",
736 "Igrave",
737 "Iacute",
738 "Icircumflex",
739 "Idieresis",
740 "Eth",
741 "Ntilde",
742 "Ograve",
743 "Oacute",
744 "Ocircumflex",
745 "Otilde",
746 "Odieresis",
747 "multiply",
748 "Oslash",
749 "Ugrave",
750 "Uacute",
751 "Ucircumflex",
752 "Udieresis",
753 "Yacute",
754 "Thorn",
755 "germandbls",
756 "agrave",
757 "aacute",
758 "acircumflex",
759 "atilde",
760 "adieresis",
761 "aring",
762 "ae",
763 "ccedilla",
764 "egrave",
765 "eacute",
766 "ecircumflex",
767 "edieresis",
768 "igrave",
769 "iacute",
770 "icircumflex",
771 "idieresis",
772 "eth",
773 "ntilde",
774 "ograve",
775 "oacute",
776 "ocircumflex",
777 "otilde",
778 "odieresis",
779 "divide",
780 "oslash",
781 "ugrave",
782 "uacute",
783 "ucircumflex",
784 "udieresis",
785 "yacute",
786 "thorn",
787 "ydieresis"
788};
789
790char *standardEncoding[256] = {
791 NULL,
792 NULL,
793 NULL,
794 NULL,
795 NULL,
796 NULL,
797 NULL,
798 NULL,
799 NULL,
800 NULL,
801 NULL,
802 NULL,
803 NULL,
804 NULL,
805 NULL,
806 NULL,
807 NULL,
808 NULL,
809 NULL,
810 NULL,
811 NULL,
812 NULL,
813 NULL,
814 NULL,
815 NULL,
816 NULL,
817 NULL,
818 NULL,
819 NULL,
820 NULL,
821 NULL,
822 NULL,
823 "space",
824 "exclam",
825 "quotedbl",
826 "numbersign",
827 "dollar",
828 "percent",
829 "ampersand",
830 "quoteright",
831 "parenleft",
832 "parenright",
833 "asterisk",
834 "plus",
835 "comma",
836 "hyphen",
837 "period",
838 "slash",
839 "zero",
840 "one",
841 "two",
842 "three",
843 "four",
844 "five",
845 "six",
846 "seven",
847 "eight",
848 "nine",
849 "colon",
850 "semicolon",
851 "less",
852 "equal",
853 "greater",
854 "question",
855 "at",
856 "A",
857 "B",
858 "C",
859 "D",
860 "E",
861 "F",
862 "G",
863 "H",
864 "I",
865 "J",
866 "K",
867 "L",
868 "M",
869 "N",
870 "O",
871 "P",
872 "Q",
873 "R",
874 "S",
875 "T",
876 "U",
877 "V",
878 "W",
879 "X",
880 "Y",
881 "Z",
882 "bracketleft",
883 "backslash",
884 "bracketright",
885 "asciicircum",
886 "underscore",
887 "quoteleft",
888 "a",
889 "b",
890 "c",
891 "d",
892 "e",
893 "f",
894 "g",
895 "h",
896 "i",
897 "j",
898 "k",
899 "l",
900 "m",
901 "n",
902 "o",
903 "p",
904 "q",
905 "r",
906 "s",
907 "t",
908 "u",
909 "v",
910 "w",
911 "x",
912 "y",
913 "z",
914 "braceleft",
915 "bar",
916 "braceright",
917 "asciitilde",
918 NULL,
919 NULL,
920 NULL,
921 NULL,
922 NULL,
923 NULL,
924 NULL,
925 NULL,
926 NULL,
927 NULL,
928 NULL,
929 NULL,
930 NULL,
931 NULL,
932 NULL,
933 NULL,
934 NULL,
935 NULL,
936 NULL,
937 NULL,
938 NULL,
939 NULL,
940 NULL,
941 NULL,
942 NULL,
943 NULL,
944 NULL,
945 NULL,
946 NULL,
947 NULL,
948 NULL,
949 NULL,
950 NULL,
951 NULL,
952 "exclamdown",
953 "cent",
954 "sterling",
955 "fraction",
956 "yen",
957 "florin",
958 "section",
959 "currency",
960 "quotesingle",
961 "quotedblleft",
962 "guillemotleft",
963 "guilsinglleft",
964 "guilsinglright",
965 "fi",
966 "fl",
967 NULL,
968 "endash",
969 "dagger",
970 "daggerdbl",
971 "periodcentered",
972 NULL,
973 "paragraph",
974 "bullet",
975 "quotesinglbase",
976 "quotedblbase",
977 "quotedblright",
978 "guillemotright",
979 "ellipsis",
980 "perthousand",
981 NULL,
982 "questiondown",
983 NULL,
984 "grave",
985 "acute",
986 "circumflex",
987 "tilde",
988 "macron",
989 "breve",
990 "dotaccent",
991 "dieresis",
992 NULL,
993 "ring",
994 "cedilla",
995 NULL,
996 "hungarumlaut",
997 "ogonek",
998 "caron",
999 "emdash",
1000 NULL,
1001 NULL,
1002 NULL,
1003 NULL,
1004 NULL,
1005 NULL,
1006 NULL,
1007 NULL,
1008 NULL,
1009 NULL,
1010 NULL,
1011 NULL,
1012 NULL,
1013 NULL,
1014 NULL,
1015 NULL,
1016 "AE",
1017 NULL,
1018 "ordfeminine",
1019 NULL,
1020 NULL,
1021 NULL,
1022 NULL,
1023 "Lslash",
1024 "Oslash",
1025 "OE",
1026 "ordmasculine",
1027 NULL,
1028 NULL,
1029 NULL,
1030 NULL,
1031 NULL,
1032 "ae",
1033 NULL,
1034 NULL,
1035 NULL,
1036 "dotlessi",
1037 NULL,
1038 NULL,
1039 "lslash",
1040 "oslash",
1041 "oe",
1042 "germandbls",
1043 NULL,
1044 NULL,
1045 NULL,
1046 NULL
1047};
1048
1049char *expertEncoding[256] = {
1050 NULL,
1051 NULL,
1052 NULL,
1053 NULL,
1054 NULL,
1055 NULL,
1056 NULL,
1057 NULL,
1058 NULL,
1059 NULL,
1060 NULL,
1061 NULL,
1062 NULL,
1063 NULL,
1064 NULL,
1065 NULL,
1066 NULL,
1067 NULL,
1068 NULL,
1069 NULL,
1070 NULL,
1071 NULL,
1072 NULL,
1073 NULL,
1074 NULL,
1075 NULL,
1076 NULL,
1077 NULL,
1078 NULL,
1079 NULL,
1080 NULL,
1081 NULL,
1082 "space",
1083 "exclamsmall",
1084 "Hungarumlautsmall",
1085 NULL,
1086 "dollaroldstyle",
1087 "dollarsuperior",
1088 "ampersandsmall",
1089 "Acutesmall",
1090 "parenleftsuperior",
1091 "parenrightsuperior",
1092 "twodotenleader",
1093 "onedotenleader",
1094 "comma",
1095 "hyphen",
1096 "period",
1097 "fraction",
1098 "zerooldstyle",
1099 "oneoldstyle",
1100 "twooldstyle",
1101 "threeoldstyle",
1102 "fouroldstyle",
1103 "fiveoldstyle",
1104 "sixoldstyle",
1105 "sevenoldstyle",
1106 "eightoldstyle",
1107 "nineoldstyle",
1108 "colon",
1109 "semicolon",
1110 "commasuperior",
1111 "threequartersemdash",
1112 "periodsuperior",
1113 "questionsmall",
1114 NULL,
1115 "asuperior",
1116 "bsuperior",
1117 "centsuperior",
1118 "dsuperior",
1119 "esuperior",
1120 NULL,
1121 NULL,
1122 NULL,
1123 "isuperior",
1124 NULL,
1125 NULL,
1126 "lsuperior",
1127 "msuperior",
1128 "nsuperior",
1129 "osuperior",
1130 NULL,
1131 NULL,
1132 "rsuperior",
1133 "ssuperior",
1134 "tsuperior",
1135 NULL,
1136 "ff",
1137 "fi",
1138 "fl",
1139 "ffi",
1140 "ffl",
1141 "parenleftinferior",
1142 NULL,
1143 "parenrightinferior",
1144 "Circumflexsmall",
1145 "hyphensuperior",
1146 "Gravesmall",
1147 "Asmall",
1148 "Bsmall",
1149 "Csmall",
1150 "Dsmall",
1151 "Esmall",
1152 "Fsmall",
1153 "Gsmall",
1154 "Hsmall",
1155 "Ismall",
1156 "Jsmall",
1157 "Ksmall",
1158 "Lsmall",
1159 "Msmall",
1160 "Nsmall",
1161 "Osmall",
1162 "Psmall",
1163 "Qsmall",
1164 "Rsmall",
1165 "Ssmall",
1166 "Tsmall",
1167 "Usmall",
1168 "Vsmall",
1169 "Wsmall",
1170 "Xsmall",
1171 "Ysmall",
1172 "Zsmall",
1173 "colonmonetary",
1174 "onefitted",
1175 "rupiah",
1176 "Tildesmall",
1177 NULL,
1178 NULL,
1179 NULL,
1180 NULL,
1181 NULL,
1182 NULL,
1183 NULL,
1184 NULL,
1185 NULL,
1186 NULL,
1187 NULL,
1188 NULL,
1189 NULL,
1190 NULL,
1191 NULL,
1192 NULL,
1193 NULL,
1194 NULL,
1195 NULL,
1196 NULL,
1197 NULL,
1198 NULL,
1199 NULL,
1200 NULL,
1201 NULL,
1202 NULL,
1203 NULL,
1204 NULL,
1205 NULL,
1206 NULL,
1207 NULL,
1208 NULL,
1209 NULL,
1210 NULL,
1211 "exclamdownsmall",
1212 "centoldstyle",
1213 "Lslashsmall",
1214 NULL,
1215 NULL,
1216 "Scaronsmall",
1217 "Zcaronsmall",
1218 "Dieresissmall",
1219 "Brevesmall",
1220 "Caronsmall",
1221 NULL,
1222 "Dotaccentsmall",
1223 NULL,
1224 NULL,
1225 "Macronsmall",
1226 NULL,
1227 NULL,
1228 "figuredash",
1229 "hypheninferior",
1230 NULL,
1231 NULL,
1232 "Ogoneksmall",
1233 "Ringsmall",
1234 "Cedillasmall",
1235 NULL,
1236 NULL,
1237 NULL,
1238 "onequarter",
1239 "onehalf",
1240 "threequarters",
1241 "questiondownsmall",
1242 "oneeighth",
1243 "threeeighths",
1244 "fiveeighths",
1245 "seveneighths",
1246 "onethird",
1247 "twothirds",
1248 NULL,
1249 NULL,
1250 "zerosuperior",
1251 "onesuperior",
1252 "twosuperior",
1253 "threesuperior",
1254 "foursuperior",
1255 "fivesuperior",
1256 "sixsuperior",
1257 "sevensuperior",
1258 "eightsuperior",
1259 "ninesuperior",
1260 "zeroinferior",
1261 "oneinferior",
1262 "twoinferior",
1263 "threeinferior",
1264 "fourinferior",
1265 "fiveinferior",
1266 "sixinferior",
1267 "seveninferior",
1268 "eightinferior",
1269 "nineinferior",
1270 "centinferior",
1271 "dollarinferior",
1272 "periodinferior",
1273 "commainferior",
1274 "Agravesmall",
1275 "Aacutesmall",
1276 "Acircumflexsmall",
1277 "Atildesmall",
1278 "Adieresissmall",
1279 "Aringsmall",
1280 "AEsmall",
1281 "Ccedillasmall",
1282 "Egravesmall",
1283 "Eacutesmall",
1284 "Ecircumflexsmall",
1285 "Edieresissmall",
1286 "Igravesmall",
1287 "Iacutesmall",
1288 "Icircumflexsmall",
1289 "Idieresissmall",
1290 "Ethsmall",
1291 "Ntildesmall",
1292 "Ogravesmall",
1293 "Oacutesmall",
1294 "Ocircumflexsmall",
1295 "Otildesmall",
1296 "Odieresissmall",
1297 "OEsmall",
1298 "Oslashsmall",
1299 "Ugravesmall",
1300 "Uacutesmall",
1301 "Ucircumflexsmall",
1302 "Udieresissmall",
1303 "Yacutesmall",
1304 "Thornsmall",
1305 "Ydieresissmall"
1306};
1307
1308char *symbolEncoding[256] = {
1309 NULL,
1310 NULL,
1311 NULL,
1312 NULL,
1313 NULL,
1314 NULL,
1315 NULL,
1316 NULL,
1317 NULL,
1318 NULL,
1319 NULL,
1320 NULL,
1321 NULL,
1322 NULL,
1323 NULL,
1324 NULL,
1325 NULL,
1326 NULL,
1327 NULL,
1328 NULL,
1329 NULL,
1330 NULL,
1331 NULL,
1332 NULL,
1333 NULL,
1334 NULL,
1335 NULL,
1336 NULL,
1337 NULL,
1338 NULL,
1339 NULL,
1340 NULL,
1341 "space",
1342 "exclam",
1343 "universal",
1344 "numbersign",
1345 "existential",
1346 "percent",
1347 "ampersand",
1348 "suchthat",
1349 "parenleft",
1350 "parenright",
1351 "asteriskmath",
1352 "plus",
1353 "comma",
1354 "minus",
1355 "period",
1356 "slash",
1357 "zero",
1358 "one",
1359 "two",
1360 "three",
1361 "four",
1362 "five",
1363 "six",
1364 "seven",
1365 "eight",
1366 "nine",
1367 "colon",
1368 "semicolon",
1369 "less",
1370 "equal",
1371 "greater",
1372 "question",
1373 "congruent",
1374 "Alpha",
1375 "Beta",
1376 "Chi",
1377 "Delta",
1378 "Epsilon",
1379 "Phi",
1380 "Gamma",
1381 "Eta",
1382 "Iota",
1383 "theta1",
1384 "Kappa",
1385 "Lambda",
1386 "Mu",
1387 "Nu",
1388 "Omicron",
1389 "Pi",
1390 "Theta",
1391 "Rho",
1392 "Sigma",
1393 "Tau",
1394 "Upsilon",
1395 "sigma1",
1396 "Omega",
1397 "Xi",
1398 "Psi",
1399 "Zeta",
1400 "bracketleft",
1401 "therefore",
1402 "bracketright",
1403 "perpendicular",
1404 "underscore",
1405 "radicalex",
1406 "alpha",
1407 "beta",
1408 "chi",
1409 "delta",
1410 "epsilon",
1411 "phi",
1412 "gamma",
1413 "eta",
1414 "iota",
1415 "phi1",
1416 "kappa",
1417 "lambda",
1418 "mu",
1419 "nu",
1420 "omicron",
1421 "pi",
1422 "theta",
1423 "rho",
1424 "sigma",
1425 "tau",
1426 "upsilon",
1427 "omega1",
1428 "omega",
1429 "xi",
1430 "psi",
1431 "zeta",
1432 "braceleft",
1433 "bar",
1434 "braceright",
1435 "similar",
1436 NULL,
1437 NULL,
1438 NULL,
1439 NULL,
1440 NULL,
1441 NULL,
1442 NULL,
1443 NULL,
1444 NULL,
1445 NULL,
1446 NULL,
1447 NULL,
1448 NULL,
1449 NULL,
1450 NULL,
1451 NULL,
1452 NULL,
1453 NULL,
1454 NULL,
1455 NULL,
1456 NULL,
1457 NULL,
1458 NULL,
1459 NULL,
1460 NULL,
1461 NULL,
1462 NULL,
1463 NULL,
1464 NULL,
1465 NULL,
1466 NULL,
1467 NULL,
1468 NULL,
1469 NULL,
1470 "Upsilon1",
1471 "minute",
1472 "lessequal",
1473 "fraction",
1474 "infinity",
1475 "florin",
1476 "club",
1477 "diamond",
1478 "heart",
1479 "spade",
1480 "arrowboth",
1481 "arrowleft",
1482 "arrowup",
1483 "arrowright",
1484 "arrowdown",
1485 "degree",
1486 "plusminus",
1487 "second",
1488 "greaterequal",
1489 "multiply",
1490 "proportional",
1491 "partialdiff",
1492 "bullet",
1493 "divide",
1494 "notequal",
1495 "equivalence",
1496 "approxequal",
1497 "ellipsis",
1498 "arrowvertex",
1499 "arrowhorizex",
1500 "carriagereturn",
1501 "aleph",
1502 "Ifraktur",
1503 "Rfraktur",
1504 "weierstrass",
1505 "circlemultiply",
1506 "circleplus",
1507 "emptyset",
1508 "intersection",
1509 "union",
1510 "propersuperset",
1511 "reflexsuperset",
1512 "notsubset",
1513 "propersubset",
1514 "reflexsubset",
1515 "element",
1516 "notelement",
1517 "angle",
1518 "gradient",
1519 "registerserif",
1520 "copyrightserif",
1521 "trademarkserif",
1522 "product",
1523 "radical",
1524 "dotmath",
1525 "logicalnot",
1526 "logicaland",
1527 "logicalor",
1528 "arrowdblboth",
1529 "arrowdblleft",
1530 "arrowdblup",
1531 "arrowdblright",
1532 "arrowdbldown",
1533 "lozenge",
1534 "angleleft",
1535 "registersans",
1536 "copyrightsans",
1537 "trademarksans",
1538 "summation",
1539 "parenlefttp",
1540 "parenleftex",
1541 "parenleftbt",
1542 "bracketlefttp",
1543 "bracketleftex",
1544 "bracketleftbt",
1545 "bracelefttp",
1546 "braceleftmid",
1547 "braceleftbt",
1548 "braceex",
1549 NULL,
1550 "angleright",
1551 "integral",
1552 "integraltp",
1553 "integralex",
1554 "integralbt",
1555 "parenrighttp",
1556 "parenrightex",
1557 "parenrightbt",
1558 "bracketrighttp",
1559 "bracketrightex",
1560 "bracketrightbt",
1561 "bracerighttp",
1562 "bracerightmid",
1563 "bracerightbt",
1564 NULL
1565};
1566
1567char *zapfDingbatsEncoding[256] = {
1568 NULL,
1569 NULL,
1570 NULL,
1571 NULL,
1572 NULL,
1573 NULL,
1574 NULL,
1575 NULL,
1576 NULL,
1577 NULL,
1578 NULL,
1579 NULL,
1580 NULL,
1581 NULL,
1582 NULL,
1583 NULL,
1584 NULL,
1585 NULL,
1586 NULL,
1587 NULL,
1588 NULL,
1589 NULL,
1590 NULL,
1591 NULL,
1592 NULL,
1593 NULL,
1594 NULL,
1595 NULL,
1596 NULL,
1597 NULL,
1598 NULL,
1599 NULL,
1600 "space",
1601 "a1",
1602 "a2",
1603 "a202",
1604 "a3",
1605 "a4",
1606 "a5",
1607 "a119",
1608 "a118",
1609 "a117",
1610 "a11",
1611 "a12",
1612 "a13",
1613 "a14",
1614 "a15",
1615 "a16",
1616 "a105",
1617 "a17",
1618 "a18",
1619 "a19",
1620 "a20",
1621 "a21",
1622 "a22",
1623 "a23",
1624 "a24",
1625 "a25",
1626 "a26",
1627 "a27",
1628 "a28",
1629 "a6",
1630 "a7",
1631 "a8",
1632 "a9",
1633 "a10",
1634 "a29",
1635 "a30",
1636 "a31",
1637 "a32",
1638 "a33",
1639 "a34",
1640 "a35",
1641 "a36",
1642 "a37",
1643 "a38",
1644 "a39",
1645 "a40",
1646 "a41",
1647 "a42",
1648 "a43",
1649 "a44",
1650 "a45",
1651 "a46",
1652 "a47",
1653 "a48",
1654 "a49",
1655 "a50",
1656 "a51",
1657 "a52",
1658 "a53",
1659 "a54",
1660 "a55",
1661 "a56",
1662 "a57",
1663 "a58",
1664 "a59",
1665 "a60",
1666 "a61",
1667 "a62",
1668 "a63",
1669 "a64",
1670 "a65",
1671 "a66",
1672 "a67",
1673 "a68",
1674 "a69",
1675 "a70",
1676 "a71",
1677 "a72",
1678 "a73",
1679 "a74",
1680 "a203",
1681 "a75",
1682 "a204",
1683 "a76",
1684 "a77",
1685 "a78",
1686 "a79",
1687 "a81",
1688 "a82",
1689 "a83",
1690 "a84",
1691 "a97",
1692 "a98",
1693 "a99",
1694 "a100",
1695 NULL,
1696 NULL,
1697 NULL,
1698 NULL,
1699 NULL,
1700 NULL,
1701 NULL,
1702 NULL,
1703 NULL,
1704 NULL,
1705 NULL,
1706 NULL,
1707 NULL,
1708 NULL,
1709 NULL,
1710 NULL,
1711 NULL,
1712 NULL,
1713 NULL,
1714 NULL,
1715 NULL,
1716 NULL,
1717 NULL,
1718 NULL,
1719 NULL,
1720 NULL,
1721 NULL,
1722 NULL,
1723 NULL,
1724 NULL,
1725 NULL,
1726 NULL,
1727 NULL,
1728 NULL,
1729 "a101",
1730 "a102",
1731 "a103",
1732 "a104",
1733 "a106",
1734 "a107",
1735 "a108",
1736 "a112",
1737 "a111",
1738 "a110",
1739 "a109",
1740 "a120",
1741 "a121",
1742 "a122",
1743 "a123",
1744 "a124",
1745 "a125",
1746 "a126",
1747 "a127",
1748 "a128",
1749 "a129",
1750 "a130",
1751 "a131",
1752 "a132",
1753 "a133",
1754 "a134",
1755 "a135",
1756 "a136",
1757 "a137",
1758 "a138",
1759 "a139",
1760 "a140",
1761 "a141",
1762 "a142",
1763 "a143",
1764 "a144",
1765 "a145",
1766 "a146",
1767 "a147",
1768 "a148",
1769 "a149",
1770 "a150",
1771 "a151",
1772 "a152",
1773 "a153",
1774 "a154",
1775 "a155",
1776 "a156",
1777 "a157",
1778 "a158",
1779 "a159",
1780 "a160",
1781 "a161",
1782 "a163",
1783 "a164",
1784 "a196",
1785 "a165",
1786 "a192",
1787 "a166",
1788 "a167",
1789 "a168",
1790 "a169",
1791 "a170",
1792 "a171",
1793 "a172",
1794 "a173",
1795 "a162",
1796 "a174",
1797 "a175",
1798 "a176",
1799 "a177",
1800 "a178",
1801 "a179",
1802 "a193",
1803 "a180",
1804 "a199",
1805 "a181",
1806 "a200",
1807 "a182",
1808 NULL,
1809 "a201",
1810 "a183",
1811 "a184",
1812 "a197",
1813 "a185",
1814 "a194",
1815 "a198",
1816 "a186",
1817 "a195",
1818 "a187",
1819 "a188",
1820 "a189",
1821 "a190",
1822 "a191",
1823 NULL
1824};
diff --git a/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h
new file mode 100644
index 0000000..4646a43
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h
@@ -0,0 +1,20 @@
1//========================================================================
2//
3// FontEncodingTables.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef FONTENCODINGTABLES_H
10#define FONTENCODINGTABLES_H
11
12extern char *macRomanEncoding[];
13extern char *macExpertEncoding[];
14extern char *winAnsiEncoding[];
15extern char *standardEncoding[];
16extern char *expertEncoding[];
17extern char *symbolEncoding[];
18extern char *zapfDingbatsEncoding[];
19
20#endif
diff --git a/noncore/unsupported/qpdf/xpdf/FontFile.h b/noncore/unsupported/qpdf/xpdf/FontFile.h
new file mode 100644
index 0000000..e9d2ae7
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/FontFile.h
@@ -0,0 +1,10 @@
1#ifndef FONTFILE_H
2#define FONTFILE_H
3
4// dummy
5
6typedef int FontFile;
7
8
9#endif
10
diff --git a/noncore/unsupported/qpdf/xpdf/FormWidget.cc b/noncore/unsupported/qpdf/xpdf/FormWidget.cc
new file mode 100644
index 0000000..05c67a4
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/FormWidget.cc
@@ -0,0 +1,139 @@
1//========================================================================
2//
3// FormWidget.cc
4//
5// Copyright 2000 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include "gmem.h"
15#include "Object.h"
16#include "Gfx.h"
17#include "FormWidget.h"
18
19//------------------------------------------------------------------------
20// FormWidget
21//------------------------------------------------------------------------
22
23FormWidget::FormWidget(XRef *xrefA, Dict *dict) {
24 Object apObj, asObj, obj1, obj2;
25 fouble t;
26
27 ok = gFalse;
28 xref = xrefA;
29
30 if (dict->lookup("AP", &apObj)->isDict()) {
31 if (dict->lookup("AS", &asObj)->isName()) {
32 if (apObj.dictLookup("N", &obj1)->isDict()) {
33 if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
34 obj2.copy(&appearance);
35 ok = gTrue;
36 }
37 obj2.free();
38 }
39 obj1.free();
40 } else {
41 if (apObj.dictLookupNF("N", &obj1)->isRef()) {
42 obj1.copy(&appearance);
43 ok = gTrue;
44 }
45 obj1.free();
46 }
47 asObj.free();
48 }
49 apObj.free();
50
51 if (dict->lookup("Rect", &obj1)->isArray() &&
52 obj1.arrayGetLength() == 4) {
53 //~ should check object types here
54 obj1.arrayGet(0, &obj2);
55 xMin = obj2.getNum();
56 obj2.free();
57 obj1.arrayGet(1, &obj2);
58 yMin = obj2.getNum();
59 obj2.free();
60 obj1.arrayGet(2, &obj2);
61 xMax = obj2.getNum();
62 obj2.free();
63 obj1.arrayGet(3, &obj2);
64 yMax = obj2.getNum();
65 obj2.free();
66 if (xMin > xMax) {
67 t = xMin; xMin = xMax; xMax = t;
68 }
69 if (yMin > yMax) {
70 t = yMin; yMin = yMax; yMax = t;
71 }
72 } else {
73 //~ this should return an error
74 xMin = yMin = 0;
75 xMax = yMax = 1;
76 }
77 obj1.free();
78}
79
80FormWidget::~FormWidget() {
81 appearance.free();
82}
83
84void FormWidget::draw(Gfx *gfx) {
85 Object obj;
86
87 if (appearance.fetch(xref, &obj)->isStream()) {
88 gfx->doWidgetForm(&obj, xMin, yMin, xMax, yMax);
89 }
90 obj.free();
91}
92
93//------------------------------------------------------------------------
94// FormWidgets
95//------------------------------------------------------------------------
96
97FormWidgets::FormWidgets(XRef *xref, Object *annots) {
98 FormWidget *widget;
99 Object obj1, obj2;
100 int size;
101 int i;
102
103 widgets = NULL;
104 size = 0;
105 nWidgets = 0;
106
107 if (annots->isArray()) {
108 for (i = 0; i < annots->arrayGetLength(); ++i) {
109 if (annots->arrayGet(i, &obj1)->isDict()) {
110 obj1.dictLookup("Subtype", &obj2);
111 if (obj2.isName("Widget") ||
112 obj2.isName("Stamp")) {
113 widget = new FormWidget(xref, obj1.getDict());
114 if (widget->isOk()) {
115 if (nWidgets >= size) {
116 size += 16;
117 widgets = (FormWidget **)grealloc(widgets,
118 size * sizeof(FormWidget *));
119 }
120 widgets[nWidgets++] = widget;
121 } else {
122 delete widget;
123 }
124 }
125 obj2.free();
126 }
127 obj1.free();
128 }
129 }
130}
131
132FormWidgets::~FormWidgets() {
133 int i;
134
135 for (i = 0; i < nWidgets; ++i) {
136 delete widgets[i];
137 }
138 gfree(widgets);
139}
diff --git a/noncore/unsupported/qpdf/xpdf/FormWidget.h b/noncore/unsupported/qpdf/xpdf/FormWidget.h
new file mode 100644
index 0000000..7f07889
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/FormWidget.h
@@ -0,0 +1,67 @@
1//========================================================================
2//
3// FormWidget.h
4//
5// Copyright 2000 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef FORMWIDGET_H
10#define FORMWIDGET_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16class XRef;
17class Gfx;
18
19//------------------------------------------------------------------------
20// FormWidget
21//------------------------------------------------------------------------
22
23class FormWidget {
24public:
25
26 FormWidget(XRef *xrefA, Dict *dict);
27 ~FormWidget();
28 GBool isOk() { return ok; }
29
30 void draw(Gfx *gfx);
31
32 // Get appearance object.
33 Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
34
35private:
36
37 XRef *xref; // the xref table for this PDF file
38 Object appearance; // a reference to the Form XObject stream
39 // for the normal appearance
40 fouble xMin, yMin, // widget rectangle
41 xMax, yMax;
42 GBool ok;
43};
44
45//------------------------------------------------------------------------
46// FormWidgets
47//------------------------------------------------------------------------
48
49class FormWidgets {
50public:
51
52 // Extract widgets from array of annotations.
53 FormWidgets(XRef *xref, Object *annots);
54
55 ~FormWidgets();
56
57 // Iterate through list of widgets.
58 int getNumWidgets() { return nWidgets; }
59 FormWidget *getWidget(int i) { return widgets[i]; }
60
61private:
62
63 FormWidget **widgets;
64 int nWidgets;
65};
66
67#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Function.cc b/noncore/unsupported/qpdf/xpdf/Function.cc
new file mode 100644
index 0000000..815cc89
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Function.cc
@@ -0,0 +1,1511 @@
1//========================================================================
2//
3// Function.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdlib.h>
15#include <string.h>
16#include <ctype.h>
17#include <math.h>
18#include "gmem.h"
19#include "Object.h"
20#include "Dict.h"
21#include "Stream.h"
22#include "Error.h"
23#include "Function.h"
24
25//------------------------------------------------------------------------
26// Function
27//------------------------------------------------------------------------
28
29Function::Function() {
30}
31
32Function::~Function() {
33}
34
35Function *Function::parse(Object *funcObj) {
36 Function *func;
37 Dict *dict;
38 int funcType;
39 Object obj1;
40
41 if (funcObj->isStream()) {
42 dict = funcObj->streamGetDict();
43 } else if (funcObj->isDict()) {
44 dict = funcObj->getDict();
45 } else if (funcObj->isName("Identity")) {
46 return new IdentityFunction();
47 } else {
48 error(-1, "Expected function dictionary or stream");
49 return NULL;
50 }
51
52 if (!dict->lookup("FunctionType", &obj1)->isInt()) {
53 error(-1, "Function type is missing or wrong type");
54 obj1.free();
55 return NULL;
56 }
57 funcType = obj1.getInt();
58 obj1.free();
59
60 if (funcType == 0) {
61 func = new SampledFunction(funcObj, dict);
62 } else if (funcType == 2) {
63 func = new ExponentialFunction(funcObj, dict);
64 } else if (funcType == 3) {
65 func = new StitchingFunction(funcObj, dict);
66 } else if (funcType == 4) {
67 func = new PostScriptFunction(funcObj, dict);
68 } else {
69 error(-1, "Unimplemented function type (%d)", funcType);
70 return NULL;
71 }
72 if (!func->isOk()) {
73 delete func;
74 return NULL;
75 }
76
77 return func;
78}
79
80GBool Function::init(Dict *dict) {
81 Object obj1, obj2;
82 int i;
83
84 //----- Domain
85 if (!dict->lookup("Domain", &obj1)->isArray()) {
86 error(-1, "Function is missing domain");
87 goto err2;
88 }
89 m = obj1.arrayGetLength() / 2;
90 if (m > funcMaxInputs) {
91 error(-1, "Functions with more than %d inputs are unsupported",
92 funcMaxInputs);
93 goto err2;
94 }
95 for (i = 0; i < m; ++i) {
96 obj1.arrayGet(2*i, &obj2);
97 if (!obj2.isNum()) {
98 error(-1, "Illegal value in function domain array");
99 goto err1;
100 }
101 domain[i][0] = obj2.getNum();
102 obj2.free();
103 obj1.arrayGet(2*i+1, &obj2);
104 if (!obj2.isNum()) {
105 error(-1, "Illegal value in function domain array");
106 goto err1;
107 }
108 domain[i][1] = obj2.getNum();
109 obj2.free();
110 }
111 obj1.free();
112
113 //----- Range
114 hasRange = gFalse;
115 n = 0;
116 if (dict->lookup("Range", &obj1)->isArray()) {
117 hasRange = gTrue;
118 n = obj1.arrayGetLength() / 2;
119 if (n > funcMaxOutputs) {
120 error(-1, "Functions with more than %d outputs are unsupported",
121 funcMaxOutputs);
122 goto err2;
123 }
124 for (i = 0; i < n; ++i) {
125 obj1.arrayGet(2*i, &obj2);
126 if (!obj2.isNum()) {
127 error(-1, "Illegal value in function range array");
128 goto err1;
129 }
130 range[i][0] = obj2.getNum();
131 obj2.free();
132 obj1.arrayGet(2*i+1, &obj2);
133 if (!obj2.isNum()) {
134 error(-1, "Illegal value in function range array");
135 goto err1;
136 }
137 range[i][1] = obj2.getNum();
138 obj2.free();
139 }
140 }
141 obj1.free();
142
143 return gTrue;
144
145 err1:
146 obj2.free();
147 err2:
148 obj1.free();
149 return gFalse;
150}
151
152//------------------------------------------------------------------------
153// IdentityFunction
154//------------------------------------------------------------------------
155
156IdentityFunction::IdentityFunction() {
157 int i;
158
159 // fill these in with arbitrary values just in case they get used
160 // somewhere
161 m = funcMaxInputs;
162 n = funcMaxOutputs;
163 for (i = 0; i < funcMaxInputs; ++i) {
164 domain[i][0] = 0;
165 domain[i][1] = 1;
166 }
167 hasRange = gFalse;
168}
169
170IdentityFunction::~IdentityFunction() {
171}
172
173void IdentityFunction::transform(fouble *in, fouble *out) {
174 int i;
175
176 for (i = 0; i < funcMaxOutputs; ++i) {
177 out[i] = in[i];
178 }
179}
180
181//------------------------------------------------------------------------
182// SampledFunction
183//------------------------------------------------------------------------
184
185SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
186 Stream *str;
187 int nSamples, sampleBits;
188 fouble sampleMul;
189 Object obj1, obj2;
190 Guint buf, bitMask;
191 int bits;
192 int s;
193 int i;
194
195 samples = NULL;
196 ok = gFalse;
197
198 //----- initialize the generic stuff
199 if (!init(dict)) {
200 goto err1;
201 }
202 if (!hasRange) {
203 error(-1, "Type 0 function is missing range");
204 goto err1;
205 }
206
207 //----- get the stream
208 if (!funcObj->isStream()) {
209 error(-1, "Type 0 function isn't a stream");
210 goto err1;
211 }
212 str = funcObj->getStream();
213
214 //----- Size
215 if (!dict->lookup("Size", &obj1)->isArray() ||
216 obj1.arrayGetLength() != m) {
217 error(-1, "Function has missing or invalid size array");
218 goto err2;
219 }
220 for (i = 0; i < m; ++i) {
221 obj1.arrayGet(i, &obj2);
222 if (!obj2.isInt()) {
223 error(-1, "Illegal value in function size array");
224 goto err3;
225 }
226 sampleSize[i] = obj2.getInt();
227 obj2.free();
228 }
229 obj1.free();
230
231 //----- BitsPerSample
232 if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
233 error(-1, "Function has missing or invalid BitsPerSample");
234 goto err2;
235 }
236 sampleBits = obj1.getInt();
237 sampleMul = 1.0 / (fouble)((1 << sampleBits) - 1);
238 obj1.free();
239
240 //----- Encode
241 if (dict->lookup("Encode", &obj1)->isArray() &&
242 obj1.arrayGetLength() == 2*m) {
243 for (i = 0; i < m; ++i) {
244 obj1.arrayGet(2*i, &obj2);
245 if (!obj2.isNum()) {
246 error(-1, "Illegal value in function encode array");
247 goto err3;
248 }
249 encode[i][0] = obj2.getNum();
250 obj2.free();
251 obj1.arrayGet(2*i+1, &obj2);
252 if (!obj2.isNum()) {
253 error(-1, "Illegal value in function encode array");
254 goto err3;
255 }
256 encode[i][1] = obj2.getNum();
257 obj2.free();
258 }
259 } else {
260 for (i = 0; i < m; ++i) {
261 encode[i][0] = 0;
262 encode[i][1] = sampleSize[i] - 1;
263 }
264 }
265 obj1.free();
266
267 //----- Decode
268 if (dict->lookup("Decode", &obj1)->isArray() &&
269 obj1.arrayGetLength() == 2*n) {
270 for (i = 0; i < n; ++i) {
271 obj1.arrayGet(2*i, &obj2);
272 if (!obj2.isNum()) {
273 error(-1, "Illegal value in function decode array");
274 goto err3;
275 }
276 decode[i][0] = obj2.getNum();
277 obj2.free();
278 obj1.arrayGet(2*i+1, &obj2);
279 if (!obj2.isNum()) {
280 error(-1, "Illegal value in function decode array");
281 goto err3;
282 }
283 decode[i][1] = obj2.getNum();
284 obj2.free();
285 }
286 } else {
287 for (i = 0; i < n; ++i) {
288 decode[i][0] = range[i][0];
289 decode[i][1] = range[i][1];
290 }
291 }
292 obj1.free();
293
294 //----- samples
295 nSamples = n;
296 for (i = 0; i < m; ++i)
297 nSamples *= sampleSize[i];
298 samples = (fouble *)gmalloc(nSamples * sizeof(fouble));
299 buf = 0;
300 bits = 0;
301 bitMask = (1 << sampleBits) - 1;
302 str->reset();
303 for (i = 0; i < nSamples; ++i) {
304 if (sampleBits == 8) {
305 s = str->getChar();
306 } else if (sampleBits == 16) {
307 s = str->getChar();
308 s = (s << 8) + str->getChar();
309 } else if (sampleBits == 32) {
310 s = str->getChar();
311 s = (s << 8) + str->getChar();
312 s = (s << 8) + str->getChar();
313 s = (s << 8) + str->getChar();
314 } else {
315 while (bits < sampleBits) {
316 buf = (buf << 8) | (str->getChar() & 0xff);
317 bits += 8;
318 }
319 s = (buf >> (bits - sampleBits)) & bitMask;
320 bits -= sampleBits;
321 }
322 samples[i] = (fouble)s * sampleMul;
323 }
324 str->close();
325
326 ok = gTrue;
327 return;
328
329 err3:
330 obj2.free();
331 err2:
332 obj1.free();
333 err1:
334 return;
335}
336
337SampledFunction::~SampledFunction() {
338 if (samples) {
339 gfree(samples);
340 }
341}
342
343SampledFunction::SampledFunction(SampledFunction *func) {
344 int nSamples, i;
345
346 memcpy(this, func, sizeof(SampledFunction));
347
348 nSamples = n;
349 for (i = 0; i < m; ++i) {
350 nSamples *= sampleSize[i];
351 }
352 samples = (fouble *)gmalloc(nSamples * sizeof(fouble));
353 memcpy(samples, func->samples, nSamples * sizeof(fouble));
354}
355
356void SampledFunction::transform(fouble *in, fouble *out) {
357 fouble x;
358 int e[2][funcMaxInputs];
359 fouble efrac[funcMaxInputs];
360 fouble s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
361 int i, j, k, idx;
362
363 // map input values into sample array
364 for (i = 0; i < m; ++i) {
365 x = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
366 (encode[i][1] - encode[i][0]) + encode[i][0];
367 if (x < 0) {
368 x = 0;
369 } else if (x > sampleSize[i] - 1) {
370 x = sampleSize[i] - 1;
371 }
372 e[0][i] = (int)floor(x);
373 e[1][i] = (int)ceil(x);
374 efrac[i] = x - e[0][i];
375 }
376
377 // for each output, do m-linear interpolation
378 for (i = 0; i < n; ++i) {
379
380 // pull 2^m values out of the sample array
381 for (j = 0; j < (1<<m); ++j) {
382 idx = e[j & 1][m - 1];
383 for (k = m - 2; k >= 0; --k) {
384 idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
385 }
386 idx = idx * n + i;
387 s0[j] = samples[idx];
388 }
389
390 // do m sets of interpolations
391 for (j = 0; j < m; ++j) {
392 for (k = 0; k < (1 << (m - j)); k += 2) {
393 s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];
394 }
395 memcpy(s0, s1, (1 << (m - j - 1)) * sizeof(fouble));
396 }
397
398 // map output value to range
399 out[i] = s0[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
400 if (out[i] < range[i][0]) {
401 out[i] = range[i][0];
402 } else if (out[i] > range[i][1]) {
403 out[i] = range[i][1];
404 }
405 }
406}
407
408//------------------------------------------------------------------------
409// ExponentialFunction
410//------------------------------------------------------------------------
411
412ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
413 Object obj1, obj2;
414 GBool hasN;
415 int i;
416
417 ok = gFalse;
418 hasN = gFalse;
419
420 //----- initialize the generic stuff
421 if (!init(dict)) {
422 goto err1;
423 }
424 if (m != 1) {
425 error(-1, "Exponential function with more than one input");
426 goto err1;
427 }
428
429 //----- default values
430 for (i = 0; i < funcMaxOutputs; ++i) {
431 c0[i] = 0;
432 c1[i] = 1;
433 }
434
435 //----- C0
436 if (dict->lookup("C0", &obj1)->isArray()) {
437 if (!hasN) {
438 n = obj1.arrayGetLength();
439 } else if (obj1.arrayGetLength() != n) {
440 error(-1, "Function's C0 array is wrong length");
441 goto err2;
442 }
443 for (i = 0; i < n; ++i) {
444 obj1.arrayGet(i, &obj2);
445 if (!obj2.isNum()) {
446 error(-1, "Illegal value in function C0 array");
447 goto err3;
448 }
449 c0[i] = obj2.getNum();
450 obj2.free();
451 }
452 }
453 obj1.free();
454
455 //----- C1
456 if (dict->lookup("C1", &obj1)->isArray()) {
457 if (!hasN) {
458 n = obj1.arrayGetLength();
459 } else if (obj1.arrayGetLength() != n) {
460 error(-1, "Function's C1 array is wrong length");
461 goto err2;
462 }
463 for (i = 0; i < n; ++i) {
464 obj1.arrayGet(i, &obj2);
465 if (!obj2.isNum()) {
466 error(-1, "Illegal value in function C1 array");
467 goto err3;
468 }
469 c1[i] = obj2.getNum();
470 obj2.free();
471 }
472 }
473 obj1.free();
474
475 //----- N (exponent)
476 if (!dict->lookup("N", &obj1)->isNum()) {
477 error(-1, "Function has missing or invalid N");
478 goto err2;
479 }
480 e = obj1.getNum();
481 obj1.free();
482
483 ok = gTrue;
484 return;
485
486 err3:
487 obj2.free();
488 err2:
489 obj1.free();
490 err1:
491 return;
492}
493
494ExponentialFunction::~ExponentialFunction() {
495}
496
497ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
498 memcpy(this, func, sizeof(ExponentialFunction));
499}
500
501void ExponentialFunction::transform(fouble *in, fouble *out) {
502 fouble x;
503 int i;
504
505 if (in[0] < domain[0][0]) {
506 x = domain[0][0];
507 } else if (in[0] > domain[0][1]) {
508 x = domain[0][1];
509 } else {
510 x = in[0];
511 }
512 for (i = 0; i < n; ++i) {
513 out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
514 if (hasRange) {
515 if (out[i] < range[i][0]) {
516 out[i] = range[i][0];
517 } else if (out[i] > range[i][1]) {
518 out[i] = range[i][1];
519 }
520 }
521 }
522 return;
523}
524
525//------------------------------------------------------------------------
526// StitchingFunction
527//------------------------------------------------------------------------
528
529StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
530 Object obj1, obj2;
531 int i;
532
533 ok = gFalse;
534 funcs = NULL;
535 bounds = NULL;
536 encode = NULL;
537
538 //----- initialize the generic stuff
539 if (!init(dict)) {
540 goto err1;
541 }
542 if (m != 1) {
543 error(-1, "Stitching function with more than one input");
544 goto err1;
545 }
546
547 //----- Functions
548 if (!dict->lookup("Functions", &obj1)->isArray()) {
549 error(-1, "Missing 'Functions' entry in stitching function");
550 goto err1;
551 }
552 k = obj1.arrayGetLength();
553 funcs = (Function **)gmalloc(k * sizeof(Function *));
554 bounds = (fouble *)gmalloc((k + 1) * sizeof(fouble));
555 encode = (fouble *)gmalloc(2 * k * sizeof(fouble));
556 for (i = 0; i < k; ++i) {
557 funcs[i] = NULL;
558 }
559 for (i = 0; i < k; ++i) {
560 if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
561 goto err2;
562 }
563 if (i > 0 && (funcs[i]->getInputSize() != 1 ||
564 funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
565 error(-1, "Incompatible subfunctions in stitching function");
566 goto err2;
567 }
568 obj2.free();
569 }
570 obj1.free();
571
572 //----- Bounds
573 if (!dict->lookup("Bounds", &obj1)->isArray() ||
574 obj1.arrayGetLength() != k - 1) {
575 error(-1, "Missing or invalid 'Bounds' entry in stitching function");
576 goto err1;
577 }
578 bounds[0] = domain[0][0];
579 for (i = 1; i < k; ++i) {
580 if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
581 error(-1, "Invalid type in 'Bounds' array in stitching function");
582 goto err2;
583 }
584 bounds[i] = obj2.getNum();
585 obj2.free();
586 }
587 bounds[k] = domain[0][1];
588 obj1.free();
589
590 //----- Encode
591 if (!dict->lookup("Encode", &obj1)->isArray() ||
592 obj1.arrayGetLength() != 2 * k) {
593 error(-1, "Missing or invalid 'Encode' entry in stitching function");
594 goto err1;
595 }
596 for (i = 0; i < 2 * k; ++i) {
597 if (!obj1.arrayGet(i, &obj2)->isNum()) {
598 error(-1, "Invalid type in 'Encode' array in stitching function");
599 goto err2;
600 }
601 encode[i] = obj2.getNum();
602 obj2.free();
603 }
604 obj1.free();
605
606 ok = gTrue;
607 return;
608
609 err2:
610 obj2.free();
611 err1:
612 obj1.free();
613}
614
615StitchingFunction::StitchingFunction(StitchingFunction *func) {
616 k = func->k;
617 funcs = (Function **)gmalloc(k * sizeof(Function *));
618 memcpy(funcs, func->funcs, k * sizeof(Function *));
619 bounds = (fouble *)gmalloc((k + 1) * sizeof(fouble));
620 memcpy(bounds, func->bounds, (k + 1) * sizeof(fouble));
621 encode = (fouble *)gmalloc(2 * k * sizeof(fouble));
622 memcpy(encode, func->encode, 2 * k * sizeof(fouble));
623 ok = gTrue;
624}
625
626StitchingFunction::~StitchingFunction() {
627 int i;
628
629 for (i = 0; i < k; ++i) {
630 if (funcs[i]) {
631 delete funcs[i];
632 }
633 }
634 gfree(funcs);
635 gfree(bounds);
636 gfree(encode);
637}
638
639void StitchingFunction::transform(fouble *in, fouble *out) {
640 fouble x;
641 int i;
642
643 if (in[0] < domain[0][0]) {
644 x = domain[0][0];
645 } else if (in[0] > domain[0][1]) {
646 x = domain[0][1];
647 } else {
648 x = in[0];
649 }
650 for (i = 0; i < k - 1; ++i) {
651 if (x < bounds[i+1]) {
652 break;
653 }
654 }
655 x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
656 (encode[2*i+1] - encode[2*i]);
657 funcs[i]->transform(&x, out);
658}
659
660//------------------------------------------------------------------------
661// PostScriptFunction
662//------------------------------------------------------------------------
663
664enum PSOp {
665 psOpAbs,
666 psOpAdd,
667 psOpAnd,
668 psOpAtan,
669 psOpBitshift,
670 psOpCeiling,
671 psOpCopy,
672 psOpCos,
673 psOpCvi,
674 psOpCvr,
675 psOpDiv,
676 psOpDup,
677 psOpEq,
678 psOpExch,
679 psOpExp,
680 psOpFalse,
681 psOpFloor,
682 psOpGe,
683 psOpGt,
684 psOpIdiv,
685 psOpIndex,
686 psOpLe,
687 psOpLn,
688 psOpLog,
689 psOpLt,
690 psOpMod,
691 psOpMul,
692 psOpNe,
693 psOpNeg,
694 psOpNot,
695 psOpOr,
696 psOpPop,
697 psOpRoll,
698 psOpRound,
699 psOpSin,
700 psOpSqrt,
701 psOpSub,
702 psOpTrue,
703 psOpTruncate,
704 psOpXor,
705 psOpIf,
706 psOpIfelse,
707 psOpReturn
708};
709
710// Note: 'if' and 'ifelse' are parsed separately.
711// The rest are listed here in alphabetical order.
712// The index in this table is equivalent to the entry in PSOp.
713char *psOpNames[] = {
714 "abs",
715 "add",
716 "and",
717 "atan",
718 "bitshift",
719 "ceiling",
720 "copy",
721 "cos",
722 "cvi",
723 "cvr",
724 "div",
725 "dup",
726 "eq",
727 "exch",
728 "exp",
729 "false",
730 "floor",
731 "ge",
732 "gt",
733 "idiv",
734 "index",
735 "le",
736 "ln",
737 "log",
738 "lt",
739 "mod",
740 "mul",
741 "ne",
742 "neg",
743 "not",
744 "or",
745 "pop",
746 "roll",
747 "round",
748 "sin",
749 "sqrt",
750 "sub",
751 "true",
752 "truncate",
753 "xor"
754};
755
756#define nPSOps (sizeof(psOpNames) / sizeof(char *))
757
758enum PSObjectType {
759 psBool,
760 psInt,
761 psReal,
762 psOperator,
763 psBlock
764};
765
766// In the code array, 'if'/'ifelse' operators take up three slots
767// plus space for the code in the subclause(s).
768//
769// +---------------------------------+
770// | psOperator: psOpIf / psOpIfelse |
771// +---------------------------------+
772// | psBlock: ptr=<A> |
773// +---------------------------------+
774// | psBlock: ptr=<B> |
775// +---------------------------------+
776// | if clause |
777// | ... |
778// | psOperator: psOpReturn |
779// +---------------------------------+
780// <A> | else clause |
781// | ... |
782// | psOperator: psOpReturn |
783// +---------------------------------+
784// <B> | ... |
785//
786// For 'if', pointer <A> is present in the code stream but unused.
787
788struct PSObject {
789 PSObjectType type;
790 fouble real; // real (stack and code)
791 union {
792 GBool booln; // boolean (stack only)
793 int intg; // integer (stack and code)
794 PSOp op; // operator (code only)
795 int blk; // if/ifelse block pointer (code only)
796 };
797};
798
799#define psStackSize 100
800
801class PSStack {
802public:
803
804 PSStack() { sp = psStackSize; }
805 void pushBool(GBool booln);
806 void pushInt(int intg);
807 void pushReal(fouble real);
808 GBool popBool();
809 int popInt();
810 fouble popNum();
811 GBool empty() { return sp == psStackSize; }
812 GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
813 GBool topTwoAreInts()
814 { return sp < psStackSize - 1 &&
815 stack[sp].type == psInt &&
816 stack[sp+1].type == psInt; }
817 GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; }
818 GBool topTwoAreNums()
819 { return sp < psStackSize - 1 &&
820 (stack[sp].type == psInt || stack[sp].type == psReal) &&
821 (stack[sp+1].type == psInt || stack[sp+1].type == psReal); }
822 void copy(int n);
823 void roll(int n, int j);
824 void index(int i);
825 void pop();
826
827private:
828
829 GBool checkOverflow(int n = 1);
830 GBool checkUnderflow();
831 GBool checkType(PSObjectType t1, PSObjectType t2);
832
833 PSObject stack[psStackSize];
834 int sp;
835};
836
837GBool PSStack::checkOverflow(int n) {
838 if (sp - n < 0) {
839 error(-1, "Stack overflow in PostScript function");
840 return gFalse;
841 }
842 return gTrue;
843}
844
845GBool PSStack::checkUnderflow() {
846 if (sp == psStackSize) {
847 error(-1, "Stack underflow in PostScript function");
848 return gFalse;
849 }
850 return gTrue;
851}
852
853GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
854 if (stack[sp].type != t1 && stack[sp].type != t2) {
855 error(-1, "Type mismatch in PostScript function");
856 return gFalse;
857 }
858 return gTrue;
859}
860
861void PSStack::pushBool(GBool booln) {
862 if (checkOverflow()) {
863 stack[--sp].type = psBool;
864 stack[sp].booln = booln;
865 }
866}
867
868void PSStack::pushInt(int intg) {
869 if (checkOverflow()) {
870 stack[--sp].type = psInt;
871 stack[sp].intg = intg;
872 }
873}
874
875void PSStack::pushReal(fouble real) {
876 if (checkOverflow()) {
877 stack[--sp].type = psReal;
878 stack[sp].real = real;
879 }
880}
881
882GBool PSStack::popBool() {
883 if (checkUnderflow() && checkType(psBool, psBool)) {
884 return stack[sp++].booln;
885 }
886 return gFalse;
887}
888
889int PSStack::popInt() {
890 if (checkUnderflow() && checkType(psInt, psInt)) {
891 return stack[sp++].intg;
892 }
893 return 0;
894}
895
896fouble PSStack::popNum() {
897 fouble ret;
898
899 if (checkUnderflow() && checkType(psInt, psReal)) {
900 ret = (stack[sp].type == psInt) ? (fouble)stack[sp].intg : stack[sp].real;
901 ++sp;
902 return ret;
903 }
904 return 0;
905}
906
907void PSStack::copy(int n) {
908 int i;
909
910 if (!checkOverflow(n)) {
911 return;
912 }
913 for (i = sp + n - 1; i <= sp; ++i) {
914 stack[i - n] = stack[i];
915 }
916 sp -= n;
917}
918
919void PSStack::roll(int n, int j) {
920 PSObject obj;
921 int i, k;
922
923 if (j >= 0) {
924 j %= n;
925 } else {
926 j = -j % n;
927 if (j != 0) {
928 j = n - j;
929 }
930 }
931 if (n <= 0 || j == 0) {
932 return;
933 }
934 for (i = 0; i < j; ++i) {
935 obj = stack[sp];
936 for (k = sp; k < sp + n - 1; ++k) {
937 stack[k] = stack[k+1];
938 }
939 stack[sp + n - 1] = obj;
940 }
941}
942
943void PSStack::index(int i) {
944 if (!checkOverflow()) {
945 return;
946 }
947 --sp;
948 stack[sp] = stack[sp + 1 + i];
949}
950
951void PSStack::pop() {
952 if (!checkUnderflow()) {
953 return;
954 }
955 ++sp;
956}
957
958PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
959 Stream *str;
960 int codePtr;
961 GString *tok;
962
963 code = NULL;
964 codeSize = 0;
965 ok = gFalse;
966
967 //----- initialize the generic stuff
968 if (!init(dict)) {
969 goto err1;
970 }
971 if (!hasRange) {
972 error(-1, "Type 4 function is missing range");
973 goto err1;
974 }
975
976 //----- get the stream
977 if (!funcObj->isStream()) {
978 error(-1, "Type 4 function isn't a stream");
979 goto err1;
980 }
981 str = funcObj->getStream();
982
983 //----- parse the function
984 str->reset();
985 if (!(tok = getToken(str)) || tok->cmp("{")) {
986 error(-1, "Expected '{' at start of PostScript function");
987 if (tok) {
988 delete tok;
989 }
990 goto err1;
991 }
992 delete tok;
993 codePtr = 0;
994 if (!parseCode(str, &codePtr)) {
995 goto err2;
996 }
997 str->close();
998
999 ok = gTrue;
1000
1001 err2:
1002 str->close();
1003 err1:
1004 return;
1005}
1006
1007PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
1008 memcpy(this, func, sizeof(PostScriptFunction));
1009 code = (PSObject *)gmalloc(codeSize * sizeof(PSObject));
1010 memcpy(code, func->code, codeSize * sizeof(PSObject));
1011}
1012
1013PostScriptFunction::~PostScriptFunction() {
1014 gfree(code);
1015}
1016
1017void PostScriptFunction::transform(fouble *in, fouble *out) {
1018 PSStack *stack;
1019 int i;
1020
1021 stack = new PSStack();
1022 for (i = 0; i < m; ++i) {
1023 //~ may need to check for integers here
1024 stack->pushReal(in[i]);
1025 }
1026 exec(stack, 0);
1027 for (i = n - 1; i >= 0; --i) {
1028 out[i] = stack->popNum();
1029 if (out[i] < range[i][0]) {
1030 out[i] = range[i][0];
1031 } else if (out[i] > range[i][1]) {
1032 out[i] = range[i][1];
1033 }
1034 }
1035 // if (!stack->empty()) {
1036 // error(-1, "Extra values on stack at end of PostScript function");
1037 // }
1038 delete stack;
1039}
1040
1041GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
1042 GString *tok;
1043 char *p;
1044 GBool isReal;
1045 int opPtr, elsePtr;
1046 int a, b, mid, cmp;
1047
1048 while (1) {
1049 if (!(tok = getToken(str))) {
1050 error(-1, "Unexpected end of PostScript function stream");
1051 return gFalse;
1052 }
1053 p = tok->getCString();
1054 if (isdigit(*p) || *p == '.' || *p == '-') {
1055 isReal = gFalse;
1056 for (++p; *p; ++p) {
1057 if (*p == '.') {
1058 isReal = gTrue;
1059 break;
1060 }
1061 }
1062 resizeCode(*codePtr);
1063 if (isReal) {
1064 code[*codePtr].type = psReal;
1065 code[*codePtr].real = atof(tok->getCString());
1066 } else {
1067 code[*codePtr].type = psInt;
1068 code[*codePtr].intg = atoi(tok->getCString());
1069 }
1070 ++*codePtr;
1071 delete tok;
1072 } else if (!tok->cmp("{")) {
1073 delete tok;
1074 opPtr = *codePtr;
1075 *codePtr += 3;
1076 resizeCode(opPtr + 2);
1077 if (!parseCode(str, codePtr)) {
1078 return gFalse;
1079 }
1080 if (!(tok = getToken(str))) {
1081 error(-1, "Unexpected end of PostScript function stream");
1082 return gFalse;
1083 }
1084 if (!tok->cmp("{")) {
1085 elsePtr = *codePtr;
1086 if (!parseCode(str, codePtr)) {
1087 return gFalse;
1088 }
1089 } else {
1090 elsePtr = -1;
1091 }
1092 delete tok;
1093 if (!(tok = getToken(str))) {
1094 error(-1, "Unexpected end of PostScript function stream");
1095 return gFalse;
1096 }
1097 if (!tok->cmp("if")) {
1098 if (elsePtr >= 0) {
1099 error(-1, "Got 'if' operator with two blocks in PostScript function");
1100 return gFalse;
1101 }
1102 code[opPtr].type = psOperator;
1103 code[opPtr].op = psOpIf;
1104 code[opPtr+2].type = psBlock;
1105 code[opPtr+2].blk = *codePtr;
1106 } else if (!tok->cmp("ifelse")) {
1107 if (elsePtr < 0) {
1108 error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
1109 return gFalse;
1110 }
1111 code[opPtr].type = psOperator;
1112 code[opPtr].op = psOpIfelse;
1113 code[opPtr+1].type = psBlock;
1114 code[opPtr+1].blk = elsePtr;
1115 code[opPtr+2].type = psBlock;
1116 code[opPtr+2].blk = *codePtr;
1117 } else {
1118 error(-1, "Expected if/ifelse operator in PostScript function");
1119 delete tok;
1120 return gFalse;
1121 }
1122 delete tok;
1123 } else if (!tok->cmp("}")) {
1124 delete tok;
1125 resizeCode(*codePtr);
1126 code[*codePtr].type = psOperator;
1127 code[*codePtr].op = psOpReturn;
1128 ++*codePtr;
1129 break;
1130 } else {
1131 a = -1;
1132 b = nPSOps;
1133 // invariant: psOpNames[a] < tok < psOpNames[b]
1134 while (b - a > 1) {
1135 mid = (a + b) / 2;
1136 cmp = tok->cmp(psOpNames[mid]);
1137 if (cmp > 0) {
1138 a = mid;
1139 } else if (cmp < 0) {
1140 b = mid;
1141 } else {
1142 a = b = mid;
1143 }
1144 }
1145 if (cmp != 0) {
1146 error(-1, "Unknown operator '%s' in PostScript function",
1147 tok->getCString());
1148 delete tok;
1149 return gFalse;
1150 }
1151 delete tok;
1152 resizeCode(*codePtr);
1153 code[*codePtr].type = psOperator;
1154 code[*codePtr].op = (PSOp)a;
1155 ++*codePtr;
1156 }
1157 }
1158 return gTrue;
1159}
1160
1161GString *PostScriptFunction::getToken(Stream *str) {
1162 GString *s;
1163 int c;
1164
1165 s = new GString();
1166 do {
1167 c = str->getChar();
1168 } while (c != EOF && isspace(c));
1169 if (c == '{' || c == '}') {
1170 s->append((char)c);
1171 } else if (isdigit(c) || c == '.' || c == '-') {
1172 while (1) {
1173 s->append((char)c);
1174 c = str->lookChar();
1175 if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
1176 break;
1177 }
1178 str->getChar();
1179 }
1180 } else {
1181 while (1) {
1182 s->append((char)c);
1183 c = str->lookChar();
1184 if (c == EOF || !isalnum(c)) {
1185 break;
1186 }
1187 str->getChar();
1188 }
1189 }
1190 return s;
1191}
1192
1193void PostScriptFunction::resizeCode(int newSize) {
1194 if (newSize >= codeSize) {
1195 codeSize += 64;
1196 code = (PSObject *)grealloc(code, codeSize * sizeof(PSObject));
1197 }
1198}
1199
1200void PostScriptFunction::exec(PSStack *stack, int codePtr) {
1201 int i1, i2;
1202 fouble r1, r2;
1203 GBool b1, b2;
1204
1205 while (1) {
1206 switch (code[codePtr].type) {
1207 case psInt:
1208 stack->pushInt(code[codePtr++].intg);
1209 break;
1210 case psReal:
1211 stack->pushReal(code[codePtr++].real);
1212 break;
1213 case psOperator:
1214 switch (code[codePtr++].op) {
1215 case psOpAbs:
1216 if (stack->topIsInt()) {
1217 stack->pushInt(abs(stack->popInt()));
1218 } else {
1219 stack->pushReal(fabs(stack->popNum()));
1220 }
1221 break;
1222 case psOpAdd:
1223 if (stack->topTwoAreInts()) {
1224 i2 = stack->popInt();
1225 i1 = stack->popInt();
1226 stack->pushInt(i1 + i2);
1227 } else {
1228 r2 = stack->popNum();
1229 r1 = stack->popNum();
1230 stack->pushReal(r1 + r2);
1231 }
1232 break;
1233 case psOpAnd:
1234 if (stack->topTwoAreInts()) {
1235 i2 = stack->popInt();
1236 i1 = stack->popInt();
1237 stack->pushInt(i1 & i2);
1238 } else {
1239 b2 = stack->popBool();
1240 b1 = stack->popBool();
1241 stack->pushReal(b1 && b2);
1242 }
1243 break;
1244 case psOpAtan:
1245 r2 = stack->popNum();
1246 r1 = stack->popNum();
1247 stack->pushReal(atan2(r1, r2));
1248 break;
1249 case psOpBitshift:
1250 i2 = stack->popInt();
1251 i1 = stack->popInt();
1252 if (i2 > 0) {
1253 stack->pushInt(i1 << i2);
1254 } else if (i2 < 0) {
1255 stack->pushInt((int)((Guint)i1 >> i2));
1256 } else {
1257 stack->pushInt(i1);
1258 }
1259 break;
1260 case psOpCeiling:
1261 if (!stack->topIsInt()) {
1262 stack->pushReal(ceil(stack->popNum()));
1263 }
1264 break;
1265 case psOpCopy:
1266 stack->copy(stack->popInt());
1267 break;
1268 case psOpCos:
1269 stack->pushReal(cos(stack->popNum()));
1270 break;
1271 case psOpCvi:
1272 if (!stack->topIsInt()) {
1273 stack->pushInt((int)stack->popNum());
1274 }
1275 break;
1276 case psOpCvr:
1277 if (!stack->topIsReal()) {
1278 stack->pushReal(stack->popNum());
1279 }
1280 break;
1281 case psOpDiv:
1282 r2 = stack->popNum();
1283 r1 = stack->popNum();
1284 stack->pushReal(r1 / r2);
1285 break;
1286 case psOpDup:
1287 stack->copy(1);
1288 break;
1289 case psOpEq:
1290 if (stack->topTwoAreInts()) {
1291 i2 = stack->popInt();
1292 i1 = stack->popInt();
1293 stack->pushBool(i1 == i2);
1294 } else if (stack->topTwoAreNums()) {
1295 r2 = stack->popNum();
1296 r1 = stack->popNum();
1297 stack->pushBool(r1 == r2);
1298 } else {
1299 b2 = stack->popBool();
1300 b1 = stack->popBool();
1301 stack->pushBool(b1 == b2);
1302 }
1303 break;
1304 case psOpExch:
1305 stack->roll(2, 1);
1306 break;
1307 case psOpExp:
1308 r2 = stack->popInt();
1309 r1 = stack->popInt();
1310 stack->pushReal(pow(r1, r2));
1311 break;
1312 case psOpFalse:
1313 stack->pushBool(gFalse);
1314 break;
1315 case psOpFloor:
1316 if (!stack->topIsInt()) {
1317 stack->pushReal(floor(stack->popNum()));
1318 }
1319 break;
1320 case psOpGe:
1321 if (stack->topTwoAreInts()) {
1322 i2 = stack->popInt();
1323 i1 = stack->popInt();
1324 stack->pushBool(i1 >= i2);
1325 } else {
1326 r2 = stack->popNum();
1327 r1 = stack->popNum();
1328 stack->pushBool(r1 >= r2);
1329 }
1330 break;
1331 case psOpGt:
1332 if (stack->topTwoAreInts()) {
1333 i2 = stack->popInt();
1334 i1 = stack->popInt();
1335 stack->pushBool(i1 > i2);
1336 } else {
1337 r2 = stack->popNum();
1338 r1 = stack->popNum();
1339 stack->pushBool(r1 > r2);
1340 }
1341 break;
1342 case psOpIdiv:
1343 i2 = stack->popInt();
1344 i1 = stack->popInt();
1345 stack->pushInt(i1 / i2);
1346 break;
1347 case psOpIndex:
1348 stack->index(stack->popInt());
1349 break;
1350 case psOpLe:
1351 if (stack->topTwoAreInts()) {
1352 i2 = stack->popInt();
1353 i1 = stack->popInt();
1354 stack->pushBool(i1 <= i2);
1355 } else {
1356 r2 = stack->popNum();
1357 r1 = stack->popNum();
1358 stack->pushBool(r1 <= r2);
1359 }
1360 break;
1361 case psOpLn:
1362 stack->pushReal(log(stack->popNum()));
1363 break;
1364 case psOpLog:
1365 stack->pushReal(log10(stack->popNum()));
1366 break;
1367 case psOpLt:
1368 if (stack->topTwoAreInts()) {
1369 i2 = stack->popInt();
1370 i1 = stack->popInt();
1371 stack->pushBool(i1 < i2);
1372 } else {
1373 r2 = stack->popNum();
1374 r1 = stack->popNum();
1375 stack->pushBool(r1 < r2);
1376 }
1377 break;
1378 case psOpMod:
1379 i2 = stack->popInt();
1380 i1 = stack->popInt();
1381 stack->pushInt(i1 % i2);
1382 break;
1383 case psOpMul:
1384 if (stack->topTwoAreInts()) {
1385 i2 = stack->popInt();
1386 i1 = stack->popInt();
1387 //~ should check for out-of-range, and push a real instead
1388 stack->pushInt(i1 * i2);
1389 } else {
1390 r2 = stack->popNum();
1391 r1 = stack->popNum();
1392 stack->pushReal(r1 * r2);
1393 }
1394 break;
1395 case psOpNe:
1396 if (stack->topTwoAreInts()) {
1397 i2 = stack->popInt();
1398 i1 = stack->popInt();
1399 stack->pushBool(i1 != i2);
1400 } else if (stack->topTwoAreNums()) {
1401 r2 = stack->popNum();
1402 r1 = stack->popNum();
1403 stack->pushBool(r1 != r2);
1404 } else {
1405 b2 = stack->popBool();
1406 b1 = stack->popBool();
1407 stack->pushBool(b1 != b2);
1408 }
1409 break;
1410 case psOpNeg:
1411 if (stack->topIsInt()) {
1412 stack->pushInt(-stack->popInt());
1413 } else {
1414 stack->pushReal(-stack->popNum());
1415 }
1416 break;
1417 case psOpNot:
1418 if (stack->topIsInt()) {
1419 stack->pushInt(~stack->popInt());
1420 } else {
1421 stack->pushReal(!stack->popBool());
1422 }
1423 break;
1424 case psOpOr:
1425 if (stack->topTwoAreInts()) {
1426 i2 = stack->popInt();
1427 i1 = stack->popInt();
1428 stack->pushInt(i1 | i2);
1429 } else {
1430 b2 = stack->popBool();
1431 b1 = stack->popBool();
1432 stack->pushReal(b1 || b2);
1433 }
1434 break;
1435 case psOpPop:
1436 stack->pop();
1437 break;
1438 case psOpRoll:
1439 i2 = stack->popInt();
1440 i1 = stack->popInt();
1441 stack->roll(i1, i2);
1442 break;
1443 case psOpRound:
1444 if (!stack->topIsInt()) {
1445 r1 = stack->popNum();
1446 stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
1447 }
1448 break;
1449 case psOpSin:
1450 stack->pushReal(cos(stack->popNum()));
1451 break;
1452 case psOpSqrt:
1453 stack->pushReal(sqrt(stack->popNum()));
1454 break;
1455 case psOpSub:
1456 if (stack->topTwoAreInts()) {
1457 i2 = stack->popInt();
1458 i1 = stack->popInt();
1459 stack->pushInt(i1 - i2);
1460 } else {
1461 r2 = stack->popNum();
1462 r1 = stack->popNum();
1463 stack->pushReal(r1 - r2);
1464 }
1465 break;
1466 case psOpTrue:
1467 stack->pushBool(gTrue);
1468 break;
1469 case psOpTruncate:
1470 if (!stack->topIsInt()) {
1471 r1 = stack->popNum();
1472 stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
1473 }
1474 break;
1475 case psOpXor:
1476 if (stack->topTwoAreInts()) {
1477 i2 = stack->popInt();
1478 i1 = stack->popInt();
1479 stack->pushInt(i1 ^ i2);
1480 } else {
1481 b2 = stack->popBool();
1482 b1 = stack->popBool();
1483 stack->pushReal(b1 ^ b2);
1484 }
1485 break;
1486 case psOpIf:
1487 b1 = stack->popBool();
1488 if (b1) {
1489 exec(stack, codePtr + 2);
1490 }
1491 codePtr = code[codePtr + 1].blk;
1492 break;
1493 case psOpIfelse:
1494 b1 = stack->popBool();
1495 if (b1) {
1496 exec(stack, codePtr + 2);
1497 } else {
1498 exec(stack, code[codePtr].blk);
1499 }
1500 codePtr = code[codePtr + 1].blk;
1501 break;
1502 case psOpReturn:
1503 return;
1504 }
1505 break;
1506 default:
1507 error(-1, "Internal: bad object in PostScript function code");
1508 break;
1509 }
1510 }
1511}
diff --git a/noncore/unsupported/qpdf/xpdf/Function.h b/noncore/unsupported/qpdf/xpdf/Function.h
new file mode 100644
index 0000000..a223359
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Function.h
@@ -0,0 +1,181 @@
1//========================================================================
2//
3// Function.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef FUNCTION_H
10#define FUNCTION_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "Object.h"
18
19class Dict;
20class Stream;
21struct PSObject;
22class PSStack;
23
24//------------------------------------------------------------------------
25// Function
26//------------------------------------------------------------------------
27
28#define funcMaxInputs 8
29#define funcMaxOutputs 8
30
31class Function {
32public:
33
34 Function();
35
36 virtual ~Function();
37
38 // Construct a function. Returns NULL if unsuccessful.
39 static Function *parse(Object *funcObj);
40
41 // Initialize the entries common to all function types.
42 GBool init(Dict *dict);
43
44 virtual Function *copy() = 0;
45
46 // Return size of input and output tuples.
47 int getInputSize() { return m; }
48 int getOutputSize() { return n; }
49
50 // Transform an input tuple into an output tuple.
51 virtual void transform(fouble *in, fouble *out) = 0;
52
53 virtual GBool isOk() = 0;
54
55protected:
56
57 int m, n; // size of input and output tuples
58 fouble // min and max values for function domain
59 domain[funcMaxInputs][2];
60 fouble // min and max values for function range
61 range[funcMaxOutputs][2];
62 GBool hasRange; // set if range is defined
63};
64
65//------------------------------------------------------------------------
66// IdentityFunction
67//------------------------------------------------------------------------
68
69class IdentityFunction: public Function {
70public:
71
72 IdentityFunction();
73 virtual ~IdentityFunction();
74 virtual Function *copy() { return new IdentityFunction(); }
75 virtual void transform(fouble *in, fouble *out);
76 virtual GBool isOk() { return gTrue; }
77
78private:
79};
80
81//------------------------------------------------------------------------
82// SampledFunction
83//------------------------------------------------------------------------
84
85class SampledFunction: public Function {
86public:
87
88 SampledFunction(Object *funcObj, Dict *dict);
89 virtual ~SampledFunction();
90 virtual Function *copy() { return new SampledFunction(this); }
91 virtual void transform(fouble *in, fouble *out);
92 virtual GBool isOk() { return ok; }
93
94private:
95
96 SampledFunction(SampledFunction *func);
97
98 int // number of samples for each domain element
99 sampleSize[funcMaxInputs];
100 fouble // min and max values for domain encoder
101 encode[funcMaxInputs][2];
102 fouble // min and max values for range decoder
103 decode[funcMaxOutputs][2];
104 fouble *samples; // the samples
105 GBool ok;
106};
107
108//------------------------------------------------------------------------
109// ExponentialFunction
110//------------------------------------------------------------------------
111
112class ExponentialFunction: public Function {
113public:
114
115 ExponentialFunction(Object *funcObj, Dict *dict);
116 virtual ~ExponentialFunction();
117 virtual Function *copy() { return new ExponentialFunction(this); }
118 virtual void transform(fouble *in, fouble *out);
119 virtual GBool isOk() { return ok; }
120
121private:
122
123 ExponentialFunction(ExponentialFunction *func);
124
125 fouble c0[funcMaxOutputs];
126 fouble c1[funcMaxOutputs];
127 fouble e;
128 GBool ok;
129};
130
131//------------------------------------------------------------------------
132// StitchingFunction
133//------------------------------------------------------------------------
134
135class StitchingFunction: public Function {
136public:
137
138 StitchingFunction(Object *funcObj, Dict *dict);
139 virtual ~StitchingFunction();
140 virtual Function *copy() { return new StitchingFunction(this); }
141 virtual void transform(fouble *in, fouble *out);
142 virtual GBool isOk() { return ok; }
143
144private:
145
146 StitchingFunction(StitchingFunction *func);
147
148 int k;
149 Function **funcs;
150 fouble *bounds;
151 fouble *encode;
152 GBool ok;
153};
154
155//------------------------------------------------------------------------
156// PostScriptFunction
157//------------------------------------------------------------------------
158
159class PostScriptFunction: public Function {
160public:
161
162 PostScriptFunction(Object *funcObj, Dict *dict);
163 virtual ~PostScriptFunction();
164 virtual Function *copy() { return new PostScriptFunction(this); }
165 virtual void transform(fouble *in, fouble *out);
166 virtual GBool isOk() { return ok; }
167
168private:
169
170 PostScriptFunction(PostScriptFunction *func);
171 GBool parseCode(Stream *str, int *codePtr);
172 GString *getToken(Stream *str);
173 void resizeCode(int newSize);
174 void exec(PSStack *stack, int codePtr);
175
176 PSObject *code;
177 int codeSize;
178 GBool ok;
179};
180
181#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Gfx.cc b/noncore/unsupported/qpdf/xpdf/Gfx.cc
new file mode 100644
index 0000000..c19971c
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Gfx.cc
@@ -0,0 +1,2461 @@
1//========================================================================
2//
3// Gfx.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stddef.h>
16#include <string.h>
17#include <math.h>
18#include "gmem.h"
19#include "CharTypes.h"
20#include "Object.h"
21#include "Array.h"
22#include "Dict.h"
23#include "Stream.h"
24#include "Lexer.h"
25#include "Parser.h"
26#include "GfxFont.h"
27#include "GfxState.h"
28#include "OutputDev.h"
29#include "Page.h"
30#include "Error.h"
31#include "Gfx.h"
32
33//------------------------------------------------------------------------
34// constants
35//------------------------------------------------------------------------
36
37// Max number of splits along the t axis for an axial shading fill.
38#define axialMaxSplits 256
39
40// Max delta allowed in any color component for an axial shading fill.
41#define axialColorDelta (1 / 256.0)
42
43//------------------------------------------------------------------------
44// Operator table
45//------------------------------------------------------------------------
46
47Operator Gfx::opTab[] = {
48 {"\"", 3, {tchkNum, tchkNum, tchkString},
49 &Gfx::opMoveSetShowText},
50 {"'", 1, {tchkString},
51 &Gfx::opMoveShowText},
52 {"B", 0, {tchkNone},
53 &Gfx::opFillStroke},
54 {"B*", 0, {tchkNone},
55 &Gfx::opEOFillStroke},
56 {"BDC", 2, {tchkName, tchkProps},
57 &Gfx::opBeginMarkedContent},
58 {"BI", 0, {tchkNone},
59 &Gfx::opBeginImage},
60 {"BMC", 1, {tchkName},
61 &Gfx::opBeginMarkedContent},
62 {"BT", 0, {tchkNone},
63 &Gfx::opBeginText},
64 {"BX", 0, {tchkNone},
65 &Gfx::opBeginIgnoreUndef},
66 {"CS", 1, {tchkName},
67 &Gfx::opSetStrokeColorSpace},
68 {"DP", 2, {tchkName, tchkProps},
69 &Gfx::opMarkPoint},
70 {"Do", 1, {tchkName},
71 &Gfx::opXObject},
72 {"EI", 0, {tchkNone},
73 &Gfx::opEndImage},
74 {"EMC", 0, {tchkNone},
75 &Gfx::opEndMarkedContent},
76 {"ET", 0, {tchkNone},
77 &Gfx::opEndText},
78 {"EX", 0, {tchkNone},
79 &Gfx::opEndIgnoreUndef},
80 {"F", 0, {tchkNone},
81 &Gfx::opFill},
82 {"G", 1, {tchkNum},
83 &Gfx::opSetStrokeGray},
84 {"ID", 0, {tchkNone},
85 &Gfx::opImageData},
86 {"J", 1, {tchkInt},
87 &Gfx::opSetLineCap},
88 {"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
89 &Gfx::opSetStrokeCMYKColor},
90 {"M", 1, {tchkNum},
91 &Gfx::opSetMiterLimit},
92 {"MP", 1, {tchkName},
93 &Gfx::opMarkPoint},
94 {"Q", 0, {tchkNone},
95 &Gfx::opRestore},
96 {"RG", 3, {tchkNum, tchkNum, tchkNum},
97 &Gfx::opSetStrokeRGBColor},
98 {"S", 0, {tchkNone},
99 &Gfx::opStroke},
100 {"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
101 &Gfx::opSetStrokeColor},
102 {"SCN", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
103 tchkSCN},
104 &Gfx::opSetStrokeColorN},
105 {"T*", 0, {tchkNone},
106 &Gfx::opTextNextLine},
107 {"TD", 2, {tchkNum, tchkNum},
108 &Gfx::opTextMoveSet},
109 {"TJ", 1, {tchkArray},
110 &Gfx::opShowSpaceText},
111 {"TL", 1, {tchkNum},
112 &Gfx::opSetTextLeading},
113 {"Tc", 1, {tchkNum},
114 &Gfx::opSetCharSpacing},
115 {"Td", 2, {tchkNum, tchkNum},
116 &Gfx::opTextMove},
117 {"Tf", 2, {tchkName, tchkNum},
118 &Gfx::opSetFont},
119 {"Tj", 1, {tchkString},
120 &Gfx::opShowText},
121 {"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
122 tchkNum, tchkNum},
123 &Gfx::opSetTextMatrix},
124 {"Tr", 1, {tchkInt},
125 &Gfx::opSetTextRender},
126 {"Ts", 1, {tchkNum},
127 &Gfx::opSetTextRise},
128 {"Tw", 1, {tchkNum},
129 &Gfx::opSetWordSpacing},
130 {"Tz", 1, {tchkNum},
131 &Gfx::opSetHorizScaling},
132 {"W", 0, {tchkNone},
133 &Gfx::opClip},
134 {"W*", 0, {tchkNone},
135 &Gfx::opEOClip},
136 {"b", 0, {tchkNone},
137 &Gfx::opCloseFillStroke},
138 {"b*", 0, {tchkNone},
139 &Gfx::opCloseEOFillStroke},
140 {"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
141 tchkNum, tchkNum},
142 &Gfx::opCurveTo},
143 {"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
144 tchkNum, tchkNum},
145 &Gfx::opConcat},
146 {"cs", 1, {tchkName},
147 &Gfx::opSetFillColorSpace},
148 {"d", 2, {tchkArray, tchkNum},
149 &Gfx::opSetDash},
150 {"d0", 2, {tchkNum, tchkNum},
151 &Gfx::opSetCharWidth},
152 {"d1", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
153 tchkNum, tchkNum},
154 &Gfx::opSetCacheDevice},
155 {"f", 0, {tchkNone},
156 &Gfx::opFill},
157 {"f*", 0, {tchkNone},
158 &Gfx::opEOFill},
159 {"g", 1, {tchkNum},
160 &Gfx::opSetFillGray},
161 {"gs", 1, {tchkName},
162 &Gfx::opSetExtGState},
163 {"h", 0, {tchkNone},
164 &Gfx::opClosePath},
165 {"i", 1, {tchkNum},
166 &Gfx::opSetFlat},
167 {"j", 1, {tchkInt},
168 &Gfx::opSetLineJoin},
169 {"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
170 &Gfx::opSetFillCMYKColor},
171 {"l", 2, {tchkNum, tchkNum},
172 &Gfx::opLineTo},
173 {"m", 2, {tchkNum, tchkNum},
174 &Gfx::opMoveTo},
175 {"n", 0, {tchkNone},
176 &Gfx::opEndPath},
177 {"q", 0, {tchkNone},
178 &Gfx::opSave},
179 {"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
180 &Gfx::opRectangle},
181 {"rg", 3, {tchkNum, tchkNum, tchkNum},
182 &Gfx::opSetFillRGBColor},
183 {"ri", 1, {tchkName},
184 &Gfx::opSetRenderingIntent},
185 {"s", 0, {tchkNone},
186 &Gfx::opCloseStroke},
187 {"sc", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
188 &Gfx::opSetFillColor},
189 {"scn", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
190 tchkSCN},
191 &Gfx::opSetFillColorN},
192 {"sh", 1, {tchkName},
193 &Gfx::opShFill},
194 {"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
195 &Gfx::opCurveTo1},
196 {"w", 1, {tchkNum},
197 &Gfx::opSetLineWidth},
198 {"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
199 &Gfx::opCurveTo2},
200};
201
202#define numOps (sizeof(opTab) / sizeof(Operator))
203
204//------------------------------------------------------------------------
205// GfxResources
206//------------------------------------------------------------------------
207
208GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
209 Object obj1;
210
211 if (resDict) {
212
213 // build font dictionary
214 fonts = NULL;
215 resDict->lookup("Font", &obj1);
216 if (obj1.isDict()) {
217 fonts = new GfxFontDict(xref, obj1.getDict());
218 }
219 obj1.free();
220
221 // get XObject dictionary
222 resDict->lookup("XObject", &xObjDict);
223
224 // get color space dictionary
225 resDict->lookup("ColorSpace", &colorSpaceDict);
226
227 // get pattern dictionary
228 resDict->lookup("Pattern", &patternDict);
229
230 // get shading dictionary
231 resDict->lookup("Shading", &shadingDict);
232
233 // get graphics state parameter dictionary
234 resDict->lookup("ExtGState", &gStateDict);
235
236 } else {
237 fonts = NULL;
238 xObjDict.initNull();
239 colorSpaceDict.initNull();
240 patternDict.initNull();
241 gStateDict.initNull();
242 }
243
244 next = nextA;
245}
246
247GfxResources::~GfxResources() {
248 if (fonts) {
249 delete fonts;
250 }
251 xObjDict.free();
252 colorSpaceDict.free();
253 patternDict.free();
254 shadingDict.free();
255 gStateDict.free();
256}
257
258GfxFont *GfxResources::lookupFont(char *name) {
259 GfxFont *font;
260 GfxResources *resPtr;
261
262 for (resPtr = this; resPtr; resPtr = resPtr->next) {
263 if (resPtr->fonts) {
264 if ((font = resPtr->fonts->lookup(name)))
265 return font;
266 }
267 }
268 error(-1, "Unknown font tag '%s'", name);
269 return NULL;
270}
271
272GBool GfxResources::lookupXObject(char *name, Object *obj) {
273 GfxResources *resPtr;
274
275 for (resPtr = this; resPtr; resPtr = resPtr->next) {
276 if (resPtr->xObjDict.isDict()) {
277 if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
278 return gTrue;
279 obj->free();
280 }
281 }
282 error(-1, "XObject '%s' is unknown", name);
283 return gFalse;
284}
285
286GBool GfxResources::lookupXObjectNF(char *name, Object *obj) {
287 GfxResources *resPtr;
288
289 for (resPtr = this; resPtr; resPtr = resPtr->next) {
290 if (resPtr->xObjDict.isDict()) {
291 if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull())
292 return gTrue;
293 obj->free();
294 }
295 }
296 error(-1, "XObject '%s' is unknown", name);
297 return gFalse;
298}
299
300void GfxResources::lookupColorSpace(char *name, Object *obj) {
301 GfxResources *resPtr;
302
303 for (resPtr = this; resPtr; resPtr = resPtr->next) {
304 if (resPtr->colorSpaceDict.isDict()) {
305 if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) {
306 return;
307 }
308 obj->free();
309 }
310 }
311 obj->initNull();
312}
313
314GfxPattern *GfxResources::lookupPattern(char *name) {
315 GfxResources *resPtr;
316 GfxPattern *pattern;
317 Object obj;
318
319 for (resPtr = this; resPtr; resPtr = resPtr->next) {
320 if (resPtr->patternDict.isDict()) {
321 if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
322 pattern = GfxPattern::parse(&obj);
323 obj.free();
324 return pattern;
325 }
326 obj.free();
327 }
328 }
329 error(-1, "Unknown pattern '%s'", name);
330 return NULL;
331}
332
333GfxShading *GfxResources::lookupShading(char *name) {
334 GfxResources *resPtr;
335 GfxShading *shading;
336 Object obj;
337
338 for (resPtr = this; resPtr; resPtr = resPtr->next) {
339 if (resPtr->shadingDict.isDict()) {
340 if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
341 shading = GfxShading::parse(&obj);
342 obj.free();
343 return shading;
344 }
345 obj.free();
346 }
347 }
348 error(-1, "Unknown shading '%s'", name);
349 return NULL;
350}
351
352GBool GfxResources::lookupGState(char *name, Object *obj) {
353 GfxResources *resPtr;
354
355 for (resPtr = this; resPtr; resPtr = resPtr->next) {
356 if (resPtr->gStateDict.isDict()) {
357 if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) {
358 return gTrue;
359 }
360 obj->free();
361 }
362 }
363 error(-1, "ExtGState '%s' is unknown", name);
364 return gFalse;
365}
366
367//------------------------------------------------------------------------
368// Gfx
369//------------------------------------------------------------------------
370
371Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, fouble dpi,
372 PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
373 GBool printCommandsA) {
374 int i;
375
376 xref = xrefA;
377 printCommands = printCommandsA;
378
379 // start the resource stack
380 res = new GfxResources(xref, resDict, NULL);
381
382 // initialize
383 out = outA;
384 state = new GfxState(dpi, box, rotate, out->upsideDown());
385 fontChanged = gFalse;
386 clip = clipNone;
387 ignoreUndef = 0;
388 out->startPage(pageNum, state);
389 out->setDefaultCTM(state->getCTM());
390 out->updateAll(state);
391 for (i = 0; i < 6; ++i) {
392 baseMatrix[i] = state->getCTM()[i];
393 }
394
395 // set crop box
396 if (crop) {
397 state->moveTo(cropBox->x1, cropBox->y1);
398 state->lineTo(cropBox->x2, cropBox->y1);
399 state->lineTo(cropBox->x2, cropBox->y2);
400 state->lineTo(cropBox->x1, cropBox->y2);
401 state->closePath();
402 state->clip();
403 out->clip(state);
404 state->clearPath();
405 }
406}
407
408Gfx::~Gfx() {
409 GfxResources *resPtr;
410
411 while (state->hasSaves()) {
412 state = state->restore();
413 out->restoreState(state);
414 }
415 out->endPage();
416 while (res) {
417 resPtr = res->getNext();
418 delete res;
419 res = resPtr;
420 }
421 if (state)
422 delete state;
423}
424
425void Gfx::display(Object *obj, GBool topLevel) {
426 Object obj2;
427 int i;
428
429 if (obj->isArray()) {
430 for (i = 0; i < obj->arrayGetLength(); ++i) {
431 obj->arrayGet(i, &obj2);
432 if (!obj2.isStream()) {
433 error(-1, "Weird page contents");
434 obj2.free();
435 return;
436 }
437 obj2.free();
438 }
439 } else if (!obj->isStream()) {
440 error(-1, "Weird page contents");
441 return;
442 }
443 parser = new Parser(xref, new Lexer(xref, obj));
444 go(topLevel);
445 delete parser;
446 parser = NULL;
447}
448
449void Gfx::go(GBool topLevel) {
450 Object obj;
451 Object args[maxArgs];
452 int numCmds, numArgs;
453 int i;
454
455 // scan a sequence of objects
456 numCmds = 0;
457 numArgs = 0;
458 parser->getObj(&obj);
459 while (!obj.isEOF()) {
460
461 // got a command - execute it
462 if (obj.isCmd()) {
463 if (printCommands) {
464 obj.print(stdout);
465 for (i = 0; i < numArgs; ++i) {
466 printf(" ");
467 args[i].print(stdout);
468 }
469 printf("\n");
470 fflush(stdout);
471 }
472 execOp(&obj, args, numArgs);
473 obj.free();
474 for (i = 0; i < numArgs; ++i)
475 args[i].free();
476 numArgs = 0;
477
478 // periodically update display
479 if (++numCmds == 200) {
480 out->dump();
481 numCmds = 0;
482 }
483
484 // got an argument - save it
485 } else if (numArgs < maxArgs) {
486 args[numArgs++] = obj;
487
488 // too many arguments - something is wrong
489 } else {
490 error(getPos(), "Too many args in content stream");
491 if (printCommands) {
492 printf("throwing away arg: ");
493 obj.print(stdout);
494 printf("\n");
495 fflush(stdout);
496 }
497 obj.free();
498 }
499
500 // grab the next object
501 parser->getObj(&obj);
502 }
503 obj.free();
504
505 // args at end with no command
506 if (numArgs > 0) {
507 error(getPos(), "Leftover args in content stream");
508 if (printCommands) {
509 printf("%d leftovers:", numArgs);
510 for (i = 0; i < numArgs; ++i) {
511 printf(" ");
512 args[i].print(stdout);
513 }
514 printf("\n");
515 fflush(stdout);
516 }
517 for (i = 0; i < numArgs; ++i)
518 args[i].free();
519 }
520
521 // update display
522 if (topLevel && numCmds > 0) {
523 out->dump();
524 }
525}
526
527void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
528 Operator *op;
529 char *name;
530 int i;
531
532 // find operator
533 name = cmd->getName();
534 if (!(op = findOp(name))) {
535 if (ignoreUndef == 0)
536 error(getPos(), "Unknown operator '%s'", name);
537 return;
538 }
539
540 // type check args
541 if (op->numArgs >= 0) {
542 if (numArgs != op->numArgs) {
543 error(getPos(), "Wrong number (%d) of args to '%s' operator",
544 numArgs, name);
545 return;
546 }
547 } else {
548 if (numArgs > -op->numArgs) {
549 error(getPos(), "Too many (%d) args to '%s' operator",
550 numArgs, name);
551 return;
552 }
553 }
554 for (i = 0; i < numArgs; ++i) {
555 if (!checkArg(&args[i], op->tchk[i])) {
556 error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
557 i, name, args[i].getTypeName());
558 return;
559 }
560 }
561
562 // do it
563 (this->*op->func)(args, numArgs);
564}
565
566Operator *Gfx::findOp(char *name) {
567 int a, b, m, cmp;
568
569 a = -1;
570 b = numOps;
571 // invariant: opTab[a] < name < opTab[b]
572 while (b - a > 1) {
573 m = (a + b) / 2;
574 cmp = strcmp(opTab[m].name, name);
575 if (cmp < 0)
576 a = m;
577 else if (cmp > 0)
578 b = m;
579 else
580 a = b = m;
581 }
582 if (cmp != 0)
583 return NULL;
584 return &opTab[a];
585}
586
587GBool Gfx::checkArg(Object *arg, TchkType type) {
588 switch (type) {
589 case tchkBool: return arg->isBool();
590 case tchkInt: return arg->isInt();
591 case tchkNum: return arg->isNum();
592 case tchkString: return arg->isString();
593 case tchkName: return arg->isName();
594 case tchkArray: return arg->isArray();
595 case tchkProps: return arg->isDict() || arg->isName();
596 case tchkSCN: return arg->isNum() || arg->isName();
597 case tchkNone: return gFalse;
598 }
599 return gFalse;
600}
601
602int Gfx::getPos() {
603 return parser ? parser->getPos() : -1;
604}
605
606//------------------------------------------------------------------------
607// graphics state operators
608//------------------------------------------------------------------------
609
610void Gfx::opSave(Object args[], int numArgs) {
611 out->saveState(state);
612 state = state->save();
613}
614
615void Gfx::opRestore(Object args[], int numArgs) {
616 state = state->restore();
617 out->restoreState(state);
618}
619
620void Gfx::opConcat(Object args[], int numArgs) {
621 state->concatCTM(args[0].getNum(), args[1].getNum(),
622 args[2].getNum(), args[3].getNum(),
623 args[4].getNum(), args[5].getNum());
624 out->updateCTM(state, args[0].getNum(), args[1].getNum(),
625 args[2].getNum(), args[3].getNum(),
626 args[4].getNum(), args[5].getNum());
627 fontChanged = gTrue;
628}
629
630void Gfx::opSetDash(Object args[], int numArgs) {
631 Array *a;
632 int length;
633 Object obj;
634 fouble *dash;
635 int i;
636
637 a = args[0].getArray();
638 length = a->getLength();
639 if (length == 0) {
640 dash = NULL;
641 } else {
642 dash = (fouble *)gmalloc(length * sizeof(fouble));
643 for (i = 0; i < length; ++i) {
644 dash[i] = a->get(i, &obj)->getNum();
645 obj.free();
646 }
647 }
648 state->setLineDash(dash, length, args[1].getNum());
649 out->updateLineDash(state);
650}
651
652void Gfx::opSetFlat(Object args[], int numArgs) {
653 state->setFlatness((int)args[0].getNum());
654 out->updateFlatness(state);
655}
656
657void Gfx::opSetLineJoin(Object args[], int numArgs) {
658 state->setLineJoin(args[0].getInt());
659 out->updateLineJoin(state);
660}
661
662void Gfx::opSetLineCap(Object args[], int numArgs) {
663 state->setLineCap(args[0].getInt());
664 out->updateLineCap(state);
665}
666
667void Gfx::opSetMiterLimit(Object args[], int numArgs) {
668 state->setMiterLimit(args[0].getNum());
669 out->updateMiterLimit(state);
670}
671
672void Gfx::opSetLineWidth(Object args[], int numArgs) {
673 state->setLineWidth(args[0].getNum());
674 out->updateLineWidth(state);
675}
676
677void Gfx::opSetExtGState(Object args[], int numArgs) {
678 Object obj1, obj2;
679
680 if (!res->lookupGState(args[0].getName(), &obj1)) {
681 return;
682 }
683 if (!obj1.isDict()) {
684 error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
685 obj1.free();
686 return;
687 }
688 if (obj1.dictLookup("ca", &obj2)->isNum()) {
689 state->setFillOpacity(obj2.getNum());
690 out->updateFillOpacity(state);
691 }
692 obj2.free();
693 if (obj1.dictLookup("CA", &obj2)->isNum()) {
694 state->setStrokeOpacity(obj2.getNum());
695 out->updateStrokeOpacity(state);
696 }
697 obj2.free();
698 obj1.free();
699}
700
701void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
702}
703
704//------------------------------------------------------------------------
705// color operators
706//------------------------------------------------------------------------
707
708void Gfx::opSetFillGray(Object args[], int numArgs) {
709 GfxColor color;
710
711 state->setFillPattern(NULL);
712 state->setFillColorSpace(new GfxDeviceGrayColorSpace());
713 color.c[0] = args[0].getNum();
714 state->setFillColor(&color);
715 out->updateFillColor(state);
716}
717
718void Gfx::opSetStrokeGray(Object args[], int numArgs) {
719 GfxColor color;
720
721 state->setStrokePattern(NULL);
722 state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
723 color.c[0] = args[0].getNum();
724 state->setStrokeColor(&color);
725 out->updateStrokeColor(state);
726}
727
728void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
729 GfxColor color;
730 int i;
731
732 state->setFillPattern(NULL);
733 state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
734 for (i = 0; i < 4; ++i) {
735 color.c[i] = args[i].getNum();
736 }
737 state->setFillColor(&color);
738 out->updateFillColor(state);
739}
740
741void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
742 GfxColor color;
743 int i;
744
745 state->setStrokePattern(NULL);
746 state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
747 for (i = 0; i < 4; ++i) {
748 color.c[i] = args[i].getNum();
749 }
750 state->setStrokeColor(&color);
751 out->updateStrokeColor(state);
752}
753
754void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
755 GfxColor color;
756 int i;
757
758 state->setFillPattern(NULL);
759 state->setFillColorSpace(new GfxDeviceRGBColorSpace());
760 for (i = 0; i < 3; ++i) {
761 color.c[i] = args[i].getNum();
762 }
763 state->setFillColor(&color);
764 out->updateFillColor(state);
765}
766
767void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
768 GfxColor color;
769 int i;
770
771 state->setStrokePattern(NULL);
772 state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
773 for (i = 0; i < 3; ++i) {
774 color.c[i] = args[i].getNum();
775 }
776 state->setStrokeColor(&color);
777 out->updateStrokeColor(state);
778}
779
780void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
781 Object obj;
782 GfxColorSpace *colorSpace;
783 GfxColor color;
784 int i;
785
786 state->setFillPattern(NULL);
787 res->lookupColorSpace(args[0].getName(), &obj);
788 if (obj.isNull()) {
789 colorSpace = GfxColorSpace::parse(&args[0]);
790 } else {
791 colorSpace = GfxColorSpace::parse(&obj);
792 }
793 obj.free();
794 if (colorSpace) {
795 state->setFillColorSpace(colorSpace);
796 } else {
797 error(getPos(), "Bad color space (fill)");
798 }
799 for (i = 0; i < gfxColorMaxComps; ++i) {
800 color.c[i] = 0;
801 }
802 state->setFillColor(&color);
803 out->updateFillColor(state);
804}
805
806void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
807 Object obj;
808 GfxColorSpace *colorSpace;
809 GfxColor color;
810 int i;
811
812 state->setStrokePattern(NULL);
813 res->lookupColorSpace(args[0].getName(), &obj);
814 if (obj.isNull()) {
815 colorSpace = GfxColorSpace::parse(&args[0]);
816 } else {
817 colorSpace = GfxColorSpace::parse(&obj);
818 }
819 obj.free();
820 if (colorSpace) {
821 state->setStrokeColorSpace(colorSpace);
822 } else {
823 error(getPos(), "Bad color space (stroke)");
824 }
825 for (i = 0; i < gfxColorMaxComps; ++i) {
826 color.c[i] = 0;
827 }
828 state->setStrokeColor(&color);
829 out->updateStrokeColor(state);
830}
831
832void Gfx::opSetFillColor(Object args[], int numArgs) {
833 GfxColor color;
834 int i;
835
836 state->setFillPattern(NULL);
837 for (i = 0; i < numArgs; ++i) {
838 color.c[i] = args[i].getNum();
839 }
840 state->setFillColor(&color);
841 out->updateFillColor(state);
842}
843
844void Gfx::opSetStrokeColor(Object args[], int numArgs) {
845 GfxColor color;
846 int i;
847
848 state->setStrokePattern(NULL);
849 for (i = 0; i < numArgs; ++i) {
850 color.c[i] = args[i].getNum();
851 }
852 state->setStrokeColor(&color);
853 out->updateStrokeColor(state);
854}
855
856void Gfx::opSetFillColorN(Object args[], int numArgs) {
857 GfxColor color;
858 GfxPattern *pattern;
859 int i;
860
861 if (state->getFillColorSpace()->getMode() == csPattern) {
862 if (numArgs > 1) {
863 for (i = 0; i < numArgs && i < 4; ++i) {
864 if (args[i].isNum()) {
865 color.c[i] = args[i].getNum();
866 }
867 }
868 state->setFillColor(&color);
869 out->updateFillColor(state);
870 }
871 if (args[numArgs-1].isName() &&
872 (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
873 state->setFillPattern(pattern);
874 }
875
876 } else {
877 state->setFillPattern(NULL);
878 for (i = 0; i < numArgs && i < 4; ++i) {
879 if (args[i].isNum()) {
880 color.c[i] = args[i].getNum();
881 }
882 }
883 state->setFillColor(&color);
884 out->updateFillColor(state);
885 }
886}
887
888void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
889 GfxColor color;
890 GfxPattern *pattern;
891 int i;
892
893 if (state->getStrokeColorSpace()->getMode() == csPattern) {
894 if (numArgs > 1) {
895 for (i = 0; i < numArgs && i < 4; ++i) {
896 if (args[i].isNum()) {
897 color.c[i] = args[i].getNum();
898 }
899 }
900 state->setStrokeColor(&color);
901 out->updateStrokeColor(state);
902 }
903 if (args[numArgs-1].isName() &&
904 (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
905 state->setStrokePattern(pattern);
906 }
907
908 } else {
909 state->setStrokePattern(NULL);
910 for (i = 0; i < numArgs && i < 4; ++i) {
911 if (args[i].isNum()) {
912 color.c[i] = args[i].getNum();
913 }
914 }
915 state->setStrokeColor(&color);
916 out->updateStrokeColor(state);
917 }
918}
919
920//------------------------------------------------------------------------
921// path segment operators
922//------------------------------------------------------------------------
923
924void Gfx::opMoveTo(Object args[], int numArgs) {
925 state->moveTo(args[0].getNum(), args[1].getNum());
926}
927
928void Gfx::opLineTo(Object args[], int numArgs) {
929 if (!state->isCurPt()) {
930 error(getPos(), "No current point in lineto");
931 return;
932 }
933 state->lineTo(args[0].getNum(), args[1].getNum());
934}
935
936void Gfx::opCurveTo(Object args[], int numArgs) {
937 fouble x1, y1, x2, y2, x3, y3;
938
939 if (!state->isCurPt()) {
940 error(getPos(), "No current point in curveto");
941 return;
942 }
943 x1 = args[0].getNum();
944 y1 = args[1].getNum();
945 x2 = args[2].getNum();
946 y2 = args[3].getNum();
947 x3 = args[4].getNum();
948 y3 = args[5].getNum();
949 state->curveTo(x1, y1, x2, y2, x3, y3);
950}
951
952void Gfx::opCurveTo1(Object args[], int numArgs) {
953 fouble x1, y1, x2, y2, x3, y3;
954
955 if (!state->isCurPt()) {
956 error(getPos(), "No current point in curveto1");
957 return;
958 }
959 x1 = state->getCurX();
960 y1 = state->getCurY();
961 x2 = args[0].getNum();
962 y2 = args[1].getNum();
963 x3 = args[2].getNum();
964 y3 = args[3].getNum();
965 state->curveTo(x1, y1, x2, y2, x3, y3);
966}
967
968void Gfx::opCurveTo2(Object args[], int numArgs) {
969 fouble x1, y1, x2, y2, x3, y3;
970
971 if (!state->isCurPt()) {
972 error(getPos(), "No current point in curveto2");
973 return;
974 }
975 x1 = args[0].getNum();
976 y1 = args[1].getNum();
977 x2 = args[2].getNum();
978 y2 = args[3].getNum();
979 x3 = x2;
980 y3 = y2;
981 state->curveTo(x1, y1, x2, y2, x3, y3);
982}
983
984void Gfx::opRectangle(Object args[], int numArgs) {
985 fouble x, y, w, h;
986
987 x = args[0].getNum();
988 y = args[1].getNum();
989 w = args[2].getNum();
990 h = args[3].getNum();
991 state->moveTo(x, y);
992 state->lineTo(x + w, y);
993 state->lineTo(x + w, y + h);
994 state->lineTo(x, y + h);
995 state->closePath();
996}
997
998void Gfx::opClosePath(Object args[], int numArgs) {
999 if (!state->isCurPt()) {
1000 error(getPos(), "No current point in closepath");
1001 return;
1002 }
1003 state->closePath();
1004}
1005
1006//------------------------------------------------------------------------
1007// path painting operators
1008//------------------------------------------------------------------------
1009
1010void Gfx::opEndPath(Object args[], int numArgs) {
1011 doEndPath();
1012}
1013
1014void Gfx::opStroke(Object args[], int numArgs) {
1015 if (!state->isCurPt()) {
1016 //error(getPos(), "No path in stroke");
1017 return;
1018 }
1019 if (state->isPath())
1020 out->stroke(state);
1021 doEndPath();
1022}
1023
1024void Gfx::opCloseStroke(Object args[], int numArgs) {
1025 if (!state->isCurPt()) {
1026 //error(getPos(), "No path in closepath/stroke");
1027 return;
1028 }
1029 if (state->isPath()) {
1030 state->closePath();
1031 out->stroke(state);
1032 }
1033 doEndPath();
1034}
1035
1036void Gfx::opFill(Object args[], int numArgs) {
1037 if (!state->isCurPt()) {
1038 //error(getPos(), "No path in fill");
1039 return;
1040 }
1041 if (state->isPath()) {
1042 if (state->getFillColorSpace()->getMode() == csPattern) {
1043 doPatternFill(gFalse);
1044 } else {
1045 out->fill(state);
1046 }
1047 }
1048 doEndPath();
1049}
1050
1051void Gfx::opEOFill(Object args[], int numArgs) {
1052 if (!state->isCurPt()) {
1053 //error(getPos(), "No path in eofill");
1054 return;
1055 }
1056 if (state->isPath()) {
1057 if (state->getFillColorSpace()->getMode() == csPattern) {
1058 doPatternFill(gTrue);
1059 } else {
1060 out->eoFill(state);
1061 }
1062 }
1063 doEndPath();
1064}
1065
1066void Gfx::opFillStroke(Object args[], int numArgs) {
1067 if (!state->isCurPt()) {
1068 //error(getPos(), "No path in fill/stroke");
1069 return;
1070 }
1071 if (state->isPath()) {
1072 if (state->getFillColorSpace()->getMode() == csPattern) {
1073 doPatternFill(gFalse);
1074 } else {
1075 out->fill(state);
1076 }
1077 out->stroke(state);
1078 }
1079 doEndPath();
1080}
1081
1082void Gfx::opCloseFillStroke(Object args[], int numArgs) {
1083 if (!state->isCurPt()) {
1084 //error(getPos(), "No path in closepath/fill/stroke");
1085 return;
1086 }
1087 if (state->isPath()) {
1088 state->closePath();
1089 if (state->getFillColorSpace()->getMode() == csPattern) {
1090 doPatternFill(gFalse);
1091 } else {
1092 out->fill(state);
1093 }
1094 out->stroke(state);
1095 }
1096 doEndPath();
1097}
1098
1099void Gfx::opEOFillStroke(Object args[], int numArgs) {
1100 if (!state->isCurPt()) {
1101 //error(getPos(), "No path in eofill/stroke");
1102 return;
1103 }
1104 if (state->isPath()) {
1105 if (state->getFillColorSpace()->getMode() == csPattern) {
1106 doPatternFill(gTrue);
1107 } else {
1108 out->eoFill(state);
1109 }
1110 out->stroke(state);
1111 }
1112 doEndPath();
1113}
1114
1115void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
1116 if (!state->isCurPt()) {
1117 //error(getPos(), "No path in closepath/eofill/stroke");
1118 return;
1119 }
1120 if (state->isPath()) {
1121 state->closePath();
1122 if (state->getFillColorSpace()->getMode() == csPattern) {
1123 doPatternFill(gTrue);
1124 } else {
1125 out->eoFill(state);
1126 }
1127 out->stroke(state);
1128 }
1129 doEndPath();
1130}
1131
1132void Gfx::doPatternFill(GBool eoFill) {
1133 GfxPatternColorSpace *patCS;
1134 GfxPattern *pattern;
1135 GfxTilingPattern *tPat;
1136 GfxColorSpace *cs;
1137 fouble xMin, yMin, xMax, yMax, x, y, x1, y1;
1138 fouble cxMin, cyMin, cxMax, cyMax;
1139 int xi0, yi0, xi1, yi1, xi, yi;
1140 fouble *ctm, *btm, *ptm;
1141 fouble m[6], ictm[6], m1[6], im[6], imb[6];
1142 fouble det;
1143 fouble xstep, ystep;
1144 int i;
1145
1146 // this is a bit of a kludge -- patterns can be really slow, so we
1147 // skip them if we're only doing text extraction, since they almost
1148 // certainly don't contain any text
1149 if (!out->needNonText()) {
1150 return;
1151 }
1152
1153 // get color space
1154 patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
1155
1156 // get pattern
1157 if (!(pattern = state->getFillPattern())) {
1158 return;
1159 }
1160 if (pattern->getType() != 1) {
1161 return;
1162 }
1163 tPat = (GfxTilingPattern *)pattern;
1164
1165 // construct a (pattern space) -> (current space) transform matrix
1166 ctm = state->getCTM();
1167 btm = baseMatrix;
1168 ptm = tPat->getMatrix();
1169 // iCTM = invert CTM
1170 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
1171 ictm[0] = ctm[3] * det;
1172 ictm[1] = -ctm[1] * det;
1173 ictm[2] = -ctm[2] * det;
1174 ictm[3] = ctm[0] * det;
1175 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
1176 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
1177 // m1 = PTM * BTM = PTM * base transform matrix
1178 m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
1179 m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
1180 m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
1181 m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
1182 m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
1183 m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
1184 // m = m1 * iCTM = (PTM * BTM) * (iCTM)
1185 m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
1186 m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
1187 m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
1188 m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
1189 m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
1190 m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
1191
1192 // construct a (current space) -> (pattern space) transform matrix
1193 det = 1 / (m[0] * m[3] - m[1] * m[2]);
1194 im[0] = m[3] * det;
1195 im[1] = -m[1] * det;
1196 im[2] = -m[2] * det;
1197 im[3] = m[0] * det;
1198 im[4] = (m[2] * m[5] - m[3] * m[4]) * det;
1199 im[5] = (m[1] * m[4] - m[0] * m[5]) * det;
1200
1201 // construct a (base space) -> (pattern space) transform matrix
1202 det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);
1203 imb[0] = m1[3] * det;
1204 imb[1] = -m1[1] * det;
1205 imb[2] = -m1[2] * det;
1206 imb[3] = m1[0] * det;
1207 imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;
1208 imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
1209
1210 // save current graphics state
1211 out->saveState(state);
1212 state = state->save();
1213
1214 // set underlying color space (for uncolored tiling patterns)
1215 if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
1216 state->setFillColorSpace(cs->copy());
1217 } else {
1218 state->setFillColorSpace(new GfxDeviceGrayColorSpace());
1219 }
1220 state->setFillPattern(NULL);
1221 out->updateFillColor(state);
1222
1223 // clip to current path
1224 state->clip();
1225 if (eoFill) {
1226 out->eoClip(state);
1227 } else {
1228 out->clip(state);
1229 }
1230 state->clearPath();
1231
1232 // transform clip region bbox to pattern space
1233 state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
1234 xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];
1235 yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];
1236 x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];
1237 y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];
1238 if (x1 < xMin) {
1239 xMin = x1;
1240 } else if (x1 > xMax) {
1241 xMax = x1;
1242 }
1243 if (y1 < yMin) {
1244 yMin = y1;
1245 } else if (y1 > yMax) {
1246 yMax = y1;
1247 }
1248 x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];
1249 y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];
1250 if (x1 < xMin) {
1251 xMin = x1;
1252 } else if (x1 > xMax) {
1253 xMax = x1;
1254 }
1255 if (y1 < yMin) {
1256 yMin = y1;
1257 } else if (y1 > yMax) {
1258 yMax = y1;
1259 }
1260 x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];
1261 y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];
1262 if (x1 < xMin) {
1263 xMin = x1;
1264 } else if (x1 > xMax) {
1265 xMax = x1;
1266 }
1267 if (y1 < yMin) {
1268 yMin = y1;
1269 } else if (y1 > yMax) {
1270 yMax = y1;
1271 }
1272
1273 // draw the pattern
1274 //~ this should treat negative steps differently -- start at right/top
1275 //~ edge instead of left/bottom (?)
1276 xstep = fabs(tPat->getXStep());
1277 ystep = fabs(tPat->getYStep());
1278 xi0 = (int)floor(xMin / xstep);
1279 xi1 = (int)ceil(xMax / xstep);
1280 yi0 = (int)floor(yMin / ystep);
1281 yi1 = (int)ceil(yMax / ystep);
1282 for (i = 0; i < 4; ++i) {
1283 m1[i] = m[i];
1284 }
1285 for (yi = yi0; yi < yi1; ++yi) {
1286 for (xi = xi0; xi < xi1; ++xi) {
1287 x = xi * xstep;
1288 y = yi * ystep;
1289 m1[4] = x * m[0] + y * m[2] + m[4];
1290 m1[5] = x * m[1] + y * m[3] + m[5];
1291 doForm1(tPat->getContentStream(), tPat->getResDict(),
1292 m1, tPat->getBBox());
1293 }
1294 }
1295
1296 // restore graphics state
1297 state = state->restore();
1298 out->restoreState(state);
1299}
1300
1301void Gfx::opShFill(Object args[], int numArgs) {
1302 GfxShading *shading;
1303 fouble xMin, yMin, xMax, yMax;
1304
1305 if (!(shading = res->lookupShading(args[0].getName()))) {
1306 return;
1307 }
1308
1309 // save current graphics state
1310 out->saveState(state);
1311 state = state->save();
1312
1313 // clip to bbox
1314 if (shading->getHasBBox()) {
1315 shading->getBBox(&xMin, &yMin, &xMax, &yMax);
1316 state->moveTo(xMin, yMin);
1317 state->lineTo(xMax, yMin);
1318 state->lineTo(xMax, yMax);
1319 state->lineTo(xMin, yMax);
1320 state->closePath();
1321 state->clip();
1322 out->clip(state);
1323 state->clearPath();
1324 }
1325
1326 // set the color space
1327 state->setFillColorSpace(shading->getColorSpace()->copy());
1328
1329 // do shading type-specific operations
1330 switch (shading->getType()) {
1331 case 2:
1332 doAxialShFill((GfxAxialShading *)shading);
1333 break;
1334 }
1335
1336 // restore graphics state
1337 state = state->restore();
1338 out->restoreState(state);
1339
1340 delete shading;
1341}
1342
1343void Gfx::doAxialShFill(GfxAxialShading *shading) {
1344 fouble xMin, yMin, xMax, yMax;
1345 fouble x0, y0, x1, y1;
1346 fouble det;
1347 fouble *ctm;
1348 fouble ictm[6];
1349 fouble dx, dy, mul;
1350 fouble tMin, tMax, t, tx, ty;
1351 fouble s[4], sMin, sMax, tmp;
1352 fouble ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
1353 fouble t0, t1, tt;
1354 fouble ta[axialMaxSplits + 1];
1355 int next[axialMaxSplits + 1];
1356 GfxColor color0, color1;
1357 int nComps;
1358 int i, j, k, kk;
1359
1360 // get clip region bbox and transform to current user space
1361 state->getClipBBox(&x0, &y0, &x1, &y1);
1362 ctm = state->getCTM();
1363 det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
1364 ictm[0] = ctm[3] * det;
1365 ictm[1] = -ctm[1] * det;
1366 ictm[2] = -ctm[2] * det;
1367 ictm[3] = ctm[0] * det;
1368 ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
1369 ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
1370 xMin = xMax = x0 * ictm[0] + y0 * ictm[2] + ictm[4];
1371 yMin = yMax = x0 * ictm[1] + y0 * ictm[3] + ictm[5];
1372 tx = x0 * ictm[0] + y1 * ictm[2] + ictm[4];
1373 ty = x0 * ictm[1] + y1 * ictm[3] + ictm[5];
1374 if (tx < xMin) {
1375 xMin = tx;
1376 } else if (tx > xMax) {
1377 xMax = tx;
1378 }
1379 if (ty < yMin) {
1380 yMin = ty;
1381 } else if (ty > yMax) {
1382 yMax = ty;
1383 }
1384 tx = x1 * ictm[0] + y0 * ictm[2] + ictm[4];
1385 ty = x1 * ictm[1] + y0 * ictm[3] + ictm[5];
1386 if (tx < xMin) {
1387 xMin = tx;
1388 } else if (tx > xMax) {
1389 xMax = tx;
1390 }
1391 if (ty < yMin) {
1392 yMin = ty;
1393 } else if (ty > yMax) {
1394 yMax = ty;
1395 }
1396 tx = x1 * ictm[0] + y1 * ictm[2] + ictm[4];
1397 ty = x1 * ictm[1] + y1 * ictm[3] + ictm[5];
1398 if (tx < xMin) {
1399 xMin = tx;
1400 } else if (tx > xMax) {
1401 xMax = tx;
1402 }
1403 if (ty < yMin) {
1404 yMin = ty;
1405 } else if (ty > yMax) {
1406 yMax = ty;
1407 }
1408
1409 // compute min and max t values, based on the four corners of the
1410 // clip region bbox
1411 shading->getCoords(&x0, &y0, &x1, &y1);
1412 dx = x1 - x0;
1413 dy = y1 - y0;
1414 mul = 1 / (dx * dx + dy * dy);
1415 tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
1416 t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
1417 if (t < tMin) {
1418 tMin = t;
1419 } else if (t > tMax) {
1420 tMax = t;
1421 }
1422 t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
1423 if (t < tMin) {
1424 tMin = t;
1425 } else if (t > tMax) {
1426 tMax = t;
1427 }
1428 t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
1429 if (t < tMin) {
1430 tMin = t;
1431 } else if (t > tMax) {
1432 tMax = t;
1433 }
1434 if (tMin < 0 && !shading->getExtend0()) {
1435 tMin = 0;
1436 }
1437 if (tMax > 1 && !shading->getExtend1()) {
1438 tMax = 1;
1439 }
1440
1441 // get the function domain
1442 t0 = shading->getDomain0();
1443 t1 = shading->getDomain1();
1444
1445 // Traverse the t axis and do the shading.
1446 //
1447 // For each point (tx, ty) on the t axis, consider a line through
1448 // that point perpendicular to the t axis:
1449 //
1450 // x(s) = tx + s * -dy --> s = (x - tx) / -dy
1451 // y(s) = ty + s * dx --> s = (y - ty) / dx
1452 //
1453 // Then look at the intersection of this line with the bounding box
1454 // (xMin, yMin, xMax, yMax). In the general case, there are four
1455 // intersection points:
1456 //
1457 // s0 = (xMin - tx) / -dy
1458 // s1 = (xMax - tx) / -dy
1459 // s2 = (yMin - ty) / dx
1460 // s3 = (yMax - ty) / dx
1461 //
1462 // and we want the middle two s values.
1463 //
1464 // In the case where dx = 0, take s0 and s1; in the case where dy =
1465 // 0, take s2 and s3.
1466 //
1467 // Each filled polygon is bounded by two of these line segments
1468 // perpdendicular to the t axis.
1469 //
1470 // The t axis is bisected into smaller regions until the color
1471 // difference across a region is small enough, and then the region
1472 // is painted with a single color.
1473
1474 // set up
1475 nComps = shading->getColorSpace()->getNComps();
1476 ta[0] = tMin;
1477 ta[axialMaxSplits] = tMax;
1478 next[0] = axialMaxSplits;
1479
1480 // compute the color at t = tMin
1481 if (tMin < 0) {
1482 tt = t0;
1483 } else if (tMin > 1) {
1484 tt = t1;
1485 } else {
1486 tt = t0 + (t1 - t0) * tMin;
1487 }
1488 shading->getColor(tt, &color0);
1489
1490 // compute the coordinates of the point on the t axis at t = tMin;
1491 // then compute the intersection of the perpendicular line with the
1492 // bounding box
1493 tx = x0 + tMin * dx;
1494 ty = y0 + tMin * dy;
1495 if (dx == 0 && dy == 0) {
1496 sMin = sMax = 0;
1497 } if (dx == 0) {
1498 sMin = (xMin - tx) / -dy;
1499 sMax = (xMax - tx) / -dy;
1500 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1501 } else if (dy == 0) {
1502 sMin = (yMin - ty) / dx;
1503 sMax = (yMax - ty) / dx;
1504 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1505 } else {
1506 s[0] = (yMin - ty) / dx;
1507 s[1] = (yMax - ty) / dx;
1508 s[2] = (xMin - tx) / -dy;
1509 s[3] = (xMax - tx) / -dy;
1510 for (j = 0; j < 3; ++j) {
1511 kk = j;
1512 for (k = j + 1; k < 4; ++k) {
1513 if (s[k] < s[kk]) {
1514 kk = k;
1515 }
1516 }
1517 tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
1518 }
1519 sMin = s[1];
1520 sMax = s[2];
1521 }
1522 ux0 = tx - sMin * dy;
1523 uy0 = ty + sMin * dx;
1524 vx0 = tx - sMax * dy;
1525 vy0 = ty + sMax * dx;
1526
1527 i = 0;
1528 while (i < axialMaxSplits) {
1529
1530 // bisect until color difference is small enough or we hit the
1531 // bisection limit
1532 j = next[i];
1533 while (j > i + 1) {
1534 if (ta[j] < 0) {
1535 tt = t0;
1536 } else if (ta[j] > 1) {
1537 tt = t1;
1538 } else {
1539 tt = t0 + (t1 - t0) * ta[j];
1540 }
1541 shading->getColor(tt, &color1);
1542 for (k = 0; k < nComps; ++k) {
1543 if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) {
1544 break;
1545 }
1546 }
1547 if (k == nComps) {
1548 break;
1549 }
1550 k = (i + j) / 2;
1551 ta[k] = 0.5 * (ta[i] + ta[j]);
1552 next[i] = k;
1553 next[k] = j;
1554 j = k;
1555 }
1556
1557 // use the average of the colors of the two sides of the region
1558 for (k = 0; k < nComps; ++k) {
1559 color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]);
1560 }
1561
1562 // compute the coordinates of the point on the t axis; then
1563 // compute the intersection of the perpendicular line with the
1564 // bounding box
1565 tx = x0 + ta[j] * dx;
1566 ty = y0 + ta[j] * dy;
1567 if (dx == 0 && dy == 0) {
1568 sMin = sMax = 0;
1569 } if (dx == 0) {
1570 sMin = (xMin - tx) / -dy;
1571 sMax = (xMax - tx) / -dy;
1572 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1573 } else if (dy == 0) {
1574 sMin = (yMin - ty) / dx;
1575 sMax = (yMax - ty) / dx;
1576 if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
1577 } else {
1578 s[0] = (yMin - ty) / dx;
1579 s[1] = (yMax - ty) / dx;
1580 s[2] = (xMin - tx) / -dy;
1581 s[3] = (xMax - tx) / -dy;
1582 for (j = 0; j < 3; ++j) {
1583 kk = j;
1584 for (k = j + 1; k < 4; ++k) {
1585 if (s[k] < s[kk]) {
1586 kk = k;
1587 }
1588 }
1589 tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
1590 }
1591 sMin = s[1];
1592 sMax = s[2];
1593 }
1594 ux1 = tx - sMin * dy;
1595 uy1 = ty + sMin * dx;
1596 vx1 = tx - sMax * dy;
1597 vy1 = ty + sMax * dx;
1598
1599 // set the color
1600 state->setFillColor(&color0);
1601 out->updateFillColor(state);
1602
1603 // fill the region
1604 state->moveTo(ux0, uy0);
1605 state->lineTo(vx0, vy0);
1606 state->lineTo(vx1, vy1);
1607 state->lineTo(ux1, uy1);
1608 state->closePath();
1609 out->fill(state);
1610 state->clearPath();
1611
1612 // set up for next region
1613 ux0 = ux1;
1614 uy0 = uy1;
1615 vx0 = vx1;
1616 vy0 = vy1;
1617 color0 = color1;
1618 i = next[i];
1619 }
1620}
1621
1622void Gfx::doEndPath() {
1623 if (state->isPath() && clip != clipNone) {
1624 state->clip();
1625 if (clip == clipNormal) {
1626 out->clip(state);
1627 } else {
1628 out->eoClip(state);
1629 }
1630 }
1631 clip = clipNone;
1632 state->clearPath();
1633}
1634
1635//------------------------------------------------------------------------
1636// path clipping operators
1637//------------------------------------------------------------------------
1638
1639void Gfx::opClip(Object args[], int numArgs) {
1640 clip = clipNormal;
1641}
1642
1643void Gfx::opEOClip(Object args[], int numArgs) {
1644 clip = clipEO;
1645}
1646
1647//------------------------------------------------------------------------
1648// text object operators
1649//------------------------------------------------------------------------
1650
1651void Gfx::opBeginText(Object args[], int numArgs) {
1652 state->setTextMat(1, 0, 0, 1, 0, 0);
1653 state->textMoveTo(0, 0);
1654 out->updateTextMat(state);
1655 out->updateTextPos(state);
1656 fontChanged = gTrue;
1657}
1658
1659void Gfx::opEndText(Object args[], int numArgs) {
1660}
1661
1662//------------------------------------------------------------------------
1663// text state operators
1664//------------------------------------------------------------------------
1665
1666void Gfx::opSetCharSpacing(Object args[], int numArgs) {
1667 state->setCharSpace(args[0].getNum());
1668 out->updateCharSpace(state);
1669}
1670
1671void Gfx::opSetFont(Object args[], int numArgs) {
1672 GfxFont *font;
1673
1674 if (!(font = res->lookupFont(args[0].getName()))) {
1675 return;
1676 }
1677 if (printCommands) {
1678 printf(" font: tag=%s name='%s' %g\n",
1679 font->getTag()->getCString(),
1680 font->getName() ? font->getName()->getCString() : "???",
1681 args[1].getNum());
1682 fflush(stdout);
1683 }
1684 state->setFont(font, args[1].getNum());
1685 fontChanged = gTrue;
1686}
1687
1688void Gfx::opSetTextLeading(Object args[], int numArgs) {
1689 state->setLeading(args[0].getNum());
1690}
1691
1692void Gfx::opSetTextRender(Object args[], int numArgs) {
1693 state->setRender(args[0].getInt());
1694 out->updateRender(state);
1695}
1696
1697void Gfx::opSetTextRise(Object args[], int numArgs) {
1698 state->setRise(args[0].getNum());
1699 out->updateRise(state);
1700}
1701
1702void Gfx::opSetWordSpacing(Object args[], int numArgs) {
1703 state->setWordSpace(args[0].getNum());
1704 out->updateWordSpace(state);
1705}
1706
1707void Gfx::opSetHorizScaling(Object args[], int numArgs) {
1708 state->setHorizScaling(args[0].getNum());
1709 out->updateHorizScaling(state);
1710 fontChanged = gTrue;
1711}
1712
1713//------------------------------------------------------------------------
1714// text positioning operators
1715//------------------------------------------------------------------------
1716
1717void Gfx::opTextMove(Object args[], int numArgs) {
1718 fouble tx, ty;
1719
1720 tx = state->getLineX() + args[0].getNum();
1721 ty = state->getLineY() + args[1].getNum();
1722 state->textMoveTo(tx, ty);
1723 out->updateTextPos(state);
1724}
1725
1726void Gfx::opTextMoveSet(Object args[], int numArgs) {
1727 fouble tx, ty;
1728
1729 tx = state->getLineX() + args[0].getNum();
1730 ty = args[1].getNum();
1731 state->setLeading(-ty);
1732 ty += state->getLineY();
1733 state->textMoveTo(tx, ty);
1734 out->updateTextPos(state);
1735}
1736
1737void Gfx::opSetTextMatrix(Object args[], int numArgs) {
1738 state->setTextMat(args[0].getNum(), args[1].getNum(),
1739 args[2].getNum(), args[3].getNum(),
1740 args[4].getNum(), args[5].getNum());
1741 state->textMoveTo(0, 0);
1742 out->updateTextMat(state);
1743 out->updateTextPos(state);
1744 fontChanged = gTrue;
1745}
1746
1747void Gfx::opTextNextLine(Object args[], int numArgs) {
1748 fouble tx, ty;
1749
1750 tx = state->getLineX();
1751 ty = state->getLineY() - state->getLeading();
1752 state->textMoveTo(tx, ty);
1753 out->updateTextPos(state);
1754}
1755
1756//------------------------------------------------------------------------
1757// text string operators
1758//------------------------------------------------------------------------
1759
1760void Gfx::opShowText(Object args[], int numArgs) {
1761 if (!state->getFont()) {
1762 error(getPos(), "No font in show");
1763 return;
1764 }
1765 doShowText(args[0].getString());
1766}
1767
1768void Gfx::opMoveShowText(Object args[], int numArgs) {
1769 fouble tx, ty;
1770
1771 if (!state->getFont()) {
1772 error(getPos(), "No font in move/show");
1773 return;
1774 }
1775 tx = state->getLineX();
1776 ty = state->getLineY() - state->getLeading();
1777 state->textMoveTo(tx, ty);
1778 out->updateTextPos(state);
1779 doShowText(args[0].getString());
1780}
1781
1782void Gfx::opMoveSetShowText(Object args[], int numArgs) {
1783 fouble tx, ty;
1784
1785 if (!state->getFont()) {
1786 error(getPos(), "No font in move/set/show");
1787 return;
1788 }
1789 state->setWordSpace(args[0].getNum());
1790 state->setCharSpace(args[1].getNum());
1791 tx = state->getLineX();
1792 ty = state->getLineY() - state->getLeading();
1793 state->textMoveTo(tx, ty);
1794 out->updateWordSpace(state);
1795 out->updateCharSpace(state);
1796 out->updateTextPos(state);
1797 doShowText(args[2].getString());
1798}
1799
1800void Gfx::opShowSpaceText(Object args[], int numArgs) {
1801 Array *a;
1802 Object obj;
1803 int i;
1804
1805 if (!state->getFont()) {
1806 error(getPos(), "No font in show/space");
1807 return;
1808 }
1809 a = args[0].getArray();
1810 for (i = 0; i < a->getLength(); ++i) {
1811 a->get(i, &obj);
1812 if (obj.isNum()) {
1813 state->textShift(-obj.getNum() * 0.001 * state->getFontSize());
1814 out->updateTextShift(state, obj.getNum());
1815 } else if (obj.isString()) {
1816 doShowText(obj.getString());
1817 } else {
1818 error(getPos(), "Element of show/space array must be number or string");
1819 }
1820 obj.free();
1821 }
1822}
1823
1824void Gfx::doShowText(GString *s) {
1825 GfxFont *font;
1826 fouble riseX, riseY;
1827 CharCode code;
1828 Unicode u[8];
1829 fouble dx, dy, dx2, dy2, tdx, tdy;
1830 fouble originX, originY, tOriginX, tOriginY;
1831 char *p;
1832 int len, n, uLen, nChars, nSpaces;
1833
1834 if (fontChanged) {
1835 out->updateFont(state);
1836 fontChanged = gFalse;
1837 }
1838 font = state->getFont();
1839
1840#if 0 //~type3
1841 fouble x, y;
1842 fouble oldCTM[6], newCTM[6];
1843 fouble *mat;
1844 Object charProc;
1845 Parser *oldParser;
1846 int i;
1847
1848 //~ also check out->renderType3()
1849 if (font->getType() == fontType3) {
1850 out->beginString(state, s);
1851 mat = state->getCTM();
1852 for (i = 0; i < 6; ++i) {
1853 oldCTM[i] = mat[i];
1854 }
1855 mat = state->getTextMat();
1856 newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2];
1857 newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3];
1858 newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2];
1859 newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3];
1860 mat = font->getFontMatrix();
1861 newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2];
1862 newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3];
1863 newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
1864 newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
1865 newCTM[0] *= state->getFontSize();
1866 newCTM[3] *= state->getFontSize();
1867 newCTM[0] *= state->getHorizScaling();
1868 newCTM[2] *= state->getHorizScaling();
1869 state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
1870 oldParser = parser;
1871 p = s->getCString();
1872 len = s->getLength();
1873 while (len > 0) {
1874 n = font->getNextChar(p, len, &code,
1875 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
1876 &dx, &dy, &originX, &originY);
1877 state->transform(state->getCurX() + riseX, state->getCurY() + riseY,
1878 &x, &y);
1879 out->saveState(state);
1880 state = state->save();
1881 state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
1882 //~ out->updateCTM(???)
1883 ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
1884 if (charProc.isStream()) {
1885 display(&charProc, gFalse);
1886 } else {
1887 error(getPos(), "Missing or bad Type3 CharProc entry");
1888 }
1889 state = state->restore();
1890 out->restoreState(state);
1891 charProc.free();
1892 dx = dx * state->getFontSize() + state->getCharSpace();
1893 if (n == 1 && *p == ' ') {
1894 dx += state->getWordSpace();
1895 }
1896 dx *= state->getHorizScaling();
1897 dy *= state->getFontSize();
1898 state->textTransformDelta(dx, dy, &tdx, &tdy);
1899 state->shift(tdx, tdy);
1900 p += n;
1901 len -= n;
1902 }
1903 parser = oldParser;
1904 out->endString(state);
1905 return;
1906 }
1907#endif
1908
1909 if (out->useDrawChar()) {
1910 state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
1911 out->beginString(state, s);
1912 p = s->getCString();
1913 len = s->getLength();
1914 while (len > 0) {
1915 n = font->getNextChar(p, len, &code,
1916 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
1917 &dx, &dy, &originX, &originY);
1918 dx = dx * state->getFontSize() + state->getCharSpace();
1919 if (n == 1 && *p == ' ') {
1920 dx += state->getWordSpace();
1921 }
1922 dx *= state->getHorizScaling();
1923 dy *= state->getFontSize();
1924 state->textTransformDelta(dx, dy, &tdx, &tdy);
1925 originX *= state->getFontSize();
1926 originY *= state->getFontSize();
1927 state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
1928 out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
1929 tdx, tdy, tOriginX, tOriginY, code, u, uLen);
1930 state->shift(tdx, tdy);
1931 p += n;
1932 len -= n;
1933 }
1934 out->endString(state);
1935
1936 } else {
1937 dx = dy = 0;
1938 p = s->getCString();
1939 len = s->getLength();
1940 nChars = nSpaces = 0;
1941 while (len > 0) {
1942 n = font->getNextChar(p, len, &code,
1943 u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
1944 &dx2, &dy2, &originX, &originY);
1945 dx += dx2;
1946 dy += dy2;
1947 if (n == 1 && *p == ' ') {
1948 ++nSpaces;
1949 }
1950 ++nChars;
1951 p += n;
1952 len -= n;
1953 }
1954 dx = dx * state->getFontSize()
1955 + nChars * state->getCharSpace()
1956 + nSpaces * state->getWordSpace();
1957 dx *= state->getHorizScaling();
1958 dy *= state->getFontSize();
1959 state->textTransformDelta(dx, dy, &tdx, &tdy);
1960 out->drawString(state, s);
1961 state->shift(tdx, tdy);
1962 }
1963}
1964
1965//------------------------------------------------------------------------
1966// XObject operators
1967//------------------------------------------------------------------------
1968
1969void Gfx::opXObject(Object args[], int numArgs) {
1970 Object obj1, obj2, refObj;
1971#if OPI_SUPPORT
1972 Object opiDict;
1973#endif
1974
1975 if (!res->lookupXObject(args[0].getName(), &obj1)) {
1976 return;
1977 }
1978 if (!obj1.isStream()) {
1979 error(getPos(), "XObject '%s' is wrong type", args[0].getName());
1980 obj1.free();
1981 return;
1982 }
1983#if OPI_SUPPORT
1984 obj1.streamGetDict()->lookup("OPI", &opiDict);
1985 if (opiDict.isDict()) {
1986 out->opiBegin(state, opiDict.getDict());
1987 }
1988#endif
1989 obj1.streamGetDict()->lookup("Subtype", &obj2);
1990 if (obj2.isName("Image")) {
1991 res->lookupXObjectNF(args[0].getName(), &refObj);
1992 doImage(&refObj, obj1.getStream(), gFalse);
1993 refObj.free();
1994 } else if (obj2.isName("Form")) {
1995 doForm(&obj1);
1996 } else if (obj2.isName()) {
1997 error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
1998 } else {
1999 error(getPos(), "XObject subtype is missing or wrong type");
2000 }
2001 obj2.free();
2002#if OPI_SUPPORT
2003 if (opiDict.isDict()) {
2004 out->opiEnd(state, opiDict.getDict());
2005 }
2006 opiDict.free();
2007#endif
2008 obj1.free();
2009}
2010
2011void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
2012 Dict *dict;
2013 int width, height;
2014 int bits;
2015 GBool mask;
2016 GBool invert;
2017 GfxColorSpace *colorSpace;
2018 GfxImageColorMap *colorMap;
2019 Object maskObj;
2020 GBool haveMask;
2021 int maskColors[2*gfxColorMaxComps];
2022 Object obj1, obj2;
2023 int i;
2024
2025 // get stream dict
2026 dict = str->getDict();
2027
2028 // get size
2029 dict->lookup("Width", &obj1);
2030 if (obj1.isNull()) {
2031 obj1.free();
2032 dict->lookup("W", &obj1);
2033 }
2034 if (!obj1.isInt())
2035 goto err2;
2036 width = obj1.getInt();
2037 obj1.free();
2038 dict->lookup("Height", &obj1);
2039 if (obj1.isNull()) {
2040 obj1.free();
2041 dict->lookup("H", &obj1);
2042 }
2043 if (!obj1.isInt())
2044 goto err2;
2045 height = obj1.getInt();
2046 obj1.free();
2047
2048 // image or mask?
2049 dict->lookup("ImageMask", &obj1);
2050 if (obj1.isNull()) {
2051 obj1.free();
2052 dict->lookup("IM", &obj1);
2053 }
2054 mask = gFalse;
2055 if (obj1.isBool())
2056 mask = obj1.getBool();
2057 else if (!obj1.isNull())
2058 goto err2;
2059 obj1.free();
2060
2061 // bit depth
2062 dict->lookup("BitsPerComponent", &obj1);
2063 if (obj1.isNull()) {
2064 obj1.free();
2065 dict->lookup("BPC", &obj1);
2066 }
2067 if (!obj1.isInt())
2068 goto err2;
2069 bits = obj1.getInt();
2070 obj1.free();
2071
2072 // display a mask
2073 if (mask) {
2074
2075 // check for inverted mask
2076 if (bits != 1)
2077 goto err1;
2078 invert = gFalse;
2079 dict->lookup("Decode", &obj1);
2080 if (obj1.isNull()) {
2081 obj1.free();
2082 dict->lookup("D", &obj1);
2083 }
2084 if (obj1.isArray()) {
2085 obj1.arrayGet(0, &obj2);
2086 if (obj2.isInt() && obj2.getInt() == 1)
2087 invert = gTrue;
2088 obj2.free();
2089 } else if (!obj1.isNull()) {
2090 goto err2;
2091 }
2092 obj1.free();
2093
2094 // draw it
2095 out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
2096
2097 } else {
2098
2099 // get color space and color map
2100 dict->lookup("ColorSpace", &obj1);
2101 if (obj1.isNull()) {
2102 obj1.free();
2103 dict->lookup("CS", &obj1);
2104 }
2105 if (obj1.isName()) {
2106 res->lookupColorSpace(obj1.getName(), &obj2);
2107 if (!obj2.isNull()) {
2108 obj1.free();
2109 obj1 = obj2;
2110 } else {
2111 obj2.free();
2112 }
2113 }
2114 colorSpace = GfxColorSpace::parse(&obj1);
2115 obj1.free();
2116 if (!colorSpace) {
2117 goto err1;
2118 }
2119 dict->lookup("Decode", &obj1);
2120 if (obj1.isNull()) {
2121 obj1.free();
2122 dict->lookup("D", &obj1);
2123 }
2124 colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
2125 obj1.free();
2126 if (!colorMap->isOk()) {
2127 delete colorMap;
2128 goto err1;
2129 }
2130
2131 // get the mask
2132 haveMask = gFalse;
2133 dict->lookup("Mask", &maskObj);
2134 if (maskObj.isArray()) {
2135 for (i = 0; i < maskObj.arrayGetLength(); ++i) {
2136 maskObj.arrayGet(i, &obj1);
2137 maskColors[i] = obj1.getInt();
2138 obj1.free();
2139 }
2140 haveMask = gTrue;
2141 }
2142
2143 // draw it
2144 out->drawImage(state, ref, str, width, height, colorMap,
2145 haveMask ? maskColors : (int *)NULL, inlineImg);
2146 delete colorMap;
2147
2148 maskObj.free();
2149 }
2150
2151 return;
2152
2153 err2:
2154 obj1.free();
2155 err1:
2156 error(getPos(), "Bad image parameters");
2157}
2158
2159void Gfx::doForm(Object *str) {
2160 Dict *dict;
2161 Object matrixObj, bboxObj;
2162 fouble m[6], bbox[6];
2163 Object resObj;
2164 Dict *resDict;
2165 Object obj1;
2166 int i;
2167
2168 // get stream dict
2169 dict = str->streamGetDict();
2170
2171 // check form type
2172 dict->lookup("FormType", &obj1);
2173 if (!(obj1.isInt() && obj1.getInt() == 1)) {
2174 error(getPos(), "Unknown form type");
2175 }
2176 obj1.free();
2177
2178 // get bounding box
2179 dict->lookup("BBox", &bboxObj);
2180 if (!bboxObj.isArray()) {
2181 matrixObj.free();
2182 bboxObj.free();
2183 error(getPos(), "Bad form bounding box");
2184 return;
2185 }
2186 for (i = 0; i < 4; ++i) {
2187 bboxObj.arrayGet(i, &obj1);
2188 bbox[i] = obj1.getNum();
2189 obj1.free();
2190 }
2191 bboxObj.free();
2192
2193 // get matrix
2194 dict->lookup("Matrix", &matrixObj);
2195 if (matrixObj.isArray()) {
2196 for (i = 0; i < 6; ++i) {
2197 matrixObj.arrayGet(i, &obj1);
2198 m[i] = obj1.getNum();
2199 obj1.free();
2200 }
2201 } else {
2202 m[0] = 1; m[1] = 0;
2203 m[2] = 0; m[3] = 1;
2204 m[4] = 0; m[5] = 0;
2205 }
2206 matrixObj.free();
2207
2208 // get resources
2209 dict->lookup("Resources", &resObj);
2210 resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
2211
2212 // draw it
2213 doForm1(str, resDict, m, bbox);
2214
2215 resObj.free();
2216}
2217
2218void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin,
2219 fouble xMax, fouble yMax) {
2220 Dict *dict, *resDict;
2221 Object matrixObj, bboxObj, resObj;
2222 Object obj1;
2223 fouble m[6], bbox[6];
2224 fouble sx, sy;
2225 int i;
2226
2227 // get stream dict
2228 dict = str->streamGetDict();
2229
2230 // get bounding box
2231 dict->lookup("BBox", &bboxObj);
2232 if (!bboxObj.isArray()) {
2233 bboxObj.free();
2234 error(getPos(), "Bad form bounding box");
2235 return;
2236 }
2237 for (i = 0; i < 4; ++i) {
2238 bboxObj.arrayGet(i, &obj1);
2239 bbox[i] = obj1.getNum();
2240 obj1.free();
2241 }
2242 bboxObj.free();
2243
2244 // get matrix
2245 dict->lookup("Matrix", &matrixObj);
2246 if (matrixObj.isArray()) {
2247 for (i = 0; i < 6; ++i) {
2248 matrixObj.arrayGet(i, &obj1);
2249 m[i] = obj1.getNum();
2250 obj1.free();
2251 }
2252 } else {
2253 m[0] = 1; m[1] = 0;
2254 m[2] = 0; m[3] = 1;
2255 m[4] = 0; m[5] = 0;
2256 }
2257 matrixObj.free();
2258
2259 // scale form bbox to widget rectangle
2260 sx = fabs((xMax - xMin) / (bbox[2] - bbox[0]));
2261 sy = fabs((yMax - yMin) / (bbox[3] - bbox[1]));
2262 m[0] *= sx; m[1] *= sy;
2263 m[2] *= sx; m[3] *= sy;
2264 m[4] *= sx; m[5] *= sy;
2265
2266 // translate to widget rectangle
2267 m[4] += xMin;
2268 m[5] += yMin;
2269
2270 // get resources
2271 dict->lookup("Resources", &resObj);
2272 resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
2273
2274 // draw it
2275 doForm1(str, resDict, m, bbox);
2276
2277 resObj.free();
2278 bboxObj.free();
2279}
2280
2281void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) {
2282 Parser *oldParser;
2283 fouble oldBaseMatrix[6];
2284 GfxResources *resPtr;
2285 int i;
2286
2287 // push new resources on stack
2288 res = new GfxResources(xref, resDict, res);
2289
2290 // save current graphics state
2291 out->saveState(state);
2292 state = state->save();
2293
2294 // save current parser
2295 oldParser = parser;
2296
2297 // set form transformation matrix
2298 state->concatCTM(matrix[0], matrix[1], matrix[2],
2299 matrix[3], matrix[4], matrix[5]);
2300 out->updateCTM(state, matrix[0], matrix[1], matrix[2],
2301 matrix[3], matrix[4], matrix[5]);
2302
2303 // set new base matrix
2304 for (i = 0; i < 6; ++i) {
2305 oldBaseMatrix[i] = baseMatrix[i];
2306 baseMatrix[i] = state->getCTM()[i];
2307 }
2308
2309 // set form bounding box
2310 state->moveTo(bbox[0], bbox[1]);
2311 state->lineTo(bbox[2], bbox[1]);
2312 state->lineTo(bbox[2], bbox[3]);
2313 state->lineTo(bbox[0], bbox[3]);
2314 state->closePath();
2315 state->clip();
2316 out->clip(state);
2317 state->clearPath();
2318
2319 // draw the form
2320 display(str, gFalse);
2321
2322 // restore base matrix
2323 for (i = 0; i < 6; ++i) {
2324 baseMatrix[i] = oldBaseMatrix[i];
2325 }
2326
2327 // restore parser
2328 parser = oldParser;
2329
2330 // restore graphics state
2331 state = state->restore();
2332 out->restoreState(state);
2333
2334 // pop resource stack
2335 resPtr = res->getNext();
2336 delete res;
2337 res = resPtr;
2338
2339 return;
2340}
2341
2342//------------------------------------------------------------------------
2343// in-line image operators
2344//------------------------------------------------------------------------
2345
2346void Gfx::opBeginImage(Object args[], int numArgs) {
2347 Stream *str;
2348 int c1, c2;
2349
2350 // build dict/stream
2351 str = buildImageStream();
2352
2353 // display the image
2354 if (str) {
2355 doImage(NULL, str, gTrue);
2356
2357 // skip 'EI' tag
2358 c1 = str->getBaseStream()->getChar();
2359 c2 = str->getBaseStream()->getChar();
2360 while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) {
2361 c1 = c2;
2362 c2 = str->getBaseStream()->getChar();
2363 }
2364 delete str;
2365 }
2366}
2367
2368Stream *Gfx::buildImageStream() {
2369 Object dict;
2370 Object obj;
2371 char *key;
2372 Stream *str;
2373
2374 // build dictionary
2375 dict.initDict(xref);
2376 parser->getObj(&obj);
2377 while (!obj.isCmd("ID") && !obj.isEOF()) {
2378 if (!obj.isName()) {
2379 error(getPos(), "Inline image dictionary key must be a name object");
2380 obj.free();
2381 parser->getObj(&obj);
2382 } else {
2383 key = copyString(obj.getName());
2384 obj.free();
2385 parser->getObj(&obj);
2386 if (obj.isEOF() || obj.isError())
2387 break;
2388 dict.dictAdd(key, &obj);
2389 }
2390 parser->getObj(&obj);
2391 }
2392 if (obj.isEOF())
2393 error(getPos(), "End of file in inline image");
2394 obj.free();
2395
2396 // make stream
2397 str = new EmbedStream(parser->getStream(), &dict);
2398 str = str->addFilters(&dict);
2399
2400 return str;
2401}
2402
2403void Gfx::opImageData(Object args[], int numArgs) {
2404 error(getPos(), "Internal: got 'ID' operator");
2405}
2406
2407void Gfx::opEndImage(Object args[], int numArgs) {
2408 error(getPos(), "Internal: got 'EI' operator");
2409}
2410
2411//------------------------------------------------------------------------
2412// type 3 font operators
2413//------------------------------------------------------------------------
2414
2415void Gfx::opSetCharWidth(Object args[], int numArgs) {
2416 error(getPos(), "Encountered 'd0' operator in content stream");
2417}
2418
2419void Gfx::opSetCacheDevice(Object args[], int numArgs) {
2420 error(getPos(), "Encountered 'd1' operator in content stream");
2421}
2422
2423//------------------------------------------------------------------------
2424// compatibility operators
2425//------------------------------------------------------------------------
2426
2427void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
2428 ++ignoreUndef;
2429}
2430
2431void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
2432 if (ignoreUndef > 0)
2433 --ignoreUndef;
2434}
2435
2436//------------------------------------------------------------------------
2437// marked content operators
2438//------------------------------------------------------------------------
2439
2440void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
2441 if (printCommands) {
2442 printf(" marked content: %s ", args[0].getName());
2443 if (numArgs == 2)
2444 args[2].print(stdout);
2445 printf("\n");
2446 fflush(stdout);
2447 }
2448}
2449
2450void Gfx::opEndMarkedContent(Object args[], int numArgs) {
2451}
2452
2453void Gfx::opMarkPoint(Object args[], int numArgs) {
2454 if (printCommands) {
2455 printf(" mark point: %s ", args[0].getName());
2456 if (numArgs == 2)
2457 args[2].print(stdout);
2458 printf("\n");
2459 fflush(stdout);
2460 }
2461}
diff --git a/noncore/unsupported/qpdf/xpdf/Gfx.h b/noncore/unsupported/qpdf/xpdf/Gfx.h
new file mode 100644
index 0000000..be5f2c2
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Gfx.h
@@ -0,0 +1,240 @@
1//========================================================================
2//
3// Gfx.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef GFX_H
10#define GFX_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17
18class GString;
19class XRef;
20class Array;
21class Stream;
22class Parser;
23class Dict;
24class OutputDev;
25class GfxFontDict;
26class GfxFont;
27class GfxPattern;
28class GfxShading;
29class GfxAxialShading;
30class GfxState;
31class Gfx;
32struct PDFRectangle;
33
34//------------------------------------------------------------------------
35// Gfx
36//------------------------------------------------------------------------
37
38enum GfxClipType {
39 clipNone,
40 clipNormal,
41 clipEO
42};
43
44enum TchkType {
45 tchkBool, // boolean
46 tchkInt, // integer
47 tchkNum, // number (integer or real)
48 tchkString, // string
49 tchkName, // name
50 tchkArray, // array
51 tchkProps, // properties (dictionary or name)
52 tchkSCN, // scn/SCN args (number of name)
53 tchkNone // used to avoid empty initializer lists
54};
55
56#define maxArgs 8
57
58struct Operator {
59 char name[4];
60 int numArgs;
61 TchkType tchk[maxArgs];
62 void (Gfx::*func)(Object args[], int numArgs);
63};
64
65class GfxResources {
66public:
67
68 GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA);
69 ~GfxResources();
70
71 GfxFont *lookupFont(char *name);
72 GBool lookupXObject(char *name, Object *obj);
73 GBool lookupXObjectNF(char *name, Object *obj);
74 void lookupColorSpace(char *name, Object *obj);
75 GfxPattern *lookupPattern(char *name);
76 GfxShading *lookupShading(char *name);
77 GBool lookupGState(char *name, Object *obj);
78
79 GfxResources *getNext() { return next; }
80
81private:
82
83 GfxFontDict *fonts;
84 Object xObjDict;
85 Object colorSpaceDict;
86 Object patternDict;
87 Object shadingDict;
88 Object gStateDict;
89 GfxResources *next;
90};
91
92class Gfx {
93public:
94
95 // Constructor for regular output.
96 Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, fouble dpi,
97 PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
98 GBool printCommandsA);
99
100 // Destructor.
101 ~Gfx();
102
103 // Interpret a stream or array of streams.
104 void display(Object *obj, GBool topLevel = gTrue);
105
106 void doWidgetForm(Object *str, fouble xMin, fouble yMin,
107 fouble xMax, fouble yMax);
108
109private:
110
111 XRef *xref; // the xref table for this PDF file
112 OutputDev *out; // output device
113 GBool printCommands; // print the drawing commands (for debugging)
114 GfxResources *res; // resource stack
115
116 GfxState *state; // current graphics state
117 GBool fontChanged; // set if font or text matrix has changed
118 GfxClipType clip; // do a clip?
119 int ignoreUndef; // current BX/EX nesting level
120 fouble baseMatrix[6]; // default matrix for most recent
121 // page/form/pattern
122
123 Parser *parser; // parser for page content stream(s)
124
125 static Operator opTab[];// table of operators
126
127 void go(GBool topLevel);
128 void execOp(Object *cmd, Object args[], int numArgs);
129 Operator *findOp(char *name);
130 GBool checkArg(Object *arg, TchkType type);
131 int getPos();
132
133 // graphics state operators
134 void opSave(Object args[], int numArgs);
135 void opRestore(Object args[], int numArgs);
136 void opConcat(Object args[], int numArgs);
137 void opSetDash(Object args[], int numArgs);
138 void opSetFlat(Object args[], int numArgs);
139 void opSetLineJoin(Object args[], int numArgs);
140 void opSetLineCap(Object args[], int numArgs);
141 void opSetMiterLimit(Object args[], int numArgs);
142 void opSetLineWidth(Object args[], int numArgs);
143 void opSetExtGState(Object args[], int numArgs);
144 void opSetRenderingIntent(Object args[], int numArgs);
145
146 // color operators
147 void opSetFillGray(Object args[], int numArgs);
148 void opSetStrokeGray(Object args[], int numArgs);
149 void opSetFillCMYKColor(Object args[], int numArgs);
150 void opSetStrokeCMYKColor(Object args[], int numArgs);
151 void opSetFillRGBColor(Object args[], int numArgs);
152 void opSetStrokeRGBColor(Object args[], int numArgs);
153 void opSetFillColorSpace(Object args[], int numArgs);
154 void opSetStrokeColorSpace(Object args[], int numArgs);
155 void opSetFillColor(Object args[], int numArgs);
156 void opSetStrokeColor(Object args[], int numArgs);
157 void opSetFillColorN(Object args[], int numArgs);
158 void opSetStrokeColorN(Object args[], int numArgs);
159
160 // path segment operators
161 void opMoveTo(Object args[], int numArgs);
162 void opLineTo(Object args[], int numArgs);
163 void opCurveTo(Object args[], int numArgs);
164 void opCurveTo1(Object args[], int numArgs);
165 void opCurveTo2(Object args[], int numArgs);
166 void opRectangle(Object args[], int numArgs);
167 void opClosePath(Object args[], int numArgs);
168
169 // path painting operators
170 void opEndPath(Object args[], int numArgs);
171 void opStroke(Object args[], int numArgs);
172 void opCloseStroke(Object args[], int numArgs);
173 void opFill(Object args[], int numArgs);
174 void opEOFill(Object args[], int numArgs);
175 void opFillStroke(Object args[], int numArgs);
176 void opCloseFillStroke(Object args[], int numArgs);
177 void opEOFillStroke(Object args[], int numArgs);
178 void opCloseEOFillStroke(Object args[], int numArgs);
179 void doPatternFill(GBool eoFill);
180 void opShFill(Object args[], int numArgs);
181 void doAxialShFill(GfxAxialShading *shading);
182 void doEndPath();
183
184 // path clipping operators
185 void opClip(Object args[], int numArgs);
186 void opEOClip(Object args[], int numArgs);
187
188 // text object operators
189 void opBeginText(Object args[], int numArgs);
190 void opEndText(Object args[], int numArgs);
191
192 // text state operators
193 void opSetCharSpacing(Object args[], int numArgs);
194 void opSetFont(Object args[], int numArgs);
195 void opSetTextLeading(Object args[], int numArgs);
196 void opSetTextRender(Object args[], int numArgs);
197 void opSetTextRise(Object args[], int numArgs);
198 void opSetWordSpacing(Object args[], int numArgs);
199 void opSetHorizScaling(Object args[], int numArgs);
200
201 // text positioning operators
202 void opTextMove(Object args[], int numArgs);
203 void opTextMoveSet(Object args[], int numArgs);
204 void opSetTextMatrix(Object args[], int numArgs);
205 void opTextNextLine(Object args[], int numArgs);
206
207 // text string operators
208 void opShowText(Object args[], int numArgs);
209 void opMoveShowText(Object args[], int numArgs);
210 void opMoveSetShowText(Object args[], int numArgs);
211 void opShowSpaceText(Object args[], int numArgs);
212 void doShowText(GString *s);
213
214 // XObject operators
215 void opXObject(Object args[], int numArgs);
216 void doImage(Object *ref, Stream *str, GBool inlineImg);
217 void doForm(Object *str);
218 void doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox);
219
220 // in-line image operators
221 void opBeginImage(Object args[], int numArgs);
222 Stream *buildImageStream();
223 void opImageData(Object args[], int numArgs);
224 void opEndImage(Object args[], int numArgs);
225
226 // type 3 font operators
227 void opSetCharWidth(Object args[], int numArgs);
228 void opSetCacheDevice(Object args[], int numArgs);
229
230 // compatibility operators
231 void opBeginIgnoreUndef(Object args[], int numArgs);
232 void opEndIgnoreUndef(Object args[], int numArgs);
233
234 // marked content operators
235 void opBeginMarkedContent(Object args[], int numArgs);
236 void opEndMarkedContent(Object args[], int numArgs);
237 void opMarkPoint(Object args[], int numArgs);
238};
239
240#endif
diff --git a/noncore/unsupported/qpdf/xpdf/GfxFont.cc b/noncore/unsupported/qpdf/xpdf/GfxFont.cc
new file mode 100644
index 0000000..518f97b
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/GfxFont.cc
@@ -0,0 +1,1247 @@
1//========================================================================
2//
3// GfxFont.cc
4//
5// Copyright 1996-2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <ctype.h>
18#include "gmem.h"
19#include "Error.h"
20#include "Object.h"
21#include "Dict.h"
22#include "GlobalParams.h"
23#include "CMap.h"
24#include "CharCodeToUnicode.h"
25#include "FontEncodingTables.h"
26#include "BuiltinFontTables.h"
27#include "FontFile.h"
28#include "GfxFont.h"
29
30//------------------------------------------------------------------------
31
32struct StdFontMapEntry {
33 char *altName;
34 char *properName;
35};
36
37static StdFontMapEntry stdFontMap[] = {
38 { "Arial", "Helvetica" },
39 { "Arial,Bold", "Helvetica-Bold" },
40 { "Arial,BoldItalic", "Helvetica-BoldOblique" },
41 { "Arial,Italic", "Helvetica-Oblique" },
42 { "Arial-Bold", "Helvetica-Bold" },
43 { "Arial-BoldItalic", "Helvetica-BoldOblique" },
44 { "Arial-BoldItalicMT", "Helvetica-BoldOblique" },
45 { "Arial-BoldMT", "Helvetica-Bold" },
46 { "Arial-Italic", "Helvetica-Oblique" },
47 { "Arial-ItalicMT", "Helvetica-Oblique" },
48 { "ArialMT", "Helvetica" },
49 { "Courier,Bold", "Courier-Bold" },
50 { "Courier,Italic", "Courier-Oblique" },
51 { "Courier,BoldItalic", "Courier-BoldOblique" },
52 { "CourierNew", "Courier" },
53 { "CourierNew,Bold", "Courier-Bold" },
54 { "CourierNew,BoldItalic", "Courier-BoldOblique" },
55 { "CourierNew,Italic", "Courier-Oblique" },
56 { "CourierNew-Bold", "Courier-Bold" },
57 { "CourierNew-BoldItalic", "Courier-BoldOblique" },
58 { "CourierNew-Italic", "Courier-Oblique" },
59 { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" },
60 { "CourierNewPS-BoldMT", "Courier-Bold" },
61 { "CourierNewPS-ItalicMT", "Courier-Oblique" },
62 { "CourierNewPSMT", "Courier" },
63 { "Helvetica,Bold", "Helvetica-Bold" },
64 { "Helvetica,BoldItalic", "Helvetica-BoldOblique" },
65 { "Helvetica,Italic", "Helvetica-Oblique" },
66 { "Helvetica-BoldItalic", "Helvetica-BoldOblique" },
67 { "Helvetica-Italic", "Helvetica-Oblique" },
68 { "TimesNewRoman", "Times-Roman" },
69 { "TimesNewRoman,Bold", "Times-Bold" },
70 { "TimesNewRoman,BoldItalic", "Times-BoldItalic" },
71 { "TimesNewRoman,Italic", "Times-Italic" },
72 { "TimesNewRoman-Bold", "Times-Bold" },
73 { "TimesNewRoman-BoldItalic", "Times-BoldItalic" },
74 { "TimesNewRoman-Italic", "Times-Italic" },
75 { "TimesNewRomanPS", "Times-Roman" },
76 { "TimesNewRomanPS-Bold", "Times-Bold" },
77 { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" },
78 { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
79 { "TimesNewRomanPS-BoldMT", "Times-Bold" },
80 { "TimesNewRomanPS-Italic", "Times-Italic" },
81 { "TimesNewRomanPS-ItalicMT", "Times-Italic" },
82 { "TimesNewRomanPSMT", "Times-Roman" }
83};
84
85//------------------------------------------------------------------------
86// GfxFont
87//------------------------------------------------------------------------
88
89GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
90 GString *nameA;
91 GfxFont *font;
92 Object obj1;
93
94 // get base font name
95 nameA = NULL;
96 fontDict->lookup("BaseFont", &obj1);
97 if (obj1.isName()) {
98 nameA = new GString(obj1.getName());
99 }
100 obj1.free();
101
102 // get font type
103 font = NULL;
104 fontDict->lookup("Subtype", &obj1);
105 if (obj1.isName("Type1") || obj1.isName("MMType1")) {
106 font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
107 } else if (obj1.isName("Type1C")) {
108 font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
109 } else if (obj1.isName("Type3")) {
110 font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
111 } else if (obj1.isName("TrueType")) {
112 font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
113 } else if (obj1.isName("Type0")) {
114 font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
115 } else {
116 error(-1, "Unknown font type: '%s'",
117 obj1.isName() ? obj1.getName() : "???");
118 font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
119 }
120 obj1.free();
121
122 return font;
123}
124
125GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) {
126 ok = gFalse;
127 tag = new GString(tagA);
128 id = idA;
129 name = nameA;
130 embFontName = NULL;
131 extFontFile = NULL;
132}
133
134GfxFont::~GfxFont() {
135 delete tag;
136 if (name) {
137 delete name;
138 }
139 if (embFontName) {
140 delete embFontName;
141 }
142 if (extFontFile) {
143 delete extFontFile;
144 }
145}
146
147void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
148 Object obj1, obj2, obj3, obj4;
149 fouble t;
150 int i;
151
152 // assume Times-Roman by default (for substitution purposes)
153 flags = fontSerif;
154
155 embFontID.num = -1;
156 embFontID.gen = -1;
157 missingWidth = 0;
158
159 if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
160
161 // get flags
162 if (obj1.dictLookup("Flags", &obj2)->isInt()) {
163 flags = obj2.getInt();
164 }
165 obj2.free();
166
167 // get name
168 obj1.dictLookup("FontName", &obj2);
169 if (obj2.isName()) {
170 embFontName = new GString(obj2.getName());
171 }
172 obj2.free();
173
174 // look for embedded font file
175 if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
176 if (type == fontType1) {
177 embFontID = obj2.getRef();
178 } else {
179 error(-1, "Mismatch between font type and embedded font file");
180 }
181 }
182 obj2.free();
183 if (embFontID.num == -1 &&
184 obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
185 if (type == fontTrueType || type == fontCIDType2) {
186 embFontID = obj2.getRef();
187 } else {
188 error(-1, "Mismatch between font type and embedded font file");
189 }
190 }
191 obj2.free();
192 if (embFontID.num == -1 &&
193 obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
194 if (obj2.fetch(xref, &obj3)->isStream()) {
195 obj3.streamGetDict()->lookup("Subtype", &obj4);
196 if (obj4.isName("Type1")) {
197 if (type == fontType1) {
198 embFontID = obj2.getRef();
199 } else {
200 error(-1, "Mismatch between font type and embedded font file");
201 }
202 } else if (obj4.isName("Type1C")) {
203 if (type == fontType1) {
204 type = fontType1C;
205 embFontID = obj2.getRef();
206 } else if (type == fontType1C) {
207 embFontID = obj2.getRef();
208 } else {
209 error(-1, "Mismatch between font type and embedded font file");
210 }
211 } else if (obj4.isName("TrueType")) {
212 if (type == fontTrueType) {
213 embFontID = obj2.getRef();
214 } else {
215 error(-1, "Mismatch between font type and embedded font file");
216 }
217 } else if (obj4.isName("CIDFontType0C")) {
218 if (type == fontCIDType0) {
219 type = fontCIDType0C;
220 embFontID = obj2.getRef();
221 } else {
222 error(-1, "Mismatch between font type and embedded font file");
223 }
224 } else {
225 error(-1, "Unknown embedded font type '%s'",
226 obj4.isName() ? obj4.getName() : "???");
227 }
228 obj4.free();
229 }
230 obj3.free();
231 }
232 obj2.free();
233
234 // look for MissingWidth
235 obj1.dictLookup("MissingWidth", &obj2);
236 if (obj2.isNum()) {
237 missingWidth = obj2.getNum();
238 }
239 obj2.free();
240
241 // get Ascent and Descent
242 obj1.dictLookup("Ascent", &obj2);
243 if (obj2.isNum()) {
244 t = 0.001 * obj2.getNum();
245 // some broken font descriptors set ascent and descent to 0
246 if (t != 0) {
247 ascent = t;
248 }
249 }
250 obj2.free();
251 obj1.dictLookup("Descent", &obj2);
252 if (obj2.isNum()) {
253 t = 0.001 * obj2.getNum();
254 // some broken font descriptors set ascent and descent to 0
255 if (t != 0) {
256 descent = t;
257 }
258 }
259 obj2.free();
260
261 // font FontBBox
262 if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
263 for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
264 if (obj2.arrayGet(i, &obj3)->isNum()) {
265 fontBBox[i] = 0.001 * obj3.getNum();
266 }
267 obj3.free();
268 }
269 }
270 obj2.free();
271
272 }
273 obj1.free();
274}
275
276CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits) {
277 CharCodeToUnicode *ctu;
278 GString *buf;
279 Object obj1;
280 int c;
281
282 if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
283 obj1.free();
284 return NULL;
285 }
286 buf = new GString();
287 obj1.streamReset();
288 while ((c = obj1.streamGetChar()) != EOF) {
289 buf->append(c);
290 }
291 obj1.streamClose();
292 obj1.free();
293 ctu = CharCodeToUnicode::parseCMap(buf, nBits);
294 delete buf;
295 return ctu;
296}
297
298void GfxFont::findExtFontFile() {
299 if (name) {
300 if (type == fontType1) {
301 extFontFile = globalParams->findFontFile(name, ".pfa", ".pfb");
302 } else if (type == fontTrueType) {
303 extFontFile = globalParams->findFontFile(name, ".ttf", NULL);
304 }
305 }
306}
307
308char *GfxFont::readExtFontFile(int *len) {
309 FILE *f;
310 char *buf;
311
312 if (!(f = fopen(extFontFile->getCString(), "rb"))) {
313 error(-1, "External font file '%s' vanished", extFontFile->getCString());
314 return NULL;
315 }
316 fseek(f, 0, SEEK_END);
317 *len = (int)ftell(f);
318 fseek(f, 0, SEEK_SET);
319 buf = (char *)gmalloc(*len);
320 if ((int)fread(buf, 1, *len, f) != *len) {
321 error(-1, "Error reading external font file '%s'", extFontFile);
322 }
323 fclose(f);
324 return buf;
325}
326
327char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
328 char *buf;
329 Object obj1, obj2;
330 Stream *str;
331 int c;
332 int size, i;
333
334 obj1.initRef(embFontID.num, embFontID.gen);
335 obj1.fetch(xref, &obj2);
336 if (!obj2.isStream()) {
337 error(-1, "Embedded font file is not a stream");
338 obj2.free();
339 obj1.free();
340 embFontID.num = -1;
341 return NULL;
342 }
343 str = obj2.getStream();
344
345 buf = NULL;
346 i = size = 0;
347 str->reset();
348 while ((c = str->getChar()) != EOF) {
349 if (i == size) {
350 size += 4096;
351 buf = (char *)grealloc(buf, size);
352 }
353 buf[i++] = c;
354 }
355 *len = i;
356 str->close();
357
358 obj2.free();
359 obj1.free();
360
361 return buf;
362}
363
364//------------------------------------------------------------------------
365// Gfx8BitFont
366//------------------------------------------------------------------------
367
368Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
369 GfxFontType typeA, Dict *fontDict):
370 GfxFont(tagA, idA, nameA)
371{
372 BuiltinFont *builtinFont;
373 char **baseEnc;
374 GBool baseEncFromFontFile;
375 char *buf;
376 int len;
377 FontFile *fontFile;
378 int code, code2;
379 char *charName;
380 GBool missing, hex;
381 Unicode toUnicode[256];
382 fouble mul;
383 int firstChar, lastChar;
384 Gushort w;
385 Object obj1, obj2, obj3;
386 int n, i, a, b, m;
387
388 type = typeA;
389 ctu = NULL;
390
391 // Acrobat 4.0 and earlier substituted Base14-compatible fonts
392 // without providing Widths and a FontDescriptor, so we munge the
393 // names into the proper Base14 names. (This table is from
394 // implementation note 44 in the PDF 1.4 spec.)
395 if (name) {
396 a = 0;
397 b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
398 // invariant: stdFontMap[a].altName <= name < stdFontMap[b].altName
399 while (b - a > 1) {
400 m = (a + b) / 2;
401 if (name->cmp(stdFontMap[m].altName) >= 0) {
402 a = m;
403 } else {
404 b = m;
405 }
406 }
407 if (!name->cmp(stdFontMap[a].altName)) {
408 delete name;
409 name = new GString(stdFontMap[a].properName);
410 }
411 }
412
413 // is it a built-in font?
414 builtinFont = NULL;
415 if (name) {
416 for (i = 0; i < nBuiltinFonts; ++i) {
417 if (!name->cmp(builtinFonts[i].name)) {
418 builtinFont = &builtinFonts[i];
419 break;
420 }
421 }
422 }
423
424 // default ascent/descent values
425 if (builtinFont) {
426 ascent = 0.001 * builtinFont->ascent;
427 descent = 0.001 * builtinFont->descent;
428 fontBBox[0] = 0.001 * builtinFont->bbox[0];
429 fontBBox[1] = 0.001 * builtinFont->bbox[1];
430 fontBBox[2] = 0.001 * builtinFont->bbox[2];
431 fontBBox[3] = 0.001 * builtinFont->bbox[3];
432 } else {
433 ascent = 0.95;
434 descent = -0.35;
435 fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
436 }
437
438 // get info from font descriptor
439 readFontDescriptor(xref, fontDict);
440
441 // look for an external font file
442 findExtFontFile();
443
444 // get font matrix
445 fontMat[0] = fontMat[3] = 1;
446 fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
447 if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
448 for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
449 if (obj1.arrayGet(i, &obj2)->isNum()) {
450 fontMat[i] = obj2.getNum();
451 }
452 obj2.free();
453 }
454 }
455 obj1.free();
456
457 // get Type3 font definition
458 if (type == fontType3) {
459 fontDict->lookup("CharProcs", &charProcs);
460 if (!charProcs.isDict()) {
461 error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
462 charProcs.free();
463 }
464 }
465
466 //----- build the font encoding -----
467
468 // Encodings start with a base encoding, which can come from
469 // (in order of priority):
470 // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
471 // - MacRoman / MacExpert / WinAnsi / Standard
472 // 2. embedded or external font file
473 // 3. default:
474 // - builtin --> builtin encoding
475 // - TrueType --> MacRomanEncoding
476 // - others --> StandardEncoding
477 // and then add a list of differences (if any) from
478 // FontDict.Encoding.Differences.
479
480 // check FontDict for base encoding
481 hasEncoding = gFalse;
482 baseEnc = NULL;
483 baseEncFromFontFile = gFalse;
484 fontDict->lookup("Encoding", &obj1);
485 if (obj1.isDict()) {
486 obj1.dictLookup("BaseEncoding", &obj2);
487 if (obj2.isName("MacRomanEncoding")) {
488 hasEncoding = gTrue;
489 baseEnc = macRomanEncoding;
490 } else if (obj2.isName("MacExpertEncoding")) {
491 hasEncoding = gTrue;
492 baseEnc = macExpertEncoding;
493 } else if (obj2.isName("WinAnsiEncoding")) {
494 hasEncoding = gTrue;
495 baseEnc = winAnsiEncoding;
496 } else if (obj2.isName("StandardEncoding")) {
497 hasEncoding = gTrue;
498 baseEnc = standardEncoding;
499 }
500 obj2.free();
501 } else if (obj1.isName("MacRomanEncoding")) {
502 hasEncoding = gTrue;
503 baseEnc = macRomanEncoding;
504 } else if (obj1.isName("MacExpertEncoding")) {
505 hasEncoding = gTrue;
506 baseEnc = macExpertEncoding;
507 } else if (obj1.isName("WinAnsiEncoding")) {
508 hasEncoding = gTrue;
509 baseEnc = winAnsiEncoding;
510 } else if (obj1.isName("StandardEncoding")) {
511 hasEncoding = gTrue;
512 baseEnc = standardEncoding;
513 }
514
515 // check embedded or external font file for base encoding
516 fontFile = NULL;
517 buf = NULL;
518 if ((type == fontType1 || type == fontType1C || type == fontTrueType) &&
519 (extFontFile || embFontID.num >= 0)) {
520 if (extFontFile) {
521 buf = readExtFontFile(&len);
522 } else {
523 buf = readEmbFontFile(xref, &len);
524 }
525 if (buf) {
526#if 0
527 if (type == fontType1) {
528 fontFile = new Type1FontFile(buf, len);
529 } else if (type == fontType1C) {
530 fontFile = new Type1CFontFile(buf, len);
531 } else {
532 fontFile = new TrueTypeFontFile(buf, len);
533 }
534 if (fontFile->getName()) {
535 if (embFontName) {
536 delete embFontName;
537 }
538 embFontName = new GString(fontFile->getName());
539 }
540 if (!baseEnc) {
541 baseEnc = fontFile->getEncoding();
542 baseEncFromFontFile = gTrue;
543 }
544#endif
545 gfree(buf);
546 }
547 }
548
549 // get default base encoding
550 if (!baseEnc) {
551 if (builtinFont) {
552 baseEnc = builtinFont->defaultBaseEnc;
553 } else if (type == fontTrueType) {
554 baseEnc = macRomanEncoding;
555 } else {
556 baseEnc = standardEncoding;
557 }
558 }
559
560 // copy the base encoding
561 for (i = 0; i < 256; ++i) {
562 enc[i] = baseEnc[i];
563 if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
564 enc[i] = copyString(baseEnc[i]);
565 }
566 }
567
568 // merge differences into encoding
569 if (obj1.isDict()) {
570 obj1.dictLookup("Differences", &obj2);
571 if (obj2.isArray()) {
572 code = 0;
573 for (i = 0; i < obj2.arrayGetLength(); ++i) {
574 obj2.arrayGet(i, &obj3);
575 if (obj3.isInt()) {
576 code = obj3.getInt();
577 } else if (obj3.isName()) {
578 if (code < 256) {
579 if (encFree[code]) {
580 gfree(enc[code]);
581 }
582 enc[code] = copyString(obj3.getName());
583 encFree[code] = gTrue;
584 }
585 ++code;
586 } else {
587 error(-1, "Wrong type in font encoding resource differences (%s)",
588 obj3.getTypeName());
589 }
590 obj3.free();
591 }
592 }
593 obj2.free();
594 }
595 obj1.free();
596 if (fontFile) {
597 delete fontFile;
598 }
599
600 //----- build the mapping to Unicode -----
601
602 // look for a ToUnicode CMap
603 if (!(ctu = readToUnicodeCMap(fontDict, 8))) {
604
605 // no ToUnicode CMap, so use the char names
606
607 // pass 1: use the name-to-Unicode mapping table
608 missing = hex = gFalse;
609 for (code = 0; code < 256; ++code) {
610 if ((charName = enc[code])) {
611 if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
612 strcmp(charName, ".notdef")) {
613 // if it wasn't in the name-to-Unicode table, check for a
614 // name that looks like 'Axx' or 'xx', where 'A' is any letter
615 // and 'xx' is two hex digits
616 if ((strlen(charName) == 3 &&
617 isalpha(charName[0]) &&
618 isxdigit(charName[1]) && isxdigit(charName[2]) &&
619 ((charName[1] >= 'a' && charName[1] <= 'f') ||
620 (charName[1] >= 'A' && charName[1] <= 'F') ||
621 (charName[2] >= 'a' && charName[2] <= 'f') ||
622 (charName[2] >= 'A' && charName[2] <= 'F'))) ||
623 (strlen(charName) == 2 &&
624 isxdigit(charName[0]) && isxdigit(charName[1]) &&
625 ((charName[0] >= 'a' && charName[0] <= 'f') ||
626 (charName[0] >= 'A' && charName[0] <= 'F') ||
627 (charName[1] >= 'a' && charName[1] <= 'f') ||
628 (charName[1] >= 'A' && charName[1] <= 'F')))) {
629 hex = gTrue;
630 }
631 missing = gTrue;
632 }
633 } else {
634 toUnicode[code] = 0;
635 }
636 }
637
638 // pass 2: try to fill in the missing chars, looking for names of
639 // the form 'Axx', 'xx', 'Ann', or 'nn', where 'A' is any letter,
640 // 'xx' is two hex digits, and 'nn' is 2-4 decimal digits
641 if (missing && globalParams->getMapNumericCharNames()) {
642 for (code = 0; code < 256; ++code) {
643 if ((charName = enc[code]) && !toUnicode[code] &&
644 strcmp(charName, ".notdef")) {
645 n = strlen(charName);
646 code2 = -1;
647 if (hex && n == 3 && isalpha(charName[0]) &&
648 isxdigit(charName[1]) && isxdigit(charName[2])) {
649 sscanf(charName+1, "%x", &code2);
650 } else if (hex && n == 2 &&
651 isxdigit(charName[0]) && isxdigit(charName[1])) {
652 sscanf(charName, "%x", &code2);
653 } else if (!hex && n >= 2 && n <= 4 &&
654 isdigit(charName[0]) && isdigit(charName[1])) {
655 code2 = atoi(charName);
656 } else if (n >= 3 && n <= 5 &&
657 isdigit(charName[1]) && isdigit(charName[2])) {
658 code2 = atoi(charName+1);
659 }
660 if (code2 >= 0 && code2 <= 0xff) {
661 toUnicode[code] = (Unicode)code2;
662 }
663 }
664 }
665 }
666
667 ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
668 }
669
670 //----- get the character widths -----
671
672 // initialize all widths
673 for (code = 0; code < 256; ++code) {
674 widths[code] = missingWidth * 0.001;
675 }
676
677 // use widths from font dict, if present
678 fontDict->lookup("FirstChar", &obj1);
679 firstChar = obj1.isInt() ? obj1.getInt() : 0;
680 obj1.free();
681 fontDict->lookup("LastChar", &obj1);
682 lastChar = obj1.isInt() ? obj1.getInt() : 255;
683 obj1.free();
684 mul = (type == fontType3) ? fontMat[0] : fouble(0.001);
685 fontDict->lookup("Widths", &obj1);
686 if (obj1.isArray()) {
687 for (code = firstChar; code <= lastChar; ++code) {
688 obj1.arrayGet(code - firstChar, &obj2);
689 if (obj2.isNum()) {
690 widths[code] = obj2.getNum() * mul;
691 }
692 obj2.free();
693 }
694
695 // use widths from built-in font
696 } else if (builtinFont) {
697 // this is a kludge for broken PDF files that encode char 32
698 // as .notdef
699 if (builtinFont->widths->getWidth("space", &w)) {
700 widths[32] = 0.001 * w;
701 }
702 for (code = 0; code < 256; ++code) {
703 if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
704 widths[code] = 0.001 * w;
705 }
706 }
707
708 // couldn't find widths -- use defaults
709 } else {
710 // this is technically an error -- the Widths entry is required
711 // for all but the Base-14 fonts -- but certain PDF generators
712 // apparently don't include widths for Arial and TimesNewRoman
713 if (isFixedWidth()) {
714 i = 0;
715 } else if (isSerif()) {
716 i = 8;
717 } else {
718 i = 4;
719 }
720 if (isBold()) {
721 i += 2;
722 }
723 if (isItalic()) {
724 i += 1;
725 }
726 builtinFont = builtinFontSubst[i];
727 // this is a kludge for broken PDF files that encode char 32
728 // as .notdef
729 if (builtinFont->widths->getWidth("space", &w)) {
730 widths[32] = 0.001 * w;
731 }
732 for (code = 0; code < 256; ++code) {
733 if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
734 widths[code] = 0.001 * w;
735 }
736 }
737 }
738 obj1.free();
739
740 ok = gTrue;
741}
742
743Gfx8BitFont::~Gfx8BitFont() {
744 int i;
745
746 for (i = 0; i < 256; ++i) {
747 if (encFree[i] && enc[i]) {
748 gfree(enc[i]);
749 }
750 }
751 ctu->decRefCnt();
752 if (charProcs.isDict()) {
753 charProcs.free();
754 }
755}
756
757int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
758 Unicode *u, int uSize, int *uLen,
759 fouble *dx, fouble *dy, fouble *ox, fouble *oy) {
760 CharCode c;
761
762 *code = c = (CharCode)(*s & 0xff);
763 *uLen = ctu->mapToUnicode(c, u, uSize);
764 *dx = widths[c];
765 *dy = *ox = *oy = 0;
766 return 1;
767}
768
769CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
770 ctu->incRefCnt();
771 return ctu;
772}
773
774Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
775 if (charProcs.isDict()) {
776 charProcs.dictLookup(enc[code], proc);
777 } else {
778 proc->initNull();
779 }
780 return proc;
781}
782
783//------------------------------------------------------------------------
784// GfxCIDFont
785//------------------------------------------------------------------------
786
787static int cmpWidthExcep(const void *w1, const void *w2) {
788 return ((GfxFontCIDWidthExcep *)w1)->first -
789 ((GfxFontCIDWidthExcep *)w2)->first;
790}
791
792static int cmpWidthExcepV(const void *w1, const void *w2) {
793 return ((GfxFontCIDWidthExcepV *)w1)->first -
794 ((GfxFontCIDWidthExcepV *)w2)->first;
795}
796
797GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
798 Dict *fontDict):
799 GfxFont(tagA, idA, nameA)
800{
801 Dict *desFontDict;
802 GString *collection, *cMapName;
803 Object desFontDictObj;
804 Object obj1, obj2, obj3, obj4, obj5, obj6;
805 int c1, c2;
806 int excepsSize, i, j, k;
807
808 ascent = 0.95;
809 descent = -0.35;
810 fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
811 cMap = NULL;
812 ctu = NULL;
813 widths.defWidth = 1.0;
814 widths.defHeight = -1.0;
815 widths.defVY = 0.880;
816 widths.exceps = NULL;
817 widths.nExceps = 0;
818 widths.excepsV = NULL;
819 widths.nExcepsV = 0;
820 cidToGID = NULL;
821 cidToGIDLen = 0;
822
823 // get the descendant font
824 if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
825 error(-1, "Missing DescendantFonts entry in Type 0 font");
826 obj1.free();
827 goto err1;
828 }
829 if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
830 error(-1, "Bad descendant font in Type 0 font");
831 goto err3;
832 }
833 obj1.free();
834 desFontDict = desFontDictObj.getDict();
835
836 // font type
837 if (!desFontDict->lookup("Subtype", &obj1)) {
838 error(-1, "Missing Subtype entry in Type 0 descendant font");
839 goto err3;
840 }
841 if (obj1.isName("CIDFontType0")) {
842 type = fontCIDType0;
843 } else if (obj1.isName("CIDFontType2")) {
844 type = fontCIDType2;
845 } else {
846 error(-1, "Unknown Type 0 descendant font type '%s'",
847 obj1.isName() ? obj1.getName() : "???");
848 goto err3;
849 }
850 obj1.free();
851
852 // get info from font descriptor
853 readFontDescriptor(xref, desFontDict);
854
855 // look for an external font file
856 findExtFontFile();
857
858 //----- encoding info -----
859
860 // char collection
861 if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
862 error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
863 goto err3;
864 }
865 obj1.dictLookup("Registry", &obj2);
866 obj1.dictLookup("Ordering", &obj3);
867 if (!obj2.isString() || !obj3.isString()) {
868 error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
869 goto err4;
870 }
871 collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
872 obj3.free();
873 obj2.free();
874 obj1.free();
875
876 // look for a ToUnicode CMap
877 if (!(ctu = readToUnicodeCMap(fontDict, 16))) {
878
879 // the "Adobe-Identity" and "Adobe-UCS" collections don't have
880 // cidToUnicode files
881 if (collection->cmp("Adobe-Identity") &&
882 collection->cmp("Adobe-UCS")) {
883
884 // look for a user-supplied .cidToUnicode file
885 if (!(ctu = globalParams->getCIDToUnicode(collection))) {
886 error(-1, "Unknown character collection '%s'",
887 collection->getCString());
888 delete collection;
889 goto err2;
890 }
891 }
892 }
893
894 // encoding (i.e., CMap)
895 //~ need to handle a CMap stream here
896 //~ also need to deal with the UseCMap entry in the stream dict
897 if (!fontDict->lookup("Encoding", &obj1)->isName()) {
898 error(-1, "Missing or invalid Encoding entry in Type 0 font");
899 delete collection;
900 goto err3;
901 }
902 cMapName = new GString(obj1.getName());
903 obj1.free();
904 if (!(cMap = globalParams->getCMap(collection, cMapName))) {
905 error(-1, "Unknown CMap '%s' for character collection '%s'",
906 cMapName->getCString(), collection->getCString());
907 delete collection;
908 delete cMapName;
909 goto err2;
910 }
911 delete collection;
912 delete cMapName;
913
914 // CIDToGIDMap (for embedded TrueType fonts)
915 if (type == fontCIDType2) {
916 fontDict->lookup("CIDToGIDMap", &obj1);
917 if (obj1.isStream()) {
918 cidToGIDLen = 0;
919 i = 64;
920 cidToGID = (Gushort *)gmalloc(i * sizeof(Gushort));
921 obj1.streamReset();
922 while ((c1 = obj1.streamGetChar()) != EOF &&
923 (c2 = obj1.streamGetChar()) != EOF) {
924 if (cidToGIDLen == i) {
925 i *= 2;
926 cidToGID = (Gushort *)grealloc(cidToGID, i * sizeof(Gushort));
927 }
928 cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
929 }
930 } else if (!obj1.isName("Identity") && !obj1.isNull()) {
931 error(-1, "Invalid CIDToGIDMap entry in CID font");
932 }
933 obj1.free();
934 }
935
936 //----- character metrics -----
937
938 // default char width
939 if (desFontDict->lookup("DW", &obj1)->isInt()) {
940 widths.defWidth = obj1.getInt() * 0.001;
941 }
942 obj1.free();
943
944 // char width exceptions
945 if (desFontDict->lookup("W", &obj1)->isArray()) {
946 excepsSize = 0;
947 i = 0;
948 while (i + 1 < obj1.arrayGetLength()) {
949 obj1.arrayGet(i, &obj2);
950 obj1.arrayGet(i + 1, &obj3);
951 if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
952 if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
953 if (widths.nExceps == excepsSize) {
954 excepsSize += 16;
955 widths.exceps = (GfxFontCIDWidthExcep *)
956 grealloc(widths.exceps,
957 excepsSize * sizeof(GfxFontCIDWidthExcep));
958 }
959 widths.exceps[widths.nExceps].first = obj2.getInt();
960 widths.exceps[widths.nExceps].last = obj3.getInt();
961 widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
962 ++widths.nExceps;
963 } else {
964 error(-1, "Bad widths array in Type 0 font");
965 }
966 obj4.free();
967 i += 3;
968 } else if (obj2.isInt() && obj3.isArray()) {
969 if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
970 excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
971 widths.exceps = (GfxFontCIDWidthExcep *)
972 grealloc(widths.exceps,
973 excepsSize * sizeof(GfxFontCIDWidthExcep));
974 }
975 j = obj2.getInt();
976 for (k = 0; k < obj3.arrayGetLength(); ++k) {
977 if (obj3.arrayGet(k, &obj4)->isNum()) {
978 widths.exceps[widths.nExceps].first = j;
979 widths.exceps[widths.nExceps].last = j;
980 widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
981 ++j;
982 ++widths.nExceps;
983 } else {
984 error(-1, "Bad widths array in Type 0 font");
985 }
986 obj4.free();
987 }
988 i += 2;
989 } else {
990 error(-1, "Bad widths array in Type 0 font");
991 ++i;
992 }
993 obj3.free();
994 obj2.free();
995 }
996 qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
997 &cmpWidthExcep);
998 }
999 obj1.free();
1000
1001 // default metrics for vertical font
1002 if (desFontDict->lookup("DW2", &obj1)->isArray() &&
1003 obj1.arrayGetLength() == 2) {
1004 if (obj1.arrayGet(0, &obj2)->isNum()) {
1005 widths.defVY = obj1.getNum() * 0.001;
1006 }
1007 obj2.free();
1008 if (obj1.arrayGet(1, &obj2)->isNum()) {
1009 widths.defHeight = obj1.getNum() * 0.001;
1010 }
1011 obj2.free();
1012 }
1013 obj1.free();
1014
1015 // char metric exceptions for vertical font
1016 if (desFontDict->lookup("W2", &obj1)->isArray()) {
1017 excepsSize = 0;
1018 i = 0;
1019 while (i + 1 < obj1.arrayGetLength()) {
1020 obj1.arrayGet(0, &obj2);
1021 obj2.arrayGet(0, &obj3);
1022 if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
1023 if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
1024 obj1.arrayGet(i + 3, &obj5)->isNum() &&
1025 obj1.arrayGet(i + 4, &obj6)->isNum()) {
1026 if (widths.nExcepsV == excepsSize) {
1027 excepsSize += 16;
1028 widths.excepsV = (GfxFontCIDWidthExcepV *)
1029 grealloc(widths.excepsV,
1030 excepsSize * sizeof(GfxFontCIDWidthExcepV));
1031 }
1032 widths.excepsV[widths.nExcepsV].first = obj2.getInt();
1033 widths.excepsV[widths.nExcepsV].last = obj3.getInt();
1034 widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
1035 widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
1036 widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
1037 ++widths.nExcepsV;
1038 } else {
1039 error(-1, "Bad widths (W2) array in Type 0 font");
1040 }
1041 obj6.free();
1042 obj5.free();
1043 obj4.free();
1044 i += 5;
1045 } else if (obj2.isInt() && obj3.isArray()) {
1046 if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
1047 excepsSize =
1048 (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
1049 widths.excepsV = (GfxFontCIDWidthExcepV *)
1050 grealloc(widths.excepsV,
1051 excepsSize * sizeof(GfxFontCIDWidthExcepV));
1052 }
1053 j = obj2.getInt();
1054 for (k = 0; k < obj3.arrayGetLength(); ++k) {
1055 if (obj3.arrayGet(k, &obj4)->isNum() &&
1056 obj3.arrayGet(k, &obj5)->isNum() &&
1057 obj3.arrayGet(k, &obj6)->isNum()) {
1058 widths.excepsV[widths.nExceps].first = j;
1059 widths.excepsV[widths.nExceps].last = j;
1060 widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001;
1061 widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001;
1062 widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001;
1063 ++j;
1064 ++widths.nExcepsV;
1065 } else {
1066 error(-1, "Bad widths (W2) array in Type 0 font");
1067 }
1068 obj6.free();
1069 obj5.free();
1070 obj4.free();
1071 }
1072 i += 2;
1073 } else {
1074 error(-1, "Bad widths (W2) array in Type 0 font");
1075 ++i;
1076 }
1077 obj3.free();
1078 obj2.free();
1079 }
1080 qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
1081 &cmpWidthExcepV);
1082 }
1083 obj1.free();
1084
1085 desFontDictObj.free();
1086 ok = gTrue;
1087 return;
1088
1089 err4:
1090 obj3.free();
1091 obj2.free();
1092 err3:
1093 obj1.free();
1094 err2:
1095 desFontDictObj.free();
1096 err1:;
1097}
1098
1099GfxCIDFont::~GfxCIDFont() {
1100 if (cMap) {
1101 cMap->decRefCnt();
1102 }
1103 if (ctu) {
1104 ctu->decRefCnt();
1105 }
1106 gfree(widths.exceps);
1107 gfree(widths.excepsV);
1108 if (cidToGID) {
1109 gfree(cidToGID);
1110 }
1111}
1112
1113int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
1114 Unicode *u, int uSize, int *uLen,
1115 fouble *dx, fouble *dy, fouble *ox, fouble *oy) {
1116 CID cid;
1117 fouble w, h, vx, vy;
1118 int n, a, b, m;
1119
1120 if (!cMap) {
1121 *code = 0;
1122 *uLen = 0;
1123 *dx = *dy = 0;
1124 return 1;
1125 }
1126
1127 *code = (CharCode)(cid = cMap->getCID(s, len, &n));
1128 if (ctu) {
1129 *uLen = ctu->mapToUnicode(cid, u, uSize);
1130 } else {
1131 *uLen = 0;
1132 }
1133
1134 // horizontal
1135 if (cMap->getWMode() == 0) {
1136 w = widths.defWidth;
1137 h = vx = vy = 0;
1138 if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
1139 a = 0;
1140 b = widths.nExceps;
1141 // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
1142 while (b - a > 1) {
1143 m = (a + b) / 2;
1144 if (widths.exceps[m].first <= cid) {
1145 a = m;
1146 } else {
1147 b = m;
1148 }
1149 }
1150 if (cid <= widths.exceps[a].last) {
1151 w = widths.exceps[a].width;
1152 }
1153 }
1154
1155 // vertical
1156 } else {
1157 w = 0;
1158 h = widths.defHeight;
1159 vx = widths.defWidth / 2;
1160 vy = widths.defVY;
1161 if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
1162 a = 0;
1163 b = widths.nExcepsV;
1164 // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
1165 while (b - a > 1) {
1166 m = (a + b) / 2;
1167 if (widths.excepsV[m].last <= cid) {
1168 a = m;
1169 } else {
1170 b = m;
1171 }
1172 }
1173 if (cid <= widths.excepsV[a].last) {
1174 h = widths.excepsV[a].height;
1175 vx = widths.excepsV[a].vx;
1176 vy = widths.excepsV[a].vy;
1177 }
1178 }
1179 }
1180
1181 *dx = w;
1182 *dy = h;
1183 *ox = vx;
1184 *oy = vy;
1185
1186 return n;
1187}
1188
1189CharCodeToUnicode *GfxCIDFont::getToUnicode() {
1190 ctu->incRefCnt();
1191 return ctu;
1192}
1193
1194GString *GfxCIDFont::getCollection() {
1195 return cMap ? cMap->getCollection() : (GString *)NULL;
1196}
1197
1198//------------------------------------------------------------------------
1199// GfxFontDict
1200//------------------------------------------------------------------------
1201
1202GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) {
1203 int i;
1204 Object obj1, obj2;
1205
1206 numFonts = fontDict->getLength();
1207 fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
1208 for (i = 0; i < numFonts; ++i) {
1209 fontDict->getValNF(i, &obj1);
1210 obj1.fetch(xref, &obj2);
1211 if (obj1.isRef() && obj2.isDict()) {
1212 fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
1213 obj1.getRef(), obj2.getDict());
1214 if (fonts[i] && !fonts[i]->isOk()) {
1215 delete fonts[i];
1216 fonts[i] = NULL;
1217 }
1218 } else {
1219 error(-1, "font resource is not a dictionary");
1220 fonts[i] = NULL;
1221 }
1222 obj1.free();
1223 obj2.free();
1224 }
1225}
1226
1227GfxFontDict::~GfxFontDict() {
1228 int i;
1229
1230 for (i = 0; i < numFonts; ++i) {
1231 if (fonts[i]) {
1232 delete fonts[i];
1233 }
1234 }
1235 gfree(fonts);
1236}
1237
1238GfxFont *GfxFontDict::lookup(char *tag) {
1239 int i;
1240
1241 for (i = 0; i < numFonts; ++i) {
1242 if (fonts[i] && fonts[i]->matches(tag)) {
1243 return fonts[i];
1244 }
1245 }
1246 return NULL;
1247}
diff --git a/noncore/unsupported/qpdf/xpdf/GfxFont.h b/noncore/unsupported/qpdf/xpdf/GfxFont.h
new file mode 100644
index 0000000..b1aa952
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/GfxFont.h
@@ -0,0 +1,286 @@
1//========================================================================
2//
3// GfxFont.h
4//
5// Copyright 1996-2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef GFXFONT_H
10#define GFXFONT_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "GString.h"
18#include "Object.h"
19#include "CharTypes.h"
20
21class Dict;
22class CMap;
23class CharCodeToUnicode;
24struct GfxFontCIDWidths;
25
26//------------------------------------------------------------------------
27// GfxFontType
28//------------------------------------------------------------------------
29
30enum GfxFontType {
31 //----- Gfx8BitFont
32 fontUnknownType,
33 fontType1,
34 fontType1C,
35 fontType3,
36 fontTrueType,
37 //----- GfxCIDFont
38 fontCIDType0,
39 fontCIDType0C,
40 fontCIDType2
41};
42
43//------------------------------------------------------------------------
44// GfxFontCIDWidths
45//------------------------------------------------------------------------
46
47struct GfxFontCIDWidthExcep {
48 CID first; // this record applies to
49 CID last; // CIDs <first>..<last>
50 fouble width; // char width
51};
52
53struct GfxFontCIDWidthExcepV {
54 CID first; // this record applies to
55 CID last; // CIDs <first>..<last>
56 fouble height; // char height
57 fouble vx, vy; // origin position
58};
59
60struct GfxFontCIDWidths {
61 fouble defWidth; // default char width
62 fouble defHeight; // default char height
63 fouble defVY; // default origin position
64 GfxFontCIDWidthExcep *exceps;// exceptions
65 int nExceps; // number of valid entries in exceps
66 GfxFontCIDWidthExcepV *// exceptions for vertical font
67 excepsV;
68 int nExcepsV; // number of valid entries in excepsV
69};
70
71//------------------------------------------------------------------------
72// GfxFont
73//------------------------------------------------------------------------
74
75#define fontFixedWidth (1 << 0)
76#define fontSerif (1 << 1)
77#define fontSymbolic (1 << 2)
78#define fontItalic (1 << 6)
79#define fontBold (1 << 18)
80
81class GfxFont {
82public:
83
84 // Build a GfxFont object.
85 static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict);
86
87 GfxFont(char *tagA, Ref idA, GString *nameA);
88
89 virtual ~GfxFont();
90
91 GBool isOk() { return ok; }
92
93 // Get font tag.
94 GString *getTag() { return tag; }
95
96 // Get font dictionary ID.
97 Ref *getID() { return &id; }
98
99 // Does this font match the tag?
100 GBool matches(char *tagA) { return !tag->cmp(tagA); }
101
102 // Get base font name.
103 GString *getName() { return name; }
104
105 // Get font type.
106 GfxFontType getType() { return type; }
107 virtual GBool isCIDFont() { return gFalse; }
108
109 // Get embedded font ID, i.e., a ref for the font file stream.
110 // Returns false if there is no embedded font.
111 GBool getEmbeddedFontID(Ref *embID)
112 { *embID = embFontID; return embFontID.num >= 0; }
113
114 // Get the PostScript font name for the embedded font. Returns
115 // NULL if there is no embedded font.
116 char *getEmbeddedFontName()
117 { return embFontName ? embFontName->getCString() : (char *)NULL; }
118
119 // Get the name of the external font file. Returns NULL if there
120 // is no external font file.
121 GString *getExtFontFile() { return extFontFile; }
122
123 // Get font descriptor flags.
124 GBool isFixedWidth() { return flags & fontFixedWidth; }
125 GBool isSerif() { return flags & fontSerif; }
126 GBool isSymbolic() { return flags & fontSymbolic; }
127 GBool isItalic() { return flags & fontItalic; }
128 GBool isBold() { return flags & fontBold; }
129
130 // Return the font matrix.
131 fouble *getFontMatrix() { return fontMat; }
132
133 // Return the font bounding box.
134 fouble *getFontBBox() { return fontBBox; }
135
136 // Return the ascent and descent values.
137 fouble getAscent() { return ascent; }
138 fouble getDescent() { return descent; }
139
140 // Read an external or embedded font file into a buffer.
141 char *readExtFontFile(int *len);
142 char *readEmbFontFile(XRef *xref, int *len);
143
144 // Get the next char from a string <s> of <len> bytes, returning the
145 // char <code>, its Unicode mapping <u>, its displacement vector
146 // (<dx>, <dy>), and its origin offset vector (<ox>, <oy>). <uSize>
147 // is the number of entries available in <u>, and <uLen> is set to
148 // the number actually used. Returns the number of bytes used by
149 // the char code.
150 virtual int getNextChar(char *s, int len, CharCode *code,
151 Unicode *u, int uSize, int *uLen,
152 fouble *dx, fouble *dy, fouble *ox, fouble *oy) = 0;
153
154protected:
155
156 void readFontDescriptor(XRef *xref, Dict *fontDict);
157 CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits);
158 void GfxFont::findExtFontFile();
159
160 GString *tag; // PDF font tag
161 Ref id; // reference (used as unique ID)
162 GString *name; // font name
163 GfxFontType type; // type of font
164 int flags; // font descriptor flags
165 GString *embFontName; // name of embedded font
166 Ref embFontID; // ref to embedded font file stream
167 GString *extFontFile; // external font file name
168 fouble fontMat[6]; // font matrix (Type 3 only)
169 fouble fontBBox[4]; // font bounding box
170 fouble missingWidth; // "default" width
171 fouble ascent; // max height above baseline
172 fouble descent; // max depth below baseline
173 GBool ok;
174};
175
176//------------------------------------------------------------------------
177// Gfx8BitFont
178//------------------------------------------------------------------------
179
180class Gfx8BitFont: public GfxFont {
181public:
182
183 Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
184 GfxFontType typeA, Dict *fontDict);
185
186 virtual ~Gfx8BitFont();
187
188 virtual int getNextChar(char *s, int len, CharCode *code,
189 Unicode *u, int uSize, int *uLen,
190 fouble *dx, fouble *dy, fouble *ox, fouble *oy);
191
192 // Return the encoding.
193 char **getEncoding() { return enc; }
194
195 // Return the Unicode map.
196 CharCodeToUnicode *getToUnicode();
197
198 // Return the character name associated with <code>.
199 char *getCharName(int code) { return enc[code]; }
200
201 // Returns true if the PDF font specified an encoding.
202 GBool getHasEncoding() { return hasEncoding; }
203
204 // Get width of a character or string.
205 fouble getWidth(Guchar c) { return widths[c]; }
206
207 // Return the Type 3 CharProc for the character associated with <code>.
208 Object *getCharProc(int code, Object *proc);
209
210private:
211
212 char *enc[256]; // char code --> char name
213 char encFree[256]; // boolean for each char name: if set,
214 // the string is malloc'ed
215 CharCodeToUnicode *ctu;// char code --> Unicode
216 GBool hasEncoding;
217 fouble widths[256]; // character widths
218 Object charProcs; // Type3 CharProcs dictionary
219};
220
221//------------------------------------------------------------------------
222// GfxCIDFont
223//------------------------------------------------------------------------
224
225class GfxCIDFont: public GfxFont {
226public:
227
228 GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
229 Dict *fontDict);
230
231 virtual ~GfxCIDFont();
232
233 virtual GBool isCIDFont() { return gTrue; }
234
235 virtual int getNextChar(char *s, int len, CharCode *code,
236 Unicode *u, int uSize, int *uLen,
237 fouble *dx, fouble *dy, fouble *ox, fouble *oy);
238
239 // Return the Unicode map.
240 CharCodeToUnicode *getToUnicode();
241
242 // Get the collection name (<registry>-<ordering>).
243 GString *getCollection();
244
245 // Return the CID-to-GID mapping table. These should only be called
246 // if type is fontCIDType2.
247 Gushort *getCIDToGID() { return cidToGID; }
248 int getCIDToGIDLen() { return cidToGIDLen; }
249
250private:
251
252 CMap *cMap; // char code --> CID
253 CharCodeToUnicode *ctu;// CID --> Unicode
254 GfxFontCIDWidths widths;// character widths
255 Gushort *cidToGID; // CID --> GID mapping (for embedded
256 // TrueType fonts)
257 int cidToGIDLen;
258};
259
260//------------------------------------------------------------------------
261// GfxFontDict
262//------------------------------------------------------------------------
263
264class GfxFontDict {
265public:
266
267 // Build the font dictionary, given the PDF font dictionary.
268 GfxFontDict(XRef *xref, Dict *fontDict);
269
270 // Destructor.
271 ~GfxFontDict();
272
273 // Get the specified font.
274 GfxFont *lookup(char *tag);
275
276 // Iterative access.
277 int getNumFonts() { return numFonts; }
278 GfxFont *getFont(int i) { return fonts[i]; }
279
280private:
281
282 GfxFont **fonts; // list of fonts
283 int numFonts; // number of fonts
284};
285
286#endif
diff --git a/noncore/unsupported/qpdf/xpdf/GfxState.cc b/noncore/unsupported/qpdf/xpdf/GfxState.cc
new file mode 100644
index 0000000..af4e0d4
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/GfxState.cc
@@ -0,0 +1,2097 @@
1//========================================================================
2//
3// GfxState.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include <math.h>
16#include <string.h> // for memcpy()
17#include "gmem.h"
18#include "Error.h"
19#include "Object.h"
20#include "Array.h"
21#include "Page.h"
22#include "GfxState.h"
23
24//------------------------------------------------------------------------
25
26static inline fouble clip01(fouble x) {
27 return (x < 0) ? fouble(0) : ((x > 1) ? fouble(1) : x);
28}
29
30//------------------------------------------------------------------------
31// GfxColorSpace
32//------------------------------------------------------------------------
33
34GfxColorSpace::GfxColorSpace() {
35}
36
37GfxColorSpace::~GfxColorSpace() {
38}
39
40GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
41 GfxColorSpace *cs;
42 Object obj1;
43
44 cs = NULL;
45 if (csObj->isName()) {
46 if (csObj->isName("DeviceGray") || csObj->isName("G")) {
47 cs = new GfxDeviceGrayColorSpace();
48 } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
49 cs = new GfxDeviceRGBColorSpace();
50 } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
51 cs = new GfxDeviceCMYKColorSpace();
52 } else if (csObj->isName("Pattern")) {
53 cs = new GfxPatternColorSpace(NULL);
54 } else {
55 error(-1, "Bad color space '%s'", csObj->getName());
56 }
57 } else if (csObj->isArray()) {
58 csObj->arrayGet(0, &obj1);
59 if (obj1.isName("DeviceGray") || obj1.isName("G")) {
60 cs = new GfxDeviceGrayColorSpace();
61 } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
62 cs = new GfxDeviceRGBColorSpace();
63 } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
64 cs = new GfxDeviceCMYKColorSpace();
65 } else if (obj1.isName("CalGray")) {
66 cs = GfxCalGrayColorSpace::parse(csObj->getArray());
67 } else if (obj1.isName("CalRGB")) {
68 cs = GfxCalRGBColorSpace::parse(csObj->getArray());
69 } else if (obj1.isName("Lab")) {
70 cs = GfxLabColorSpace::parse(csObj->getArray());
71 } else if (obj1.isName("ICCBased")) {
72 cs = GfxICCBasedColorSpace::parse(csObj->getArray());
73 } else if (obj1.isName("Indexed") || obj1.isName("I")) {
74 cs = GfxIndexedColorSpace::parse(csObj->getArray());
75 } else if (obj1.isName("Separation")) {
76 cs = GfxSeparationColorSpace::parse(csObj->getArray());
77 } else if (obj1.isName("DeviceN")) {
78 cs = GfxDeviceNColorSpace::parse(csObj->getArray());
79 } else if (obj1.isName("Pattern")) {
80 cs = GfxPatternColorSpace::parse(csObj->getArray());
81 } else {
82 error(-1, "Bad color space '%s'", csObj->getName());
83 }
84 obj1.free();
85 } else {
86 error(-1, "Bad color space - expected name or array");
87 }
88 return cs;
89}
90
91void GfxColorSpace::getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
92 int maxImgPixel) {
93 int i;
94
95 for (i = 0; i < getNComps(); ++i) {
96 decodeLow[i] = 0;
97 decodeRange[i] = 1;
98 }
99}
100
101//------------------------------------------------------------------------
102// GfxDeviceGrayColorSpace
103//------------------------------------------------------------------------
104
105GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
106}
107
108GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
109}
110
111GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
112 return new GfxDeviceGrayColorSpace();
113}
114
115void GfxDeviceGrayColorSpace::getGray(GfxColor *color, fouble *gray) {
116 *gray = clip01(color->c[0]);
117}
118
119void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
120 rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
121}
122
123void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
124 cmyk->c = cmyk->m = cmyk->y = 0;
125 cmyk->k = clip01(1 - color->c[0]);
126}
127
128//------------------------------------------------------------------------
129// GfxCalGrayColorSpace
130//------------------------------------------------------------------------
131
132GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
133 whiteX = whiteY = whiteZ = 1;
134 blackX = blackY = blackZ = 0;
135 gamma = 1;
136}
137
138GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
139}
140
141GfxColorSpace *GfxCalGrayColorSpace::copy() {
142 GfxCalGrayColorSpace *cs;
143
144 cs = new GfxCalGrayColorSpace();
145 cs->whiteX = whiteX;
146 cs->whiteY = whiteY;
147 cs->whiteZ = whiteZ;
148 cs->blackX = blackX;
149 cs->blackY = blackY;
150 cs->blackZ = blackZ;
151 cs->gamma = gamma;
152 return cs;
153}
154
155GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
156 GfxCalGrayColorSpace *cs;
157 Object obj1, obj2, obj3;
158
159 arr->get(1, &obj1);
160 if (!obj1.isDict()) {
161 error(-1, "Bad CalGray color space");
162 obj1.free();
163 return NULL;
164 }
165 cs = new GfxCalGrayColorSpace();
166 if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
167 obj2.arrayGetLength() == 3) {
168 obj2.arrayGet(0, &obj3);
169 cs->whiteX = obj3.getNum();
170 obj3.free();
171 obj2.arrayGet(1, &obj3);
172 cs->whiteY = obj3.getNum();
173 obj3.free();
174 obj2.arrayGet(2, &obj3);
175 cs->whiteZ = obj3.getNum();
176 obj3.free();
177 }
178 obj2.free();
179 if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
180 obj2.arrayGetLength() == 3) {
181 obj2.arrayGet(0, &obj3);
182 cs->blackX = obj3.getNum();
183 obj3.free();
184 obj2.arrayGet(1, &obj3);
185 cs->blackY = obj3.getNum();
186 obj3.free();
187 obj2.arrayGet(2, &obj3);
188 cs->blackZ = obj3.getNum();
189 obj3.free();
190 }
191 obj2.free();
192 if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
193 cs->gamma = obj2.getNum();
194 }
195 obj2.free();
196 obj1.free();
197 return cs;
198}
199
200void GfxCalGrayColorSpace::getGray(GfxColor *color, fouble *gray) {
201 *gray = clip01(color->c[0]);
202}
203
204void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
205 rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
206}
207
208void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
209 cmyk->c = cmyk->m = cmyk->y = 0;
210 cmyk->k = clip01(1 - color->c[0]);
211}
212
213//------------------------------------------------------------------------
214// GfxDeviceRGBColorSpace
215//------------------------------------------------------------------------
216
217GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
218}
219
220GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
221}
222
223GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
224 return new GfxDeviceRGBColorSpace();
225}
226
227void GfxDeviceRGBColorSpace::getGray(GfxColor *color, fouble *gray) {
228 *gray = clip01(0.299 * color->c[0] +
229 0.587 * color->c[1] +
230 0.114 * color->c[2]);
231}
232
233void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
234 rgb->r = clip01(color->c[0]);
235 rgb->g = clip01(color->c[1]);
236 rgb->b = clip01(color->c[2]);
237}
238
239void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
240 fouble c, m, y, k;
241
242 c = clip01(1 - color->c[0]);
243 m = clip01(1 - color->c[1]);
244 y = clip01(1 - color->c[2]);
245 k = c;
246 if (m < k) {
247 k = m;
248 }
249 if (y < k) {
250 k = y;
251 }
252 cmyk->c = c - k;
253 cmyk->m = m - k;
254 cmyk->y = y - k;
255 cmyk->k = k;
256}
257
258//------------------------------------------------------------------------
259// GfxCalRGBColorSpace
260//------------------------------------------------------------------------
261
262GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
263 whiteX = whiteY = whiteZ = 1;
264 blackX = blackY = blackZ = 0;
265 gammaR = gammaG = gammaB = 1;
266 mat[0] = 1; mat[1] = 0; mat[2] = 0;
267 mat[3] = 0; mat[4] = 1; mat[5] = 0;
268 mat[6] = 0; mat[7] = 0; mat[8] = 1;
269}
270
271GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
272}
273
274GfxColorSpace *GfxCalRGBColorSpace::copy() {
275 GfxCalRGBColorSpace *cs;
276 int i;
277
278 cs = new GfxCalRGBColorSpace();
279 cs->whiteX = whiteX;
280 cs->whiteY = whiteY;
281 cs->whiteZ = whiteZ;
282 cs->blackX = blackX;
283 cs->blackY = blackY;
284 cs->blackZ = blackZ;
285 cs->gammaR = gammaR;
286 cs->gammaG = gammaG;
287 cs->gammaB = gammaB;
288 for (i = 0; i < 9; ++i) {
289 cs->mat[i] = mat[i];
290 }
291 return cs;
292}
293
294GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
295 GfxCalRGBColorSpace *cs;
296 Object obj1, obj2, obj3;
297 int i;
298
299 arr->get(1, &obj1);
300 if (!obj1.isDict()) {
301 error(-1, "Bad CalRGB color space");
302 obj1.free();
303 return NULL;
304 }
305 cs = new GfxCalRGBColorSpace();
306 if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
307 obj2.arrayGetLength() == 3) {
308 obj2.arrayGet(0, &obj3);
309 cs->whiteX = obj3.getNum();
310 obj3.free();
311 obj2.arrayGet(1, &obj3);
312 cs->whiteY = obj3.getNum();
313 obj3.free();
314 obj2.arrayGet(2, &obj3);
315 cs->whiteZ = obj3.getNum();
316 obj3.free();
317 }
318 obj2.free();
319 if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
320 obj2.arrayGetLength() == 3) {
321 obj2.arrayGet(0, &obj3);
322 cs->blackX = obj3.getNum();
323 obj3.free();
324 obj2.arrayGet(1, &obj3);
325 cs->blackY = obj3.getNum();
326 obj3.free();
327 obj2.arrayGet(2, &obj3);
328 cs->blackZ = obj3.getNum();
329 obj3.free();
330 }
331 obj2.free();
332 if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
333 obj2.arrayGetLength() == 3) {
334 obj2.arrayGet(0, &obj3);
335 cs->gammaR = obj3.getNum();
336 obj3.free();
337 obj2.arrayGet(1, &obj3);
338 cs->gammaG = obj3.getNum();
339 obj3.free();
340 obj2.arrayGet(2, &obj3);
341 cs->gammaB = obj3.getNum();
342 obj3.free();
343 }
344 obj2.free();
345 if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
346 obj2.arrayGetLength() == 9) {
347 for (i = 0; i < 9; ++i) {
348 obj2.arrayGet(i, &obj3);
349 cs->mat[i] = obj3.getNum();
350 obj3.free();
351 }
352 }
353 obj2.free();
354 obj1.free();
355 return cs;
356}
357
358void GfxCalRGBColorSpace::getGray(GfxColor *color, fouble *gray) {
359 *gray = clip01(0.299 * color->c[0] +
360 0.587 * color->c[1] +
361 0.114 * color->c[2]);
362}
363
364void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
365 rgb->r = clip01(color->c[0]);
366 rgb->g = clip01(color->c[1]);
367 rgb->b = clip01(color->c[2]);
368}
369
370void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
371 fouble c, m, y, k;
372
373 c = clip01(1 - color->c[0]);
374 m = clip01(1 - color->c[1]);
375 y = clip01(1 - color->c[2]);
376 k = c;
377 if (m < k) {
378 k = m;
379 }
380 if (y < k) {
381 k = y;
382 }
383 cmyk->c = c - k;
384 cmyk->m = m - k;
385 cmyk->y = y - k;
386 cmyk->k = k;
387}
388
389//------------------------------------------------------------------------
390// GfxDeviceCMYKColorSpace
391//------------------------------------------------------------------------
392
393GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
394}
395
396GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
397}
398
399GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
400 return new GfxDeviceCMYKColorSpace();
401}
402
403void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, fouble *gray) {
404 *gray = clip01(1 - color->c[3]
405 - 0.299 * color->c[0]
406 - 0.587 * color->c[1]
407 - 0.114 * color->c[2]);
408}
409
410void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
411 rgb->r = clip01(1 - (color->c[0] + color->c[3]));
412 rgb->g = clip01(1 - (color->c[1] + color->c[3]));
413 rgb->b = clip01(1 - (color->c[2] + color->c[3]));
414}
415
416void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
417 cmyk->c = clip01(color->c[0]);
418 cmyk->m = clip01(color->c[1]);
419 cmyk->y = clip01(color->c[2]);
420 cmyk->k = clip01(color->c[3]);
421}
422
423//------------------------------------------------------------------------
424// GfxLabColorSpace
425//------------------------------------------------------------------------
426
427// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
428// Language Reference, Third Edition.
429static fouble xyzrgb[3][3] = {
430 { 3.240449, -1.537136, -0.498531 },
431 { -0.969265, 1.876011, 0.041556 },
432 { 0.055643, -0.204026, 1.057229 }
433};
434
435GfxLabColorSpace::GfxLabColorSpace() {
436 whiteX = whiteY = whiteZ = 1;
437 blackX = blackY = blackZ = 0;
438 aMin = bMin = -100;
439 aMax = bMax = 100;
440}
441
442GfxLabColorSpace::~GfxLabColorSpace() {
443}
444
445GfxColorSpace *GfxLabColorSpace::copy() {
446 GfxLabColorSpace *cs;
447
448 cs = new GfxLabColorSpace();
449 cs->whiteX = whiteX;
450 cs->whiteY = whiteY;
451 cs->whiteZ = whiteZ;
452 cs->blackX = blackX;
453 cs->blackY = blackY;
454 cs->blackZ = blackZ;
455 cs->aMin = aMin;
456 cs->aMax = aMax;
457 cs->bMin = bMin;
458 cs->bMax = bMax;
459 cs->kr = kr;
460 cs->kg = kg;
461 cs->kb = kb;
462 return cs;
463}
464
465GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
466 GfxLabColorSpace *cs;
467 Object obj1, obj2, obj3;
468
469 arr->get(1, &obj1);
470 if (!obj1.isDict()) {
471 error(-1, "Bad Lab color space");
472 obj1.free();
473 return NULL;
474 }
475 cs = new GfxLabColorSpace();
476 if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
477 obj2.arrayGetLength() == 3) {
478 obj2.arrayGet(0, &obj3);
479 cs->whiteX = obj3.getNum();
480 obj3.free();
481 obj2.arrayGet(1, &obj3);
482 cs->whiteY = obj3.getNum();
483 obj3.free();
484 obj2.arrayGet(2, &obj3);
485 cs->whiteZ = obj3.getNum();
486 obj3.free();
487 }
488 obj2.free();
489 if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
490 obj2.arrayGetLength() == 3) {
491 obj2.arrayGet(0, &obj3);
492 cs->blackX = obj3.getNum();
493 obj3.free();
494 obj2.arrayGet(1, &obj3);
495 cs->blackY = obj3.getNum();
496 obj3.free();
497 obj2.arrayGet(2, &obj3);
498 cs->blackZ = obj3.getNum();
499 obj3.free();
500 }
501 obj2.free();
502 if (obj1.dictLookup("Range", &obj2)->isArray() &&
503 obj2.arrayGetLength() == 4) {
504 obj2.arrayGet(0, &obj3);
505 cs->aMin = obj3.getNum();
506 obj3.free();
507 obj2.arrayGet(1, &obj3);
508 cs->aMax = obj3.getNum();
509 obj3.free();
510 obj2.arrayGet(2, &obj3);
511 cs->bMin = obj3.getNum();
512 obj3.free();
513 obj2.arrayGet(3, &obj3);
514 cs->bMax = obj3.getNum();
515 obj3.free();
516 }
517 obj2.free();
518 obj1.free();
519
520 cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
521 xyzrgb[0][1] * cs->whiteY +
522 xyzrgb[0][2] * cs->whiteZ);
523 cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
524 xyzrgb[1][1] * cs->whiteY +
525 xyzrgb[1][2] * cs->whiteZ);
526 cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
527 xyzrgb[2][1] * cs->whiteY +
528 xyzrgb[2][2] * cs->whiteZ);
529
530 return cs;
531}
532
533void GfxLabColorSpace::getGray(GfxColor *color, fouble *gray) {
534 GfxRGB rgb;
535
536 getRGB(color, &rgb);
537 *gray = clip01(0.299 * rgb.r +
538 0.587 * rgb.g +
539 0.114 * rgb.b);
540}
541
542void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
543 fouble X, Y, Z;
544 fouble t1, t2;
545 fouble r, g, b;
546
547 // convert L*a*b* to CIE 1931 XYZ color space
548 t1 = (color->c[0] + 16) / 116;
549 t2 = t1 + color->c[1] / 500;
550 if (t2 >= (6.0 / 29.0)) {
551 X = t2 * t2 * t2;
552 } else {
553 X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
554 }
555 X *= whiteX;
556 if (t1 >= (6.0 / 29.0)) {
557 Y = t1 * t1 * t1;
558 } else {
559 Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
560 }
561 Y *= whiteY;
562 t2 = t1 - color->c[2] / 200;
563 if (t2 >= (6.0 / 29.0)) {
564 Z = t2 * t2 * t2;
565 } else {
566 Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
567 }
568 Z *= whiteZ;
569
570 // convert XYZ to RGB, including gamut mapping and gamma correction
571 r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
572 g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
573 b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
574 rgb->r = pow(clip01(r * kr), 0.5);
575 rgb->g = pow(clip01(g * kg), 0.5);
576 rgb->b = pow(clip01(b * kb), 0.5);
577}
578
579void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
580 GfxRGB rgb;
581 fouble c, m, y, k;
582
583 getRGB(color, &rgb);
584 c = clip01(1 - rgb.r);
585 m = clip01(1 - rgb.g);
586 y = clip01(1 - rgb.b);
587 k = c;
588 if (m < k) {
589 k = m;
590 }
591 if (y < k) {
592 k = y;
593 }
594 cmyk->c = c - k;
595 cmyk->m = m - k;
596 cmyk->y = y - k;
597 cmyk->k = k;
598}
599
600void GfxLabColorSpace::getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
601 int maxImgPixel) {
602 decodeLow[0] = 0;
603 decodeRange[0] = 100;
604 decodeLow[1] = aMin;
605 decodeRange[1] = aMax - aMin;
606 decodeLow[2] = bMin;
607 decodeRange[2] = bMax - bMin;
608}
609
610//------------------------------------------------------------------------
611// GfxICCBasedColorSpace
612//------------------------------------------------------------------------
613
614GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
615 Ref *iccProfileStreamA) {
616 nComps = nCompsA;
617 alt = altA;
618 iccProfileStream = *iccProfileStreamA;
619 rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
620 rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
621}
622
623GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
624 delete alt;
625}
626
627GfxColorSpace *GfxICCBasedColorSpace::copy() {
628 GfxICCBasedColorSpace *cs;
629 int i;
630
631 cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
632 for (i = 0; i < 4; ++i) {
633 cs->rangeMin[i] = rangeMin[i];
634 cs->rangeMax[i] = rangeMax[i];
635 }
636 return cs;
637}
638
639GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
640 GfxICCBasedColorSpace *cs;
641 Ref iccProfileStreamA;
642 int nCompsA;
643 GfxColorSpace *altA;
644 Dict *dict;
645 Object obj1, obj2, obj3;
646 int i;
647
648 arr->getNF(1, &obj1);
649 if (obj1.isRef()) {
650 iccProfileStreamA = obj1.getRef();
651 } else {
652 iccProfileStreamA.num = 0;
653 iccProfileStreamA.gen = 0;
654 }
655 obj1.free();
656 arr->get(1, &obj1);
657 if (!obj1.isStream()) {
658 error(-1, "Bad ICCBased color space (stream)");
659 obj1.free();
660 return NULL;
661 }
662 dict = obj1.streamGetDict();
663 if (!dict->lookup("N", &obj2)->isInt()) {
664 error(-1, "Bad ICCBased color space (N)");
665 obj2.free();
666 obj1.free();
667 return NULL;
668 }
669 nCompsA = obj2.getInt();
670 obj2.free();
671 if (dict->lookup("Alternate", &obj2)->isNull() ||
672 !(altA = GfxColorSpace::parse(&obj2))) {
673 switch (nCompsA) {
674 case 1:
675 altA = new GfxDeviceGrayColorSpace();
676 break;
677 case 3:
678 altA = new GfxDeviceRGBColorSpace();
679 break;
680 case 4:
681 altA = new GfxDeviceCMYKColorSpace();
682 break;
683 default:
684 error(-1, "Bad ICCBased color space - invalid N");
685 obj2.free();
686 obj1.free();
687 return NULL;
688 }
689 }
690 obj2.free();
691 cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
692 if (dict->lookup("Range", &obj2)->isArray() &&
693 obj2.arrayGetLength() == 2 * nCompsA) {
694 for (i = 0; i < nCompsA; ++i) {
695 obj2.arrayGet(2*i, &obj3);
696 cs->rangeMin[i] = obj3.getNum();
697 obj3.free();
698 obj2.arrayGet(2*i+1, &obj3);
699 cs->rangeMax[i] = obj3.getNum();
700 obj3.free();
701 }
702 }
703 obj2.free();
704 obj1.free();
705 return cs;
706}
707
708void GfxICCBasedColorSpace::getGray(GfxColor *color, fouble *gray) {
709 alt->getGray(color, gray);
710}
711
712void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
713 alt->getRGB(color, rgb);
714}
715
716void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
717 alt->getCMYK(color, cmyk);
718}
719
720void GfxICCBasedColorSpace::getDefaultRanges(fouble *decodeLow,
721 fouble *decodeRange,
722 int maxImgPixel) {
723 int i;
724
725 for (i = 0; i < nComps; ++i) {
726 decodeLow[i] = rangeMin[i];
727 decodeRange[i] = rangeMax[i] - rangeMin[i];
728 }
729}
730
731//------------------------------------------------------------------------
732// GfxIndexedColorSpace
733//------------------------------------------------------------------------
734
735GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
736 int indexHighA) {
737 base = baseA;
738 indexHigh = indexHighA;
739 lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
740 sizeof(Guchar));
741}
742
743GfxIndexedColorSpace::~GfxIndexedColorSpace() {
744 delete base;
745 gfree(lookup);
746}
747
748GfxColorSpace *GfxIndexedColorSpace::copy() {
749 GfxIndexedColorSpace *cs;
750
751 cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
752 memcpy(cs->lookup, lookup,
753 (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
754 return cs;
755}
756
757GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
758 GfxIndexedColorSpace *cs;
759 GfxColorSpace *baseA;
760 int indexHighA;
761 Object obj1;
762 int x;
763 char *s;
764 int n, i, j;
765
766 if (arr->getLength() != 4) {
767 error(-1, "Bad Indexed color space");
768 goto err1;
769 }
770 arr->get(1, &obj1);
771 if (!(baseA = GfxColorSpace::parse(&obj1))) {
772 error(-1, "Bad Indexed color space (base color space)");
773 goto err2;
774 }
775 obj1.free();
776 if (!arr->get(2, &obj1)->isInt()) {
777 error(-1, "Bad Indexed color space (hival)");
778 goto err2;
779 }
780 indexHighA = obj1.getInt();
781 obj1.free();
782 cs = new GfxIndexedColorSpace(baseA, indexHighA);
783 arr->get(3, &obj1);
784 n = baseA->getNComps();
785 if (obj1.isStream()) {
786 obj1.streamReset();
787 for (i = 0; i <= indexHighA; ++i) {
788 for (j = 0; j < n; ++j) {
789 if ((x = obj1.streamGetChar()) == EOF) {
790 error(-1, "Bad Indexed color space (lookup table stream too short)");
791 goto err3;
792 }
793 cs->lookup[i*n + j] = (Guchar)x;
794 }
795 }
796 obj1.streamClose();
797 } else if (obj1.isString()) {
798 if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
799 error(-1, "Bad Indexed color space (lookup table string too short)");
800 goto err3;
801 }
802 s = obj1.getString()->getCString();
803 for (i = 0; i <= indexHighA; ++i) {
804 for (j = 0; j < n; ++j) {
805 cs->lookup[i*n + j] = (Guchar)*s++;
806 }
807 }
808 } else {
809 error(-1, "Bad Indexed color space (lookup table)");
810 goto err3;
811 }
812 obj1.free();
813 return cs;
814
815 err3:
816 delete cs;
817 err2:
818 obj1.free();
819 err1:
820 return NULL;
821}
822
823void GfxIndexedColorSpace::getGray(GfxColor *color, fouble *gray) {
824 Guchar *p;
825 GfxColor color2;
826 int n, i;
827
828 n = base->getNComps();
829 p = &lookup[(int)(color->c[0] + 0.5) * n];
830 for (i = 0; i < n; ++i) {
831 color2.c[i] = p[i] / 255.0;
832 }
833 base->getGray(&color2, gray);
834}
835
836void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
837 Guchar *p;
838 GfxColor color2;
839 int n, i;
840
841 n = base->getNComps();
842 p = &lookup[(int)(color->c[0] + 0.5) * n];
843 for (i = 0; i < n; ++i) {
844 color2.c[i] = p[i] / 255.0;
845 }
846 base->getRGB(&color2, rgb);
847}
848
849void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
850 Guchar *p;
851 GfxColor color2;
852 int n, i;
853
854 n = base->getNComps();
855 p = &lookup[(int)(color->c[0] + 0.5) * n];
856 for (i = 0; i < n; ++i) {
857 color2.c[i] = p[i] / 255.0;
858 }
859 base->getCMYK(&color2, cmyk);
860}
861
862void GfxIndexedColorSpace::getDefaultRanges(fouble *decodeLow,
863 fouble *decodeRange,
864 int maxImgPixel) {
865 decodeLow[0] = 0;
866 decodeRange[0] = maxImgPixel;
867}
868
869//------------------------------------------------------------------------
870// GfxSeparationColorSpace
871//------------------------------------------------------------------------
872
873GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
874 GfxColorSpace *altA,
875 Function *funcA) {
876 name = nameA;
877 alt = altA;
878 func = funcA;
879}
880
881GfxSeparationColorSpace::~GfxSeparationColorSpace() {
882 delete name;
883 delete alt;
884 delete func;
885}
886
887GfxColorSpace *GfxSeparationColorSpace::copy() {
888 return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
889}
890
891//~ handle the 'All' and 'None' colorants
892GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
893 GfxSeparationColorSpace *cs;
894 GString *nameA;
895 GfxColorSpace *altA;
896 Function *funcA;
897 Object obj1;
898
899 if (arr->getLength() != 4) {
900 error(-1, "Bad Separation color space");
901 goto err1;
902 }
903 if (!arr->get(1, &obj1)->isName()) {
904 error(-1, "Bad Separation color space (name)");
905 goto err2;
906 }
907 nameA = new GString(obj1.getName());
908 obj1.free();
909 arr->get(2, &obj1);
910 if (!(altA = GfxColorSpace::parse(&obj1))) {
911 error(-1, "Bad Separation color space (alternate color space)");
912 goto err3;
913 }
914 obj1.free();
915 arr->get(3, &obj1);
916 if (!(funcA = Function::parse(&obj1))) {
917 goto err4;
918 }
919 obj1.free();
920 cs = new GfxSeparationColorSpace(nameA, altA, funcA);
921 return cs;
922
923 err4:
924 delete altA;
925 err3:
926 delete nameA;
927 err2:
928 obj1.free();
929 err1:
930 return NULL;
931}
932
933void GfxSeparationColorSpace::getGray(GfxColor *color, fouble *gray) {
934 GfxColor color2;
935
936 func->transform(color->c, color2.c);
937 alt->getGray(&color2, gray);
938}
939
940void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
941 GfxColor color2;
942
943 func->transform(color->c, color2.c);
944 alt->getRGB(&color2, rgb);
945}
946
947void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
948 GfxColor color2;
949
950 func->transform(color->c, color2.c);
951 alt->getCMYK(&color2, cmyk);
952}
953
954//------------------------------------------------------------------------
955// GfxDeviceNColorSpace
956//------------------------------------------------------------------------
957
958GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
959 GfxColorSpace *altA,
960 Function *funcA) {
961 nComps = nCompsA;
962 alt = altA;
963 func = funcA;
964}
965
966GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
967 int i;
968
969 for (i = 0; i < nComps; ++i) {
970 delete names[i];
971 }
972 delete alt;
973 delete func;
974}
975
976GfxColorSpace *GfxDeviceNColorSpace::copy() {
977 GfxDeviceNColorSpace *cs;
978 int i;
979
980 cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
981 for (i = 0; i < nComps; ++i) {
982 cs->names[i] = names[i]->copy();
983 }
984 return cs;
985}
986
987//~ handle the 'None' colorant
988GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
989 GfxDeviceNColorSpace *cs;
990 int nCompsA;
991 GString *namesA[gfxColorMaxComps];
992 GfxColorSpace *altA;
993 Function *funcA;
994 Object obj1, obj2;
995 int i;
996
997 if (arr->getLength() != 4 && arr->getLength() != 5) {
998 error(-1, "Bad DeviceN color space");
999 goto err1;
1000 }
1001 if (!arr->get(1, &obj1)->isArray()) {
1002 error(-1, "Bad DeviceN color space (names)");
1003 goto err2;
1004 }
1005 nCompsA = obj1.arrayGetLength();
1006 for (i = 0; i < nCompsA; ++i) {
1007 if (!obj1.arrayGet(i, &obj2)->isName()) {
1008 error(-1, "Bad DeviceN color space (names)");
1009 obj2.free();
1010 goto err2;
1011 }
1012 namesA[i] = new GString(obj2.getName());
1013 obj2.free();
1014 }
1015 obj1.free();
1016 arr->get(2, &obj1);
1017 if (!(altA = GfxColorSpace::parse(&obj1))) {
1018 error(-1, "Bad DeviceN color space (alternate color space)");
1019 goto err3;
1020 }
1021 obj1.free();
1022 arr->get(3, &obj1);
1023 if (!(funcA = Function::parse(&obj1))) {
1024 goto err4;
1025 }
1026 obj1.free();
1027 cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
1028 for (i = 0; i < nCompsA; ++i) {
1029 cs->names[i] = namesA[i];
1030 }
1031 return cs;
1032
1033 err4:
1034 delete altA;
1035 err3:
1036 for (i = 0; i < nCompsA; ++i) {
1037 delete namesA[i];
1038 }
1039 err2:
1040 obj1.free();
1041 err1:
1042 return NULL;
1043}
1044
1045void GfxDeviceNColorSpace::getGray(GfxColor *color, fouble *gray) {
1046 GfxColor color2;
1047
1048 func->transform(color->c, color2.c);
1049 alt->getGray(&color2, gray);
1050}
1051
1052void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
1053 GfxColor color2;
1054
1055 func->transform(color->c, color2.c);
1056 alt->getRGB(&color2, rgb);
1057}
1058
1059void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
1060 GfxColor color2;
1061
1062 func->transform(color->c, color2.c);
1063 alt->getCMYK(&color2, cmyk);
1064}
1065
1066//------------------------------------------------------------------------
1067// GfxPatternColorSpace
1068//------------------------------------------------------------------------
1069
1070GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
1071 under = underA;
1072}
1073
1074GfxPatternColorSpace::~GfxPatternColorSpace() {
1075 if (under) {
1076 delete under;
1077 }
1078}
1079
1080GfxColorSpace *GfxPatternColorSpace::copy() {
1081 return new GfxPatternColorSpace(under ? under->copy() :
1082 (GfxColorSpace *)NULL);
1083}
1084
1085GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
1086 GfxPatternColorSpace *cs;
1087 GfxColorSpace *underA;
1088 Object obj1;
1089
1090 if (arr->getLength() != 1 && arr->getLength() != 2) {
1091 error(-1, "Bad Pattern color space");
1092 return NULL;
1093 }
1094 underA = NULL;
1095 if (arr->getLength() == 2) {
1096 arr->get(1, &obj1);
1097 if (!(underA = GfxColorSpace::parse(&obj1))) {
1098 error(-1, "Bad Pattern color space (underlying color space)");
1099 obj1.free();
1100 return NULL;
1101 }
1102 obj1.free();
1103 }
1104 cs = new GfxPatternColorSpace(underA);
1105 return cs;
1106}
1107
1108void GfxPatternColorSpace::getGray(GfxColor *color, fouble *gray) {
1109 *gray = 0;
1110}
1111
1112void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
1113 rgb->r = rgb->g = rgb->b = 0;
1114}
1115
1116void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
1117 cmyk->c = cmyk->m = cmyk->y = 0;
1118 cmyk->k = 1;
1119}
1120
1121//------------------------------------------------------------------------
1122// Pattern
1123//------------------------------------------------------------------------
1124
1125GfxPattern::GfxPattern(int typeA) {
1126 type = typeA;
1127}
1128
1129GfxPattern::~GfxPattern() {
1130}
1131
1132GfxPattern *GfxPattern::parse(Object *obj) {
1133 GfxPattern *pattern;
1134 Dict *dict;
1135 Object obj1;
1136
1137 pattern = NULL;
1138 if (obj->isStream()) {
1139 dict = obj->streamGetDict();
1140 dict->lookup("PatternType", &obj1);
1141 if (obj1.isInt() && obj1.getInt() == 1) {
1142 pattern = new GfxTilingPattern(dict, obj);
1143 }
1144 obj1.free();
1145 }
1146 return pattern;
1147}
1148
1149//------------------------------------------------------------------------
1150// GfxTilingPattern
1151//------------------------------------------------------------------------
1152
1153GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
1154 GfxPattern(1)
1155{
1156 Object obj1, obj2;
1157 int i;
1158
1159 if (streamDict->lookup("PaintType", &obj1)->isInt()) {
1160 paintType = obj1.getInt();
1161 } else {
1162 paintType = 1;
1163 error(-1, "Invalid or missing PaintType in pattern");
1164 }
1165 obj1.free();
1166 if (streamDict->lookup("TilingType", &obj1)->isInt()) {
1167 tilingType = obj1.getInt();
1168 } else {
1169 tilingType = 1;
1170 error(-1, "Invalid or missing TilingType in pattern");
1171 }
1172 obj1.free();
1173 bbox[0] = bbox[1] = 0;
1174 bbox[2] = bbox[3] = 1;
1175 if (streamDict->lookup("BBox", &obj1)->isArray() &&
1176 obj1.arrayGetLength() == 4) {
1177 for (i = 0; i < 4; ++i) {
1178 if (obj1.arrayGet(i, &obj2)->isNum()) {
1179 bbox[i] = obj2.getNum();
1180 }
1181 obj2.free();
1182 }
1183 } else {
1184 error(-1, "Invalid or missing BBox in pattern");
1185 }
1186 obj1.free();
1187 if (streamDict->lookup("XStep", &obj1)->isNum()) {
1188 xStep = obj1.getNum();
1189 } else {
1190 xStep = 1;
1191 error(-1, "Invalid or missing XStep in pattern");
1192 }
1193 obj1.free();
1194 if (streamDict->lookup("YStep", &obj1)->isNum()) {
1195 yStep = obj1.getNum();
1196 } else {
1197 yStep = 1;
1198 error(-1, "Invalid or missing YStep in pattern");
1199 }
1200 obj1.free();
1201 if (!streamDict->lookup("Resources", &resDict)->isDict()) {
1202 resDict.free();
1203 resDict.initNull();
1204 error(-1, "Invalid or missing Resources in pattern");
1205 }
1206 matrix[0] = 1; matrix[1] = 0;
1207 matrix[2] = 0; matrix[3] = 1;
1208 matrix[4] = 0; matrix[5] = 0;
1209 if (streamDict->lookup("Matrix", &obj1)->isArray() &&
1210 obj1.arrayGetLength() == 6) {
1211 for (i = 0; i < 6; ++i) {
1212 if (obj1.arrayGet(i, &obj2)->isNum()) {
1213 matrix[i] = obj2.getNum();
1214 }
1215 obj2.free();
1216 }
1217 }
1218 obj1.free();
1219 stream->copy(&contentStream);
1220}
1221
1222GfxTilingPattern::~GfxTilingPattern() {
1223 resDict.free();
1224 contentStream.free();
1225}
1226
1227GfxPattern *GfxTilingPattern::copy() {
1228 return new GfxTilingPattern(this);
1229}
1230
1231GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
1232 GfxPattern(1)
1233{
1234 memcpy(this, pat, sizeof(GfxTilingPattern));
1235 pat->resDict.copy(&resDict);
1236 pat->contentStream.copy(&contentStream);
1237}
1238
1239//------------------------------------------------------------------------
1240// GfxShading
1241//------------------------------------------------------------------------
1242
1243GfxShading::GfxShading() {
1244}
1245
1246GfxShading::~GfxShading() {
1247 delete colorSpace;
1248}
1249
1250GfxShading *GfxShading::parse(Object *obj) {
1251 GfxShading *shading;
1252 int typeA;
1253 GfxColorSpace *colorSpaceA;
1254 GfxColor backgroundA;
1255 GBool hasBackgroundA;
1256 fouble xMinA, yMinA, xMaxA, yMaxA;
1257 GBool hasBBoxA;
1258 Object obj1, obj2;
1259 int i;
1260
1261 shading = NULL;
1262 if (obj->isDict()) {
1263
1264 if (!obj->dictLookup("ShadingType", &obj1)->isInt()) {
1265 error(-1, "Invalid ShadingType in shading dictionary");
1266 obj1.free();
1267 goto err1;
1268 }
1269 typeA = obj1.getInt();
1270 obj1.free();
1271 if (typeA != 2) {
1272 error(-1, "Unimplemented shading type %d", typeA);
1273 goto err1;
1274 }
1275
1276 obj->dictLookup("ColorSpace", &obj1);
1277 if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
1278 error(-1, "Bad color space in shading dictionary");
1279 obj1.free();
1280 goto err1;
1281 }
1282 obj1.free();
1283
1284 for (i = 0; i < gfxColorMaxComps; ++i) {
1285 backgroundA.c[i] = 0;
1286 }
1287 hasBackgroundA = gFalse;
1288 if (obj->dictLookup("Background", &obj1)->isArray()) {
1289 if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
1290 hasBackgroundA = gTrue;
1291 for (i = 0; i < colorSpaceA->getNComps(); ++i) {
1292 backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
1293 obj2.free();
1294 }
1295 } else {
1296 error(-1, "Bad Background in shading dictionary");
1297 }
1298 }
1299 obj1.free();
1300
1301 xMinA = yMinA = xMaxA = yMaxA = 0;
1302 hasBBoxA = gFalse;
1303 if (obj->dictLookup("BBox", &obj1)->isArray()) {
1304 if (obj1.arrayGetLength() == 4) {
1305 hasBBoxA = gTrue;
1306 xMinA = obj1.arrayGet(0, &obj2)->getNum();
1307 obj2.free();
1308 yMinA = obj1.arrayGet(1, &obj2)->getNum();
1309 obj2.free();
1310 xMaxA = obj1.arrayGet(2, &obj2)->getNum();
1311 obj2.free();
1312 yMaxA = obj1.arrayGet(3, &obj2)->getNum();
1313 obj2.free();
1314 } else {
1315 error(-1, "Bad BBox in shading dictionary");
1316 }
1317 }
1318 obj1.free();
1319
1320 shading = GfxAxialShading::parse(obj->getDict());
1321
1322 if (shading) {
1323 shading->type = typeA;
1324 shading->colorSpace = colorSpaceA;
1325 shading->background = backgroundA;
1326 shading->hasBackground = hasBackgroundA;
1327 shading->xMin = xMinA;
1328 shading->yMin = yMinA;
1329 shading->xMax = xMaxA;
1330 shading->yMax = yMaxA;
1331 shading->hasBBox = hasBBoxA;
1332 } else {
1333 delete colorSpaceA;
1334 }
1335 }
1336
1337 return shading;
1338
1339 err1:
1340 return NULL;
1341}
1342
1343//------------------------------------------------------------------------
1344// GfxAxialShading
1345//------------------------------------------------------------------------
1346
1347GfxAxialShading::GfxAxialShading(fouble x0A, fouble y0A,
1348 fouble x1A, fouble y1A,
1349 fouble t0A, fouble t1A,
1350 Function **funcsA, int nFuncsA,
1351 GBool extend0A, GBool extend1A) {
1352 int i;
1353
1354 x0 = x0A;
1355 y0 = y0A;
1356 x1 = x1A;
1357 y1 = y1A;
1358 t0 = t0A;
1359 t1 = t1A;
1360 nFuncs = nFuncsA;
1361 for (i = 0; i < nFuncs; ++i) {
1362 funcs[i] = funcsA[i];
1363 }
1364 extend0 = extend0A;
1365 extend1 = extend1A;
1366}
1367
1368GfxAxialShading::~GfxAxialShading() {
1369 int i;
1370
1371 for (i = 0; i < nFuncs; ++i) {
1372 delete funcs[i];
1373 }
1374}
1375
1376GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
1377 fouble x0A, y0A, x1A, y1A;
1378 fouble t0A, t1A;
1379 Function *funcsA[gfxColorMaxComps];
1380 int nFuncsA;
1381 GBool extend0A, extend1A;
1382 Object obj1, obj2;
1383 int i;
1384
1385 x0A = y0A = x1A = y1A = 0;
1386 if (dict->lookup("Coords", &obj1)->isArray() &&
1387 obj1.arrayGetLength() == 4) {
1388 x0A = obj1.arrayGet(0, &obj2)->getNum();
1389 obj2.free();
1390 y0A = obj1.arrayGet(1, &obj2)->getNum();
1391 obj2.free();
1392 x1A = obj1.arrayGet(2, &obj2)->getNum();
1393 obj2.free();
1394 y1A = obj1.arrayGet(3, &obj2)->getNum();
1395 obj2.free();
1396 } else {
1397 error(-1, "Missing or invalid Coords in shading dictionary");
1398 goto err1;
1399 }
1400 obj1.free();
1401
1402 t0A = 0;
1403 t1A = 1;
1404 if (dict->lookup("Domain", &obj1)->isArray() &&
1405 obj1.arrayGetLength() == 2) {
1406 t0A = obj1.arrayGet(0, &obj2)->getNum();
1407 obj2.free();
1408 t1A = obj1.arrayGet(1, &obj2)->getNum();
1409 obj2.free();
1410 }
1411 obj1.free();
1412
1413 dict->lookup("Function", &obj1);
1414 if (obj1.isArray()) {
1415 nFuncsA = obj1.arrayGetLength();
1416 for (i = 0; i < nFuncsA; ++i) {
1417 obj1.arrayGet(i, &obj2);
1418 if (!(funcsA[i] = Function::parse(&obj2))) {
1419 obj1.free();
1420 obj2.free();
1421 goto err1;
1422 }
1423 obj2.free();
1424 }
1425 } else {
1426 nFuncsA = 1;
1427 if (!(funcsA[0] = Function::parse(&obj1))) {
1428 obj1.free();
1429 goto err1;
1430 }
1431 }
1432 obj1.free();
1433
1434 extend0A = extend1A = gFalse;
1435 if (dict->lookup("Extend", &obj1)->isArray() &&
1436 obj1.arrayGetLength() == 2) {
1437 extend0A = obj1.arrayGet(0, &obj2)->getBool();
1438 obj2.free();
1439 extend1A = obj1.arrayGet(1, &obj2)->getBool();
1440 obj2.free();
1441 }
1442 obj1.free();
1443
1444 return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
1445 funcsA, nFuncsA, extend0A, extend1A);
1446
1447 err1:
1448 return NULL;
1449}
1450
1451void GfxAxialShading::getColor(fouble t, GfxColor *color) {
1452 int i;
1453
1454 for (i = 0; i < nFuncs; ++i) {
1455 funcs[i]->transform(&t, &color->c[i]);
1456 }
1457}
1458
1459//------------------------------------------------------------------------
1460// GfxImageColorMap
1461//------------------------------------------------------------------------
1462
1463GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
1464 GfxColorSpace *colorSpaceA) {
1465 GfxIndexedColorSpace *indexedCS;
1466 GfxSeparationColorSpace *sepCS;
1467 int maxPixel, indexHigh;
1468 Guchar *lookup2;
1469 Function *sepFunc;
1470 Object obj;
1471 fouble x[gfxColorMaxComps];
1472 fouble y[gfxColorMaxComps];
1473 int i, j, k;
1474
1475 ok = gTrue;
1476
1477 // bits per component and color space
1478 bits = bitsA;
1479 maxPixel = (1 << bits) - 1;
1480 colorSpace = colorSpaceA;
1481
1482 // get decode map
1483 if (decode->isNull()) {
1484 nComps = colorSpace->getNComps();
1485 colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
1486 } else if (decode->isArray()) {
1487 nComps = decode->arrayGetLength() / 2;
1488 if (nComps != colorSpace->getNComps()) {
1489 goto err1;
1490 }
1491 for (i = 0; i < nComps; ++i) {
1492 decode->arrayGet(2*i, &obj);
1493 if (!obj.isNum()) {
1494 goto err2;
1495 }
1496 decodeLow[i] = obj.getNum();
1497 obj.free();
1498 decode->arrayGet(2*i+1, &obj);
1499 if (!obj.isNum()) {
1500 goto err2;
1501 }
1502 decodeRange[i] = obj.getNum() - decodeLow[i];
1503 obj.free();
1504 }
1505 } else {
1506 goto err1;
1507 }
1508
1509 // Construct a lookup table -- this stores pre-computed decoded
1510 // values for each component, i.e., the result of applying the
1511 // decode mapping to each possible image pixel component value.
1512 //
1513 // Optimization: for Indexed and Separation color spaces (which have
1514 // only one component), we store color values in the lookup table
1515 // rather than component values.
1516 colorSpace2 = NULL;
1517 nComps2 = 0;
1518 if (colorSpace->getMode() == csIndexed) {
1519 // Note that indexHigh may not be the same as maxPixel --
1520 // Distiller will remove unused palette entries, resulting in
1521 // indexHigh < maxPixel.
1522 indexedCS = (GfxIndexedColorSpace *)colorSpace;
1523 colorSpace2 = indexedCS->getBase();
1524 indexHigh = indexedCS->getIndexHigh();
1525 nComps2 = colorSpace2->getNComps();
1526 lookup = (fouble *)gmalloc((indexHigh + 1) * nComps2 * sizeof(fouble));
1527 lookup2 = indexedCS->getLookup();
1528 for (i = 0; i <= indexHigh; ++i) {
1529 j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
1530 for (k = 0; k < nComps2; ++k) {
1531 lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
1532 }
1533 }
1534 } else if (colorSpace->getMode() == csSeparation) {
1535 sepCS = (GfxSeparationColorSpace *)colorSpace;
1536 colorSpace2 = sepCS->getAlt();
1537 nComps2 = colorSpace2->getNComps();
1538 lookup = (fouble *)gmalloc((maxPixel + 1) * nComps2 * sizeof(fouble));
1539 sepFunc = sepCS->getFunc();
1540 for (i = 0; i <= maxPixel; ++i) {
1541 x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
1542 sepFunc->transform(x, y);
1543 for (k = 0; k < nComps2; ++k) {
1544 lookup[i*nComps2 + k] = y[k];
1545 }
1546 }
1547 } else {
1548 lookup = (fouble *)gmalloc((maxPixel + 1) * nComps * sizeof(fouble));
1549 for (i = 0; i <= maxPixel; ++i) {
1550 for (k = 0; k < nComps; ++k) {
1551 lookup[i*nComps + k] = decodeLow[k] +
1552 (i * decodeRange[k]) / maxPixel;
1553 }
1554 }
1555 }
1556
1557 return;
1558
1559 err2:
1560 obj.free();
1561 err1:
1562 ok = gFalse;
1563}
1564
1565GfxImageColorMap::~GfxImageColorMap() {
1566 delete colorSpace;
1567 gfree(lookup);
1568}
1569
1570void GfxImageColorMap::getGray(Guchar *x, fouble *gray) {
1571 GfxColor color;
1572 fouble *p;
1573 int i;
1574
1575 if (colorSpace2) {
1576 p = &lookup[x[0] * nComps2];
1577 for (i = 0; i < nComps2; ++i) {
1578 color.c[i] = *p++;
1579 }
1580 colorSpace2->getGray(&color, gray);
1581 } else {
1582 for (i = 0; i < nComps; ++i) {
1583 color.c[i] = lookup[x[i] * nComps + i];
1584 }
1585 colorSpace->getGray(&color, gray);
1586 }
1587}
1588
1589void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
1590 GfxColor color;
1591 fouble *p;
1592 int i;
1593
1594 if (colorSpace2) {
1595 p = &lookup[x[0] * nComps2];
1596 for (i = 0; i < nComps2; ++i) {
1597 color.c[i] = *p++;
1598 }
1599 colorSpace2->getRGB(&color, rgb);
1600 } else {
1601 for (i = 0; i < nComps; ++i) {
1602 color.c[i] = lookup[x[i] * nComps + i];
1603 }
1604 colorSpace->getRGB(&color, rgb);
1605 }
1606}
1607
1608void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
1609 GfxColor color;
1610 fouble *p;
1611 int i;
1612
1613 if (colorSpace2) {
1614 p = &lookup[x[0] * nComps2];
1615 for (i = 0; i < nComps2; ++i) {
1616 color.c[i] = *p++;
1617 }
1618 colorSpace2->getCMYK(&color, cmyk);
1619 } else {
1620 for (i = 0; i < nComps; ++i) {
1621 color.c[i] = lookup[x[i] * nComps + i];
1622 }
1623 colorSpace->getCMYK(&color, cmyk);
1624 }
1625}
1626
1627//------------------------------------------------------------------------
1628// GfxSubpath and GfxPath
1629//------------------------------------------------------------------------
1630
1631GfxSubpath::GfxSubpath(fouble x1, fouble y1) {
1632 size = 16;
1633 x = (fouble *)gmalloc(size * sizeof(fouble));
1634 y = (fouble *)gmalloc(size * sizeof(fouble));
1635 curve = (GBool *)gmalloc(size * sizeof(GBool));
1636 n = 1;
1637 x[0] = x1;
1638 y[0] = y1;
1639 curve[0] = gFalse;
1640 closed = gFalse;
1641}
1642
1643GfxSubpath::~GfxSubpath() {
1644 gfree(x);
1645 gfree(y);
1646 gfree(curve);
1647}
1648
1649// Used for copy().
1650GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
1651 size = subpath->size;
1652 n = subpath->n;
1653 x = (fouble *)gmalloc(size * sizeof(fouble));
1654 y = (fouble *)gmalloc(size * sizeof(fouble));
1655 curve = (GBool *)gmalloc(size * sizeof(GBool));
1656 memcpy(x, subpath->x, n * sizeof(fouble));
1657 memcpy(y, subpath->y, n * sizeof(fouble));
1658 memcpy(curve, subpath->curve, n * sizeof(GBool));
1659 closed = subpath->closed;
1660}
1661
1662void GfxSubpath::lineTo(fouble x1, fouble y1) {
1663 if (n >= size) {
1664 size += 16;
1665 x = (fouble *)grealloc(x, size * sizeof(fouble));
1666 y = (fouble *)grealloc(y, size * sizeof(fouble));
1667 curve = (GBool *)grealloc(curve, size * sizeof(GBool));
1668 }
1669 x[n] = x1;
1670 y[n] = y1;
1671 curve[n] = gFalse;
1672 ++n;
1673}
1674
1675void GfxSubpath::curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
1676 fouble x3, fouble y3) {
1677 if (n+3 > size) {
1678 size += 16;
1679 x = (fouble *)grealloc(x, size * sizeof(fouble));
1680 y = (fouble *)grealloc(y, size * sizeof(fouble));
1681 curve = (GBool *)grealloc(curve, size * sizeof(GBool));
1682 }
1683 x[n] = x1;
1684 y[n] = y1;
1685 x[n+1] = x2;
1686 y[n+1] = y2;
1687 x[n+2] = x3;
1688 y[n+2] = y3;
1689 curve[n] = curve[n+1] = gTrue;
1690 curve[n+2] = gFalse;
1691 n += 3;
1692}
1693
1694void GfxSubpath::close() {
1695 if (x[n-1] != x[0] || y[n-1] != y[0]) {
1696 lineTo(x[0], y[0]);
1697 }
1698 closed = gTrue;
1699}
1700
1701GfxPath::GfxPath() {
1702 justMoved = gFalse;
1703 size = 16;
1704 n = 0;
1705 firstX = firstY = 0;
1706 subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
1707}
1708
1709GfxPath::~GfxPath() {
1710 int i;
1711
1712 for (i = 0; i < n; ++i)
1713 delete subpaths[i];
1714 gfree(subpaths);
1715}
1716
1717// Used for copy().
1718GfxPath::GfxPath(GBool justMoved1, fouble firstX1, fouble firstY1,
1719 GfxSubpath **subpaths1, int n1, int size1) {
1720 int i;
1721
1722 justMoved = justMoved1;
1723 firstX = firstX1;
1724 firstY = firstY1;
1725 size = size1;
1726 n = n1;
1727 subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
1728 for (i = 0; i < n; ++i)
1729 subpaths[i] = subpaths1[i]->copy();
1730}
1731
1732void GfxPath::moveTo(fouble x, fouble y) {
1733 justMoved = gTrue;
1734 firstX = x;
1735 firstY = y;
1736}
1737
1738void GfxPath::lineTo(fouble x, fouble y) {
1739 if (justMoved) {
1740 if (n >= size) {
1741 size += 16;
1742 subpaths = (GfxSubpath **)
1743 grealloc(subpaths, size * sizeof(GfxSubpath *));
1744 }
1745 subpaths[n] = new GfxSubpath(firstX, firstY);
1746 ++n;
1747 justMoved = gFalse;
1748 }
1749 subpaths[n-1]->lineTo(x, y);
1750}
1751
1752void GfxPath::curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
1753 fouble x3, fouble y3) {
1754 if (justMoved) {
1755 if (n >= size) {
1756 size += 16;
1757 subpaths = (GfxSubpath **)
1758 grealloc(subpaths, size * sizeof(GfxSubpath *));
1759 }
1760 subpaths[n] = new GfxSubpath(firstX, firstY);
1761 ++n;
1762 justMoved = gFalse;
1763 }
1764 subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
1765}
1766
1767void GfxPath::close() {
1768 // this is necessary to handle the pathological case of
1769 // moveto/closepath/clip, which defines an empty clipping region
1770 if (justMoved) {
1771 if (n >= size) {
1772 size += 16;
1773 subpaths = (GfxSubpath **)
1774 grealloc(subpaths, size * sizeof(GfxSubpath *));
1775 }
1776 subpaths[n] = new GfxSubpath(firstX, firstY);
1777 ++n;
1778 justMoved = gFalse;
1779 }
1780 subpaths[n-1]->close();
1781}
1782
1783//------------------------------------------------------------------------
1784// GfxState
1785//------------------------------------------------------------------------
1786
1787GfxState::GfxState(fouble dpi, PDFRectangle *pageBox, int rotate,
1788 GBool upsideDown) {
1789 fouble k;
1790
1791 px1 = pageBox->x1;
1792 py1 = pageBox->y1;
1793 px2 = pageBox->x2;
1794 py2 = pageBox->y2;
1795 k = dpi / 72.0;
1796 if (rotate == 90) {
1797 ctm[0] = 0;
1798 ctm[1] = upsideDown ? k : -k;
1799 ctm[2] = k;
1800 ctm[3] = 0;
1801 ctm[4] = -k * py1;
1802 ctm[5] = k * (upsideDown ? -px1 : px2);
1803 pageWidth = k * (py2 - py1);
1804 pageHeight = k * (px2 - px1);
1805 } else if (rotate == 180) {
1806 ctm[0] = -k;
1807 ctm[1] = 0;
1808 ctm[2] = 0;
1809 ctm[3] = upsideDown ? k : -k;
1810 ctm[4] = k * px2;
1811 ctm[5] = k * (upsideDown ? -py1 : py2);
1812 pageWidth = k * (px2 - px1);
1813 pageHeight = k * (py2 - py1);
1814 } else if (rotate == 270) {
1815 ctm[0] = 0;
1816 ctm[1] = upsideDown ? -k : k;
1817 ctm[2] = -k;
1818 ctm[3] = 0;
1819 ctm[4] = k * py2;
1820 ctm[5] = k * (upsideDown ? px2 : -px1);
1821 pageWidth = k * (py2 - py1);
1822 pageHeight = k * (px2 - px1);
1823 } else {
1824 ctm[0] = k;
1825 ctm[1] = 0;
1826 ctm[2] = 0;
1827 ctm[3] = upsideDown ? -k : k;
1828 ctm[4] = -k * px1;
1829 ctm[5] = k * (upsideDown ? py2 : -py1);
1830 pageWidth = k * (px2 - px1);
1831 pageHeight = k * (py2 - py1);
1832 }
1833
1834 fillColorSpace = new GfxDeviceGrayColorSpace();
1835 strokeColorSpace = new GfxDeviceGrayColorSpace();
1836 fillColor.c[0] = 0;
1837 strokeColor.c[0] = 0;
1838 fillPattern = NULL;
1839 strokePattern = NULL;
1840 fillOpacity = 1;
1841 strokeOpacity = 1;
1842
1843 lineWidth = 1;
1844 lineDash = NULL;
1845 lineDashLength = 0;
1846 lineDashStart = 0;
1847 flatness = 0;
1848 lineJoin = 0;
1849 lineCap = 0;
1850 miterLimit = 10;
1851
1852 font = NULL;
1853 fontSize = 0;
1854 textMat[0] = 1; textMat[1] = 0;
1855 textMat[2] = 0; textMat[3] = 1;
1856 textMat[4] = 0; textMat[5] = 0;
1857 charSpace = 0;
1858 wordSpace = 0;
1859 horizScaling = 1;
1860 leading = 0;
1861 rise = 0;
1862 render = 0;
1863
1864 path = new GfxPath();
1865 curX = curY = 0;
1866 lineX = lineY = 0;
1867
1868 clipXMin = 0;
1869 clipYMin = 0;
1870 clipXMax = pageWidth;
1871 clipYMax = pageHeight;
1872
1873 saved = NULL;
1874}
1875
1876GfxState::~GfxState() {
1877 if (fillColorSpace) {
1878 delete fillColorSpace;
1879 }
1880 if (strokeColorSpace) {
1881 delete strokeColorSpace;
1882 }
1883 if (fillPattern) {
1884 delete fillPattern;
1885 }
1886 if (strokePattern) {
1887 delete strokePattern;
1888 }
1889 gfree(lineDash);
1890 if (path) {
1891 // this gets set to NULL by restore()
1892 delete path;
1893 }
1894 if (saved) {
1895 delete saved;
1896 }
1897}
1898
1899// Used for copy();
1900GfxState::GfxState(GfxState *state) {
1901 memcpy(this, state, sizeof(GfxState));
1902 if (fillColorSpace) {
1903 fillColorSpace = state->fillColorSpace->copy();
1904 }
1905 if (strokeColorSpace) {
1906 strokeColorSpace = state->strokeColorSpace->copy();
1907 }
1908 if (fillPattern) {
1909 fillPattern = state->fillPattern->copy();
1910 }
1911 if (strokePattern) {
1912 strokePattern = state->strokePattern->copy();
1913 }
1914 if (lineDashLength > 0) {
1915 lineDash = (fouble *)gmalloc(lineDashLength * sizeof(fouble));
1916 memcpy(lineDash, state->lineDash, lineDashLength * sizeof(fouble));
1917 }
1918 saved = NULL;
1919}
1920
1921fouble GfxState::transformWidth(fouble w) {
1922 fouble x, y;
1923
1924 x = ctm[0] + ctm[2];
1925 y = ctm[1] + ctm[3];
1926 return w * sqrt(0.5 * (x * x + y * y));
1927}
1928
1929fouble GfxState::getTransformedFontSize() {
1930 fouble x1, y1, x2, y2;
1931
1932 x1 = textMat[2] * fontSize;
1933 y1 = textMat[3] * fontSize;
1934 x2 = ctm[0] * x1 + ctm[2] * y1;
1935 y2 = ctm[1] * x1 + ctm[3] * y1;
1936 return sqrt(x2 * x2 + y2 * y2);
1937}
1938
1939void GfxState::getFontTransMat(fouble *m11, fouble *m12,
1940 fouble *m21, fouble *m22) {
1941 *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
1942 *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
1943 *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
1944 *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
1945}
1946
1947void GfxState::setCTM(fouble a, fouble b, fouble c,
1948 fouble d, fouble e, fouble f) {
1949 ctm[0] = a;
1950 ctm[1] = b;
1951 ctm[2] = c;
1952 ctm[3] = d;
1953 ctm[4] = e;
1954 ctm[5] = f;
1955}
1956
1957void GfxState::concatCTM(fouble a, fouble b, fouble c,
1958 fouble d, fouble e, fouble f) {
1959 fouble a1 = ctm[0];
1960 fouble b1 = ctm[1];
1961 fouble c1 = ctm[2];
1962 fouble d1 = ctm[3];
1963
1964 ctm[0] = a * a1 + b * c1;
1965 ctm[1] = a * b1 + b * d1;
1966 ctm[2] = c * a1 + d * c1;
1967 ctm[3] = c * b1 + d * d1;
1968 ctm[4] = e * a1 + f * c1 + ctm[4];
1969 ctm[5] = e * b1 + f * d1 + ctm[5];
1970}
1971
1972void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
1973 if (fillColorSpace) {
1974 delete fillColorSpace;
1975 }
1976 fillColorSpace = colorSpace;
1977}
1978
1979void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
1980 if (strokeColorSpace) {
1981 delete strokeColorSpace;
1982 }
1983 strokeColorSpace = colorSpace;
1984}
1985
1986void GfxState::setFillPattern(GfxPattern *pattern) {
1987 if (fillPattern) {
1988 delete fillPattern;
1989 }
1990 fillPattern = pattern;
1991}
1992
1993void GfxState::setStrokePattern(GfxPattern *pattern) {
1994 if (strokePattern) {
1995 delete strokePattern;
1996 }
1997 strokePattern = pattern;
1998}
1999
2000void GfxState::setLineDash(fouble *dash, int length, fouble start) {
2001 if (lineDash)
2002 gfree(lineDash);
2003 lineDash = dash;
2004 lineDashLength = length;
2005 lineDashStart = start;
2006}
2007
2008void GfxState::clearPath() {
2009 delete path;
2010 path = new GfxPath();
2011}
2012
2013void GfxState::clip() {
2014 fouble xMin, yMin, xMax, yMax, x, y;
2015 GfxSubpath *subpath;
2016 int i, j;
2017
2018 xMin = xMax = yMin = yMax = 0; // make gcc happy
2019 for (i = 0; i < path->getNumSubpaths(); ++i) {
2020 subpath = path->getSubpath(i);
2021 for (j = 0; j < subpath->getNumPoints(); ++j) {
2022 transform(subpath->getX(j), subpath->getY(j), &x, &y);
2023 if (i == 0 && j == 0) {
2024 xMin = xMax = x;
2025 yMin = yMax = y;
2026 } else {
2027 if (x < xMin) {
2028 xMin = x;
2029 } else if (x > xMax) {
2030 xMax = x;
2031 }
2032 if (y < yMin) {
2033 yMin = y;
2034 } else if (y > yMax) {
2035 yMax = y;
2036 }
2037 }
2038 }
2039 }
2040 if (xMin > clipXMin) {
2041 clipXMin = xMin;
2042 }
2043 if (yMin > clipYMin) {
2044 clipYMin = yMin;
2045 }
2046 if (xMax < clipXMax) {
2047 clipXMax = xMax;
2048 }
2049 if (yMax < clipYMax) {
2050 clipYMax = yMax;
2051 }
2052}
2053
2054void GfxState::textShift(fouble tx) {
2055 fouble dx, dy;
2056
2057 textTransformDelta(tx, 0, &dx, &dy);
2058 curX += dx;
2059 curY += dy;
2060}
2061
2062void GfxState::shift(fouble dx, fouble dy) {
2063 curX += dx;
2064 curY += dy;
2065}
2066
2067GfxState *GfxState::save() {
2068 GfxState *newState;
2069
2070 newState = copy();
2071 newState->saved = this;
2072 return newState;
2073}
2074
2075GfxState *GfxState::restore() {
2076 GfxState *oldState;
2077
2078 if (saved) {
2079 oldState = saved;
2080
2081 // these attributes aren't saved/restored by the q/Q operators
2082 oldState->path = path;
2083 oldState->curX = curX;
2084 oldState->curY = curY;
2085 oldState->lineX = lineX;
2086 oldState->lineY = lineY;
2087
2088 path = NULL;
2089 saved = NULL;
2090 delete this;
2091
2092 } else {
2093 oldState = this;
2094 }
2095
2096 return oldState;
2097}
diff --git a/noncore/unsupported/qpdf/xpdf/GfxState.h b/noncore/unsupported/qpdf/xpdf/GfxState.h
new file mode 100644
index 0000000..7fe16ea
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/GfxState.h
@@ -0,0 +1,922 @@
1//========================================================================
2//
3// GfxState.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef GFXSTATE_H
10#define GFXSTATE_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "Object.h"
18#include "Function.h"
19
20class Array;
21class GfxFont;
22struct PDFRectangle;
23
24//------------------------------------------------------------------------
25// GfxColor
26//------------------------------------------------------------------------
27
28#define gfxColorMaxComps funcMaxOutputs
29
30struct GfxColor {
31 fouble c[gfxColorMaxComps];
32};
33
34//------------------------------------------------------------------------
35// GfxRGB
36//------------------------------------------------------------------------
37
38struct GfxRGB {
39 fouble r, g, b;
40};
41
42//------------------------------------------------------------------------
43// GfxCMYK
44//------------------------------------------------------------------------
45
46struct GfxCMYK {
47 fouble c, m, y, k;
48};
49
50//------------------------------------------------------------------------
51// GfxColorSpace
52//------------------------------------------------------------------------
53
54enum GfxColorSpaceMode {
55 csDeviceGray,
56 csCalGray,
57 csDeviceRGB,
58 csCalRGB,
59 csDeviceCMYK,
60 csLab,
61 csICCBased,
62 csIndexed,
63 csSeparation,
64 csDeviceN,
65 csPattern
66};
67
68class GfxColorSpace {
69public:
70
71 GfxColorSpace();
72 virtual ~GfxColorSpace();
73 virtual GfxColorSpace *copy() = 0;
74 virtual GfxColorSpaceMode getMode() = 0;
75
76 // Construct a color space. Returns NULL if unsuccessful.
77 static GfxColorSpace *parse(Object *csObj);
78
79 // Convert to gray, RGB, or CMYK.
80 virtual void getGray(GfxColor *color, fouble *gray) = 0;
81 virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
82 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
83
84 // Return the number of color components.
85 virtual int getNComps() = 0;
86
87 // Return the default ranges for each component, assuming an image
88 // with a max pixel value of <maxImgPixel>.
89 virtual void getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
90 int maxImgPixel);
91
92private:
93};
94
95//------------------------------------------------------------------------
96// GfxDeviceGrayColorSpace
97//------------------------------------------------------------------------
98
99class GfxDeviceGrayColorSpace: public GfxColorSpace {
100public:
101
102 GfxDeviceGrayColorSpace();
103 virtual ~GfxDeviceGrayColorSpace();
104 virtual GfxColorSpace *copy();
105 virtual GfxColorSpaceMode getMode() { return csDeviceGray; }
106
107 virtual void getGray(GfxColor *color, fouble *gray);
108 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
109 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
110
111 virtual int getNComps() { return 1; }
112
113private:
114};
115
116//------------------------------------------------------------------------
117// GfxCalGrayColorSpace
118//------------------------------------------------------------------------
119
120class GfxCalGrayColorSpace: public GfxColorSpace {
121public:
122
123 GfxCalGrayColorSpace();
124 virtual ~GfxCalGrayColorSpace();
125 virtual GfxColorSpace *copy();
126 virtual GfxColorSpaceMode getMode() { return csCalGray; }
127
128 // Construct a CalGray color space. Returns NULL if unsuccessful.
129 static GfxColorSpace *parse(Array *arr);
130
131 virtual void getGray(GfxColor *color, fouble *gray);
132 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
133 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
134
135 virtual int getNComps() { return 1; }
136
137 // CalGray-specific access.
138 fouble getWhiteX() { return whiteX; }
139 fouble getWhiteY() { return whiteY; }
140 fouble getWhiteZ() { return whiteZ; }
141 fouble getBlackX() { return blackX; }
142 fouble getBlackY() { return blackY; }
143 fouble getBlackZ() { return blackZ; }
144 fouble getGamma() { return gamma; }
145
146private:
147
148 fouble whiteX, whiteY, whiteZ; // white point
149 fouble blackX, blackY, blackZ; // black point
150 fouble gamma; // gamma value
151};
152
153//------------------------------------------------------------------------
154// GfxDeviceRGBColorSpace
155//------------------------------------------------------------------------
156
157class GfxDeviceRGBColorSpace: public GfxColorSpace {
158public:
159
160 GfxDeviceRGBColorSpace();
161 virtual ~GfxDeviceRGBColorSpace();
162 virtual GfxColorSpace *copy();
163 virtual GfxColorSpaceMode getMode() { return csDeviceRGB; }
164
165 virtual void getGray(GfxColor *color, fouble *gray);
166 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
167 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
168
169 virtual int getNComps() { return 3; }
170
171private:
172};
173
174//------------------------------------------------------------------------
175// GfxCalRGBColorSpace
176//------------------------------------------------------------------------
177
178class GfxCalRGBColorSpace: public GfxColorSpace {
179public:
180
181 GfxCalRGBColorSpace();
182 virtual ~GfxCalRGBColorSpace();
183 virtual GfxColorSpace *copy();
184 virtual GfxColorSpaceMode getMode() { return csCalRGB; }
185
186 // Construct a CalRGB color space. Returns NULL if unsuccessful.
187 static GfxColorSpace *parse(Array *arr);
188
189 virtual void getGray(GfxColor *color, fouble *gray);
190 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
191 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
192
193 virtual int getNComps() { return 3; }
194
195 // CalRGB-specific access.
196 fouble getWhiteX() { return whiteX; }
197 fouble getWhiteY() { return whiteY; }
198 fouble getWhiteZ() { return whiteZ; }
199 fouble getBlackX() { return blackX; }
200 fouble getBlackY() { return blackY; }
201 fouble getBlackZ() { return blackZ; }
202 fouble getGammaR() { return gammaR; }
203 fouble getGammaG() { return gammaG; }
204 fouble getGammaB() { return gammaB; }
205 fouble *getMatrix() { return mat; }
206
207private:
208
209 fouble whiteX, whiteY, whiteZ; // white point
210 fouble blackX, blackY, blackZ; // black point
211 fouble gammaR, gammaG, gammaB; // gamma values
212 fouble mat[9]; // ABC -> XYZ transform matrix
213};
214
215//------------------------------------------------------------------------
216// GfxDeviceCMYKColorSpace
217//------------------------------------------------------------------------
218
219class GfxDeviceCMYKColorSpace: public GfxColorSpace {
220public:
221
222 GfxDeviceCMYKColorSpace();
223 virtual ~GfxDeviceCMYKColorSpace();
224 virtual GfxColorSpace *copy();
225 virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; }
226
227 virtual void getGray(GfxColor *color, fouble *gray);
228 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
229 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
230
231 virtual int getNComps() { return 4; }
232
233private:
234};
235
236//------------------------------------------------------------------------
237// GfxLabColorSpace
238//------------------------------------------------------------------------
239
240class GfxLabColorSpace: public GfxColorSpace {
241public:
242
243 GfxLabColorSpace();
244 virtual ~GfxLabColorSpace();
245 virtual GfxColorSpace *copy();
246 virtual GfxColorSpaceMode getMode() { return csLab; }
247
248 // Construct a Lab color space. Returns NULL if unsuccessful.
249 static GfxColorSpace *parse(Array *arr);
250
251 virtual void getGray(GfxColor *color, fouble *gray);
252 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
253 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
254
255 virtual int getNComps() { return 3; }
256
257 virtual void getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
258 int maxImgPixel);
259
260 // Lab-specific access.
261 fouble getWhiteX() { return whiteX; }
262 fouble getWhiteY() { return whiteY; }
263 fouble getWhiteZ() { return whiteZ; }
264 fouble getBlackX() { return blackX; }
265 fouble getBlackY() { return blackY; }
266 fouble getBlackZ() { return blackZ; }
267 fouble getAMin() { return aMin; }
268 fouble getAMax() { return aMax; }
269 fouble getBMin() { return bMin; }
270 fouble getBMax() { return bMax; }
271
272private:
273
274 fouble whiteX, whiteY, whiteZ; // white point
275 fouble blackX, blackY, blackZ; // black point
276 fouble aMin, aMax, bMin, bMax; // range for the a and b components
277 fouble kr, kg, kb; // gamut mapping mulitpliers
278};
279
280//------------------------------------------------------------------------
281// GfxICCBasedColorSpace
282//------------------------------------------------------------------------
283
284class GfxICCBasedColorSpace: public GfxColorSpace {
285public:
286
287 GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
288 Ref *iccProfileStreamA);
289 virtual ~GfxICCBasedColorSpace();
290 virtual GfxColorSpace *copy();
291 virtual GfxColorSpaceMode getMode() { return csICCBased; }
292
293 // Construct an ICCBased color space. Returns NULL if unsuccessful.
294 static GfxColorSpace *parse(Array *arr);
295
296 virtual void getGray(GfxColor *color, fouble *gray);
297 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
298 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
299
300 virtual int getNComps() { return nComps; }
301
302 virtual void getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
303 int maxImgPixel);
304
305 // ICCBased-specific access.
306 GfxColorSpace *getAlt() { return alt; }
307
308private:
309
310 int nComps; // number of color components (1, 3, or 4)
311 GfxColorSpace *alt; // alternate color space
312 fouble rangeMin[4]; // min values for each component
313 fouble rangeMax[4]; // max values for each component
314 Ref iccProfileStream; // the ICC profile
315};
316
317//------------------------------------------------------------------------
318// GfxIndexedColorSpace
319//------------------------------------------------------------------------
320
321class GfxIndexedColorSpace: public GfxColorSpace {
322public:
323
324 GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA);
325 virtual ~GfxIndexedColorSpace();
326 virtual GfxColorSpace *copy();
327 virtual GfxColorSpaceMode getMode() { return csIndexed; }
328
329 // Construct a Lab color space. Returns NULL if unsuccessful.
330 static GfxColorSpace *parse(Array *arr);
331
332 virtual void getGray(GfxColor *color, fouble *gray);
333 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
334 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
335
336 virtual int getNComps() { return 1; }
337
338 virtual void getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
339 int maxImgPixel);
340
341 // Indexed-specific access.
342 GfxColorSpace *getBase() { return base; }
343 int getIndexHigh() { return indexHigh; }
344 Guchar *getLookup() { return lookup; }
345
346private:
347
348 GfxColorSpace *base; // base color space
349 int indexHigh; // max pixel value
350 Guchar *lookup; // lookup table
351};
352
353//------------------------------------------------------------------------
354// GfxSeparationColorSpace
355//------------------------------------------------------------------------
356
357class GfxSeparationColorSpace: public GfxColorSpace {
358public:
359
360 GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA,
361 Function *funcA);
362 virtual ~GfxSeparationColorSpace();
363 virtual GfxColorSpace *copy();
364 virtual GfxColorSpaceMode getMode() { return csSeparation; }
365
366 // Construct a Separation color space. Returns NULL if unsuccessful.
367 static GfxColorSpace *parse(Array *arr);
368
369 virtual void getGray(GfxColor *color, fouble *gray);
370 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
371 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
372
373 virtual int getNComps() { return 1; }
374
375 // Separation-specific access.
376 GString *getName() { return name; }
377 GfxColorSpace *getAlt() { return alt; }
378 Function *getFunc() { return func; }
379
380private:
381
382 GString *name; // colorant name
383 GfxColorSpace *alt; // alternate color space
384 Function *func; // tint transform (into alternate color space)
385};
386
387//------------------------------------------------------------------------
388// GfxDeviceNColorSpace
389//------------------------------------------------------------------------
390
391class GfxDeviceNColorSpace: public GfxColorSpace {
392public:
393
394 GfxDeviceNColorSpace(int nComps, GfxColorSpace *alt, Function *func);
395 virtual ~GfxDeviceNColorSpace();
396 virtual GfxColorSpace *copy();
397 virtual GfxColorSpaceMode getMode() { return csDeviceN; }
398
399 // Construct a DeviceN color space. Returns NULL if unsuccessful.
400 static GfxColorSpace *parse(Array *arr);
401
402 virtual void getGray(GfxColor *color, fouble *gray);
403 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
404 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
405
406 virtual int getNComps() { return nComps; }
407
408 // DeviceN-specific access.
409 GfxColorSpace *getAlt() { return alt; }
410
411private:
412
413 int nComps; // number of components
414 GString // colorant names
415 *names[gfxColorMaxComps];
416 GfxColorSpace *alt; // alternate color space
417 Function *func; // tint transform (into alternate color space)
418
419};
420
421//------------------------------------------------------------------------
422// GfxPatternColorSpace
423//------------------------------------------------------------------------
424
425class GfxPatternColorSpace: public GfxColorSpace {
426public:
427
428 GfxPatternColorSpace(GfxColorSpace *underA);
429 virtual ~GfxPatternColorSpace();
430 virtual GfxColorSpace *copy();
431 virtual GfxColorSpaceMode getMode() { return csPattern; }
432
433 // Construct a Pattern color space. Returns NULL if unsuccessful.
434 static GfxColorSpace *parse(Array *arr);
435
436 virtual void getGray(GfxColor *color, fouble *gray);
437 virtual void getRGB(GfxColor *color, GfxRGB *rgb);
438 virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
439
440 virtual int getNComps() { return 0; }
441
442 // Pattern-specific access.
443 GfxColorSpace *getUnder() { return under; }
444
445private:
446
447 GfxColorSpace *under; // underlying color space (for uncolored
448 // patterns)
449};
450
451//------------------------------------------------------------------------
452// GfxPattern
453//------------------------------------------------------------------------
454
455class GfxPattern {
456public:
457
458 GfxPattern(int typeA);
459 virtual ~GfxPattern();
460
461 static GfxPattern *parse(Object *obj);
462
463 virtual GfxPattern *copy() = 0;
464
465 int getType() { return type; }
466
467private:
468
469 int type;
470};
471
472//------------------------------------------------------------------------
473// GfxTilingPattern
474//------------------------------------------------------------------------
475
476class GfxTilingPattern: public GfxPattern {
477public:
478
479 GfxTilingPattern(Dict *streamDict, Object *stream);
480 virtual ~GfxTilingPattern();
481
482 virtual GfxPattern *copy();
483
484 int getPaintType() { return paintType; }
485 int getTilingType() { return tilingType; }
486 fouble *getBBox() { return bbox; }
487 fouble getXStep() { return xStep; }
488 fouble getYStep() { return yStep; }
489 Dict *getResDict()
490 { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; }
491 fouble *getMatrix() { return matrix; }
492 Object *getContentStream() { return &contentStream; }
493
494private:
495
496 GfxTilingPattern(GfxTilingPattern *pat);
497
498 int paintType;
499 int tilingType;
500 fouble bbox[4];
501 fouble xStep, yStep;
502 Object resDict;
503 fouble matrix[6];
504 Object contentStream;
505};
506
507//------------------------------------------------------------------------
508// GfxShading
509//------------------------------------------------------------------------
510
511class GfxShading {
512public:
513
514 GfxShading();
515 virtual ~GfxShading();
516
517 static GfxShading *parse(Object *obj);
518
519 int getType() { return type; }
520 GfxColorSpace *getColorSpace() { return colorSpace; }
521 GfxColor *getBackground() { return &background; }
522 GBool getHasBackground() { return hasBackground; }
523 void getBBox(fouble *xMinA, fouble *yMinA, fouble *xMaxA, fouble *yMaxA)
524 { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
525 GBool getHasBBox() { return hasBBox; }
526
527private:
528
529 int type;
530 GfxColorSpace *colorSpace;
531 GfxColor background;
532 GBool hasBackground;
533 fouble xMin, yMin, xMax, yMax;
534 GBool hasBBox;
535};
536
537//------------------------------------------------------------------------
538// GfxAxialShading
539//------------------------------------------------------------------------
540
541class GfxAxialShading: public GfxShading {
542public:
543
544 GfxAxialShading(fouble x0A, fouble y0A,
545 fouble x1A, fouble y1A,
546 fouble t0A, fouble t1A,
547 Function **funcsA, int nFuncsA,
548 GBool extend0A, GBool extend1A);
549 virtual ~GfxAxialShading();
550
551 static GfxAxialShading *parse(Dict *dict);
552
553 void getCoords(fouble *x0A, fouble *y0A, fouble *x1A, fouble *y1A)
554 { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
555 fouble getDomain0() { return t0; }
556 fouble getDomain1() { return t1; }
557 void getColor(fouble t, GfxColor *color);
558 GBool getExtend0() { return extend0; }
559 GBool getExtend1() { return extend1; }
560
561private:
562
563 fouble x0, y0, x1, y1;
564 fouble t0, t1;
565 Function *funcs[gfxColorMaxComps];
566 int nFuncs;
567 GBool extend0, extend1;
568};
569
570//------------------------------------------------------------------------
571// GfxImageColorMap
572//------------------------------------------------------------------------
573
574class GfxImageColorMap {
575public:
576
577 // Constructor.
578 GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA);
579
580 // Destructor.
581 ~GfxImageColorMap();
582
583 // Is color map valid?
584 GBool isOk() { return ok; }
585
586 // Get the color space.
587 GfxColorSpace *getColorSpace() { return colorSpace; }
588
589 // Get stream decoding info.
590 int getNumPixelComps() { return nComps; }
591 int getBits() { return bits; }
592
593 // Get decode table.
594 fouble getDecodeLow(int i) { return decodeLow[i]; }
595 fouble getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
596
597 // Convert an image pixel to a color.
598 void getGray(Guchar *x, fouble *gray);
599 void getRGB(Guchar *x, GfxRGB *rgb);
600 void getCMYK(Guchar *x, GfxCMYK *cmyk);
601
602private:
603
604 GfxColorSpace *colorSpace;// the image color space
605 int bits; // bits per component
606 int nComps; // number of components in a pixel
607 GfxColorSpace *colorSpace2;// secondary color space
608 int nComps2; // number of components in colorSpace2
609 fouble *lookup; // lookup table
610 fouble // minimum values for each component
611 decodeLow[gfxColorMaxComps];
612 fouble // max - min value for each component
613 decodeRange[gfxColorMaxComps];
614 GBool ok;
615};
616
617//------------------------------------------------------------------------
618// GfxSubpath and GfxPath
619//------------------------------------------------------------------------
620
621class GfxSubpath {
622public:
623
624 // Constructor.
625 GfxSubpath(fouble x1, fouble y1);
626
627 // Destructor.
628 ~GfxSubpath();
629
630 // Copy.
631 GfxSubpath *copy() { return new GfxSubpath(this); }
632
633 // Get points.
634 int getNumPoints() { return n; }
635 fouble getX(int i) { return x[i]; }
636 fouble getY(int i) { return y[i]; }
637 GBool getCurve(int i) { return curve[i]; }
638
639 // Get last point.
640 fouble getLastX() { return x[n-1]; }
641 fouble getLastY() { return y[n-1]; }
642
643 // Add a line segment.
644 void lineTo(fouble x1, fouble y1);
645
646 // Add a Bezier curve.
647 void curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
648 fouble x3, fouble y3);
649
650 // Close the subpath.
651 void close();
652 GBool isClosed() { return closed; }
653
654private:
655
656 fouble *x, *y; // points
657 GBool *curve; // curve[i] => point i is a control point
658 // for a Bezier curve
659 int n; // number of points
660 int size; // size of x/y arrays
661 GBool closed; // set if path is closed
662
663 GfxSubpath(GfxSubpath *subpath);
664};
665
666class GfxPath {
667public:
668
669 // Constructor.
670 GfxPath();
671
672 // Destructor.
673 ~GfxPath();
674
675 // Copy.
676 GfxPath *copy()
677 { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); }
678
679 // Is there a current point?
680 GBool isCurPt() { return n > 0 || justMoved; }
681
682 // Is the path non-empty, i.e., is there at least one segment?
683 GBool isPath() { return n > 0; }
684
685 // Get subpaths.
686 int getNumSubpaths() { return n; }
687 GfxSubpath *getSubpath(int i) { return subpaths[i]; }
688
689 // Get last point on last subpath.
690 fouble getLastX() { return subpaths[n-1]->getLastX(); }
691 fouble getLastY() { return subpaths[n-1]->getLastY(); }
692
693 // Move the current point.
694 void moveTo(fouble x, fouble y);
695
696 // Add a segment to the last subpath.
697 void lineTo(fouble x, fouble y);
698
699 // Add a Bezier curve to the last subpath
700 void curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
701 fouble x3, fouble y3);
702
703 // Close the last subpath.
704 void close();
705
706private:
707
708 GBool justMoved; // set if a new subpath was just started
709 fouble firstX, firstY;// first point in new subpath
710 GfxSubpath **subpaths;// subpaths
711 int n; // number of subpaths
712 int size; // size of subpaths array
713
714 GfxPath(GBool justMoved1, fouble firstX1, fouble firstY1,
715 GfxSubpath **subpaths1, int n1, int size1);
716};
717
718//------------------------------------------------------------------------
719// GfxState
720//------------------------------------------------------------------------
721
722class GfxState {
723public:
724
725 // Construct a default GfxState, for a device with resolution <dpi>,
726 // page box <pageBox>, page rotation <rotate>, and coordinate system
727 // specified by <upsideDown>.
728 GfxState(fouble dpi, PDFRectangle *pageBox, int rotate,
729 GBool upsideDown);
730
731 // Destructor.
732 ~GfxState();
733
734 // Copy.
735 GfxState *copy() { return new GfxState(this); }
736
737 // Accessors.
738 fouble *getCTM() { return ctm; }
739 fouble getX1() { return px1; }
740 fouble getY1() { return py1; }
741 fouble getX2() { return px2; }
742 fouble getY2() { return py2; }
743 fouble getPageWidth() { return pageWidth; }
744 fouble getPageHeight() { return pageHeight; }
745 GfxColor *getFillColor() { return &fillColor; }
746 GfxColor *getStrokeColor() { return &strokeColor; }
747 void getFillGray(fouble *gray)
748 { fillColorSpace->getGray(&fillColor, gray); }
749 void getStrokeGray(fouble *gray)
750 { strokeColorSpace->getGray(&fillColor, gray); }
751 void getFillRGB(GfxRGB *rgb)
752 { fillColorSpace->getRGB(&fillColor, rgb); }
753 void getStrokeRGB(GfxRGB *rgb)
754 { strokeColorSpace->getRGB(&strokeColor, rgb); }
755 void getFillCMYK(GfxCMYK *cmyk)
756 { fillColorSpace->getCMYK(&fillColor, cmyk); }
757 void getStrokeCMYK(GfxCMYK *cmyk)
758 { strokeColorSpace->getCMYK(&strokeColor, cmyk); }
759 GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
760 GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
761 GfxPattern *getFillPattern() { return fillPattern; }
762 GfxPattern *getStrokePattern() { return strokePattern; }
763 fouble getFillOpacity() { return fillOpacity; }
764 fouble getStrokeOpacity() { return strokeOpacity; }
765 fouble getLineWidth() { return lineWidth; }
766 void getLineDash(fouble **dash, int *length, fouble *start)
767 { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
768 int getFlatness() { return flatness; }
769 int getLineJoin() { return lineJoin; }
770 int getLineCap() { return lineCap; }
771 fouble getMiterLimit() { return miterLimit; }
772 GfxFont *getFont() { return font; }
773 fouble getFontSize() { return fontSize; }
774 fouble *getTextMat() { return textMat; }
775 fouble getCharSpace() { return charSpace; }
776 fouble getWordSpace() { return wordSpace; }
777 fouble getHorizScaling() { return horizScaling; }
778 fouble getLeading() { return leading; }
779 fouble getRise() { return rise; }
780 int getRender() { return render; }
781 GfxPath *getPath() { return path; }
782 fouble getCurX() { return curX; }
783 fouble getCurY() { return curY; }
784 void getClipBBox(fouble *xMin, fouble *yMin, fouble *xMax, fouble *yMax)
785 { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; }
786 fouble getLineX() { return lineX; }
787 fouble getLineY() { return lineY; }
788
789 // Is there a current point/path?
790 GBool isCurPt() { return path->isCurPt(); }
791 GBool isPath() { return path->isPath(); }
792
793 // Transforms.
794 void transform(fouble x1, fouble y1, fouble *x2, fouble *y2)
795 { *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4];
796 *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; }
797 void transformDelta(fouble x1, fouble y1, fouble *x2, fouble *y2)
798 { *x2 = ctm[0] * x1 + ctm[2] * y1;
799 *y2 = ctm[1] * x1 + ctm[3] * y1; }
800 void textTransform(fouble x1, fouble y1, fouble *x2, fouble *y2)
801 { *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4];
802 *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; }
803 void textTransformDelta(fouble x1, fouble y1, fouble *x2, fouble *y2)
804 { *x2 = textMat[0] * x1 + textMat[2] * y1;
805 *y2 = textMat[1] * x1 + textMat[3] * y1; }
806 fouble transformWidth(fouble w);
807 fouble getTransformedLineWidth()
808 { return transformWidth(lineWidth); }
809 fouble getTransformedFontSize();
810 void getFontTransMat(fouble *m11, fouble *m12, fouble *m21, fouble *m22);
811
812 // Change state parameters.
813 void setCTM(fouble a, fouble b, fouble c,
814 fouble d, fouble e, fouble f);
815 void concatCTM(fouble a, fouble b, fouble c,
816 fouble d, fouble e, fouble f);
817 void setFillColorSpace(GfxColorSpace *colorSpace);
818 void setStrokeColorSpace(GfxColorSpace *colorSpace);
819 void setFillColor(GfxColor *color) { fillColor = *color; }
820 void setStrokeColor(GfxColor *color) { strokeColor = *color; }
821 void setFillPattern(GfxPattern *pattern);
822 void setStrokePattern(GfxPattern *pattern);
823 void setFillOpacity(fouble opac) { fillOpacity = opac; }
824 void setStrokeOpacity(fouble opac) { strokeOpacity = opac; }
825 void setLineWidth(fouble width) { lineWidth = width; }
826 void setLineDash(fouble *dash, int length, fouble start);
827 void setFlatness(int flatness1) { flatness = flatness1; }
828 void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
829 void setLineCap(int lineCap1) { lineCap = lineCap1; }
830 void setMiterLimit(fouble limit) { miterLimit = limit; }
831 void setFont(GfxFont *fontA, fouble fontSizeA)
832 { font = fontA; fontSize = fontSizeA; }
833 void setTextMat(fouble a, fouble b, fouble c,
834 fouble d, fouble e, fouble f)
835 { textMat[0] = a; textMat[1] = b; textMat[2] = c;
836 textMat[3] = d; textMat[4] = e; textMat[5] = f; }
837 void setCharSpace(fouble space)
838 { charSpace = space; }
839 void setWordSpace(fouble space)
840 { wordSpace = space; }
841 void setHorizScaling(fouble scale)
842 { horizScaling = 0.01 * scale; }
843 void setLeading(fouble leadingA)
844 { leading = leadingA; }
845 void setRise(fouble riseA)
846 { rise = riseA; }
847 void setRender(int renderA)
848 { render = renderA; }
849
850 // Add to path.
851 void moveTo(fouble x, fouble y)
852 { path->moveTo(curX = x, curY = y); }
853 void lineTo(fouble x, fouble y)
854 { path->lineTo(curX = x, curY = y); }
855 void curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
856 fouble x3, fouble y3)
857 { path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); }
858 void closePath()
859 { path->close(); curX = path->getLastX(); curY = path->getLastY(); }
860 void clearPath();
861
862 // Update clip region.
863 void clip();
864
865 // Text position.
866 void textMoveTo(fouble tx, fouble ty)
867 { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); }
868 void textShift(fouble tx);
869 void shift(fouble dx, fouble dy);
870
871 // Push/pop GfxState on/off stack.
872 GfxState *save();
873 GfxState *restore();
874 GBool hasSaves() { return saved != NULL; }
875
876private:
877
878 fouble ctm[6]; // coord transform matrix
879 fouble px1, py1, px2, py2;// page corners (user coords)
880 fouble pageWidth, pageHeight;// page size (pixels)
881
882 GfxColorSpace *fillColorSpace; // fill color space
883 GfxColorSpace *strokeColorSpace; // stroke color space
884 GfxColor fillColor; // fill color
885 GfxColor strokeColor; // stroke color
886 GfxPattern *fillPattern;// fill pattern
887 GfxPattern *strokePattern;// stroke pattern
888 fouble fillOpacity; // fill opacity
889 fouble strokeOpacity; // stroke opacity
890
891 fouble lineWidth; // line width
892 fouble *lineDash; // line dash
893 int lineDashLength;
894 fouble lineDashStart;
895 int flatness; // curve flatness
896 int lineJoin; // line join style
897 int lineCap; // line cap style
898 fouble miterLimit; // line miter limit
899
900 GfxFont *font; // font
901 fouble fontSize; // font size
902 fouble textMat[6]; // text matrix
903 fouble charSpace; // character spacing
904 fouble wordSpace; // word spacing
905 fouble horizScaling; // horizontal scaling
906 fouble leading; // text leading
907 fouble rise; // text rise
908 int render; // text rendering mode
909
910 GfxPath *path; // array of path elements
911 fouble curX, curY; // current point (user coords)
912 fouble lineX, lineY; // start of current text line (text coords)
913
914 fouble clipXMin, clipYMin,// bounding box for clip region
915 clipXMax, clipYMax;
916
917 GfxState *saved; // next GfxState on stack
918
919 GfxState(GfxState *state);
920};
921
922#endif
diff --git a/noncore/unsupported/qpdf/xpdf/GlobalParams.cc b/noncore/unsupported/qpdf/xpdf/GlobalParams.cc
new file mode 100644
index 0000000..8be58a3
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/GlobalParams.cc
@@ -0,0 +1,916 @@
1//========================================================================
2//
3// GlobalParams.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <string.h>
15#include <ctype.h>
16#if HAVE_PAPER_H
17#include <paper.h>
18#endif
19#include "gmem.h"
20#include "GString.h"
21#include "GList.h"
22#include "GHash.h"
23#include "gfile.h"
24#include "Error.h"
25#include "NameToCharCode.h"
26#include "CharCodeToUnicode.h"
27#include "UnicodeMap.h"
28#include "CMap.h"
29#include "BuiltinFontTables.h"
30#include "FontEncodingTables.h"
31#include "GlobalParams.h"
32
33#include "NameToUnicodeTable.h"
34#include "UnicodeMapTables.h"
35#include "DisplayFontTable.h"
36#include "UTF8.h"
37
38//------------------------------------------------------------------------
39
40GlobalParams *globalParams = NULL;
41
42//------------------------------------------------------------------------
43// DisplayFontParam
44//------------------------------------------------------------------------
45
46DisplayFontParam::DisplayFontParam(GString *nameA,
47 DisplayFontParamKind kindA) {
48 name = nameA;
49 kind = kindA;
50 switch (kind) {
51 case displayFontX:
52 x.xlfd = NULL;
53 x.encoding = NULL;
54 break;
55 case displayFontT1:
56 t1.fileName = NULL;
57 break;
58 case displayFontTT:
59 tt.fileName = NULL;
60 break;
61 }
62}
63
64DisplayFontParam::DisplayFontParam(char *nameA, char *xlfdA, char *encodingA) {
65 name = new GString(nameA);
66 kind = displayFontX;
67 x.xlfd = new GString(xlfdA);
68 x.encoding = new GString(encodingA);
69}
70
71DisplayFontParam::~DisplayFontParam() {
72 delete name;
73 switch (kind) {
74 case displayFontX:
75 if (x.xlfd) {
76 delete x.xlfd;
77 }
78 if (x.encoding) {
79 delete x.encoding;
80 }
81 break;
82 case displayFontT1:
83 if (t1.fileName) {
84 delete t1.fileName;
85 }
86 break;
87 case displayFontTT:
88 if (tt.fileName) {
89 delete tt.fileName;
90 }
91 break;
92 }
93}
94
95//------------------------------------------------------------------------
96// PSFontParam
97//------------------------------------------------------------------------
98
99PSFontParam::PSFontParam(GString *pdfFontNameA, GString *psFontNameA) {
100 pdfFontName = pdfFontNameA;
101 psFontName = psFontNameA;
102}
103
104PSFontParam::~PSFontParam() {
105 delete pdfFontName;
106 delete psFontName;
107}
108
109//------------------------------------------------------------------------
110// parsing
111//------------------------------------------------------------------------
112
113GlobalParams::GlobalParams(char *cfgFileName) {
114 UnicodeMap *map;
115 DisplayFontParam *dfp;
116 GString *fileName;
117 FILE *f;
118 char buf[512];
119 int line;
120 GList *tokens;
121 GString *cmd;
122 char *p1, *p2;
123 int i;
124
125 initBuiltinFontTables();
126
127 macRomanReverseMap = new NameToCharCode();
128 for (i = 0; i < 256; ++i) {
129 if (macRomanEncoding[i]) {
130 macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
131 }
132 }
133
134 nameToUnicode = new NameToCharCode();
135 cidToUnicodes = new GHash(gTrue);
136 residentUnicodeMaps = new GHash();
137 unicodeMaps = new GHash(gTrue);
138 cMapDirs = new GHash(gTrue);
139 toUnicodeDirs = new GList();
140 displayFonts = new GHash();
141 displayCIDFonts = new GHash();
142#if HAVE_PAPER_H
143 const struct paper *paperType;
144 paperinit();
145 paperType = paperinfo(systempapername());
146 psPaperWidth = (int)paperpswidth(paperType);
147 psPaperHeight = (int)paperpsheight(paperType);
148 paperdone();
149#else
150 psPaperWidth = defPaperWidth;
151 psPaperHeight = defPaperHeight;
152#endif
153 psDuplex = gFalse;
154 psLevel = psLevel2;
155 psFile = NULL;
156 psFonts = new GHash();
157 psEmbedType1 = gTrue;
158 psEmbedTrueType = gTrue;
159 psOPI = gFalse;
160 textEncoding = new GString("Latin1");
161#if defined(WIN32)
162 textEOL = eolDOS;
163#elif defined(MACOS)
164 textEOL = eolMac;
165#else
166 textEOL = eolUnix;
167#endif
168 fontDirs = new GList();
169 t1libControl = fontRastAALow;
170 freetypeControl = fontRastAALow;
171 urlCommand = NULL;
172 mapNumericCharNames = gTrue;
173 errQuiet = gFalse;
174
175 cidToUnicodeCache = new CIDToUnicodeCache();
176 unicodeMapCache = new UnicodeMapCache();
177 cMapCache = new CMapCache();
178
179 // set up the initial nameToUnicode table
180 for (i = 0; nameToUnicodeTab[i].name; ++i) {
181 nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
182 }
183
184 // set up the residentUnicodeMaps table
185 map = new UnicodeMap("Latin1", latin1UnicodeMapRanges, latin1UnicodeMapLen);
186 residentUnicodeMaps->add(map->getEncodingName(), map);
187 map = new UnicodeMap("ASCII7", ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
188 residentUnicodeMaps->add(map->getEncodingName(), map);
189 map = new UnicodeMap("Symbol", symbolUnicodeMapRanges, symbolUnicodeMapLen);
190 residentUnicodeMaps->add(map->getEncodingName(), map);
191 map = new UnicodeMap("ZapfDingbats", zapfDingbatsUnicodeMapRanges,
192 zapfDingbatsUnicodeMapLen);
193 residentUnicodeMaps->add(map->getEncodingName(), map);
194 map = new UnicodeMap("UTF-8", &mapUTF8);
195 residentUnicodeMaps->add(map->getEncodingName(), map);
196
197 // default displayFonts table
198 for (i = 0; displayFontTab[i].name; ++i) {
199 dfp = new DisplayFontParam(displayFontTab[i].name,
200 displayFontTab[i].xlfd,
201 displayFontTab[i].encoding);
202 displayFonts->add(dfp->name, dfp);
203 }
204
205 // look for a user config file, then a system-wide config file
206 f = NULL;
207 fileName = NULL;
208 if (cfgFileName && cfgFileName[0]) {
209 fileName = new GString(cfgFileName);
210 if (!(f = fopen(fileName->getCString(), "r"))) {
211 delete fileName;
212 }
213 }
214 if (!f) {
215 fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
216 if (!(f = fopen(fileName->getCString(), "r"))) {
217 delete fileName;
218 }
219 }
220 if (!f) {
221#if defined(WIN32) && !defined(__CYGWIN32__)
222 i = GetModuleFileName(NULL, buf, sizeof(buf));
223 if (i <= 0 || i >= sizeof(buf)) {
224 // error or path too long for buffer - just use the current dir
225 buf[i] = '\0';
226 }
227 fileName = grabPath(buf);
228 appendToPath(fileName, xpdfSysConfigFile);
229#else
230 fileName = new GString(xpdfSysConfigFile);
231#endif
232 if (!(f = fopen(fileName->getCString(), "r"))) {
233 delete fileName;
234 }
235 }
236 if (f) {
237 line = 1;
238 while (fgets(buf, sizeof(buf) - 1, f)) {
239
240 // break the line into tokens
241 tokens = new GList();
242 p1 = buf;
243 while (*p1) {
244 for (; *p1 && isspace(*p1); ++p1) ;
245 if (!*p1) {
246 break;
247 }
248 if (*p1 == '"' || *p1 == '\'') {
249 for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
250 ++p1;
251 } else {
252 for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
253 }
254 tokens->append(new GString(p1, p2 - p1));
255 p1 = p2 + 1;
256 }
257
258 if (tokens->getLength() > 0 &&
259 ((GString *)tokens->get(0))->getChar(0) != '#') {
260 cmd = (GString *)tokens->get(0);
261 if (!cmd->cmp("nameToUnicode")) {
262 parseNameToUnicode(tokens, fileName, line);
263 } else if (!cmd->cmp("cidToUnicode")) {
264 parseCIDToUnicode(tokens, fileName, line);
265 } else if (!cmd->cmp("unicodeMap")) {
266 parseUnicodeMap(tokens, fileName, line);
267 } else if (!cmd->cmp("cMapDir")) {
268 parseCMapDir(tokens, fileName, line);
269 } else if (!cmd->cmp("toUnicodeDir")) {
270 parseToUnicodeDir(tokens, fileName, line);
271 } else if (!cmd->cmp("displayFontX")) {
272 parseDisplayFont(tokens, gFalse, displayFontX, fileName, line);
273 } else if (!cmd->cmp("displayFontT1")) {
274 parseDisplayFont(tokens, gFalse, displayFontT1, fileName, line);
275 } else if (!cmd->cmp("displayFontTT")) {
276 parseDisplayFont(tokens, gFalse, displayFontTT, fileName, line);
277 } else if (!cmd->cmp("displayCIDFontX")) {
278 parseDisplayFont(tokens, gTrue, displayFontX, fileName, line);
279 } else if (!cmd->cmp("psFile")) {
280 parsePSFile(tokens, fileName, line);
281 } else if (!cmd->cmp("psFont")) {
282 parsePSFont(tokens, fileName, line);
283 } else if (!cmd->cmp("psPaperSize")) {
284 parsePSPaperSize(tokens, fileName, line);
285 } else if (!cmd->cmp("psDuplex")) {
286 parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
287 } else if (!cmd->cmp("psLevel")) {
288 parsePSLevel(tokens, fileName, line);
289 } else if (!cmd->cmp("psEmbedType1")) {
290 parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
291 } else if (!cmd->cmp("psEmbedTrueType")) {
292 parseYesNo("psEmbedTrueType", &psEmbedTrueType,
293 tokens, fileName, line);
294 } else if (!cmd->cmp("psOPI")) {
295 parseYesNo("psOPI", &psOPI, tokens, fileName, line);
296 } else if (!cmd->cmp("textEncoding")) {
297 parseTextEncoding(tokens, fileName, line);
298 } else if (!cmd->cmp("textEOL")) {
299 parseTextEOL(tokens, fileName, line);
300 } else if (!cmd->cmp("fontDir")) {
301 parseFontDir(tokens, fileName, line);
302 } else if (!cmd->cmp("t1libControl")) {
303 parseFontRastControl("t1libControl", &t1libControl,
304 tokens, fileName, line);
305 } else if (!cmd->cmp("freetypeControl")) {
306 parseFontRastControl("freetypeControl", &freetypeControl,
307 tokens, fileName, line);
308 } else if (!cmd->cmp("urlCommand")) {
309 parseURLCommand(tokens, fileName, line);
310 } else if (!cmd->cmp("mapNumericCharNames")) {
311 parseYesNo("mapNumericCharNames", &mapNumericCharNames,
312 tokens, fileName, line);
313 } else if (!cmd->cmp("errQuiet")) {
314 parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
315 } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
316 error(-1, "Unknown config file command");
317 error(-1, "-- the config file format has changed since Xpdf 0.9x");
318 } else {
319 error(-1, "Unknown config file command '%s' (%s:%d)",
320 cmd->getCString(), fileName->getCString(), line);
321 }
322 }
323
324 deleteGList(tokens, GString);
325 ++line;
326 }
327
328 delete fileName;
329 }
330}
331
332void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
333 int line) {
334 GString *name;
335 char *tok1, *tok2;
336 FILE *f;
337 char buf[256];
338 int line2;
339 Unicode u;
340
341 if (tokens->getLength() != 2) {
342 error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
343 fileName->getCString(), line);
344 return;
345 }
346 name = (GString *)tokens->get(1);
347 if (!(f = fopen(name->getCString(), "r"))) {
348 error(-1, "Couldn't open 'nameToUnicode' file '%s'",
349 name->getCString());
350 return;
351 }
352 line2 = 1;
353 while (fgets(buf, sizeof(buf), f)) {
354 tok1 = strtok(buf, " \t\r\n");
355 tok2 = strtok(NULL, " \t\r\n");
356 if (tok1 && tok2) {
357 sscanf(tok1, "%x", &u);
358 nameToUnicode->add(tok2, u);
359 } else {
360 error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
361 }
362 ++line2;
363 }
364 fclose(f);
365}
366
367void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
368 int line) {
369 GString *collection, *name, *old;
370
371 if (tokens->getLength() != 3) {
372 error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
373 fileName->getCString(), line);
374 return;
375 }
376 collection = (GString *)tokens->get(1);
377 name = (GString *)tokens->get(2);
378 if ((old = (GString *)cidToUnicodes->remove(collection))) {
379 delete old;
380 }
381 cidToUnicodes->add(collection->copy(), name->copy());
382}
383
384void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
385 int line) {
386 GString *encodingName, *name, *old;
387
388 if (tokens->getLength() != 3) {
389 error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
390 fileName->getCString(), line);
391 return;
392 }
393 encodingName = (GString *)tokens->get(1);
394 name = (GString *)tokens->get(2);
395 if ((old = (GString *)unicodeMaps->remove(encodingName))) {
396 delete old;
397 }
398 unicodeMaps->add(encodingName->copy(), name->copy());
399}
400
401void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
402 GString *collection, *dir;
403 GList *list;
404
405 if (tokens->getLength() != 3) {
406 error(-1, "Bad 'cMapDir' config file command (%s:%d)",
407 fileName->getCString(), line);
408 return;
409 }
410 collection = (GString *)tokens->get(1);
411 dir = (GString *)tokens->get(2);
412 if (!(list = (GList *)cMapDirs->lookup(collection))) {
413 list = new GList();
414 cMapDirs->add(collection->copy(), list);
415 }
416 list->append(dir->copy());
417}
418
419void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
420 int line) {
421 if (tokens->getLength() != 2) {
422 error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
423 fileName->getCString(), line);
424 return;
425 }
426 toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
427}
428
429void GlobalParams::parseDisplayFont(GList *tokens, GBool isCID,
430 DisplayFontParamKind kind,
431 GString *fileName, int line) {
432 DisplayFontParam *param, *old;
433
434 if (tokens->getLength() < 2) {
435 goto err1;
436 }
437 param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
438
439 switch (kind) {
440 case displayFontX:
441 if (tokens->getLength() != 4) {
442 goto err2;
443 }
444 param->x.xlfd = ((GString *)tokens->get(2))->copy();
445 param->x.encoding = ((GString *)tokens->get(3))->copy();
446 break;
447 case displayFontT1:
448 if (tokens->getLength() != 3) {
449 goto err2;
450 }
451 param->t1.fileName = ((GString *)tokens->get(2))->copy();
452 break;
453 case displayFontTT:
454 if (tokens->getLength() != 3) {
455 goto err2;
456 }
457 param->tt.fileName = ((GString *)tokens->get(2))->copy();
458 break;
459 }
460
461 if (isCID) {
462 if ((old = (DisplayFontParam *)displayCIDFonts->remove(param->name))) {
463 delete old;
464 }
465 displayCIDFonts->add(param->name, param);
466 } else {
467 if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
468 delete old;
469 }
470 displayFonts->add(param->name, param);
471 }
472 return;
473
474 err2:
475 delete param;
476 err1:
477 error(-1, "Bad 'displayFont...' config file command (%s:%d)",
478 fileName->getCString(), line);
479}
480
481void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
482 int line) {
483 GString *tok;
484
485 if (tokens->getLength() == 2) {
486 tok = (GString *)tokens->get(1);
487 if (!setPSPaperSize(tok->getCString())) {
488 error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
489 fileName->getCString(), line);
490 }
491 } else if (tokens->getLength() == 3) {
492 tok = (GString *)tokens->get(1);
493 psPaperWidth = atoi(tok->getCString());
494 tok = (GString *)tokens->get(2);
495 psPaperHeight = atoi(tok->getCString());
496 } else {
497 error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
498 fileName->getCString(), line);
499 }
500}
501
502void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
503 GString *tok;
504
505 if (tokens->getLength() != 2) {
506 error(-1, "Bad 'psLevel' config file command (%s:%d)",
507 fileName->getCString(), line);
508 return;
509 }
510 tok = (GString *)tokens->get(1);
511 if (!tok->cmp("level1")) {
512 psLevel = psLevel1;
513 } else if (!tok->cmp("level1sep")) {
514 psLevel = psLevel1Sep;
515 } else if (!tok->cmp("level2")) {
516 psLevel = psLevel2;
517 } else if (!tok->cmp("level2sep")) {
518 psLevel = psLevel2Sep;
519 } else {
520 error(-1, "Bad 'psLevel' config file command (%s:%d)",
521 fileName->getCString(), line);
522 }
523}
524
525void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
526 if (tokens->getLength() != 2) {
527 error(-1, "Bad 'psFile' config file command (%s:%d)",
528 fileName->getCString(), line);
529 return;
530 }
531 if (psFile) {
532 delete psFile;
533 }
534 psFile = ((GString *)tokens->get(1))->copy();
535}
536
537void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
538 PSFontParam *param;
539
540 if (tokens->getLength() != 3) {
541 error(-1, "Bad 'psFont' config file command (%s:%d)",
542 fileName->getCString(), line);
543 return;
544 }
545 param = new PSFontParam(((GString *)tokens->get(1))->copy(),
546 ((GString *)tokens->get(2))->copy());
547 psFonts->add(param->pdfFontName, param);
548}
549
550void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
551 int line) {
552 if (tokens->getLength() != 2) {
553 error(-1, "Bad 'textEncoding' config file command (%s:%d)",
554 fileName->getCString(), line);
555 return;
556 }
557 delete textEncoding;
558 textEncoding = ((GString *)tokens->get(1))->copy();
559}
560
561void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
562 GString *tok;
563
564 if (tokens->getLength() != 2) {
565 error(-1, "Bad 'textEOL' config file command (%s:%d)",
566 fileName->getCString(), line);
567 return;
568 }
569 tok = (GString *)tokens->get(1);
570 if (!tok->cmp("unix")) {
571 textEOL = eolUnix;
572 } else if (!tok->cmp("dos")) {
573 textEOL = eolDOS;
574 } else if (!tok->cmp("mac")) {
575 textEOL = eolMac;
576 } else {
577 error(-1, "Bad 'textEOL' config file command (%s:%d)",
578 fileName->getCString(), line);
579 }
580}
581
582void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
583 if (tokens->getLength() != 2) {
584 error(-1, "Bad 'fontDir' config file command (%s:%d)",
585 fileName->getCString(), line);
586 return;
587 }
588 fontDirs->append(((GString *)tokens->get(1))->copy());
589}
590
591void GlobalParams::parseURLCommand(GList *tokens, GString *fileName,
592 int line) {
593 if (tokens->getLength() != 2) {
594 error(-1, "Bad 'urlCommand' config file command (%s:%d)",
595 fileName->getCString(), line);
596 return;
597 }
598 if (urlCommand) {
599 delete urlCommand;
600 }
601 urlCommand = ((GString *)tokens->get(1))->copy();
602}
603
604void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val,
605 GList *tokens, GString *fileName,
606 int line) {
607 GString *tok;
608
609 if (tokens->getLength() != 2) {
610 error(-1, "Bad '%s' config file command (%s:%d)",
611 cmdName, fileName->getCString(), line);
612 return;
613 }
614 tok = (GString *)tokens->get(1);
615 if (!setFontRastControl(val, tok->getCString())) {
616 error(-1, "Bad '%s' config file command (%s:%d)",
617 cmdName, fileName->getCString(), line);
618 }
619}
620
621void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
622 GList *tokens, GString *fileName, int line) {
623 GString *tok;
624
625 if (tokens->getLength() != 2) {
626 error(-1, "Bad '%s' config file command (%s:%d)",
627 cmdName, fileName->getCString(), line);
628 return;
629 }
630 tok = (GString *)tokens->get(1);
631 if (!tok->cmp("yes")) {
632 *flag = gTrue;
633 } else if (!tok->cmp("no")) {
634 *flag = gFalse;
635 } else {
636 error(-1, "Bad '%s' config file command (%s:%d)",
637 cmdName, fileName->getCString(), line);
638 }
639}
640
641GlobalParams::~GlobalParams() {
642 GHashIter *iter;
643 GString *key;
644 GList *list;
645
646 freeBuiltinFontTables();
647
648 delete macRomanReverseMap;
649
650 delete nameToUnicode;
651 deleteGHash(cidToUnicodes, GString);
652 deleteGHash(residentUnicodeMaps, UnicodeMap);
653 deleteGHash(unicodeMaps, GString);
654 deleteGList(toUnicodeDirs, GString);
655 deleteGHash(displayFonts, DisplayFontParam);
656 deleteGHash(displayCIDFonts, DisplayFontParam);
657 if (psFile) {
658 delete psFile;
659 }
660 deleteGHash(psFonts, PSFontParam);
661 delete textEncoding;
662 deleteGList(fontDirs, GString);
663 if (urlCommand) {
664 delete urlCommand;
665 }
666
667 cMapDirs->startIter(&iter);
668 while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
669 deleteGList(list, GString);
670 }
671 delete cMapDirs;
672
673 delete cidToUnicodeCache;
674 delete unicodeMapCache;
675 delete cMapCache;
676}
677
678//------------------------------------------------------------------------
679// accessors
680//------------------------------------------------------------------------
681
682CharCode GlobalParams::getMacRomanCharCode(char *charName) {
683 return macRomanReverseMap->lookup(charName);
684}
685
686Unicode GlobalParams::mapNameToUnicode(char *charName) {
687 return nameToUnicode->lookup(charName);
688}
689
690FILE *GlobalParams::getCIDToUnicodeFile(GString *collection) {
691 GString *fileName;
692
693 if (!(fileName = (GString *)cidToUnicodes->lookup(collection))) {
694 return NULL;
695 }
696 return fopen(fileName->getCString(), "r");
697}
698
699UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
700 return (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
701}
702
703FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
704 GString *fileName;
705
706 if (!(fileName = (GString *)unicodeMaps->lookup(encodingName))) {
707 return NULL;
708 }
709 return fopen(fileName->getCString(), "r");
710}
711
712FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
713 GList *list;
714 GString *dir;
715 GString *fileName;
716 FILE *f;
717 int i;
718
719 if (!(list = (GList *)cMapDirs->lookup(collection))) {
720 return NULL;
721 }
722 for (i = 0; i < list->getLength(); ++i) {
723 dir = (GString *)list->get(i);
724 fileName = appendToPath(dir->copy(), cMapName->getCString());
725 f = fopen(fileName->getCString(), "r");
726 delete fileName;
727 if (f) {
728 return f;
729 }
730 }
731 return NULL;
732}
733
734FILE *GlobalParams::findToUnicodeFile(GString *name) {
735 GString *dir, *fileName;
736 FILE *f;
737 int i;
738
739 for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
740 dir = (GString *)toUnicodeDirs->get(i);
741 fileName = appendToPath(dir->copy(), name->getCString());
742 f = fopen(fileName->getCString(), "r");
743 delete fileName;
744 if (f) {
745 return f;
746 }
747 }
748 return NULL;
749}
750
751DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
752 return (DisplayFontParam *)displayFonts->lookup(fontName);
753}
754
755DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *collection) {
756 return (DisplayFontParam *)displayCIDFonts->lookup(collection);
757}
758
759PSFontParam *GlobalParams::getPSFont(GString *fontName) {
760 return (PSFontParam *)psFonts->lookup(fontName);
761}
762
763GString *GlobalParams::findFontFile(GString *fontName,
764 char *ext1, char *ext2) {
765 GString *dir, *fileName;
766 FILE *f;
767 int i;
768
769 for (i = 0; i < fontDirs->getLength(); ++i) {
770 dir = (GString *)fontDirs->get(i);
771 if (ext1) {
772 fileName = appendToPath(dir->copy(), fontName->getCString());
773 fileName->append(ext1);
774 if ((f = fopen(fileName->getCString(), "r"))) {
775 fclose(f);
776 return fileName;
777 }
778 delete fileName;
779 }
780 if (ext2) {
781 fileName = appendToPath(dir->copy(), fontName->getCString());
782 fileName->append(ext2);
783 if ((f = fopen(fileName->getCString(), "r"))) {
784 fclose(f);
785 return fileName;
786 }
787 delete fileName;
788 }
789 }
790 return NULL;
791}
792
793CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
794 return cidToUnicodeCache->getCIDToUnicode(collection);
795}
796
797UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
798 UnicodeMap *map;
799
800 if ((map = getResidentUnicodeMap(encodingName))) {
801 map->incRefCnt();
802 return map;
803 }
804 return unicodeMapCache->getUnicodeMap(encodingName);
805}
806
807CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
808 return cMapCache->getCMap(collection, cMapName);
809}
810
811UnicodeMap *GlobalParams::getTextEncoding() {
812 return getUnicodeMap(textEncoding);
813}
814
815//------------------------------------------------------------------------
816// functions to set parameters
817//------------------------------------------------------------------------
818
819void GlobalParams::setPSFile(char *file) {
820 if (psFile) {
821 delete psFile;
822 }
823 psFile = new GString(file);
824}
825
826GBool GlobalParams::setPSPaperSize(char *size) {
827 if (!strcmp(size, "letter")) {
828 psPaperWidth = 612;
829 psPaperHeight = 792;
830 } else if (!strcmp(size, "legal")) {
831 psPaperWidth = 612;
832 psPaperHeight = 1008;
833 } else if (!strcmp(size, "A4")) {
834 psPaperWidth = 595;
835 psPaperHeight = 842;
836 } else if (!strcmp(size, "A3")) {
837 psPaperWidth = 842;
838 psPaperHeight = 1190;
839 } else {
840 return gFalse;
841 }
842 return gTrue;
843}
844
845void GlobalParams::setPSPaperWidth(int width) {
846 psPaperWidth = width;
847}
848
849void GlobalParams::setPSPaperHeight(int height) {
850 psPaperHeight = height;
851}
852
853void GlobalParams::setPSDuplex(GBool duplex) {
854 psDuplex = duplex;
855}
856
857void GlobalParams::setPSLevel(PSLevel level) {
858 psLevel = level;
859}
860
861void GlobalParams::setPSEmbedType1(GBool embed) {
862 psEmbedType1 = embed;
863}
864
865void GlobalParams::setPSEmbedTrueType(GBool embed) {
866 psEmbedTrueType = embed;
867}
868
869void GlobalParams::setPSOPI(GBool opi) {
870 psOPI = opi;
871}
872
873void GlobalParams::setTextEncoding(char *encodingName) {
874 delete textEncoding;
875 textEncoding = new GString(encodingName);
876}
877
878GBool GlobalParams::setTextEOL(char *s) {
879 if (!strcmp(s, "unix")) {
880 textEOL = eolUnix;
881 } else if (!strcmp(s, "dos")) {
882 textEOL = eolDOS;
883 } else if (!strcmp(s, "mac")) {
884 textEOL = eolMac;
885 } else {
886 return gFalse;
887 }
888 return gTrue;
889}
890
891GBool GlobalParams::setT1libControl(char *s) {
892 return setFontRastControl(&t1libControl, s);
893}
894
895GBool GlobalParams::setFreeTypeControl(char *s) {
896 return setFontRastControl(&freetypeControl, s);
897}
898
899GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
900 if (!strcmp(s, "none")) {
901 *val = fontRastNone;
902 } else if (!strcmp(s, "plain")) {
903 *val = fontRastPlain;
904 } else if (!strcmp(s, "low")) {
905 *val = fontRastAALow;
906 } else if (!strcmp(s, "high")) {
907 *val = fontRastAAHigh;
908 } else {
909 return gFalse;
910 }
911 return gTrue;
912}
913
914void GlobalParams::setErrQuiet(GBool errQuietA) {
915 errQuiet = errQuietA;
916}
diff --git a/noncore/unsupported/qpdf/xpdf/GlobalParams.h b/noncore/unsupported/qpdf/xpdf/GlobalParams.h
new file mode 100644
index 0000000..ecbb5fc
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/GlobalParams.h
@@ -0,0 +1,242 @@
1//========================================================================
2//
3// GlobalParams.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef GLOBALPARAMS_H
10#define GLOBALPARAMS_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include <stdio.h>
17#include "gtypes.h"
18#include "CharTypes.h"
19
20class GString;
21class GList;
22class GHash;
23class NameToCharCode;
24class CharCodeToUnicode;
25class CIDToUnicodeCache;
26class UnicodeMap;
27class UnicodeMapCache;
28class CMap;
29class CMapCache;
30class GlobalParams;
31
32//------------------------------------------------------------------------
33
34// The global parameters object.
35extern GlobalParams *globalParams;
36
37//------------------------------------------------------------------------
38
39enum DisplayFontParamKind {
40 displayFontX,
41 displayFontT1,
42 displayFontTT
43};
44
45class DisplayFontParam {
46public:
47
48 GString *name; // font name for 8-bit fonts;
49 // collection name for CID fonts
50 DisplayFontParamKind kind;
51 union {
52 struct {
53 GString *xlfd;
54 GString *encoding;
55 } x;
56 struct {
57 GString *fileName;
58 } t1;
59 struct {
60 GString *fileName;
61 } tt;
62 };
63
64 DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
65 DisplayFontParam(char *nameA, char *xlfdA, char *encodingA);
66 ~DisplayFontParam();
67};
68
69// Font rasterizer control.
70enum FontRastControl {
71 fontRastNone, // don't use this rasterizer
72 fontRastPlain, // use it, without anti-aliasing
73 fontRastAALow, // use it, with low-level anti-aliasing
74 fontRastAAHigh // use it, with high-level anti-aliasing
75};
76
77//------------------------------------------------------------------------
78
79class PSFontParam {
80public:
81
82 GString *pdfFontName;
83 GString *psFontName;
84
85 PSFontParam(GString *pdfFontNameA, GString *psFontNameA);
86 ~PSFontParam();
87};
88
89//------------------------------------------------------------------------
90
91enum PSLevel {
92 psLevel1,
93 psLevel1Sep,
94 psLevel2,
95 psLevel2Sep
96};
97
98//------------------------------------------------------------------------
99
100enum EndOfLineKind {
101 eolUnix, // LF
102 eolDOS, // CR+LF
103 eolMac // CR
104};
105
106//------------------------------------------------------------------------
107
108class GlobalParams {
109public:
110
111 // Initialize the global parameters by attempting to read a config
112 // file.
113 GlobalParams(char *cfgFileName);
114
115 ~GlobalParams();
116
117 //----- accessors
118
119 CharCode getMacRomanCharCode(char *charName);
120
121 Unicode mapNameToUnicode(char *charName);
122 FILE *getCIDToUnicodeFile(GString *collection);
123 UnicodeMap *getResidentUnicodeMap(GString *encodingName);
124 FILE *getUnicodeMapFile(GString *encodingName);
125 FILE *findCMapFile(GString *collection, GString *cMapName);
126 FILE *findToUnicodeFile(GString *name);
127 DisplayFontParam *getDisplayFont(GString *fontName);
128 DisplayFontParam *getDisplayCIDFont(GString *collection);
129 GString *getPSFile() { return psFile; }
130 int getPSPaperWidth() { return psPaperWidth; }
131 int getPSPaperHeight() { return psPaperHeight; }
132 GBool getPSDuplex() { return psDuplex; }
133 PSLevel getPSLevel() { return psLevel; }
134 PSFontParam *getPSFont(GString *fontName);
135 GBool getPSEmbedType1() { return psEmbedType1; }
136 GBool getPSEmbedTrueType() { return psEmbedTrueType; }
137 GBool getPSOPI() { return psOPI; }
138 GString *getTextEncodingName() { return textEncoding; }
139 EndOfLineKind getTextEOL() { return textEOL; }
140 GString *findFontFile(GString *fontName, char *ext1, char *ext2);
141 FontRastControl getT1libControl() { return t1libControl; }
142 FontRastControl getFreeTypeControl() { return freetypeControl; }
143 GString *getURLCommand() { return urlCommand; }
144 GBool getMapNumericCharNames() { return mapNumericCharNames; }
145 GBool getErrQuiet() { return errQuiet; }
146
147 CharCodeToUnicode *getCIDToUnicode(GString *collection);
148 UnicodeMap *getUnicodeMap(GString *encodingName);
149 CMap *getCMap(GString *collection, GString *cMapName);
150 UnicodeMap *getTextEncoding();
151
152 //----- functions to set parameters
153
154 void setPSFile(char *file);
155 GBool setPSPaperSize(char *size);
156 void setPSPaperWidth(int width);
157 void setPSPaperHeight(int height);
158 void setPSDuplex(GBool duplex);
159 void setPSLevel(PSLevel level);
160 void setPSEmbedType1(GBool embed);
161 void setPSEmbedTrueType(GBool embed);
162 void setPSOPI(GBool opi);
163 void setTextEncoding(char *encodingName);
164 GBool setTextEOL(char *s);
165 GBool setT1libControl(char *s);
166 GBool setFreeTypeControl(char *s);
167 void setErrQuiet(GBool errQuietA);
168
169private:
170
171 void parseNameToUnicode(GList *tokens, GString *fileName, int line);
172 void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
173 void parseUnicodeMap(GList *tokens, GString *fileName, int line);
174 void parseCMapDir(GList *tokens, GString *fileName, int line);
175 void parseToUnicodeDir(GList *tokens, GString *fileName, int line);
176 void parseDisplayFont(GList *tokens, GBool isCID, DisplayFontParamKind kind,
177 GString *fileName, int line);
178 void parsePSFile(GList *tokens, GString *fileName, int line);
179 void parsePSPaperSize(GList *tokens, GString *fileName, int line);
180 void parsePSLevel(GList *tokens, GString *fileName, int line);
181 void parsePSFont(GList *tokens, GString *fileName, int line);
182 void parseTextEncoding(GList *tokens, GString *fileName, int line);
183 void parseTextEOL(GList *tokens, GString *fileName, int line);
184 void parseFontDir(GList *tokens, GString *fileName, int line);
185 void parseFontRastControl(char *cmdName, FontRastControl *val,
186 GList *tokens, GString *fileName, int line);
187 void parseURLCommand(GList *tokens, GString *fileName, int line);
188 void parseYesNo(char *cmdName, GBool *flag,
189 GList *tokens, GString *fileName, int line);
190 GBool setFontRastControl(FontRastControl *val, char *s);
191
192 //----- static tables
193
194 NameToCharCode * // mapping from char name to
195 macRomanReverseMap; // MacRomanEncoding index
196
197 //----- user-modifiable settings
198
199 NameToCharCode * // mapping from char name to Unicode
200 nameToUnicode;
201 GHash *cidToUnicodes; // files for mappings from char collections
202 // to Unicode, indexed by collection name
203 // [GString]
204 GHash *residentUnicodeMaps;// mappings from Unicode to char codes,
205 // indexed by encoding name [UnicodeMap]
206 GHash *unicodeMaps; // files for mappings from Unicode to char
207 // codes, indexed by encoding name [GString]
208 GHash *cMapDirs; // list of CMap dirs, indexed by collection
209 // name [GList[GString]]
210 GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString]
211 GHash *displayFonts; // display font info, indexed by font name
212 // [DisplayFontParam]
213 GHash *displayCIDFonts;// display CID font info, indexed by
214 // collection [DisplayFontParam]
215 GString *psFile; // PostScript file or command (for xpdf)
216 int psPaperWidth; // paper size, in PostScript points, for
217 int psPaperHeight; // PostScript output
218 GBool psDuplex; // enable duplexing in PostScript?
219 PSLevel psLevel; // PostScript level to generate
220 GHash *psFonts; // PostScript font info, indexed by PDF
221 // font name [PSFontParam]
222 GBool psEmbedType1; // embed Type 1 fonts?
223 GBool psEmbedTrueType;// embed TrueType fonts?
224 GBool psOPI; // generate PostScript OPI comments?
225 GString *textEncoding;// encoding (unicodeMap) to use for text
226 // output
227 EndOfLineKind textEOL;// type of EOL marker to use for text
228 // output
229 GList *fontDirs; // list of font dirs [GString]
230 FontRastControl t1libControl;// t1lib rasterization mode
231 FontRastControl // FreeType rasterization mode
232 freetypeControl;
233 GString *urlCommand; // command executed for URL links
234 GBool mapNumericCharNames;// map numeric char names (from font subsets)?
235 GBool errQuiet; // suppress error messages?
236
237 CIDToUnicodeCache *cidToUnicodeCache;
238 UnicodeMapCache *unicodeMapCache;
239 CMapCache *cMapCache;
240};
241
242#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Lexer.cc b/noncore/unsupported/qpdf/xpdf/Lexer.cc
new file mode 100644
index 0000000..fff4bcb
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Lexer.cc
@@ -0,0 +1,473 @@
1//========================================================================
2//
3// Lexer.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdlib.h>
15#include <stddef.h>
16#include <string.h>
17#include <ctype.h>
18#include "Lexer.h"
19#include "Error.h"
20
21//------------------------------------------------------------------------
22
23// A '1' in this array means the character is white space. A '1' or
24// '2' means the character ends a name or command.
25static char specialChars[256] = {
26 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
28 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
42};
43
44//------------------------------------------------------------------------
45// Lexer
46//------------------------------------------------------------------------
47
48Lexer::Lexer(XRef *xref, Stream *str) {
49 Object obj;
50
51 curStr.initStream(str);
52 streams = new Array(xref);
53 streams->add(curStr.copy(&obj));
54 strPtr = 0;
55 freeArray = gTrue;
56 curStr.streamReset();
57}
58
59Lexer::Lexer(XRef *xref, Object *obj) {
60 Object obj2;
61
62 if (obj->isStream()) {
63 streams = new Array(xref);
64 freeArray = gTrue;
65 streams->add(obj->copy(&obj2));
66 } else {
67 streams = obj->getArray();
68 freeArray = gFalse;
69 }
70 strPtr = 0;
71 if (streams->getLength() > 0) {
72 streams->get(strPtr, &curStr);
73 curStr.streamReset();
74 }
75}
76
77Lexer::~Lexer() {
78 if (!curStr.isNone()) {
79 curStr.streamClose();
80 curStr.free();
81 }
82 if (freeArray) {
83 delete streams;
84 }
85}
86
87int Lexer::getChar() {
88 int c;
89
90 c = EOF;
91 while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
92 curStr.streamClose();
93 curStr.free();
94 ++strPtr;
95 if (strPtr < streams->getLength()) {
96 streams->get(strPtr, &curStr);
97 curStr.streamReset();
98 }
99 }
100 return c;
101}
102
103int Lexer::lookChar() {
104 if (curStr.isNone()) {
105 return EOF;
106 }
107 return curStr.streamLookChar();
108}
109
110Object *Lexer::getObj(Object *obj) {
111 char *p;
112 int c, c2;
113 GBool comment, neg, done;
114 int numParen;
115 int xi;
116 fouble xf, scale;
117 GString *s;
118 int n, m;
119
120 // skip whitespace and comments
121 comment = gFalse;
122 while (1) {
123 if ((c = getChar()) == EOF) {
124 return obj->initEOF();
125 }
126 if (comment) {
127 if (c == '\r' || c == '\n')
128 comment = gFalse;
129 } else if (c == '%') {
130 comment = gTrue;
131 } else if (specialChars[c] != 1) {
132 break;
133 }
134 }
135
136 // start reading token
137 switch (c) {
138
139 // number
140 case '0': case '1': case '2': case '3': case '4':
141 case '5': case '6': case '7': case '8': case '9':
142 case '-': case '.':
143 neg = gFalse;
144 xi = 0;
145 if (c == '-') {
146 neg = gTrue;
147 } else if (c == '.') {
148 goto doReal;
149 } else {
150 xi = c - '0';
151 }
152 while (1) {
153 c = lookChar();
154 if (isdigit(c)) {
155 getChar();
156 xi = xi * 10 + (c - '0');
157 } else if (c == '.') {
158 getChar();
159 goto doReal;
160 } else {
161 break;
162 }
163 }
164 if (neg)
165 xi = -xi;
166 obj->initInt(xi);
167 break;
168 doReal:
169 xf = xi;
170 scale = 0.1;
171 while (1) {
172 c = lookChar();
173 if (!isdigit(c)) {
174 break;
175 }
176 getChar();
177 xf = xf + scale * (c - '0');
178 scale *= 0.1;
179 }
180 if (neg)
181 xf = -xf;
182 obj->initReal(xf);
183 break;
184
185 // string
186 case '(':
187 p = tokBuf;
188 n = 0;
189 numParen = 1;
190 done = gFalse;
191 s = NULL;
192 do {
193 c2 = EOF;
194 switch (c = getChar()) {
195
196 case EOF:
197#if 0
198 // This breaks some PDF files, e.g., ones from Photoshop.
199 case '\r':
200 case '\n':
201#endif
202 error(getPos(), "Unterminated string");
203 done = gTrue;
204 break;
205
206 case '(':
207 ++numParen;
208 c2 = c;
209 break;
210
211 case ')':
212 if (--numParen == 0) {
213 done = gTrue;
214 } else {
215 c2 = c;
216 }
217 break;
218
219 case '\\':
220 switch (c = getChar()) {
221 case 'n':
222 c2 = '\n';
223 break;
224 case 'r':
225 c2 = '\r';
226 break;
227 case 't':
228 c2 = '\t';
229 break;
230 case 'b':
231 c2 = '\b';
232 break;
233 case 'f':
234 c2 = '\f';
235 break;
236 case '\\':
237 case '(':
238 case ')':
239 c2 = c;
240 break;
241 case '0': case '1': case '2': case '3':
242 case '4': case '5': case '6': case '7':
243 c2 = c - '0';
244 c = lookChar();
245 if (c >= '0' && c <= '7') {
246 getChar();
247 c2 = (c2 << 3) + (c - '0');
248 c = lookChar();
249 if (c >= '0' && c <= '7') {
250 getChar();
251 c2 = (c2 << 3) + (c - '0');
252 }
253 }
254 break;
255 case '\r':
256 c = lookChar();
257 if (c == '\n') {
258 getChar();
259 }
260 break;
261 case '\n':
262 break;
263 case EOF:
264 error(getPos(), "Unterminated string");
265 done = gTrue;
266 break;
267 default:
268 c2 = c;
269 break;
270 }
271 break;
272
273 default:
274 c2 = c;
275 break;
276 }
277
278 if (c2 != EOF) {
279 if (n == tokBufSize) {
280 if (!s)
281 s = new GString(tokBuf, tokBufSize);
282 else
283 s->append(tokBuf, tokBufSize);
284 p = tokBuf;
285 n = 0;
286 }
287 *p++ = (char)c2;
288 ++n;
289 }
290 } while (!done);
291 if (!s)
292 s = new GString(tokBuf, n);
293 else
294 s->append(tokBuf, n);
295 obj->initString(s);
296 break;
297
298 // name
299 case '/':
300 p = tokBuf;
301 n = 0;
302 while ((c = lookChar()) != EOF && !specialChars[c]) {
303 getChar();
304 if (c == '#') {
305 c2 = lookChar();
306 if (c2 >= '0' && c2 <= '9') {
307 c = c2 - '0';
308 } else if (c2 >= 'A' && c2 <= 'F') {
309 c = c2 - 'A' + 10;
310 } else if (c2 >= 'a' && c2 <= 'f') {
311 c = c2 - 'a' + 10;
312 } else {
313 goto notEscChar;
314 }
315 getChar();
316 c <<= 4;
317 c2 = getChar();
318 if (c2 >= '0' && c2 <= '9') {
319 c += c2 - '0';
320 } else if (c2 >= 'A' && c2 <= 'F') {
321 c += c2 - 'A' + 10;
322 } else if (c2 >= 'a' && c2 <= 'f') {
323 c += c2 - 'a' + 10;
324 } else {
325 error(getPos(), "Illegal digit in hex char in name");
326 }
327 }
328 notEscChar:
329 if (++n == tokBufSize) {
330 error(getPos(), "Name token too long");
331 break;
332 }
333 *p++ = c;
334 }
335 *p = '\0';
336 obj->initName(tokBuf);
337 break;
338
339 // array punctuation
340 case '[':
341 case ']':
342 tokBuf[0] = c;
343 tokBuf[1] = '\0';
344 obj->initCmd(tokBuf);
345 break;
346
347 // hex string or dict punctuation
348 case '<':
349 c = lookChar();
350
351 // dict punctuation
352 if (c == '<') {
353 getChar();
354 tokBuf[0] = tokBuf[1] = '<';
355 tokBuf[2] = '\0';
356 obj->initCmd(tokBuf);
357
358 // hex string
359 } else {
360 p = tokBuf;
361 m = n = 0;
362 c2 = 0;
363 s = NULL;
364 while (1) {
365 c = getChar();
366 if (c == '>') {
367 break;
368 } else if (c == EOF) {
369 error(getPos(), "Unterminated hex string");
370 break;
371 } else if (specialChars[c] != 1) {
372 c2 = c2 << 4;
373 if (c >= '0' && c <= '9')
374 c2 += c - '0';
375 else if (c >= 'A' && c <= 'F')
376 c2 += c - 'A' + 10;
377 else if (c >= 'a' && c <= 'f')
378 c2 += c - 'a' + 10;
379 else
380 error(getPos(), "Illegal character <%02x> in hex string", c);
381 if (++m == 2) {
382 if (n == tokBufSize) {
383 if (!s)
384 s = new GString(tokBuf, tokBufSize);
385 else
386 s->append(tokBuf, tokBufSize);
387 p = tokBuf;
388 n = 0;
389 }
390 *p++ = (char)c2;
391 ++n;
392 c2 = 0;
393 m = 0;
394 }
395 }
396 }
397 if (!s)
398 s = new GString(tokBuf, n);
399 else
400 s->append(tokBuf, n);
401 if (m == 1)
402 s->append((char)(c2 << 4));
403 obj->initString(s);
404 }
405 break;
406
407 // dict punctuation
408 case '>':
409 c = lookChar();
410 if (c == '>') {
411 getChar();
412 tokBuf[0] = tokBuf[1] = '>';
413 tokBuf[2] = '\0';
414 obj->initCmd(tokBuf);
415 } else {
416 error(getPos(), "Illegal character '>'");
417 obj->initError();
418 }
419 break;
420
421 // error
422 case ')':
423 case '{':
424 case '}':
425 error(getPos(), "Illegal character '%c'", c);
426 obj->initError();
427 break;
428
429 // command
430 default:
431 p = tokBuf;
432 *p++ = c;
433 n = 1;
434 while ((c = lookChar()) != EOF && !specialChars[c]) {
435 getChar();
436 if (++n == tokBufSize) {
437 error(getPos(), "Command token too long");
438 break;
439 }
440 *p++ = c;
441 }
442 *p = '\0';
443 if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) {
444 obj->initBool(gTrue);
445 } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) {
446 obj->initBool(gFalse);
447 } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) {
448 obj->initNull();
449 } else {
450 obj->initCmd(tokBuf);
451 }
452 break;
453 }
454
455 return obj;
456}
457
458void Lexer::skipToNextLine() {
459 int c;
460
461 while (1) {
462 c = getChar();
463 if (c == EOF || c == '\n') {
464 return;
465 }
466 if (c == '\r') {
467 if ((c = lookChar()) == '\n') {
468 getChar();
469 }
470 return;
471 }
472 }
473}
diff --git a/noncore/unsupported/qpdf/xpdf/Lexer.h b/noncore/unsupported/qpdf/xpdf/Lexer.h
new file mode 100644
index 0000000..5edbeda
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Lexer.h
@@ -0,0 +1,74 @@
1//========================================================================
2//
3// Lexer.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef LEXER_H
10#define LEXER_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "Object.h"
17#include "Stream.h"
18
19class XRef;
20
21 #define tokBufSize 128 // size of token buffer
22
23//------------------------------------------------------------------------
24// Lexer
25//------------------------------------------------------------------------
26
27class Lexer {
28public:
29
30 // Construct a lexer for a single stream. Deletes the stream when
31 // lexer is deleted.
32 Lexer(XRef *xref, Stream *str);
33
34 // Construct a lexer for a stream or array of streams (assumes obj
35 // is either a stream or array of streams).
36 Lexer(XRef *xref, Object *obj);
37
38 // Destructor.
39 ~Lexer();
40
41 // Get the next object from the input stream.
42 Object *getObj(Object *obj);
43
44 // Skip to the beginning of the next line in the input stream.
45 void skipToNextLine();
46
47 // Skip over one character.
48 void skipChar() { getChar(); }
49
50 // Get stream.
51 Stream *getStream()
52 { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); }
53
54 // Get current position in file.
55 int getPos()
56 { return curStr.isNone() ? -1 : curStr.streamGetPos(); }
57
58 // Set position in file.
59 void setPos(int pos)
60 { if (!curStr.isNone()) curStr.streamSetPos(pos); }
61
62private:
63
64 int getChar();
65 int lookChar();
66
67 Array *streams; // array of input streams
68 int strPtr; // index of current stream
69 Object curStr; // current stream
70 GBool freeArray; // should lexer free the streams array?
71 char tokBuf[tokBufSize];// temporary token buffer
72};
73
74#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Link.cc b/noncore/unsupported/qpdf/xpdf/Link.cc
new file mode 100644
index 0000000..79a5f6e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Link.cc
@@ -0,0 +1,634 @@
1//========================================================================
2//
3// Link.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include <string.h>
16#include "gmem.h"
17#include "GString.h"
18#include "Error.h"
19#include "Object.h"
20#include "Array.h"
21#include "Dict.h"
22#include "Link.h"
23
24//------------------------------------------------------------------------
25
26static GString *getFileSpecName(Object *fileSpecObj);
27
28//------------------------------------------------------------------------
29// LinkDest
30//------------------------------------------------------------------------
31
32LinkDest::LinkDest(Array *a, GBool pageIsRefA) {
33 Object obj1, obj2;
34
35 // initialize fields
36 pageIsRef = pageIsRefA;
37 left = bottom = right = top = zoom = 0;
38 ok = gFalse;
39
40 // get page
41 if (pageIsRef) {
42 if (!a->getNF(0, &obj1)->isRef()) {
43 error(-1, "Bad annotation destination");
44 goto err2;
45 }
46 pageRef.num = obj1.getRefNum();
47 pageRef.gen = obj1.getRefGen();
48 obj1.free();
49 } else {
50 if (!a->get(0, &obj1)->isInt()) {
51 error(-1, "Bad annotation destination");
52 goto err2;
53 }
54 pageNum = obj1.getInt() + 1;
55 obj1.free();
56 }
57
58 // get destination type
59 a->get(1, &obj1);
60
61 // XYZ link
62 if (obj1.isName("XYZ")) {
63 kind = destXYZ;
64 a->get(2, &obj2);
65 if (obj2.isNull()) {
66 changeLeft = gFalse;
67 } else if (obj2.isNum()) {
68 changeLeft = gTrue;
69 left = obj2.getNum();
70 } else {
71 error(-1, "Bad annotation destination position");
72 goto err1;
73 }
74 obj2.free();
75 a->get(3, &obj2);
76 if (obj2.isNull()) {
77 changeTop = gFalse;
78 } else if (obj2.isNum()) {
79 changeTop = gTrue;
80 top = obj2.getNum();
81 } else {
82 error(-1, "Bad annotation destination position");
83 goto err1;
84 }
85 obj2.free();
86 a->get(4, &obj2);
87 if (obj2.isNull()) {
88 changeZoom = gFalse;
89 } else if (obj2.isNum()) {
90 changeZoom = gTrue;
91 zoom = obj2.getNum();
92 } else {
93 error(-1, "Bad annotation destination position");
94 goto err1;
95 }
96 obj2.free();
97
98 // Fit link
99 } else if (obj1.isName("Fit")) {
100 kind = destFit;
101
102 // FitH link
103 } else if (obj1.isName("FitH")) {
104 kind = destFitH;
105 if (!a->get(2, &obj2)->isNum()) {
106 error(-1, "Bad annotation destination position");
107 goto err1;
108 }
109 top = obj2.getNum();
110 obj2.free();
111
112 // FitV link
113 } else if (obj1.isName("FitV")) {
114 kind = destFitV;
115 if (!a->get(2, &obj2)->isNum()) {
116 error(-1, "Bad annotation destination position");
117 goto err1;
118 }
119 left = obj2.getNum();
120 obj2.free();
121
122 // FitR link
123 } else if (obj1.isName("FitR")) {
124 kind = destFitR;
125 if (!a->get(2, &obj2)->isNum()) {
126 error(-1, "Bad annotation destination position");
127 goto err1;
128 }
129 left = obj2.getNum();
130 obj2.free();
131 if (!a->get(3, &obj2)->isNum()) {
132 error(-1, "Bad annotation destination position");
133 goto err1;
134 }
135 bottom = obj2.getNum();
136 obj2.free();
137 if (!a->get(4, &obj2)->isNum()) {
138 error(-1, "Bad annotation destination position");
139 goto err1;
140 }
141 right = obj2.getNum();
142 obj2.free();
143 if (!a->get(5, &obj2)->isNum()) {
144 error(-1, "Bad annotation destination position");
145 goto err1;
146 }
147 top = obj2.getNum();
148 obj2.free();
149
150 // FitB link
151 } else if (obj1.isName("FitB")) {
152 kind = destFitB;
153
154 // FitBH link
155 } else if (obj1.isName("FitBH")) {
156 kind = destFitBH;
157 if (!a->get(2, &obj2)->isNum()) {
158 error(-1, "Bad annotation destination position");
159 goto err1;
160 }
161 top = obj2.getNum();
162 obj2.free();
163
164 // FitBV link
165 } else if (obj1.isName("FitBV")) {
166 kind = destFitBV;
167 if (!a->get(2, &obj2)->isNum()) {
168 error(-1, "Bad annotation destination position");
169 goto err1;
170 }
171 left = obj2.getNum();
172 obj2.free();
173
174 // unknown link kind
175 } else {
176 error(-1, "Unknown annotation destination type");
177 goto err2;
178 }
179
180 obj1.free();
181 ok = gTrue;
182 return;
183
184 err1:
185 obj2.free();
186 err2:
187 obj1.free();
188}
189
190LinkDest::LinkDest(LinkDest *dest) {
191 kind = dest->kind;
192 pageIsRef = dest->pageIsRef;
193 if (pageIsRef)
194 pageRef = dest->pageRef;
195 else
196 pageNum = dest->pageNum;
197 left = dest->left;
198 bottom = dest->bottom;
199 right = dest->right;
200 top = dest->top;
201 zoom = dest->zoom;
202 changeLeft = dest->changeLeft;
203 changeTop = dest->changeTop;
204 changeZoom = dest->changeZoom;
205 ok = gTrue;
206}
207
208//------------------------------------------------------------------------
209// LinkGoTo
210//------------------------------------------------------------------------
211
212LinkGoTo::LinkGoTo(Object *destObj) {
213 dest = NULL;
214 namedDest = NULL;
215
216 // named destination
217 if (destObj->isName()) {
218 namedDest = new GString(destObj->getName());
219 } else if (destObj->isString()) {
220 namedDest = destObj->getString()->copy();
221
222 // destination dictionary
223 } else if (destObj->isArray()) {
224 dest = new LinkDest(destObj->getArray(), gTrue);
225 if (!dest->isOk()) {
226 delete dest;
227 dest = NULL;
228 }
229
230 // error
231 } else {
232 error(-1, "Illegal annotation destination");
233 }
234}
235
236LinkGoTo::~LinkGoTo() {
237 if (dest)
238 delete dest;
239 if (namedDest)
240 delete namedDest;
241}
242
243//------------------------------------------------------------------------
244// LinkGoToR
245//------------------------------------------------------------------------
246
247LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
248 dest = NULL;
249 namedDest = NULL;
250
251 // get file name
252 fileName = getFileSpecName(fileSpecObj);
253
254 // named destination
255 if (destObj->isName()) {
256 namedDest = new GString(destObj->getName());
257 } else if (destObj->isString()) {
258 namedDest = destObj->getString()->copy();
259
260 // destination dictionary
261 } else if (destObj->isArray()) {
262 dest = new LinkDest(destObj->getArray(), gFalse);
263 if (!dest->isOk()) {
264 delete dest;
265 dest = NULL;
266 }
267
268 // error
269 } else {
270 error(-1, "Illegal annotation destination");
271 }
272}
273
274LinkGoToR::~LinkGoToR() {
275 if (fileName)
276 delete fileName;
277 if (dest)
278 delete dest;
279 if (namedDest)
280 delete namedDest;
281}
282
283
284//------------------------------------------------------------------------
285// LinkLaunch
286//------------------------------------------------------------------------
287
288LinkLaunch::LinkLaunch(Object *actionObj) {
289 Object obj1, obj2;
290
291 fileName = NULL;
292 params = NULL;
293
294 if (actionObj->isDict()) {
295 if (!actionObj->dictLookup("F", &obj1)->isNull()) {
296 fileName = getFileSpecName(&obj1);
297 } else {
298 obj1.free();
299 //~ This hasn't been defined by Adobe yet, so assume it looks
300 //~ just like the Win dictionary until they say otherwise.
301 if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
302 obj1.dictLookup("F", &obj2);
303 fileName = getFileSpecName(&obj2);
304 obj2.free();
305 if (obj1.dictLookup("P", &obj2)->isString())
306 params = obj2.getString()->copy();
307 obj2.free();
308 } else {
309 error(-1, "Bad launch-type link action");
310 }
311 }
312 obj1.free();
313 }
314}
315
316LinkLaunch::~LinkLaunch() {
317 if (fileName)
318 delete fileName;
319 if (params)
320 delete params;
321}
322
323//------------------------------------------------------------------------
324// LinkURI
325//------------------------------------------------------------------------
326
327LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
328 GString *uri2;
329 int n;
330 char c;
331
332 uri = NULL;
333 if (uriObj->isString()) {
334 uri2 = uriObj->getString()->copy();
335 if (baseURI) {
336 n = strcspn(uri2->getCString(), "/:");
337 if (n == uri2->getLength() || uri2->getChar(n) == '/') {
338 uri = baseURI->copy();
339 c = uri->getChar(uri->getLength() - 1);
340 if (c == '/' || c == '?') {
341 if (uri2->getChar(0) == '/') {
342 uri2->del(0);
343 }
344 } else {
345 if (uri2->getChar(0) != '/') {
346 uri->append('/');
347 }
348 }
349 uri->append(uri2);
350 delete uri2;
351 } else {
352 uri = uri2;
353 }
354 } else {
355 uri = uri2;
356 }
357 } else {
358 error(-1, "Illegal URI-type link");
359 }
360}
361
362LinkURI::~LinkURI() {
363 if (uri)
364 delete uri;
365}
366
367//------------------------------------------------------------------------
368// LinkNamed
369//------------------------------------------------------------------------
370
371LinkNamed::LinkNamed(Object *nameObj) {
372 name = NULL;
373 if (nameObj->isName()) {
374 name = new GString(nameObj->getName());
375 }
376}
377
378LinkNamed::~LinkNamed() {
379 if (name) {
380 delete name;
381 }
382}
383
384//------------------------------------------------------------------------
385// LinkUnknown
386//------------------------------------------------------------------------
387
388LinkUnknown::LinkUnknown(char *actionA) {
389 action = new GString(actionA);
390}
391
392LinkUnknown::~LinkUnknown() {
393 delete action;
394}
395
396//------------------------------------------------------------------------
397// Link
398//------------------------------------------------------------------------
399
400Link::Link(Dict *dict, GString *baseURI) {
401 Object obj1, obj2, obj3, obj4;
402 fouble t;
403
404 action = NULL;
405 ok = gFalse;
406
407 // get rectangle
408 if (!dict->lookup("Rect", &obj1)->isArray()) {
409 error(-1, "Annotation rectangle is wrong type");
410 goto err2;
411 }
412 if (!obj1.arrayGet(0, &obj2)->isNum()) {
413 error(-1, "Bad annotation rectangle");
414 goto err1;
415 }
416 x1 = obj2.getNum();
417 obj2.free();
418 if (!obj1.arrayGet(1, &obj2)->isNum()) {
419 error(-1, "Bad annotation rectangle");
420 goto err1;
421 }
422 y1 = obj2.getNum();
423 obj2.free();
424 if (!obj1.arrayGet(2, &obj2)->isNum()) {
425 error(-1, "Bad annotation rectangle");
426 goto err1;
427 }
428 x2 = obj2.getNum();
429 obj2.free();
430 if (!obj1.arrayGet(3, &obj2)->isNum()) {
431 error(-1, "Bad annotation rectangle");
432 goto err1;
433 }
434 y2 = obj2.getNum();
435 obj2.free();
436 obj1.free();
437 if (x1 > x2) {
438 t = x1;
439 x1 = x2;
440 x2 = t;
441 }
442 if (y1 > y2) {
443 t = y1;
444 y1 = y2;
445 y2 = t;
446 }
447
448 // get border
449 borderW = 0;
450 if (!dict->lookup("Border", &obj1)->isNull()) {
451 if (obj1.isArray() && obj1.arrayGetLength() >= 3) {
452 if (obj1.arrayGet(2, &obj2)->isNum()) {
453 borderW = obj2.getNum();
454 } else {
455 error(-1, "Bad annotation border");
456 }
457 obj2.free();
458 }
459 }
460 obj1.free();
461
462 // look for destination
463 if (!dict->lookup("Dest", &obj1)->isNull()) {
464 action = new LinkGoTo(&obj1);
465
466 // look for action
467 } else {
468 obj1.free();
469 if (dict->lookup("A", &obj1)->isDict()) {
470 obj1.dictLookup("S", &obj2);
471
472 // GoTo action
473 if (obj2.isName("GoTo")) {
474 obj1.dictLookup("D", &obj3);
475 action = new LinkGoTo(&obj3);
476 obj3.free();
477
478 // GoToR action
479 } else if (obj2.isName("GoToR")) {
480 obj1.dictLookup("F", &obj3);
481 obj1.dictLookup("D", &obj4);
482 action = new LinkGoToR(&obj3, &obj4);
483 obj3.free();
484 obj4.free();
485
486 // Launch action
487 } else if (obj2.isName("Launch")) {
488 action = new LinkLaunch(&obj1);
489
490 // URI action
491 } else if (obj2.isName("URI")) {
492 obj1.dictLookup("URI", &obj3);
493 action = new LinkURI(&obj3, baseURI);
494 obj3.free();
495
496 // Named action
497 } else if (obj2.isName("Named")) {
498 obj1.dictLookup("N", &obj3);
499 action = new LinkNamed(&obj3);
500 obj3.free();
501
502 // unknown action
503 } else if (obj2.isName()) {
504 action = new LinkUnknown(obj2.getName());
505
506 // action is missing or wrong type
507 } else {
508 error(-1, "Bad annotation action");
509 action = NULL;
510 }
511
512 obj2.free();
513
514 } else {
515 error(-1, "Missing annotation destination/action");
516 action = NULL;
517 }
518 }
519 obj1.free();
520
521 // check for bad action
522 if (action && action->isOk())
523 ok = gTrue;
524
525 return;
526
527 err1:
528 obj2.free();
529 err2:
530 obj1.free();
531}
532
533Link::~Link() {
534 if (action)
535 delete action;
536}
537
538//------------------------------------------------------------------------
539// Links
540//------------------------------------------------------------------------
541
542Links::Links(Object *annots, GString *baseURI) {
543 Link *link;
544 Object obj1, obj2;
545 int size;
546 int i;
547
548 links = NULL;
549 size = 0;
550 numLinks = 0;
551
552 if (annots->isArray()) {
553 for (i = 0; i < annots->arrayGetLength(); ++i) {
554 if (annots->arrayGet(i, &obj1)->isDict()) {
555 if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
556 link = new Link(obj1.getDict(), baseURI);
557 if (link->isOk()) {
558 if (numLinks >= size) {
559 size += 16;
560 links = (Link **)grealloc(links, size * sizeof(Link *));
561 }
562 links[numLinks++] = link;
563 } else {
564 delete link;
565 }
566 }
567 obj2.free();
568 }
569 obj1.free();
570 }
571 }
572}
573
574Links::~Links() {
575 int i;
576
577 for (i = 0; i < numLinks; ++i)
578 delete links[i];
579 gfree(links);
580}
581
582LinkAction *Links::find(fouble x, fouble y) {
583 int i;
584
585 for (i = 0; i < numLinks; ++i) {
586 if (links[i]->inRect(x, y)) {
587 return links[i]->getAction();
588 }
589 }
590 return NULL;
591}
592
593GBool Links::onLink(fouble x, fouble y) {
594 int i;
595
596 for (i = 0; i < numLinks; ++i) {
597 if (links[i]->inRect(x, y))
598 return gTrue;
599 }
600 return gFalse;
601}
602
603//------------------------------------------------------------------------
604
605// Extract a file name from a file specification (string or dictionary).
606static GString *getFileSpecName(Object *fileSpecObj) {
607 GString *name;
608 Object obj1;
609
610 name = NULL;
611
612 // string
613 if (fileSpecObj->isString()) {
614 name = fileSpecObj->getString()->copy();
615
616 // dictionary
617 } else if (fileSpecObj->isDict()) {
618 if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
619 obj1.free();
620 fileSpecObj->dictLookup("F", &obj1);
621 }
622 if (obj1.isString())
623 name = obj1.getString()->copy();
624 else
625 error(-1, "Illegal file spec in link");
626 obj1.free();
627
628 // error
629 } else {
630 error(-1, "Illegal file spec in link");
631 }
632
633 return name;
634}
diff --git a/noncore/unsupported/qpdf/xpdf/Link.h b/noncore/unsupported/qpdf/xpdf/Link.h
new file mode 100644
index 0000000..0ad4581
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Link.h
@@ -0,0 +1,336 @@
1//========================================================================
2//
3// Link.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef LINK_H
10#define LINK_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "Object.h"
17
18class GString;
19class Array;
20class Dict;
21
22//------------------------------------------------------------------------
23// LinkAction
24//------------------------------------------------------------------------
25
26enum LinkActionKind {
27 actionGoTo, // go to destination
28 actionGoToR, // go to destination in new file
29 actionLaunch, // launch app (or open document)
30 actionURI, // URI
31 actionNamed, // named action
32 actionUnknown // anything else
33};
34
35class LinkAction {
36public:
37
38 // Destructor.
39 virtual ~LinkAction() {}
40
41 // Was the LinkAction created successfully?
42 virtual GBool isOk() = 0;
43
44 // Check link action type.
45 virtual LinkActionKind getKind() = 0;
46};
47
48//------------------------------------------------------------------------
49// LinkDest
50//------------------------------------------------------------------------
51
52enum LinkDestKind {
53 destXYZ,
54 destFit,
55 destFitH,
56 destFitV,
57 destFitR,
58 destFitB,
59 destFitBH,
60 destFitBV
61};
62
63class LinkDest {
64public:
65
66 // Build a LinkDest from the array. If <pageIsRef> is true, the
67 // page is specified by an object reference; otherwise the page is
68 // specified by a (zero-relative) page number.
69 LinkDest(Array *a, GBool pageIsRef1);
70
71 // Copy a LinkDest.
72 LinkDest *copy() { return new LinkDest(this); }
73
74 // Was the LinkDest created successfully?
75 GBool isOk() { return ok; }
76
77 // Accessors.
78 LinkDestKind getKind() { return kind; }
79 GBool isPageRef() { return pageIsRef; }
80 int getPageNum() { return pageNum; }
81 Ref getPageRef() { return pageRef; }
82 fouble getLeft() { return left; }
83 fouble getBottom() { return bottom; }
84 fouble getRight() { return right; }
85 fouble getTop() { return top; }
86 fouble getZoom() { return zoom; }
87 GBool getChangeLeft() { return changeLeft; }
88 GBool getChangeTop() { return changeTop; }
89 GBool getChangeZoom() { return changeZoom; }
90
91private:
92
93 LinkDestKind kind; // destination type
94 GBool pageIsRef; // is the page a reference or number?
95 union {
96 Ref pageRef; // reference to page
97 int pageNum; // one-relative page number
98 };
99 fouble left, bottom; // position
100 fouble right, top;
101 fouble zoom; // zoom factor
102 GBool changeLeft, changeTop;// for destXYZ links, which position
103 GBool changeZoom; // components to change
104 GBool ok; // set if created successfully
105
106 LinkDest(LinkDest *dest);
107};
108
109//------------------------------------------------------------------------
110// LinkGoTo
111//------------------------------------------------------------------------
112
113class LinkGoTo: public LinkAction {
114public:
115
116 // Build a LinkGoTo from a destination (dictionary, name, or string).
117 LinkGoTo(Object *destObj);
118
119 // Destructor.
120 virtual ~LinkGoTo();
121
122 // Was the LinkGoTo created successfully?
123 virtual GBool isOk() { return dest || namedDest; }
124
125 // Accessors.
126 virtual LinkActionKind getKind() { return actionGoTo; }
127 LinkDest *getDest() { return dest; }
128 GString *getNamedDest() { return namedDest; }
129
130private:
131
132 LinkDest *dest; // regular destination (NULL for remote
133 // link with bad destination)
134 GString *namedDest; // named destination (only one of dest and
135 // and namedDest may be non-NULL)
136};
137
138//------------------------------------------------------------------------
139// LinkGoToR
140//------------------------------------------------------------------------
141
142class LinkGoToR: public LinkAction {
143public:
144
145 // Build a LinkGoToR from a file spec (dictionary) and destination
146 // (dictionary, name, or string).
147 LinkGoToR(Object *fileSpecObj, Object *destObj);
148
149 // Destructor.
150 virtual ~LinkGoToR();
151
152 // Was the LinkGoToR created successfully?
153 virtual GBool isOk() { return fileName && (dest || namedDest); }
154
155 // Accessors.
156 virtual LinkActionKind getKind() { return actionGoToR; }
157 GString *getFileName() { return fileName; }
158 LinkDest *getDest() { return dest; }
159 GString *getNamedDest() { return namedDest; }
160
161private:
162
163 GString *fileName; // file name
164 LinkDest *dest; // regular destination (NULL for remote
165 // link with bad destination)
166 GString *namedDest; // named destination (only one of dest and
167 // and namedDest may be non-NULL)
168};
169
170//------------------------------------------------------------------------
171// LinkLaunch
172//------------------------------------------------------------------------
173
174class LinkLaunch: public LinkAction {
175public:
176
177 // Build a LinkLaunch from an action dictionary.
178 LinkLaunch(Object *actionObj);
179
180 // Destructor.
181 virtual ~LinkLaunch();
182
183 // Was the LinkLaunch created successfully?
184 virtual GBool isOk() { return fileName != NULL; }
185
186 // Accessors.
187 virtual LinkActionKind getKind() { return actionLaunch; }
188 GString *getFileName() { return fileName; }
189 GString *getParams() { return params; }
190
191private:
192
193 GString *fileName; // file name
194 GString *params; // parameters
195};
196
197//------------------------------------------------------------------------
198// LinkURI
199//------------------------------------------------------------------------
200
201class LinkURI: public LinkAction {
202public:
203
204 // Build a LinkURI given the URI (string) and base URI.
205 LinkURI(Object *uriObj, GString *baseURI);
206
207 // Destructor.
208 virtual ~LinkURI();
209
210 // Was the LinkURI created successfully?
211 virtual GBool isOk() { return uri != NULL; }
212
213 // Accessors.
214 virtual LinkActionKind getKind() { return actionURI; }
215 GString *getURI() { return uri; }
216
217private:
218
219 GString *uri; // the URI
220};
221
222//------------------------------------------------------------------------
223// LinkNamed
224//------------------------------------------------------------------------
225
226class LinkNamed: public LinkAction {
227public:
228
229 // Build a LinkNamed given the action name.
230 LinkNamed(Object *nameObj);
231
232 virtual ~LinkNamed();
233
234 virtual GBool isOk() { return name != NULL; }
235
236 virtual LinkActionKind getKind() { return actionNamed; }
237 GString *getName() { return name; }
238
239private:
240
241 GString *name;
242};
243
244//------------------------------------------------------------------------
245// LinkUnknown
246//------------------------------------------------------------------------
247
248class LinkUnknown: public LinkAction {
249public:
250
251 // Build a LinkUnknown with the specified action type.
252 LinkUnknown(char *actionA);
253
254 // Destructor.
255 virtual ~LinkUnknown();
256
257 // Was the LinkUnknown create successfully?
258 virtual GBool isOk() { return action != NULL; }
259
260 // Accessors.
261 virtual LinkActionKind getKind() { return actionUnknown; }
262 GString *getAction() { return action; }
263
264private:
265
266 GString *action; // action subtype
267};
268
269//------------------------------------------------------------------------
270// Link
271//------------------------------------------------------------------------
272
273class Link {
274public:
275
276 // Construct a link, given its dictionary.
277 Link(Dict *dict, GString *baseURI);
278
279 // Destructor.
280 ~Link();
281
282 // Was the link created successfully?
283 GBool isOk() { return ok; }
284
285 // Check if point is inside the link rectangle.
286 GBool inRect(fouble x, fouble y)
287 { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
288
289 // Get action.
290 LinkAction *getAction() { return action; }
291
292 // Get border corners and width.
293 void getBorder(fouble *xa1, fouble *ya1, fouble *xa2, fouble *ya2,
294 fouble *wa)
295 { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; *wa = borderW; }
296
297private:
298
299 fouble x1, y1; // lower left corner
300 fouble x2, y2; // upper right corner
301 fouble borderW; // border width
302 LinkAction *action; // action
303 GBool ok; // is link valid?
304};
305
306//------------------------------------------------------------------------
307// Links
308//------------------------------------------------------------------------
309
310class Links {
311public:
312
313 // Extract links from array of annotations.
314 Links(Object *annots, GString *baseURI);
315
316 // Destructor.
317 ~Links();
318
319 // Iterate through list of links.
320 int getNumLinks() { return numLinks; }
321 Link *getLink(int i) { return links[i]; }
322
323 // If point <x>,<y> is in a link, return the associated action;
324 // else return NULL.
325 LinkAction *find(fouble x, fouble y);
326
327 // Return true if <x>,<y> is in a link.
328 GBool onLink(fouble x, fouble y);
329
330private:
331
332 Link **links;
333 int numLinks;
334};
335
336#endif
diff --git a/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc b/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc
new file mode 100644
index 0000000..06be2f4
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc
@@ -0,0 +1,115 @@
1//========================================================================
2//
3// NameToCharCode.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <string.h>
15#include "gmem.h"
16#include "NameToCharCode.h"
17
18//------------------------------------------------------------------------
19
20struct NameToCharCodeEntry {
21 char *name;
22 CharCode c;
23};
24
25//------------------------------------------------------------------------
26
27NameToCharCode::NameToCharCode() {
28 int i;
29
30 size = 31;
31 len = 0;
32 tab = (NameToCharCodeEntry *)gmalloc(size * sizeof(NameToCharCodeEntry));
33 for (i = 0; i < size; ++i) {
34 tab[i].name = NULL;
35 }
36}
37
38NameToCharCode::~NameToCharCode() {
39 int i;
40
41 for (i = 0; i < size; ++i) {
42 if (tab[i].name) {
43 gfree(tab[i].name);
44 }
45 }
46 gfree(tab);
47}
48
49void NameToCharCode::add(char *name, CharCode c) {
50 NameToCharCodeEntry *oldTab;
51 int h, i, oldSize;
52
53 // expand the table if necessary
54 if (len >= size / 2) {
55 oldSize = size;
56 oldTab = tab;
57 size = 2*size + 1;
58 tab = (NameToCharCodeEntry *)gmalloc(size * sizeof(NameToCharCodeEntry));
59 for (h = 0; h < size; ++h) {
60 tab[h].name = NULL;
61 }
62 for (i = 0; i < oldSize; ++i) {
63 if (oldTab[i].name) {
64 h = hash(oldTab[i].name);
65 while (tab[h].name) {
66 if (++h == size) {
67 h = 0;
68 }
69 }
70 tab[h] = oldTab[i];
71 }
72 }
73 gfree(oldTab);
74 }
75
76 // add the new name
77 h = hash(name);
78 while (tab[h].name && strcmp(tab[h].name, name)) {
79 if (++h == size) {
80 h = 0;
81 }
82 }
83 if (!tab[h].name) {
84 tab[h].name = copyString(name);
85 }
86 tab[h].c = c;
87
88 ++len;
89}
90
91CharCode NameToCharCode::lookup(char *name) {
92 int h;
93
94 h = hash(name);
95 while (tab[h].name) {
96 if (!strcmp(tab[h].name, name)) {
97 return tab[h].c;
98 }
99 if (++h == size) {
100 h = 0;
101 }
102 }
103 return 0;
104}
105
106int NameToCharCode::hash(char *name) {
107 char *p;
108 unsigned int h;
109
110 h = 0;
111 for (p = name; *p; ++p) {
112 h = 17 * h + (int)(*p & 0xff);
113 }
114 return (int)(h % size);
115}
diff --git a/noncore/unsupported/qpdf/xpdf/NameToCharCode.h b/noncore/unsupported/qpdf/xpdf/NameToCharCode.h
new file mode 100644
index 0000000..9f9b1c3
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/NameToCharCode.h
@@ -0,0 +1,40 @@
1//========================================================================
2//
3// NameToCharCode.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef NAMETOCHARCODE_H
10#define NAMETOCHARCODE_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "CharTypes.h"
17
18struct NameToCharCodeEntry;
19
20//------------------------------------------------------------------------
21
22class NameToCharCode {
23public:
24
25 NameToCharCode();
26 ~NameToCharCode();
27
28 void add(char *name, CharCode c);
29 CharCode lookup(char *name);
30
31private:
32
33 int hash(char *name);
34
35 NameToCharCodeEntry *tab;
36 int size;
37 int len;
38};
39
40#endif
diff --git a/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h b/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h
new file mode 100644
index 0000000..7ca635e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h
@@ -0,0 +1,1055 @@
1//========================================================================
2//
3// NameToUnicodeTable.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9static struct {
10 Unicode u;
11 char *name;
12} nameToUnicodeTab[] = {
13 {0x0041, "A"},
14 {0x00c6, "AE"},
15 {0x01fc, "AEacute"},
16 {0x00c6, "AEsmall"},
17 {0x00c1, "Aacute"},
18 {0x00c1, "Aacutesmall"},
19 {0x0102, "Abreve"},
20 {0x00c2, "Acircumflex"},
21 {0x00c2, "Acircumflexsmall"},
22 {0xf6c9, "Acute"},
23 {0xf6c9, "Acutesmall"},
24 {0x00c4, "Adieresis"},
25 {0x00c4, "Adieresissmall"},
26 {0x00c0, "Agrave"},
27 {0x00c0, "Agravesmall"},
28 {0x0391, "Alpha"},
29 {0x0386, "Alphatonos"},
30 {0x0100, "Amacron"},
31 {0x0104, "Aogonek"},
32 {0x00c5, "Aring"},
33 {0x01fa, "Aringacute"},
34 {0x00c5, "Aringsmall"},
35 {0x0041, "Asmall"},
36 {0x00c3, "Atilde"},
37 {0x00c3, "Atildesmall"},
38 {0x0042, "B"},
39 {0x0392, "Beta"},
40 {0xf6f4, "Brevesmall"},
41 {0x0042, "Bsmall"},
42 {0x0043, "C"},
43 {0x0106, "Cacute"},
44 {0xf6ca, "Caron"},
45 {0xf6ca, "Caronsmall"},
46 {0x010c, "Ccaron"},
47 {0x00c7, "Ccedilla"},
48 {0x00c7, "Ccedillasmall"},
49 {0x0108, "Ccircumflex"},
50 {0x010a, "Cdotaccent"},
51 {0xf7b8, "Cedillasmall"},
52 {0x03a7, "Chi"},
53 {0xf6f6, "Circumflexsmall"},
54 {0x0043, "Csmall"},
55 {0x0044, "D"},
56 {0x010e, "Dcaron"},
57 {0x0110, "Dcroat"},
58 {0x2206, "Delta"},
59 {0xf6cb, "Dieresis"},
60 {0xf6cc, "DieresisAcute"},
61 {0xf6cd, "DieresisGrave"},
62 {0xf6cb, "Dieresissmall"},
63 {0xf6f7, "Dotaccentsmall"},
64 {0x0044, "Dsmall"},
65 {0x0045, "E"},
66 {0x00c9, "Eacute"},
67 {0x00c9, "Eacutesmall"},
68 {0x0114, "Ebreve"},
69 {0x011a, "Ecaron"},
70 {0x00ca, "Ecircumflex"},
71 {0x00ca, "Ecircumflexsmall"},
72 {0x00cb, "Edieresis"},
73 {0x00cb, "Edieresissmall"},
74 {0x0116, "Edotaccent"},
75 {0x00c8, "Egrave"},
76 {0x00c8, "Egravesmall"},
77 {0x0112, "Emacron"},
78 {0x014a, "Eng"},
79 {0x0118, "Eogonek"},
80 {0x0395, "Epsilon"},
81 {0x0388, "Epsilontonos"},
82 {0x0045, "Esmall"},
83 {0x0397, "Eta"},
84 {0x0389, "Etatonos"},
85 {0x00d0, "Eth"},
86 {0x00d0, "Ethsmall"},
87 {0x20ac, "Euro"},
88 {0x0046, "F"},
89 {0x0046, "Fsmall"},
90 {0x0047, "G"},
91 {0x0393, "Gamma"},
92 {0x011e, "Gbreve"},
93 {0x01e6, "Gcaron"},
94 {0x011c, "Gcircumflex"},
95 {0x0122, "Gcommaaccent"},
96 {0x0120, "Gdotaccent"},
97 {0xf6ce, "Grave"},
98 {0xf6ce, "Gravesmall"},
99 {0x0047, "Gsmall"},
100 {0x0048, "H"},
101 {0x25cf, "H18533"},
102 {0x25aa, "H18543"},
103 {0x25ab, "H18551"},
104 {0x25a1, "H22073"},
105 {0x0126, "Hbar"},
106 {0x0124, "Hcircumflex"},
107 {0x0048, "Hsmall"},
108 {0xf6cf, "Hungarumlaut"},
109 {0xf6cf, "Hungarumlautsmall"},
110 {0x0049, "I"},
111 {0x0132, "IJ"},
112 {0x00cd, "Iacute"},
113 {0x00cd, "Iacutesmall"},
114 {0x012c, "Ibreve"},
115 {0x00ce, "Icircumflex"},
116 {0x00ce, "Icircumflexsmall"},
117 {0x00cf, "Idieresis"},
118 {0x00cf, "Idieresissmall"},
119 {0x0130, "Idotaccent"},
120 {0x2111, "Ifraktur"},
121 {0x00cc, "Igrave"},
122 {0x00cc, "Igravesmall"},
123 {0x012a, "Imacron"},
124 {0x012e, "Iogonek"},
125 {0x0399, "Iota"},
126 {0x03aa, "Iotadieresis"},
127 {0x038a, "Iotatonos"},
128 {0x0049, "Ismall"},
129 {0x0128, "Itilde"},
130 {0x004a, "J"},
131 {0x0134, "Jcircumflex"},
132 {0x004a, "Jsmall"},
133 {0x004b, "K"},
134 {0x039a, "Kappa"},
135 {0x0136, "Kcommaaccent"},
136 {0x004b, "Ksmall"},
137 {0x004c, "L"},
138 {0xf6bf, "LL"},
139 {0x0139, "Lacute"},
140 {0x039b, "Lambda"},
141 {0x013d, "Lcaron"},
142 {0x013b, "Lcommaaccent"},
143 {0x013f, "Ldot"},
144 {0x0141, "Lslash"},
145 {0x0141, "Lslashsmall"},
146 {0x004c, "Lsmall"},
147 {0x004d, "M"},
148 {0xf6d0, "Macron"},
149 {0xf6d0, "Macronsmall"},
150 {0x004d, "Msmall"},
151 {0x039c, "Mu"},
152 {0x004e, "N"},
153 {0x0143, "Nacute"},
154 {0x0147, "Ncaron"},
155 {0x0145, "Ncommaaccent"},
156 {0x004e, "Nsmall"},
157 {0x00d1, "Ntilde"},
158 {0x00d1, "Ntildesmall"},
159 {0x039d, "Nu"},
160 {0x004f, "O"},
161 {0x0152, "OE"},
162 {0x0152, "OEsmall"},
163 {0x00d3, "Oacute"},
164 {0x00d3, "Oacutesmall"},
165 {0x014e, "Obreve"},
166 {0x00d4, "Ocircumflex"},
167 {0x00d4, "Ocircumflexsmall"},
168 {0x00d6, "Odieresis"},
169 {0x00d6, "Odieresissmall"},
170 {0xf6fb, "Ogoneksmall"},
171 {0x00d2, "Ograve"},
172 {0x00d2, "Ogravesmall"},
173 {0x01a0, "Ohorn"},
174 {0x0150, "Ohungarumlaut"},
175 {0x014c, "Omacron"},
176 {0x2126, "Omega"},
177 {0x038f, "Omegatonos"},
178 {0x039f, "Omicron"},
179 {0x038c, "Omicrontonos"},
180 {0x00d8, "Oslash"},
181 {0x01fe, "Oslashacute"},
182 {0x00d8, "Oslashsmall"},
183 {0x004f, "Osmall"},
184 {0x00d5, "Otilde"},
185 {0x00d5, "Otildesmall"},
186 {0x0050, "P"},
187 {0x03a6, "Phi"},
188 {0x03a0, "Pi"},
189 {0x03a8, "Psi"},
190 {0x0050, "Psmall"},
191 {0x0051, "Q"},
192 {0x0051, "Qsmall"},
193 {0x0052, "R"},
194 {0x0154, "Racute"},
195 {0x0158, "Rcaron"},
196 {0x0156, "Rcommaaccent"},
197 {0x211c, "Rfraktur"},
198 {0x03a1, "Rho"},
199 {0xf6fc, "Ringsmall"},
200 {0x0052, "Rsmall"},
201 {0x0053, "S"},
202 {0x250c, "SF010000"},
203 {0x2514, "SF020000"},
204 {0x2510, "SF030000"},
205 {0x2518, "SF040000"},
206 {0x253c, "SF050000"},
207 {0x252c, "SF060000"},
208 {0x2534, "SF070000"},
209 {0x251c, "SF080000"},
210 {0x2524, "SF090000"},
211 {0x2500, "SF100000"},
212 {0x2502, "SF110000"},
213 {0x2561, "SF190000"},
214 {0x2562, "SF200000"},
215 {0x2556, "SF210000"},
216 {0x2555, "SF220000"},
217 {0x2563, "SF230000"},
218 {0x2551, "SF240000"},
219 {0x2557, "SF250000"},
220 {0x255d, "SF260000"},
221 {0x255c, "SF270000"},
222 {0x255b, "SF280000"},
223 {0x255e, "SF360000"},
224 {0x255f, "SF370000"},
225 {0x255a, "SF380000"},
226 {0x2554, "SF390000"},
227 {0x2569, "SF400000"},
228 {0x2566, "SF410000"},
229 {0x2560, "SF420000"},
230 {0x2550, "SF430000"},
231 {0x256c, "SF440000"},
232 {0x2567, "SF450000"},
233 {0x2568, "SF460000"},
234 {0x2564, "SF470000"},
235 {0x2565, "SF480000"},
236 {0x2559, "SF490000"},
237 {0x2558, "SF500000"},
238 {0x2552, "SF510000"},
239 {0x2553, "SF520000"},
240 {0x256b, "SF530000"},
241 {0x256a, "SF540000"},
242 {0x015a, "Sacute"},
243 {0x0160, "Scaron"},
244 {0x0160, "Scaronsmall"},
245 {0x015e, "Scedilla"},
246 {0x015c, "Scircumflex"},
247 {0x0218, "Scommaaccent"},
248 {0x03a3, "Sigma"},
249 {0x0053, "Ssmall"},
250 {0x0054, "T"},
251 {0x03a4, "Tau"},
252 {0x0166, "Tbar"},
253 {0x0164, "Tcaron"},
254 {0x0162, "Tcommaaccent"},
255 {0x0398, "Theta"},
256 {0x00de, "Thorn"},
257 {0x00de, "Thornsmall"},
258 {0xf6fe, "Tildesmall"},
259 {0x0054, "Tsmall"},
260 {0x0055, "U"},
261 {0x00da, "Uacute"},
262 {0x00da, "Uacutesmall"},
263 {0x016c, "Ubreve"},
264 {0x00db, "Ucircumflex"},
265 {0x00db, "Ucircumflexsmall"},
266 {0x00dc, "Udieresis"},
267 {0x00dc, "Udieresissmall"},
268 {0x00d9, "Ugrave"},
269 {0x00d9, "Ugravesmall"},
270 {0x01af, "Uhorn"},
271 {0x0170, "Uhungarumlaut"},
272 {0x016a, "Umacron"},
273 {0x0172, "Uogonek"},
274 {0x03a5, "Upsilon"},
275 {0x03d2, "Upsilon1"},
276 {0x03ab, "Upsilondieresis"},
277 {0x038e, "Upsilontonos"},
278 {0x016e, "Uring"},
279 {0x0055, "Usmall"},
280 {0x0168, "Utilde"},
281 {0x0056, "V"},
282 {0x0056, "Vsmall"},
283 {0x0057, "W"},
284 {0x1e82, "Wacute"},
285 {0x0174, "Wcircumflex"},
286 {0x1e84, "Wdieresis"},
287 {0x1e80, "Wgrave"},
288 {0x0057, "Wsmall"},
289 {0x0058, "X"},
290 {0x039e, "Xi"},
291 {0x0058, "Xsmall"},
292 {0x0059, "Y"},
293 {0x00dd, "Yacute"},
294 {0x00dd, "Yacutesmall"},
295 {0x0176, "Ycircumflex"},
296 {0x0178, "Ydieresis"},
297 {0x0178, "Ydieresissmall"},
298 {0x1ef2, "Ygrave"},
299 {0x0059, "Ysmall"},
300 {0x005a, "Z"},
301 {0x0179, "Zacute"},
302 {0x017d, "Zcaron"},
303 {0x017d, "Zcaronsmall"},
304 {0x017b, "Zdotaccent"},
305 {0x0396, "Zeta"},
306 {0x005a, "Zsmall"},
307 {0x0061, "a"},
308 {0x00e1, "aacute"},
309 {0x0103, "abreve"},
310 {0x00e2, "acircumflex"},
311 {0x00b4, "acute"},
312 {0x0301, "acutecomb"},
313 {0x00e4, "adieresis"},
314 {0x00e6, "ae"},
315 {0x01fd, "aeacute"},
316 {0x2015, "afii00208"},
317 {0x0410, "afii10017"},
318 {0x0411, "afii10018"},
319 {0x0412, "afii10019"},
320 {0x0413, "afii10020"},
321 {0x0414, "afii10021"},
322 {0x0415, "afii10022"},
323 {0x0401, "afii10023"},
324 {0x0416, "afii10024"},
325 {0x0417, "afii10025"},
326 {0x0418, "afii10026"},
327 {0x0419, "afii10027"},
328 {0x041a, "afii10028"},
329 {0x041b, "afii10029"},
330 {0x041c, "afii10030"},
331 {0x041d, "afii10031"},
332 {0x041e, "afii10032"},
333 {0x041f, "afii10033"},
334 {0x0420, "afii10034"},
335 {0x0421, "afii10035"},
336 {0x0422, "afii10036"},
337 {0x0423, "afii10037"},
338 {0x0424, "afii10038"},
339 {0x0425, "afii10039"},
340 {0x0426, "afii10040"},
341 {0x0427, "afii10041"},
342 {0x0428, "afii10042"},
343 {0x0429, "afii10043"},
344 {0x042a, "afii10044"},
345 {0x042b, "afii10045"},
346 {0x042c, "afii10046"},
347 {0x042d, "afii10047"},
348 {0x042e, "afii10048"},
349 {0x042f, "afii10049"},
350 {0x0490, "afii10050"},
351 {0x0402, "afii10051"},
352 {0x0403, "afii10052"},
353 {0x0404, "afii10053"},
354 {0x0405, "afii10054"},
355 {0x0406, "afii10055"},
356 {0x0407, "afii10056"},
357 {0x0408, "afii10057"},
358 {0x0409, "afii10058"},
359 {0x040a, "afii10059"},
360 {0x040b, "afii10060"},
361 {0x040c, "afii10061"},
362 {0x040e, "afii10062"},
363 {0xf6c4, "afii10063"},
364 {0xf6c5, "afii10064"},
365 {0x0430, "afii10065"},
366 {0x0431, "afii10066"},
367 {0x0432, "afii10067"},
368 {0x0433, "afii10068"},
369 {0x0434, "afii10069"},
370 {0x0435, "afii10070"},
371 {0x0451, "afii10071"},
372 {0x0436, "afii10072"},
373 {0x0437, "afii10073"},
374 {0x0438, "afii10074"},
375 {0x0439, "afii10075"},
376 {0x043a, "afii10076"},
377 {0x043b, "afii10077"},
378 {0x043c, "afii10078"},
379 {0x043d, "afii10079"},
380 {0x043e, "afii10080"},
381 {0x043f, "afii10081"},
382 {0x0440, "afii10082"},
383 {0x0441, "afii10083"},
384 {0x0442, "afii10084"},
385 {0x0443, "afii10085"},
386 {0x0444, "afii10086"},
387 {0x0445, "afii10087"},
388 {0x0446, "afii10088"},
389 {0x0447, "afii10089"},
390 {0x0448, "afii10090"},
391 {0x0449, "afii10091"},
392 {0x044a, "afii10092"},
393 {0x044b, "afii10093"},
394 {0x044c, "afii10094"},
395 {0x044d, "afii10095"},
396 {0x044e, "afii10096"},
397 {0x044f, "afii10097"},
398 {0x0491, "afii10098"},
399 {0x0452, "afii10099"},
400 {0x0453, "afii10100"},
401 {0x0454, "afii10101"},
402 {0x0455, "afii10102"},
403 {0x0456, "afii10103"},
404 {0x0457, "afii10104"},
405 {0x0458, "afii10105"},
406 {0x0459, "afii10106"},
407 {0x045a, "afii10107"},
408 {0x045b, "afii10108"},
409 {0x045c, "afii10109"},
410 {0x045e, "afii10110"},
411 {0x040f, "afii10145"},
412 {0x0462, "afii10146"},
413 {0x0472, "afii10147"},
414 {0x0474, "afii10148"},
415 {0xf6c6, "afii10192"},
416 {0x045f, "afii10193"},
417 {0x0463, "afii10194"},
418 {0x0473, "afii10195"},
419 {0x0475, "afii10196"},
420 {0xf6c7, "afii10831"},
421 {0xf6c8, "afii10832"},
422 {0x04d9, "afii10846"},
423 {0x200e, "afii299"},
424 {0x200f, "afii300"},
425 {0x200d, "afii301"},
426 {0x066a, "afii57381"},
427 {0x060c, "afii57388"},
428 {0x0660, "afii57392"},
429 {0x0661, "afii57393"},
430 {0x0662, "afii57394"},
431 {0x0663, "afii57395"},
432 {0x0664, "afii57396"},
433 {0x0665, "afii57397"},
434 {0x0666, "afii57398"},
435 {0x0667, "afii57399"},
436 {0x0668, "afii57400"},
437 {0x0669, "afii57401"},
438 {0x061b, "afii57403"},
439 {0x061f, "afii57407"},
440 {0x0621, "afii57409"},
441 {0x0622, "afii57410"},
442 {0x0623, "afii57411"},
443 {0x0624, "afii57412"},
444 {0x0625, "afii57413"},
445 {0x0626, "afii57414"},
446 {0x0627, "afii57415"},
447 {0x0628, "afii57416"},
448 {0x0629, "afii57417"},
449 {0x062a, "afii57418"},
450 {0x062b, "afii57419"},
451 {0x062c, "afii57420"},
452 {0x062d, "afii57421"},
453 {0x062e, "afii57422"},
454 {0x062f, "afii57423"},
455 {0x0630, "afii57424"},
456 {0x0631, "afii57425"},
457 {0x0632, "afii57426"},
458 {0x0633, "afii57427"},
459 {0x0634, "afii57428"},
460 {0x0635, "afii57429"},
461 {0x0636, "afii57430"},
462 {0x0637, "afii57431"},
463 {0x0638, "afii57432"},
464 {0x0639, "afii57433"},
465 {0x063a, "afii57434"},
466 {0x0640, "afii57440"},
467 {0x0641, "afii57441"},
468 {0x0642, "afii57442"},
469 {0x0643, "afii57443"},
470 {0x0644, "afii57444"},
471 {0x0645, "afii57445"},
472 {0x0646, "afii57446"},
473 {0x0648, "afii57448"},
474 {0x0649, "afii57449"},
475 {0x064a, "afii57450"},
476 {0x064b, "afii57451"},
477 {0x064c, "afii57452"},
478 {0x064d, "afii57453"},
479 {0x064e, "afii57454"},
480 {0x064f, "afii57455"},
481 {0x0650, "afii57456"},
482 {0x0651, "afii57457"},
483 {0x0652, "afii57458"},
484 {0x0647, "afii57470"},
485 {0x06a4, "afii57505"},
486 {0x067e, "afii57506"},
487 {0x0686, "afii57507"},
488 {0x0698, "afii57508"},
489 {0x06af, "afii57509"},
490 {0x0679, "afii57511"},
491 {0x0688, "afii57512"},
492 {0x0691, "afii57513"},
493 {0x06ba, "afii57514"},
494 {0x06d2, "afii57519"},
495 {0x06d5, "afii57534"},
496 {0x20aa, "afii57636"},
497 {0x05be, "afii57645"},
498 {0x05c3, "afii57658"},
499 {0x05d0, "afii57664"},
500 {0x05d1, "afii57665"},
501 {0x05d2, "afii57666"},
502 {0x05d3, "afii57667"},
503 {0x05d4, "afii57668"},
504 {0x05d5, "afii57669"},
505 {0x05d6, "afii57670"},
506 {0x05d7, "afii57671"},
507 {0x05d8, "afii57672"},
508 {0x05d9, "afii57673"},
509 {0x05da, "afii57674"},
510 {0x05db, "afii57675"},
511 {0x05dc, "afii57676"},
512 {0x05dd, "afii57677"},
513 {0x05de, "afii57678"},
514 {0x05df, "afii57679"},
515 {0x05e0, "afii57680"},
516 {0x05e1, "afii57681"},
517 {0x05e2, "afii57682"},
518 {0x05e3, "afii57683"},
519 {0x05e4, "afii57684"},
520 {0x05e5, "afii57685"},
521 {0x05e6, "afii57686"},
522 {0x05e7, "afii57687"},
523 {0x05e8, "afii57688"},
524 {0x05e9, "afii57689"},
525 {0x05ea, "afii57690"},
526 {0xfb2a, "afii57694"},
527 {0xfb2b, "afii57695"},
528 {0xfb4b, "afii57700"},
529 {0xfb1f, "afii57705"},
530 {0x05f0, "afii57716"},
531 {0x05f1, "afii57717"},
532 {0x05f2, "afii57718"},
533 {0xfb35, "afii57723"},
534 {0x05b4, "afii57793"},
535 {0x05b5, "afii57794"},
536 {0x05b6, "afii57795"},
537 {0x05bb, "afii57796"},
538 {0x05b8, "afii57797"},
539 {0x05b7, "afii57798"},
540 {0x05b0, "afii57799"},
541 {0x05b2, "afii57800"},
542 {0x05b1, "afii57801"},
543 {0x05b3, "afii57802"},
544 {0x05c2, "afii57803"},
545 {0x05c1, "afii57804"},
546 {0x05b9, "afii57806"},
547 {0x05bc, "afii57807"},
548 {0x05bd, "afii57839"},
549 {0x05bf, "afii57841"},
550 {0x05c0, "afii57842"},
551 {0x02bc, "afii57929"},
552 {0x2105, "afii61248"},
553 {0x2113, "afii61289"},
554 {0x2116, "afii61352"},
555 {0x202c, "afii61573"},
556 {0x202d, "afii61574"},
557 {0x202e, "afii61575"},
558 {0x200c, "afii61664"},
559 {0x066d, "afii63167"},
560 {0x02bd, "afii64937"},
561 {0x00e0, "agrave"},
562 {0x2135, "aleph"},
563 {0x03b1, "alpha"},
564 {0x03ac, "alphatonos"},
565 {0x0101, "amacron"},
566 {0x0026, "ampersand"},
567 {0x0026, "ampersandsmall"},
568 {0x2220, "angle"},
569 {0x2329, "angleleft"},
570 {0x232a, "angleright"},
571 {0x0387, "anoteleia"},
572 {0x0105, "aogonek"},
573 {0x2248, "approxequal"},
574 {0x00e5, "aring"},
575 {0x01fb, "aringacute"},
576 {0x2194, "arrowboth"},
577 {0x21d4, "arrowdblboth"},
578 {0x21d3, "arrowdbldown"},
579 {0x21d0, "arrowdblleft"},
580 {0x21d2, "arrowdblright"},
581 {0x21d1, "arrowdblup"},
582 {0x2193, "arrowdown"},
583 {0xf8e7, "arrowhorizex"},
584 {0x2190, "arrowleft"},
585 {0x2192, "arrowright"},
586 {0x2191, "arrowup"},
587 {0x2195, "arrowupdn"},
588 {0x21a8, "arrowupdnbse"},
589 {0xf8e6, "arrowvertex"},
590 {0x005e, "asciicircum"},
591 {0x007e, "asciitilde"},
592 {0x002a, "asterisk"},
593 {0x2217, "asteriskmath"},
594 {0xf6e9, "asuperior"},
595 {0x0040, "at"},
596 {0x00e3, "atilde"},
597 {0x0062, "b"},
598 {0x005c, "backslash"},
599 {0x007c, "bar"},
600 {0x03b2, "beta"},
601 {0x2588, "block"},
602 {0xf8f4, "braceex"},
603 {0x007b, "braceleft"},
604 {0xf8f3, "braceleftbt"},
605 {0xf8f2, "braceleftmid"},
606 {0xf8f1, "bracelefttp"},
607 {0x007d, "braceright"},
608 {0xf8fe, "bracerightbt"},
609 {0xf8fd, "bracerightmid"},
610 {0xf8fc, "bracerighttp"},
611 {0x005b, "bracketleft"},
612 {0xf8f0, "bracketleftbt"},
613 {0xf8ef, "bracketleftex"},
614 {0xf8ee, "bracketlefttp"},
615 {0x005d, "bracketright"},
616 {0xf8fb, "bracketrightbt"},
617 {0xf8fa, "bracketrightex"},
618 {0xf8f9, "bracketrighttp"},
619 {0x02d8, "breve"},
620 {0x00a6, "brokenbar"},
621 {0xf6ea, "bsuperior"},
622 {0x2022, "bullet"},
623 {0x0063, "c"},
624 {0x0107, "cacute"},
625 {0x02c7, "caron"},
626 {0x21b5, "carriagereturn"},
627 {0x010d, "ccaron"},
628 {0x00e7, "ccedilla"},
629 {0x0109, "ccircumflex"},
630 {0x010b, "cdotaccent"},
631 {0x00b8, "cedilla"},
632 {0x00a2, "cent"},
633 {0xf6df, "centinferior"},
634 {0x00a2, "centoldstyle"},
635 {0xf6e0, "centsuperior"},
636 {0x03c7, "chi"},
637 {0x25cb, "circle"},
638 {0x2297, "circlemultiply"},
639 {0x2295, "circleplus"},
640 {0x02c6, "circumflex"},
641 {0x2663, "club"},
642 {0x003a, "colon"},
643 {0x20a1, "colonmonetary"},
644 {0x002c, "comma"},
645 {0xf6c3, "commaaccent"},
646 {0xf6e1, "commainferior"},
647 {0xf6e2, "commasuperior"},
648 {0x2245, "congruent"},
649 {0x00a9, "copyright"},
650 {0xf8e9, "copyrightsans"},
651 {0xf6d9, "copyrightserif"},
652 {0x00a4, "currency"},
653 {0xf6d1, "cyrBreve"},
654 {0xf6d2, "cyrFlex"},
655 {0xf6d4, "cyrbreve"},
656 {0xf6d5, "cyrflex"},
657 {0x0064, "d"},
658 {0x2020, "dagger"},
659 {0x2021, "daggerdbl"},
660 {0xf6d3, "dblGrave"},
661 {0xf6d6, "dblgrave"},
662 {0x010f, "dcaron"},
663 {0x0111, "dcroat"},
664 {0x00b0, "degree"},
665 {0x03b4, "delta"},
666 {0x2666, "diamond"},
667 {0x00a8, "dieresis"},
668 {0xf6d7, "dieresisacute"},
669 {0xf6d8, "dieresisgrave"},
670 {0x0385, "dieresistonos"},
671 {0x00f7, "divide"},
672 {0x2593, "dkshade"},
673 {0x2584, "dnblock"},
674 {0x0024, "dollar"},
675 {0xf6e3, "dollarinferior"},
676 {0x0024, "dollaroldstyle"},
677 {0xf6e4, "dollarsuperior"},
678 {0x20ab, "dong"},
679 {0x02d9, "dotaccent"},
680 {0x0323, "dotbelowcomb"},
681 {0x0131, "dotlessi"},
682 {0xf6be, "dotlessj"},
683 {0x22c5, "dotmath"},
684 {0xf6eb, "dsuperior"},
685 {0x0065, "e"},
686 {0x00e9, "eacute"},
687 {0x0115, "ebreve"},
688 {0x011b, "ecaron"},
689 {0x00ea, "ecircumflex"},
690 {0x00eb, "edieresis"},
691 {0x0117, "edotaccent"},
692 {0x00e8, "egrave"},
693 {0x0038, "eight"},
694 {0x2088, "eightinferior"},
695 {0x0038, "eightoldstyle"},
696 {0x2078, "eightsuperior"},
697 {0x2208, "element"},
698 {0x2026, "ellipsis"},
699 {0x0113, "emacron"},
700 {0x2014, "emdash"},
701 {0x2205, "emptyset"},
702 {0x2013, "endash"},
703 {0x014b, "eng"},
704 {0x0119, "eogonek"},
705 {0x03b5, "epsilon"},
706 {0x03ad, "epsilontonos"},
707 {0x003d, "equal"},
708 {0x2261, "equivalence"},
709 {0x212e, "estimated"},
710 {0xf6ec, "esuperior"},
711 {0x03b7, "eta"},
712 {0x03ae, "etatonos"},
713 {0x00f0, "eth"},
714 {0x0021, "exclam"},
715 {0x203c, "exclamdbl"},
716 {0x00a1, "exclamdown"},
717 {0x00a1, "exclamdownsmall"},
718 {0x0021, "exclamsmall"},
719 {0x2203, "existential"},
720 {0x0066, "f"},
721 {0x2640, "female"},
722 {0xfb00, "ff"},
723 {0xfb03, "ffi"},
724 {0xfb04, "ffl"},
725 {0xfb01, "fi"},
726 {0x2012, "figuredash"},
727 {0x25a0, "filledbox"},
728 {0x25ac, "filledrect"},
729 {0x0035, "five"},
730 {0x215d, "fiveeighths"},
731 {0x2085, "fiveinferior"},
732 {0x0035, "fiveoldstyle"},
733 {0x2075, "fivesuperior"},
734 {0xfb02, "fl"},
735 {0x0192, "florin"},
736 {0x0034, "four"},
737 {0x2084, "fourinferior"},
738 {0x0034, "fouroldstyle"},
739 {0x2074, "foursuperior"},
740 {0x2044, "fraction"},
741 {0x20a3, "franc"},
742 {0x0067, "g"},
743 {0x03b3, "gamma"},
744 {0x011f, "gbreve"},
745 {0x01e7, "gcaron"},
746 {0x011d, "gcircumflex"},
747 {0x0123, "gcommaaccent"},
748 {0x0121, "gdotaccent"},
749 {0x00df, "germandbls"},
750 {0x2207, "gradient"},
751 {0x0060, "grave"},
752 {0x0300, "gravecomb"},
753 {0x003e, "greater"},
754 {0x2265, "greaterequal"},
755 {0x00ab, "guillemotleft"},
756 {0x00bb, "guillemotright"},
757 {0x2039, "guilsinglleft"},
758 {0x203a, "guilsinglright"},
759 {0x0068, "h"},
760 {0x0127, "hbar"},
761 {0x0125, "hcircumflex"},
762 {0x2665, "heart"},
763 {0x0309, "hookabovecomb"},
764 {0x2302, "house"},
765 {0x02dd, "hungarumlaut"},
766 {0x002d, "hyphen"},
767 {0xf6e5, "hypheninferior"},
768 {0xf6e6, "hyphensuperior"},
769 {0x0069, "i"},
770 {0x00ed, "iacute"},
771 {0x012d, "ibreve"},
772 {0x00ee, "icircumflex"},
773 {0x00ef, "idieresis"},
774 {0x00ec, "igrave"},
775 {0x0133, "ij"},
776 {0x012b, "imacron"},
777 {0x221e, "infinity"},
778 {0x222b, "integral"},
779 {0x2321, "integralbt"},
780 {0xf8f5, "integralex"},
781 {0x2320, "integraltp"},
782 {0x2229, "intersection"},
783 {0x25d8, "invbullet"},
784 {0x25d9, "invcircle"},
785 {0x263b, "invsmileface"},
786 {0x012f, "iogonek"},
787 {0x03b9, "iota"},
788 {0x03ca, "iotadieresis"},
789 {0x0390, "iotadieresistonos"},
790 {0x03af, "iotatonos"},
791 {0xf6ed, "isuperior"},
792 {0x0129, "itilde"},
793 {0x006a, "j"},
794 {0x0135, "jcircumflex"},
795 {0x006b, "k"},
796 {0x03ba, "kappa"},
797 {0x0137, "kcommaaccent"},
798 {0x0138, "kgreenlandic"},
799 {0x006c, "l"},
800 {0x013a, "lacute"},
801 {0x03bb, "lambda"},
802 {0x013e, "lcaron"},
803 {0x013c, "lcommaaccent"},
804 {0x0140, "ldot"},
805 {0x003c, "less"},
806 {0x2264, "lessequal"},
807 {0x258c, "lfblock"},
808 {0x20a4, "lira"},
809 {0xf6c0, "ll"},
810 {0x2227, "logicaland"},
811 {0x00ac, "logicalnot"},
812 {0x2228, "logicalor"},
813 {0x017f, "longs"},
814 {0x25ca, "lozenge"},
815 {0x0142, "lslash"},
816 {0xf6ee, "lsuperior"},
817 {0x2591, "ltshade"},
818 {0x006d, "m"},
819 {0x00af, "macron"},
820 {0x2642, "male"},
821 {0x2212, "minus"},
822 {0x2032, "minute"},
823 {0xf6ef, "msuperior"},
824 {0x00b5, "mu"},
825 {0x00d7, "multiply"},
826 {0x266a, "musicalnote"},
827 {0x266b, "musicalnotedbl"},
828 {0x006e, "n"},
829 {0x0144, "nacute"},
830 {0x0149, "napostrophe"},
831 {0x00a0, "nbspace"},
832 {0x0148, "ncaron"},
833 {0x0146, "ncommaaccent"},
834 {0x0039, "nine"},
835 {0x2089, "nineinferior"},
836 {0x0039, "nineoldstyle"},
837 {0x2079, "ninesuperior"},
838 {0x00a0, "nonbreakingspace"},
839 {0x2209, "notelement"},
840 {0x2260, "notequal"},
841 {0x2284, "notsubset"},
842 {0x207f, "nsuperior"},
843 {0x00f1, "ntilde"},
844 {0x03bd, "nu"},
845 {0x0023, "numbersign"},
846 {0x006f, "o"},
847 {0x00f3, "oacute"},
848 {0x014f, "obreve"},
849 {0x00f4, "ocircumflex"},
850 {0x00f6, "odieresis"},
851 {0x0153, "oe"},
852 {0x02db, "ogonek"},
853 {0x00f2, "ograve"},
854 {0x01a1, "ohorn"},
855 {0x0151, "ohungarumlaut"},
856 {0x014d, "omacron"},
857 {0x03c9, "omega"},
858 {0x03d6, "omega1"},
859 {0x03ce, "omegatonos"},
860 {0x03bf, "omicron"},
861 {0x03cc, "omicrontonos"},
862 {0x0031, "one"},
863 {0x2024, "onedotenleader"},
864 {0x215b, "oneeighth"},
865 {0xf6dc, "onefitted"},
866 {0x00bd, "onehalf"},
867 {0x2081, "oneinferior"},
868 {0x0031, "oneoldstyle"},
869 {0x00bc, "onequarter"},
870 {0x00b9, "onesuperior"},
871 {0x2153, "onethird"},
872 {0x25e6, "openbullet"},
873 {0x00aa, "ordfeminine"},
874 {0x00ba, "ordmasculine"},
875 {0x221f, "orthogonal"},
876 {0x00f8, "oslash"},
877 {0x01ff, "oslashacute"},
878 {0xf6f0, "osuperior"},
879 {0x00f5, "otilde"},
880 {0x0070, "p"},
881 {0x00b6, "paragraph"},
882 {0x0028, "parenleft"},
883 {0xf8ed, "parenleftbt"},
884 {0xf8ec, "parenleftex"},
885 {0x208d, "parenleftinferior"},
886 {0x207d, "parenleftsuperior"},
887 {0xf8eb, "parenlefttp"},
888 {0x0029, "parenright"},
889 {0xf8f8, "parenrightbt"},
890 {0xf8f7, "parenrightex"},
891 {0x208e, "parenrightinferior"},
892 {0x207e, "parenrightsuperior"},
893 {0xf8f6, "parenrighttp"},
894 {0x2202, "partialdiff"},
895 {0x0025, "percent"},
896 {0x002e, "period"},
897 {0x00b7, "periodcentered"},
898 {0xf6e7, "periodinferior"},
899 {0xf6e8, "periodsuperior"},
900 {0x22a5, "perpendicular"},
901 {0x2030, "perthousand"},
902 {0x20a7, "peseta"},
903 {0x03c6, "phi"},
904 {0x03d5, "phi1"},
905 {0x03c0, "pi"},
906 {0x002b, "plus"},
907 {0x00b1, "plusminus"},
908 {0x211e, "prescription"},
909 {0x220f, "product"},
910 {0x2282, "propersubset"},
911 {0x2283, "propersuperset"},
912 {0x221d, "proportional"},
913 {0x03c8, "psi"},
914 {0x0071, "q"},
915 {0x003f, "question"},
916 {0x00bf, "questiondown"},
917 {0x00bf, "questiondownsmall"},
918 {0x003f, "questionsmall"},
919 {0x0022, "quotedbl"},
920 {0x201e, "quotedblbase"},
921 {0x201c, "quotedblleft"},
922 {0x201d, "quotedblright"},
923 {0x2018, "quoteleft"},
924 {0x201b, "quotereversed"},
925 {0x2019, "quoteright"},
926 {0x201a, "quotesinglbase"},
927 {0x0027, "quotesingle"},
928 {0x0072, "r"},
929 {0x0155, "racute"},
930 {0x221a, "radical"},
931 {0xf8e5, "radicalex"},
932 {0x0159, "rcaron"},
933 {0x0157, "rcommaaccent"},
934 {0x2286, "reflexsubset"},
935 {0x2287, "reflexsuperset"},
936 {0x00ae, "registered"},
937 {0xf8e8, "registersans"},
938 {0xf6da, "registerserif"},
939 {0x2310, "revlogicalnot"},
940 {0x03c1, "rho"},
941 {0x02da, "ring"},
942 {0xf6f1, "rsuperior"},
943 {0x2590, "rtblock"},
944 {0xf6dd, "rupiah"},
945 {0x0073, "s"},
946 {0x015b, "sacute"},
947 {0x0161, "scaron"},
948 {0x015f, "scedilla"},
949 {0x015d, "scircumflex"},
950 {0x0219, "scommaaccent"},
951 {0x2033, "second"},
952 {0x00a7, "section"},
953 {0x003b, "semicolon"},
954 {0x0037, "seven"},
955 {0x215e, "seveneighths"},
956 {0x2087, "seveninferior"},
957 {0x0037, "sevenoldstyle"},
958 {0x2077, "sevensuperior"},
959 {0x2592, "shade"},
960 {0x03c3, "sigma"},
961 {0x03c2, "sigma1"},
962 {0x223c, "similar"},
963 {0x0036, "six"},
964 {0x2086, "sixinferior"},
965 {0x0036, "sixoldstyle"},
966 {0x2076, "sixsuperior"},
967 {0x002f, "slash"},
968 {0x263a, "smileface"},
969 {0x0020, "space"},
970 {0x2660, "spade"},
971 {0xf6f2, "ssuperior"},
972 {0x00a3, "sterling"},
973 {0x220b, "suchthat"},
974 {0x2211, "summation"},
975 {0x263c, "sun"},
976 {0x0074, "t"},
977 {0x03c4, "tau"},
978 {0x0167, "tbar"},
979 {0x0165, "tcaron"},
980 {0x0163, "tcommaaccent"},
981 {0x2234, "therefore"},
982 {0x03b8, "theta"},
983 {0x03d1, "theta1"},
984 {0x00fe, "thorn"},
985 {0x0033, "three"},
986 {0x215c, "threeeighths"},
987 {0x2083, "threeinferior"},
988 {0x0033, "threeoldstyle"},
989 {0x00be, "threequarters"},
990 {0xf6de, "threequartersemdash"},
991 {0x00b3, "threesuperior"},
992 {0x02dc, "tilde"},
993 {0x0303, "tildecomb"},
994 {0x0384, "tonos"},
995 {0x2122, "trademark"},
996 {0xf8ea, "trademarksans"},
997 {0xf6db, "trademarkserif"},
998 {0x25bc, "triagdn"},
999 {0x25c4, "triaglf"},
1000 {0x25ba, "triagrt"},
1001 {0x25b2, "triagup"},
1002 {0xf6f3, "tsuperior"},
1003 {0x0032, "two"},
1004 {0x2025, "twodotenleader"},
1005 {0x2082, "twoinferior"},
1006 {0x0032, "twooldstyle"},
1007 {0x00b2, "twosuperior"},
1008 {0x2154, "twothirds"},
1009 {0x0075, "u"},
1010 {0x00fa, "uacute"},
1011 {0x016d, "ubreve"},
1012 {0x00fb, "ucircumflex"},
1013 {0x00fc, "udieresis"},
1014 {0x00f9, "ugrave"},
1015 {0x01b0, "uhorn"},
1016 {0x0171, "uhungarumlaut"},
1017 {0x016b, "umacron"},
1018 {0x005f, "underscore"},
1019 {0x2017, "underscoredbl"},
1020 {0x222a, "union"},
1021 {0x2200, "universal"},
1022 {0x0173, "uogonek"},
1023 {0x2580, "upblock"},
1024 {0x03c5, "upsilon"},
1025 {0x03cb, "upsilondieresis"},
1026 {0x03b0, "upsilondieresistonos"},
1027 {0x03cd, "upsilontonos"},
1028 {0x016f, "uring"},
1029 {0x0169, "utilde"},
1030 {0x0076, "v"},
1031 {0x0077, "w"},
1032 {0x1e83, "wacute"},
1033 {0x0175, "wcircumflex"},
1034 {0x1e85, "wdieresis"},
1035 {0x2118, "weierstrass"},
1036 {0x1e81, "wgrave"},
1037 {0x0078, "x"},
1038 {0x03be, "xi"},
1039 {0x0079, "y"},
1040 {0x00fd, "yacute"},
1041 {0x0177, "ycircumflex"},
1042 {0x00ff, "ydieresis"},
1043 {0x00a5, "yen"},
1044 {0x1ef3, "ygrave"},
1045 {0x007a, "z"},
1046 {0x017a, "zacute"},
1047 {0x017e, "zcaron"},
1048 {0x017c, "zdotaccent"},
1049 {0x0030, "zero"},
1050 {0x2080, "zeroinferior"},
1051 {0x0030, "zerooldstyle"},
1052 {0x2070, "zerosuperior"},
1053 {0x03b6, "zeta"},
1054 { 0, NULL }
1055};
diff --git a/noncore/unsupported/qpdf/xpdf/Object.cc b/noncore/unsupported/qpdf/xpdf/Object.cc
new file mode 100644
index 0000000..5ecade3
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Object.cc
@@ -0,0 +1,223 @@
1//========================================================================
2//
3// Object.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include "Object.h"
16#include "Array.h"
17#include "Dict.h"
18#include "Error.h"
19#include "Stream.h"
20#include "XRef.h"
21
22//------------------------------------------------------------------------
23// Object
24//------------------------------------------------------------------------
25
26char *objTypeNames[numObjTypes] = {
27 "boolean",
28 "integer",
29 "real",
30 "string",
31 "name",
32 "null",
33 "array",
34 "dictionary",
35 "stream",
36 "ref",
37 "cmd",
38 "error",
39 "eof",
40 "none"
41};
42
43#ifdef DEBUG_MEM
44int Object::numAlloc[numObjTypes] =
45 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
46#endif
47
48Object *Object::initArray(XRef *xref) {
49 initObj(objArray);
50 array = new Array(xref);
51 return this;
52}
53
54Object *Object::initDict(XRef *xref) {
55 initObj(objDict);
56 dict = new Dict(xref);
57 return this;
58}
59
60Object *Object::initStream(Stream *streamA) {
61 initObj(objStream);
62 stream = streamA;
63 return this;
64}
65
66Object *Object::copy(Object *obj) {
67 *obj = *this;
68 switch (type) {
69 case objString:
70 obj->string = string->copy();
71 break;
72 case objName:
73 obj->name = copyString(name);
74 break;
75 case objArray:
76 array->incRef();
77 break;
78 case objDict:
79 dict->incRef();
80 break;
81 case objStream:
82 stream->incRef();
83 break;
84 case objCmd:
85 obj->cmd = copyString(cmd);
86 break;
87 default:
88 break;
89 }
90#ifdef DEBUG_MEM
91 ++numAlloc[type];
92#endif
93 return obj;
94}
95
96Object *Object::fetch(XRef *xref, Object *obj) {
97 return (type == objRef && xref) ?
98 xref->fetch(ref.num, ref.gen, obj) : copy(obj);
99}
100
101void Object::free() {
102 switch (type) {
103 case objString:
104 delete string;
105 break;
106 case objName:
107 gfree(name);
108 break;
109 case objArray:
110 if (!array->decRef()) {
111 delete array;
112 }
113 break;
114 case objDict:
115 if (!dict->decRef()) {
116 delete dict;
117 }
118 break;
119 case objStream:
120 if (!stream->decRef()) {
121 delete stream;
122 }
123 break;
124 case objCmd:
125 gfree(cmd);
126 break;
127 default:
128 break;
129 }
130#ifdef DEBUG_MEM
131 --numAlloc[type];
132#endif
133 type = objNone;
134}
135
136char *Object::getTypeName() {
137 return objTypeNames[type];
138}
139
140void Object::print(FILE *f) {
141 Object obj;
142 int i;
143
144 switch (type) {
145 case objBool:
146 fprintf(f, "%s", booln ? "true" : "false");
147 break;
148 case objInt:
149 fprintf(f, "%d", intg);
150 break;
151 case objReal:
152 fprintf(f, "%g", real);
153 break;
154 case objString:
155 fprintf(f, "(");
156 fwrite(string->getCString(), 1, string->getLength(), stdout);
157 fprintf(f, ")");
158 break;
159 case objName:
160 fprintf(f, "/%s", name);
161 break;
162 case objNull:
163 fprintf(f, "null");
164 break;
165 case objArray:
166 fprintf(f, "[");
167 for (i = 0; i < arrayGetLength(); ++i) {
168 if (i > 0)
169 fprintf(f, " ");
170 arrayGetNF(i, &obj);
171 obj.print(f);
172 obj.free();
173 }
174 fprintf(f, "]");
175 break;
176 case objDict:
177 fprintf(f, "<<");
178 for (i = 0; i < dictGetLength(); ++i) {
179 fprintf(f, " /%s ", dictGetKey(i));
180 dictGetValNF(i, &obj);
181 obj.print(f);
182 obj.free();
183 }
184 fprintf(f, " >>");
185 break;
186 case objStream:
187 fprintf(f, "<stream>");
188 break;
189 case objRef:
190 fprintf(f, "%d %d R", ref.num, ref.gen);
191 break;
192 case objCmd:
193 fprintf(f, "%s", cmd);
194 break;
195 case objError:
196 fprintf(f, "<error>");
197 break;
198 case objEOF:
199 fprintf(f, "<EOF>");
200 break;
201 case objNone:
202 fprintf(f, "<none>");
203 break;
204 }
205}
206
207void Object::memCheck(FILE *f) {
208#ifdef DEBUG_MEM
209 int i;
210 int t;
211
212 t = 0;
213 for (i = 0; i < numObjTypes; ++i)
214 t += numAlloc[i];
215 if (t > 0) {
216 fprintf(f, "Allocated objects:\n");
217 for (i = 0; i < numObjTypes; ++i) {
218 if (numAlloc[i] > 0)
219 fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
220 }
221 }
222#endif
223}
diff --git a/noncore/unsupported/qpdf/xpdf/Object.h b/noncore/unsupported/qpdf/xpdf/Object.h
new file mode 100644
index 0000000..000ffa0
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Object.h
@@ -0,0 +1,299 @@
1//========================================================================
2//
3// Object.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef OBJECT_H
10#define OBJECT_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include <stdio.h>
17#include <string.h>
18#include "gtypes.h"
19#include "gmem.h"
20#include "GString.h"
21
22class XRef;
23class Array;
24class Dict;
25class Stream;
26
27//------------------------------------------------------------------------
28// Ref
29//------------------------------------------------------------------------
30
31struct Ref {
32 int num; // object number
33 int gen; // generation number
34};
35
36//------------------------------------------------------------------------
37// object types
38//------------------------------------------------------------------------
39
40enum ObjType {
41 // simple objects
42 objBool, // boolean
43 objInt, // integer
44 objReal, // real
45 objString, // string
46 objName, // name
47 objNull, // null
48
49 // complex objects
50 objArray, // array
51 objDict, // dictionary
52 objStream, // stream
53 objRef, // indirect reference
54
55 // special objects
56 objCmd, // command name
57 objError, // error return from Lexer
58 objEOF, // end of file return from Lexer
59 objNone // uninitialized object
60};
61
62 #define numObjTypes 14 // total number of object types
63
64//------------------------------------------------------------------------
65// Object
66//------------------------------------------------------------------------
67
68#ifdef DEBUG_MEM
69#define initObj(t) ++numAlloc[type = t]
70#else
71#define initObj(t) type = t
72#endif
73
74class Object {
75public:
76
77 // Default constructor.
78 Object():
79 type(objNone) {}
80
81 // Initialize an object.
82 Object *initBool(GBool boolnA)
83 { initObj(objBool); booln = boolnA; return this; }
84 Object *initInt(int intgA)
85 { initObj(objInt); intg = intgA; return this; }
86 Object *initReal(fouble realA)
87 { initObj(objReal); real = realA; return this; }
88 Object *initString(GString *stringA)
89 { initObj(objString); string = stringA; return this; }
90 Object *initName(char *nameA)
91 { initObj(objName); name = copyString(nameA); return this; }
92 Object *initNull()
93 { initObj(objNull); return this; }
94 Object *initArray(XRef *xref);
95 Object *initDict(XRef *xref);
96 Object *initStream(Stream *streamA);
97 Object *initRef(int numA, int genA)
98 { initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
99 Object *initCmd(char *cmdA)
100 { initObj(objCmd); cmd = copyString(cmdA); return this; }
101 Object *initError()
102 { initObj(objError); return this; }
103 Object *initEOF()
104 { initObj(objEOF); return this; }
105
106 // Copy an object.
107 Object *copy(Object *obj);
108
109 // If object is a Ref, fetch and return the referenced object.
110 // Otherwise, return a copy of the object.
111 Object *fetch(XRef *xref, Object *obj);
112
113 // Free object contents.
114 void free();
115
116 // Type checking.
117 ObjType getType() { return type; }
118 GBool isBool() { return type == objBool; }
119 GBool isInt() { return type == objInt; }
120 GBool isReal() { return type == objReal; }
121 GBool isNum() { return type == objInt || type == objReal; }
122 GBool isString() { return type == objString; }
123 GBool isName() { return type == objName; }
124 GBool isNull() { return type == objNull; }
125 GBool isArray() { return type == objArray; }
126 GBool isDict() { return type == objDict; }
127 GBool isStream() { return type == objStream; }
128 GBool isRef() { return type == objRef; }
129 GBool isCmd() { return type == objCmd; }
130 GBool isError() { return type == objError; }
131 GBool isEOF() { return type == objEOF; }
132 GBool isNone() { return type == objNone; }
133
134 // Special type checking.
135 GBool isName(char *nameA)
136 { return type == objName && !strcmp(name, nameA); }
137 GBool isDict(char *dictType);
138 GBool isStream(char *dictType);
139 GBool isCmd(char *cmdA)
140 { return type == objCmd && !strcmp(cmd, cmdA); }
141
142 // Accessors. NB: these assume object is of correct type.
143 GBool getBool() { return booln; }
144 int getInt() { return intg; }
145 fouble getReal() { return real; }
146 fouble getNum() { return type == objInt ? (fouble)intg : real; }
147 GString *getString() { return string; }
148 char *getName() { return name; }
149 Array *getArray() { return array; }
150 Dict *getDict() { return dict; }
151 Stream *getStream() { return stream; }
152 Ref getRef() { return ref; }
153 int getRefNum() { return ref.num; }
154 int getRefGen() { return ref.gen; }
155
156 // Array accessors.
157 int arrayGetLength();
158 void arrayAdd(Object *elem);
159 Object *arrayGet(int i, Object *obj);
160 Object *arrayGetNF(int i, Object *obj);
161
162 // Dict accessors.
163 int dictGetLength();
164 void dictAdd(char *key, Object *val);
165 GBool dictIs(char *dictType);
166 Object *dictLookup(char *key, Object *obj);
167 Object *dictLookupNF(char *key, Object *obj);
168 char *dictGetKey(int i);
169 Object *dictGetVal(int i, Object *obj);
170 Object *dictGetValNF(int i, Object *obj);
171
172 // Stream accessors.
173 GBool streamIs(char *dictType);
174 void streamReset();
175 void streamClose();
176 int streamGetChar();
177 int streamLookChar();
178 char *streamGetLine(char *buf, int size);
179 int streamGetPos();
180 void streamSetPos(int pos);
181 Dict *streamGetDict();
182
183 // Output.
184 char *getTypeName();
185 void print(FILE *f = stdout);
186
187 // Memory testing.
188 static void memCheck(FILE *f);
189
190private:
191
192 ObjType type; // object type
193 fouble real; // real
194 union { // value for each type:
195 GBool booln; // boolean
196 int intg; // integer
197 GString *string; // string
198 char *name; // name
199 Array *array; // array
200 Dict *dict; // dictionary
201 Stream *stream; // stream
202 Ref ref; // indirect reference
203 char *cmd; // command
204 };
205
206#ifdef DEBUG_MEM
207 static int // number of each type of object
208 numAlloc[numObjTypes];// currently allocated
209#endif
210};
211
212//------------------------------------------------------------------------
213// Array accessors.
214//------------------------------------------------------------------------
215
216#include "Array.h"
217
218inline int Object::arrayGetLength()
219 { return array->getLength(); }
220
221inline void Object::arrayAdd(Object *elem)
222 { array->add(elem); }
223
224inline Object *Object::arrayGet(int i, Object *obj)
225 { return array->get(i, obj); }
226
227inline Object *Object::arrayGetNF(int i, Object *obj)
228 { return array->getNF(i, obj); }
229
230//------------------------------------------------------------------------
231// Dict accessors.
232//------------------------------------------------------------------------
233
234#include "Dict.h"
235
236inline int Object::dictGetLength()
237 { return dict->getLength(); }
238
239inline void Object::dictAdd(char *key, Object *val)
240 { dict->add(key, val); }
241
242inline GBool Object::dictIs(char *dictType)
243 { return dict->is(dictType); }
244
245inline GBool Object::isDict(char *dictType)
246 { return type == objDict && dictIs(dictType); }
247
248inline Object *Object::dictLookup(char *key, Object *obj)
249 { return dict->lookup(key, obj); }
250
251inline Object *Object::dictLookupNF(char *key, Object *obj)
252 { return dict->lookupNF(key, obj); }
253
254inline char *Object::dictGetKey(int i)
255 { return dict->getKey(i); }
256
257inline Object *Object::dictGetVal(int i, Object *obj)
258 { return dict->getVal(i, obj); }
259
260inline Object *Object::dictGetValNF(int i, Object *obj)
261 { return dict->getValNF(i, obj); }
262
263//------------------------------------------------------------------------
264// Stream accessors.
265//------------------------------------------------------------------------
266
267#include "Stream.h"
268
269inline GBool Object::streamIs(char *dictType)
270 { return stream->getDict()->is(dictType); }
271
272inline GBool Object::isStream(char *dictType)
273 { return type == objStream && streamIs(dictType); }
274
275inline void Object::streamReset()
276 { stream->reset(); }
277
278inline void Object::streamClose()
279 { stream->close(); }
280
281inline int Object::streamGetChar()
282 { return stream->getChar(); }
283
284inline int Object::streamLookChar()
285 { return stream->lookChar(); }
286
287inline char *Object::streamGetLine(char *buf, int size)
288 { return stream->getLine(buf, size); }
289
290inline int Object::streamGetPos()
291 { return stream->getPos(); }
292
293inline void Object::streamSetPos(int pos)
294 { stream->setPos(pos); }
295
296inline Dict *Object::streamGetDict()
297 { return stream->getDict(); }
298
299#endif
diff --git a/noncore/unsupported/qpdf/xpdf/OutputDev.cc b/noncore/unsupported/qpdf/xpdf/OutputDev.cc
new file mode 100644
index 0000000..3c02835
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/OutputDev.cc
@@ -0,0 +1,97 @@
1//========================================================================
2//
3// OutputDev.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include "Object.h"
16#include "Stream.h"
17#include "GfxState.h"
18#include "OutputDev.h"
19
20//------------------------------------------------------------------------
21// OutputDev
22//------------------------------------------------------------------------
23
24void OutputDev::setDefaultCTM(fouble *ctm) {
25 int i;
26 fouble det;
27
28 for (i = 0; i < 6; ++i) {
29 defCTM[i] = ctm[i];
30 }
31 det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]);
32 defICTM[0] = defCTM[3] * det;
33 defICTM[1] = -defCTM[1] * det;
34 defICTM[2] = -defCTM[2] * det;
35 defICTM[3] = defCTM[0] * det;
36 defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det;
37 defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det;
38}
39
40void OutputDev::cvtDevToUser(int dx, int dy, fouble *ux, fouble *uy) {
41 *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4];
42 *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5];
43}
44
45void OutputDev::cvtUserToDev(fouble ux, fouble uy, int *dx, int *dy) {
46 *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5);
47 *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5);
48}
49
50void OutputDev::updateAll(GfxState *state) {
51 updateLineDash(state);
52 updateFlatness(state);
53 updateLineJoin(state);
54 updateLineCap(state);
55 updateMiterLimit(state);
56 updateLineWidth(state);
57 updateFillColor(state);
58 updateStrokeColor(state);
59 updateFont(state);
60}
61
62void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
63 int width, int height, GBool invert,
64 GBool inlineImg) {
65 int i, j;
66
67 if (inlineImg) {
68 str->reset();
69 j = height * ((width + 7) / 8);
70 for (i = 0; i < j; ++i)
71 str->getChar();
72 str->close();
73 }
74}
75
76void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
77 int width, int height, GfxImageColorMap *colorMap,
78 int *maskColors, GBool inlineImg) {
79 int i, j;
80
81 if (inlineImg) {
82 str->reset();
83 j = height * ((width * colorMap->getNumPixelComps() *
84 colorMap->getBits() + 7) / 8);
85 for (i = 0; i < j; ++i)
86 str->getChar();
87 str->close();
88 }
89}
90
91#if OPI_SUPPORT
92void OutputDev::opiBegin(GfxState *state, Dict *opiDict) {
93}
94
95void OutputDev::opiEnd(GfxState *state, Dict *opiDict) {
96}
97#endif
diff --git a/noncore/unsupported/qpdf/xpdf/OutputDev.h b/noncore/unsupported/qpdf/xpdf/OutputDev.h
new file mode 100644
index 0000000..04cbace
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/OutputDev.h
@@ -0,0 +1,143 @@
1//========================================================================
2//
3// OutputDev.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef OUTPUTDEV_H
10#define OUTPUTDEV_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "CharTypes.h"
18
19class GString;
20class GfxState;
21class GfxColorSpace;
22class GfxImageColorMap;
23class Stream;
24class Link;
25class Catalog;
26
27//------------------------------------------------------------------------
28// OutputDev
29//------------------------------------------------------------------------
30
31class OutputDev {
32public:
33
34 // Constructor.
35 OutputDev() {}
36
37 // Destructor.
38 virtual ~OutputDev() {}
39
40 //----- get info about output device
41
42 // Does this device use upside-down coordinates?
43 // (Upside-down means (0,0) is the top left corner of the page.)
44 virtual GBool upsideDown() = 0;
45
46 // Does this device use drawChar() or drawString()?
47 virtual GBool useDrawChar() = 0;
48
49 // Does this device need non-text content?
50 virtual GBool needNonText() { return gTrue; }
51
52 //----- initialization and control
53
54 // Set default transform matrix.
55 virtual void setDefaultCTM(fouble *ctm);
56
57 // Start a page.
58 virtual void startPage(int pageNum, GfxState *state) {}
59
60 // End a page.
61 virtual void endPage() {}
62
63 // Dump page contents to display.
64 virtual void dump() {}
65
66 //----- coordinate conversion
67
68 // Convert between device and user coordinates.
69 virtual void cvtDevToUser(int dx, int dy, fouble *ux, fouble *uy);
70 virtual void cvtUserToDev(fouble ux, fouble uy, int *dx, int *dy);
71
72 //----- link borders
73 virtual void drawLink(Link *link, Catalog *catalog) {}
74
75 //----- save/restore graphics state
76 virtual void saveState(GfxState *state) {}
77 virtual void restoreState(GfxState *state) {}
78
79 //----- update graphics state
80 virtual void updateAll(GfxState *state);
81 virtual void updateCTM(GfxState *state, fouble m11, fouble m12,
82 fouble m21, fouble m22, fouble m31, fouble m32) {}
83 virtual void updateLineDash(GfxState *state) {}
84 virtual void updateFlatness(GfxState *state) {}
85 virtual void updateLineJoin(GfxState *state) {}
86 virtual void updateLineCap(GfxState *state) {}
87 virtual void updateMiterLimit(GfxState *state) {}
88 virtual void updateLineWidth(GfxState *state) {}
89 virtual void updateFillColor(GfxState *state) {}
90 virtual void updateStrokeColor(GfxState *state) {}
91 virtual void updateFillOpacity(GfxState *state) {}
92 virtual void updateStrokeOpacity(GfxState *state) {}
93
94 //----- update text state
95 virtual void updateFont(GfxState *state) {}
96 virtual void updateTextMat(GfxState *state) {}
97 virtual void updateCharSpace(GfxState *state) {}
98 virtual void updateRender(GfxState *state) {}
99 virtual void updateRise(GfxState *state) {}
100 virtual void updateWordSpace(GfxState *state) {}
101 virtual void updateHorizScaling(GfxState *state) {}
102 virtual void updateTextPos(GfxState *state) {}
103 virtual void updateTextShift(GfxState *state, fouble shift) {}
104
105 //----- path painting
106 virtual void stroke(GfxState *state) {}
107 virtual void fill(GfxState *state) {}
108 virtual void eoFill(GfxState *state) {}
109
110 //----- path clipping
111 virtual void clip(GfxState *state) {}
112 virtual void eoClip(GfxState *state) {}
113
114 //----- text drawing
115 virtual void beginString(GfxState *state, GString *s) {}
116 virtual void endString(GfxState *state) {}
117 virtual void drawChar(GfxState *state, fouble x, fouble y,
118 fouble dx, fouble dy,
119 fouble originX, fouble originY,
120 CharCode code, Unicode *u, int uLen) {}
121 virtual void drawString(GfxState *state, GString *s) {}
122
123 //----- image drawing
124 virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
125 int width, int height, GBool invert,
126 GBool inlineImg);
127 virtual void drawImage(GfxState *state, Object *ref, Stream *str,
128 int width, int height, GfxImageColorMap *colorMap,
129 int *maskColors, GBool inlineImg);
130
131#if OPI_SUPPORT
132 //----- OPI functions
133 virtual void opiBegin(GfxState *state, Dict *opiDict);
134 virtual void opiEnd(GfxState *state, Dict *opiDict);
135#endif
136
137private:
138
139 fouble defCTM[6]; // default coordinate transform matrix
140 fouble defICTM[6]; // inverse of default CTM
141};
142
143#endif
diff --git a/noncore/unsupported/qpdf/xpdf/PDFDoc.cc b/noncore/unsupported/qpdf/xpdf/PDFDoc.cc
new file mode 100644
index 0000000..4bbe9b7
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/PDFDoc.cc
@@ -0,0 +1,251 @@
1//========================================================================
2//
3// PDFDoc.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <stddef.h>
17#include <string.h>
18#include "GString.h"
19#include "config.h"
20#include "Page.h"
21#include "Catalog.h"
22#include "Stream.h"
23#include "XRef.h"
24#include "Link.h"
25#include "OutputDev.h"
26#include "Error.h"
27#include "Lexer.h"
28#include "Parser.h"
29#include "PDFDoc.h"
30
31//------------------------------------------------------------------------
32
33 #define headerSearchSize 1024// read this many bytes at beginning of
34 // file to look for '%PDF'
35
36//------------------------------------------------------------------------
37// PDFDoc
38//------------------------------------------------------------------------
39
40PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
41 GString *userPassword, GBool printCommandsA) {
42 Object obj;
43 GString *fileName2;
44
45 ok = gFalse;
46
47 file = NULL;
48 str = NULL;
49 xref = NULL;
50 catalog = NULL;
51 links = NULL;
52 printCommands = printCommandsA;
53
54 // try to open file
55 fileName = fileNameA;
56 fileName2 = NULL;
57#ifdef VMS
58 if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
59 error(-1, "Couldn't open file '%s'", fileName->getCString());
60 return;
61 }
62#else
63 if (!(file = fopen(fileName->getCString(), "rb"))) {
64 fileName2 = fileName->copy();
65 fileName2->lowerCase();
66 if (!(file = fopen(fileName2->getCString(), "rb"))) {
67 fileName2->upperCase();
68 if (!(file = fopen(fileName2->getCString(), "rb"))) {
69 error(-1, "Couldn't open file '%s'", fileName->getCString());
70 delete fileName2;
71 return;
72 }
73 }
74 delete fileName2;
75 }
76#endif
77
78 // create stream
79 obj.initNull();
80 str = new FileStream(file, 0, -1, &obj);
81
82 ok = setup(ownerPassword, userPassword);
83}
84
85PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
86 GString *userPassword, GBool printCommandsA) {
87 ok = gFalse;
88 fileName = NULL;
89 file = NULL;
90 str = strA;
91 xref = NULL;
92 catalog = NULL;
93 links = NULL;
94 printCommands = printCommandsA;
95 ok = setup(ownerPassword, userPassword);
96}
97
98GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
99 // check header
100 checkHeader();
101
102 // read xref table
103 xref = new XRef(str, ownerPassword, userPassword);
104 if (!xref->isOk()) {
105 error(-1, "Couldn't read xref table");
106 return gFalse;
107 }
108
109 // read catalog
110 catalog = new Catalog(xref, printCommands);
111 if (!catalog->isOk()) {
112 error(-1, "Couldn't read page catalog");
113 return gFalse;
114 }
115
116 // done
117 return gTrue;
118}
119
120PDFDoc::~PDFDoc() {
121 if (catalog) {
122 delete catalog;
123 }
124 if (xref) {
125 delete xref;
126 }
127 if (str) {
128 delete str;
129 }
130 if (file) {
131 fclose(file);
132 }
133 if (fileName) {
134 delete fileName;
135 }
136 if (links) {
137 delete links;
138 }
139}
140
141// Check for a PDF header on this stream. Skip past some garbage
142// if necessary.
143void PDFDoc::checkHeader() {
144 char hdrBuf[headerSearchSize+1];
145 char *p;
146 int i;
147
148 pdfVersion = 0;
149 for (i = 0; i < headerSearchSize; ++i) {
150 hdrBuf[i] = str->getChar();
151 }
152 hdrBuf[headerSearchSize] = '\0';
153 for (i = 0; i < headerSearchSize - 5; ++i) {
154 if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
155 break;
156 }
157 }
158 if (i >= headerSearchSize - 5) {
159 error(-1, "May not be a PDF file (continuing anyway)");
160 return;
161 }
162 str->moveStart(i);
163 p = strtok(&hdrBuf[i+5], " \t\n\r");
164 pdfVersion = atof(p);
165 if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
166 pdfVersion > supportedPDFVersionNum + 0.0001) {
167 error(-1, "PDF version %s -- xpdf supports version %s"
168 " (continuing anyway)", p, supportedPDFVersionStr);
169 }
170}
171
172void PDFDoc::displayPage(OutputDev *out, int page, fouble zoom,
173 int rotate, GBool doLinks) {
174 Page *p;
175
176 if (printCommands) {
177 printf("***** page %d *****\n", page);
178 }
179 p = catalog->getPage(page);
180 if (doLinks) {
181 if (links) {
182 delete links;
183 }
184 getLinks(p);
185 p->display(out, zoom, rotate, links, catalog);
186 } else {
187 p->display(out, zoom, rotate, NULL, catalog);
188 }
189}
190
191void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
192 int zoom, int rotate, GBool doLinks) {
193 int page;
194
195 for (page = firstPage; page <= lastPage; ++page) {
196 displayPage(out, page, zoom, rotate, doLinks);
197 }
198}
199
200GBool PDFDoc::isLinearized() {
201 Parser *parser;
202 Object obj1, obj2, obj3, obj4, obj5;
203 GBool lin;
204
205 lin = gFalse;
206 obj1.initNull();
207 parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(),
208 -1, &obj1)));
209 parser->getObj(&obj1);
210 parser->getObj(&obj2);
211 parser->getObj(&obj3);
212 parser->getObj(&obj4);
213 if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
214 obj4.isDict()) {
215 obj4.dictLookup("Linearized", &obj5);
216 if (obj5.isNum() && obj5.getNum() > 0) {
217 lin = gTrue;
218 }
219 obj5.free();
220 }
221 obj4.free();
222 obj3.free();
223 obj2.free();
224 obj1.free();
225 delete parser;
226 return lin;
227}
228
229GBool PDFDoc::saveAs(GString *name) {
230 FILE *f;
231 int c;
232
233 if (!(f = fopen(name->getCString(), "wb"))) {
234 error(-1, "Couldn't open file '%s'", name->getCString());
235 return gFalse;
236 }
237 str->reset();
238 while ((c = str->getChar()) != EOF) {
239 fputc(c, f);
240 }
241 str->close();
242 fclose(f);
243 return gTrue;
244}
245
246void PDFDoc::getLinks(Page *page) {
247 Object obj;
248
249 links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
250 obj.free();
251}
diff --git a/noncore/unsupported/qpdf/xpdf/PDFDoc.h b/noncore/unsupported/qpdf/xpdf/PDFDoc.h
new file mode 100644
index 0000000..592095e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/PDFDoc.h
@@ -0,0 +1,142 @@
1//========================================================================
2//
3// PDFDoc.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef PDFDOC_H
10#define PDFDOC_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include <stdio.h>
17#include "XRef.h"
18#include "Link.h"
19#include "Catalog.h"
20#include "Page.h"
21
22class GString;
23class BaseStream;
24class OutputDev;
25class Links;
26class LinkAction;
27class LinkDest;
28
29//------------------------------------------------------------------------
30// PDFDoc
31//------------------------------------------------------------------------
32
33class PDFDoc {
34public:
35
36 PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
37 GString *userPassword = NULL, GBool printCommandsA = gFalse);
38 PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
39 GString *userPassword = NULL, GBool printCommandsA = gFalse);
40 ~PDFDoc();
41
42 // Was PDF document successfully opened?
43 GBool isOk() { return ok; }
44
45 // Get file name.
46 GString *getFileName() { return fileName; }
47
48 // Get the xref table.
49 XRef *getXRef() { return xref; }
50
51 // Get catalog.
52 Catalog *getCatalog() { return catalog; }
53
54 // Get base stream.
55 BaseStream *getBaseStream() { return str; }
56
57 // Get page parameters.
58 fouble getPageWidth(int page)
59 { return catalog->getPage(page)->getWidth(); }
60 fouble getPageHeight(int page)
61 { return catalog->getPage(page)->getHeight(); }
62 int getPageRotate(int page)
63 { return catalog->getPage(page)->getRotate(); }
64
65 // Get number of pages.
66 int getNumPages() { return catalog->getNumPages(); }
67
68 // Return the contents of the metadata stream, or NULL if there is
69 // no metadata.
70 GString *readMetadata() { return catalog->readMetadata(); }
71
72 // Return the structure tree root object.
73 Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
74
75 // Display a page.
76 void displayPage(OutputDev *out, int page, fouble zoom,
77 int rotate, GBool doLinks);
78
79 // Display a range of pages.
80 void displayPages(OutputDev *out, int firstPage, int lastPage,
81 int zoom, int rotate, GBool doLinks);
82
83 // Find a page, given its object ID. Returns page number, or 0 if
84 // not found.
85 int findPage(int num, int gen) { return catalog->findPage(num, gen); }
86
87 // If point <x>,<y> is in a link, return the associated action;
88 // else return NULL.
89 LinkAction *findLink(fouble x, fouble y) { return links->find(x, y); }
90
91 // Return true if <x>,<y> is in a link.
92 GBool onLink(fouble x, fouble y) { return links->onLink(x, y); }
93
94 // Find a named destination. Returns the link destination, or
95 // NULL if <name> is not a destination.
96 LinkDest *findDest(GString *name)
97 { return catalog->findDest(name); }
98
99 // Is the file encrypted?
100 GBool isEncrypted() { return xref->isEncrypted(); }
101
102 // Check various permissions.
103 GBool okToPrint(GBool ignoreOwnerPW = gFalse)
104 { return xref->okToPrint(ignoreOwnerPW); }
105 GBool okToChange(GBool ignoreOwnerPW = gFalse)
106 { return xref->okToChange(ignoreOwnerPW); }
107 GBool okToCopy(GBool ignoreOwnerPW = gFalse)
108 { return xref->okToCopy(ignoreOwnerPW); }
109 GBool okToAddNotes(GBool ignoreOwnerPW = gFalse)
110 { return xref->okToAddNotes(ignoreOwnerPW); }
111
112 // Is this document linearized?
113 GBool isLinearized();
114
115 // Return the document's Info dictionary (if any).
116 Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); }
117
118 // Return the PDF version specified by the file.
119 fouble getPDFVersion() { return pdfVersion; }
120
121 // Save this file with another name.
122 GBool saveAs(GString *name);
123
124private:
125
126 GBool setup(GString *ownerPassword, GString *userPassword);
127 void checkHeader();
128 void getLinks(Page *page);
129
130 GString *fileName;
131 FILE *file;
132 BaseStream *str;
133 fouble pdfVersion;
134 XRef *xref;
135 Catalog *catalog;
136 Links *links;
137 GBool printCommands;
138
139 GBool ok;
140};
141
142#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Page.cc b/noncore/unsupported/qpdf/xpdf/Page.cc
new file mode 100644
index 0000000..17c4481
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Page.cc
@@ -0,0 +1,267 @@
1//========================================================================
2//
3// Page.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include "Object.h"
16#include "Array.h"
17#include "Dict.h"
18#include "XRef.h"
19#include "Link.h"
20#include "OutputDev.h"
21#ifndef PDF_PARSER_ONLY
22#include "Gfx.h"
23#include "FormWidget.h"
24#endif
25#include "Error.h"
26#include "Page.h"
27
28//------------------------------------------------------------------------
29// PageAttrs
30//------------------------------------------------------------------------
31
32PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
33 Object obj1;
34 fouble w, h;
35
36 // get old/default values
37 if (attrs) {
38 mediaBox = attrs->mediaBox;
39 cropBox = attrs->cropBox;
40 haveCropBox = attrs->haveCropBox;
41 rotate = attrs->rotate;
42 attrs->resources.copy(&resources);
43 } else {
44 // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
45 // but some (non-compliant) PDF files don't specify a MediaBox
46 mediaBox.x1 = 0;
47 mediaBox.y1 = 0;
48 mediaBox.x2 = 612;
49 mediaBox.y2 = 792;
50 cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
51 haveCropBox = gFalse;
52 rotate = 0;
53 resources.initNull();
54 }
55
56 // media box
57 readBox(dict, "MediaBox", &mediaBox);
58
59 // crop box
60 cropBox = mediaBox;
61 haveCropBox = readBox(dict, "CropBox", &cropBox);
62
63 // if the MediaBox is excessively larger than the CropBox,
64 // just use the CropBox
65 limitToCropBox = gFalse;
66 if (haveCropBox) {
67 w = 0.25 * (cropBox.x2 - cropBox.x1);
68 h = 0.25 * (cropBox.y2 - cropBox.y1);
69 if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
70 (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
71 limitToCropBox = gTrue;
72 }
73 }
74
75 // other boxes
76 bleedBox = cropBox;
77 readBox(dict, "BleedBox", &bleedBox);
78 trimBox = cropBox;
79 readBox(dict, "TrimBox", &trimBox);
80 artBox = cropBox;
81 readBox(dict, "ArtBox", &artBox);
82
83 // rotate
84 dict->lookup("Rotate", &obj1);
85 if (obj1.isInt()) {
86 rotate = obj1.getInt();
87 }
88 obj1.free();
89 while (rotate < 0) {
90 rotate += 360;
91 }
92 while (rotate >= 360) {
93 rotate -= 360;
94 }
95
96 // resource dictionary
97 dict->lookup("Resources", &obj1);
98 if (obj1.isDict()) {
99 resources.free();
100 obj1.copy(&resources);
101 }
102 obj1.free();
103}
104
105PageAttrs::~PageAttrs() {
106 resources.free();
107}
108
109GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
110 PDFRectangle tmp;
111 Object obj1, obj2;
112 GBool ok;
113
114 dict->lookup(key, &obj1);
115 if (obj1.isArray() && obj1.arrayGetLength() == 4) {
116 ok = gTrue;
117 obj1.arrayGet(0, &obj2);
118 if (obj2.isNum()) {
119 tmp.x1 = obj2.getNum();
120 } else {
121 ok = gFalse;
122 }
123 obj2.free();
124 obj1.arrayGet(1, &obj2);
125 if (obj2.isNum()) {
126 tmp.y1 = obj2.getNum();
127 } else {
128 ok = gFalse;
129 }
130 obj2.free();
131 obj1.arrayGet(2, &obj2);
132 if (obj2.isNum()) {
133 tmp.x2 = obj2.getNum();
134 } else {
135 ok = gFalse;
136 }
137 obj2.free();
138 obj1.arrayGet(3, &obj2);
139 if (obj2.isNum()) {
140 tmp.y2 = obj2.getNum();
141 } else {
142 ok = gFalse;
143 }
144 obj2.free();
145 if (ok) {
146 *box = tmp;
147 }
148 } else {
149 ok = gFalse;
150 }
151 obj1.free();
152 return ok;
153}
154
155//------------------------------------------------------------------------
156// Page
157//------------------------------------------------------------------------
158
159Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
160 GBool printCommandsA) {
161
162 ok = gTrue;
163 xref = xrefA;
164 num = numA;
165 printCommands = printCommandsA;
166
167 // get attributes
168 attrs = attrsA;
169
170 // annotations
171 pageDict->lookupNF("Annots", &annots);
172 if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
173 error(-1, "Page annotations object (page %d) is wrong type (%s)",
174 num, annots.getTypeName());
175 annots.free();
176 goto err2;
177 }
178
179 // contents
180 pageDict->lookupNF("Contents", &contents);
181 if (!(contents.isRef() || contents.isArray() ||
182 contents.isNull())) {
183 error(-1, "Page contents object (page %d) is wrong type (%s)",
184 num, contents.getTypeName());
185 contents.free();
186 goto err1;
187 }
188
189 return;
190
191 err2:
192 annots.initNull();
193 err1:
194 contents.initNull();
195 ok = gFalse;
196}
197
198Page::~Page() {
199 delete attrs;
200 annots.free();
201 contents.free();
202}
203
204void Page::display(OutputDev *out, fouble dpi, int rotate,
205 Links *links, Catalog *catalog) {
206#ifndef PDF_PARSER_ONLY
207 PDFRectangle *box, *cropBox;
208 Gfx *gfx;
209 Object obj;
210 Link *link;
211 int i;
212 FormWidgets *formWidgets;
213
214 box = getBox();
215 cropBox = getCropBox();
216
217 if (printCommands) {
218 printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
219 box->x1, box->y1, box->x2, box->y2);
220 if (isCropped()) {
221 printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
222 cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
223 }
224 printf("***** Rotate = %d\n", attrs->getRotate());
225 }
226
227 rotate += getRotate();
228 if (rotate >= 360) {
229 rotate -= 360;
230 } else if (rotate < 0) {
231 rotate += 360;
232 }
233 gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
234 dpi, box, isCropped(), cropBox, rotate, printCommands);
235 contents.fetch(xref, &obj);
236 if (!obj.isNull()) {
237 gfx->display(&obj);
238 }
239 obj.free();
240
241 // draw links
242 if (links) {
243 for (i = 0; i < links->getNumLinks(); ++i) {
244 link = links->getLink(i);
245 out->drawLink(link, catalog);
246 }
247 out->dump();
248 }
249
250 // draw AcroForm widgets
251 //~ need to reset CTM ???
252 formWidgets = new FormWidgets(xref, annots.fetch(xref, &obj));
253 obj.free();
254 if (printCommands && formWidgets->getNumWidgets() > 0) {
255 printf("***** AcroForm widgets\n");
256 }
257 for (i = 0; i < formWidgets->getNumWidgets(); ++i) {
258 formWidgets->getWidget(i)->draw(gfx);
259 }
260 if (formWidgets->getNumWidgets() > 0) {
261 out->dump();
262 }
263 delete formWidgets;
264
265 delete gfx;
266#endif
267}
diff --git a/noncore/unsupported/qpdf/xpdf/Page.h b/noncore/unsupported/qpdf/xpdf/Page.h
new file mode 100644
index 0000000..203878f
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Page.h
@@ -0,0 +1,125 @@
1//========================================================================
2//
3// Page.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef PAGE_H
10#define PAGE_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "Object.h"
17
18class Dict;
19class XRef;
20class OutputDev;
21class Links;
22class Catalog;
23
24//------------------------------------------------------------------------
25
26struct PDFRectangle {
27 fouble x1, y1, x2, y2;
28};
29
30//------------------------------------------------------------------------
31// PageAttrs
32//------------------------------------------------------------------------
33
34class PageAttrs {
35public:
36
37 // Construct a new PageAttrs object by merging a dictionary
38 // (of type Pages or Page) into another PageAttrs object. If
39 // <attrs> is NULL, uses defaults.
40 PageAttrs(PageAttrs *attrs, Dict *dict);
41
42 // Destructor.
43 ~PageAttrs();
44
45 // Accessors.
46 PDFRectangle *getBox() { return limitToCropBox ? &cropBox : &mediaBox; }
47 PDFRectangle *getMediaBox() { return &mediaBox; }
48 PDFRectangle *getCropBox() { return &cropBox; }
49 GBool isCropped() { return haveCropBox; }
50 PDFRectangle *getBleedBox() { return &bleedBox; }
51 PDFRectangle *getTrimBox() { return &trimBox; }
52 PDFRectangle *getArtBox() { return &artBox; }
53 int getRotate() { return rotate; }
54 Dict *getResourceDict()
55 { return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
56
57private:
58
59 GBool readBox(Dict *dict, char *key, PDFRectangle *box);
60
61 PDFRectangle mediaBox;
62 PDFRectangle cropBox;
63 GBool haveCropBox;
64 GBool limitToCropBox;
65 PDFRectangle bleedBox;
66 PDFRectangle trimBox;
67 PDFRectangle artBox;
68 int rotate;
69 Object resources;
70};
71
72//------------------------------------------------------------------------
73// Page
74//------------------------------------------------------------------------
75
76class Page {
77public:
78
79 // Constructor.
80 Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
81 GBool printCommandsA);
82
83 // Destructor.
84 ~Page();
85
86 // Is page valid?
87 GBool isOk() { return ok; }
88
89 // Get page parameters.
90 PDFRectangle *getBox() { return attrs->getBox(); }
91 PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
92 PDFRectangle *getCropBox() { return attrs->getCropBox(); }
93 GBool isCropped() { return attrs->isCropped(); }
94 fouble getWidth() { return attrs->getBox()->x2 - attrs->getBox()->x1; }
95 fouble getHeight() { return attrs->getBox()->y2 - attrs->getBox()->y1; }
96 PDFRectangle *getBleedBox() { return attrs->getBleedBox(); }
97 PDFRectangle *getTrimBox() { return attrs->getTrimBox(); }
98 PDFRectangle *getArtBox() { return attrs->getArtBox(); }
99 int getRotate() { return attrs->getRotate(); }
100
101 // Get resource dictionary.
102 Dict *getResourceDict() { return attrs->getResourceDict(); }
103
104 // Get annotations array.
105 Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
106
107 // Get contents.
108 Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
109
110 // Display a page.
111 void display(OutputDev *out, fouble dpi, int rotate,
112 Links *links, Catalog *catalog);
113
114private:
115
116 XRef *xref; // the xref table for this PDF file
117 int num; // page number
118 PageAttrs *attrs; // page attributes
119 Object annots; // annotations array
120 Object contents; // page contents
121 GBool printCommands; // print the drawing commands (for debugging)
122 GBool ok; // true if page is valid
123};
124
125#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Parser.cc b/noncore/unsupported/qpdf/xpdf/Parser.cc
new file mode 100644
index 0000000..a98753d
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Parser.cc
@@ -0,0 +1,213 @@
1//========================================================================
2//
3// Parser.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stddef.h>
15#include "Object.h"
16#include "Array.h"
17#include "Dict.h"
18#include "Parser.h"
19#include "XRef.h"
20#include "Error.h"
21#ifndef NO_DECRYPTION
22#include "Decrypt.h"
23#endif
24
25Parser::Parser(XRef *xrefA, Lexer *lexerA) {
26 xref = xrefA;
27 lexer = lexerA;
28 inlineImg = 0;
29 lexer->getObj(&buf1);
30 lexer->getObj(&buf2);
31}
32
33Parser::~Parser() {
34 buf1.free();
35 buf2.free();
36 delete lexer;
37}
38
39#ifndef NO_DECRYPTION
40Object *Parser::getObj(Object *obj,
41 Guchar *fileKey, int keyLength,
42 int objNum, int objGen) {
43#else
44Object *Parser::getObj(Object *obj) {
45#endif
46 char *key;
47 Stream *str;
48 Object obj2;
49 int num;
50#ifndef NO_DECRYPTION
51 Decrypt *decrypt;
52 GString *s;
53 char *p;
54 int i;
55#endif
56
57 // refill buffer after inline image data
58 if (inlineImg == 2) {
59 buf1.free();
60 buf2.free();
61 lexer->getObj(&buf1);
62 lexer->getObj(&buf2);
63 inlineImg = 0;
64 }
65
66 // array
67 if (buf1.isCmd("[")) {
68 shift();
69 obj->initArray(xref);
70 while (!buf1.isCmd("]") && !buf1.isEOF())
71#ifndef NO_DECRYPTION
72 obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
73#else
74 obj->arrayAdd(getObj(&obj2));
75#endif
76 if (buf1.isEOF())
77 error(getPos(), "End of file inside array");
78 shift();
79
80 // dictionary or stream
81 } else if (buf1.isCmd("<<")) {
82 shift();
83 obj->initDict(xref);
84 while (!buf1.isCmd(">>") && !buf1.isEOF()) {
85 if (!buf1.isName()) {
86 error(getPos(), "Dictionary key must be a name object");
87 shift();
88 } else {
89 key = copyString(buf1.getName());
90 shift();
91 if (buf1.isEOF() || buf1.isError())
92 break;
93#ifndef NO_DECRYPTION
94 obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
95#else
96 obj->dictAdd(key, getObj(&obj2));
97#endif
98 }
99 }
100 if (buf1.isEOF())
101 error(getPos(), "End of file inside dictionary");
102 if (buf2.isCmd("stream")) {
103 if ((str = makeStream(obj))) {
104 obj->initStream(str);
105#ifndef NO_DECRYPTION
106 if (fileKey) {
107 str->getBaseStream()->doDecryption(fileKey, keyLength,
108 objNum, objGen);
109 }
110#endif
111 } else {
112 obj->free();
113 obj->initError();
114 }
115 } else {
116 shift();
117 }
118
119 // indirect reference or integer
120 } else if (buf1.isInt()) {
121 num = buf1.getInt();
122 shift();
123 if (buf1.isInt() && buf2.isCmd("R")) {
124 obj->initRef(num, buf1.getInt());
125 shift();
126 shift();
127 } else {
128 obj->initInt(num);
129 }
130
131#ifndef NO_DECRYPTION
132 // string
133 } else if (buf1.isString() && fileKey) {
134 buf1.copy(obj);
135 s = obj->getString();
136 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
137 for (i = 0, p = obj->getString()->getCString();
138 i < s->getLength();
139 ++i, ++p) {
140 *p = decrypt->decryptByte(*p);
141 }
142 delete decrypt;
143 shift();
144#endif
145
146 // simple object
147 } else {
148 buf1.copy(obj);
149 shift();
150 }
151
152 return obj;
153}
154
155Stream *Parser::makeStream(Object *dict) {
156 Object obj;
157 Stream *str;
158 int pos, endPos, length;
159
160 // get stream start position
161 lexer->skipToNextLine();
162 pos = lexer->getPos();
163
164 // get length
165 dict->dictLookup("Length", &obj);
166 if (obj.isInt()) {
167 length = obj.getInt();
168 obj.free();
169 } else {
170 error(getPos(), "Bad 'Length' attribute in stream");
171 obj.free();
172 return NULL;
173 }
174
175 // check for length in damaged file
176 if ((endPos = xref->getStreamEnd(pos)) >= 0) {
177 length = endPos - pos;
178 }
179
180 // make base stream
181 str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict);
182
183 // get filters
184 str = str->addFilters(dict);
185
186 // skip over stream data
187 lexer->setPos(pos + length);
188
189 // refill token buffers and check for 'endstream'
190 shift(); // kill '>>'
191 shift(); // kill 'stream'
192 if (buf1.isCmd("endstream"))
193 shift();
194 else
195 error(getPos(), "Missing 'endstream'");
196
197 return str;
198}
199
200void Parser::shift() {
201 if (inlineImg > 0) {
202 ++inlineImg;
203 } else if (buf2.isCmd("ID")) {
204 lexer->skipChar(); // skip char after 'ID' command
205 inlineImg = 1;
206 }
207 buf1.free();
208 buf1 = buf2;
209 if (inlineImg > 0) // don't buffer inline image data
210 buf2.initNull();
211 else
212 lexer->getObj(&buf2);
213}
diff --git a/noncore/unsupported/qpdf/xpdf/Parser.h b/noncore/unsupported/qpdf/xpdf/Parser.h
new file mode 100644
index 0000000..463d998
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Parser.h
@@ -0,0 +1,58 @@
1//========================================================================
2//
3// Parser.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef PARSER_H
10#define PARSER_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "Lexer.h"
17
18//------------------------------------------------------------------------
19// Parser
20//------------------------------------------------------------------------
21
22class Parser {
23public:
24
25 // Constructor.
26 Parser(XRef *xrefA, Lexer *lexerA);
27
28 // Destructor.
29 ~Parser();
30
31 // Get the next object from the input stream.
32#ifndef NO_DECRYPTION
33 Object *getObj(Object *obj,
34 Guchar *fileKey = NULL, int keyLength = 0,
35 int objNum = 0, int objGen = 0);
36#else
37 Object *getObj(Object *obj);
38#endif
39
40 // Get stream.
41 Stream *getStream() { return lexer->getStream(); }
42
43 // Get current position in file.
44 int getPos() { return lexer->getPos(); }
45
46private:
47
48 XRef *xref; // the xref table for this PDF file
49 Lexer *lexer; // input stream
50 Object buf1, buf2; // next two tokens
51 int inlineImg; // set when inline image data is encountered
52
53 Stream *makeStream(Object *dict);
54 void shift();
55};
56
57#endif
58
diff --git a/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h b/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h
new file mode 100644
index 0000000..1af8742
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h
@@ -0,0 +1,459 @@
1//========================================================================
2//
3// Stream-CCITT.h
4//
5// Tables for CCITT Fax decoding.
6//
7// Copyright 1996 Derek B. Noonburg
8//
9//========================================================================
10
11struct CCITTCode {
12 short bits;
13 short n;
14};
15
16#define ccittEOL -2
17
18//------------------------------------------------------------------------
19// 2D codes
20//------------------------------------------------------------------------
21
22#define twoDimPass 0
23#define twoDimHoriz 1
24#define twoDimVert0 2
25#define twoDimVertR1 3
26#define twoDimVertL1 4
27#define twoDimVertR2 5
28#define twoDimVertL2 6
29#define twoDimVertR3 7
30#define twoDimVertL3 8
31
32// 1-7 bit codes
33static CCITTCode twoDimTab1[128] = {
34 {-1, -1}, {-1, -1}, // 000000x
35 {7, twoDimVertL3}, // 0000010
36 {7, twoDimVertR3}, // 0000011
37 {6, twoDimVertL2}, {6, twoDimVertL2},// 000010x
38 {6, twoDimVertR2}, {6, twoDimVertR2},// 000011x
39 {4, twoDimPass}, {4, twoDimPass}, // 0001xxx
40 {4, twoDimPass}, {4, twoDimPass},
41 {4, twoDimPass}, {4, twoDimPass},
42 {4, twoDimPass}, {4, twoDimPass},
43 {3, twoDimHoriz}, {3, twoDimHoriz},// 001xxxx
44 {3, twoDimHoriz}, {3, twoDimHoriz},
45 {3, twoDimHoriz}, {3, twoDimHoriz},
46 {3, twoDimHoriz}, {3, twoDimHoriz},
47 {3, twoDimHoriz}, {3, twoDimHoriz},
48 {3, twoDimHoriz}, {3, twoDimHoriz},
49 {3, twoDimHoriz}, {3, twoDimHoriz},
50 {3, twoDimHoriz}, {3, twoDimHoriz},
51 {3, twoDimVertL1}, {3, twoDimVertL1},// 010xxxx
52 {3, twoDimVertL1}, {3, twoDimVertL1},
53 {3, twoDimVertL1}, {3, twoDimVertL1},
54 {3, twoDimVertL1}, {3, twoDimVertL1},
55 {3, twoDimVertL1}, {3, twoDimVertL1},
56 {3, twoDimVertL1}, {3, twoDimVertL1},
57 {3, twoDimVertL1}, {3, twoDimVertL1},
58 {3, twoDimVertL1}, {3, twoDimVertL1},
59 {3, twoDimVertR1}, {3, twoDimVertR1},// 011xxxx
60 {3, twoDimVertR1}, {3, twoDimVertR1},
61 {3, twoDimVertR1}, {3, twoDimVertR1},
62 {3, twoDimVertR1}, {3, twoDimVertR1},
63 {3, twoDimVertR1}, {3, twoDimVertR1},
64 {3, twoDimVertR1}, {3, twoDimVertR1},
65 {3, twoDimVertR1}, {3, twoDimVertR1},
66 {3, twoDimVertR1}, {3, twoDimVertR1},
67 {1, twoDimVert0}, {1, twoDimVert0},// 1xxxxxx
68 {1, twoDimVert0}, {1, twoDimVert0},
69 {1, twoDimVert0}, {1, twoDimVert0},
70 {1, twoDimVert0}, {1, twoDimVert0},
71 {1, twoDimVert0}, {1, twoDimVert0},
72 {1, twoDimVert0}, {1, twoDimVert0},
73 {1, twoDimVert0}, {1, twoDimVert0},
74 {1, twoDimVert0}, {1, twoDimVert0},
75 {1, twoDimVert0}, {1, twoDimVert0},
76 {1, twoDimVert0}, {1, twoDimVert0},
77 {1, twoDimVert0}, {1, twoDimVert0},
78 {1, twoDimVert0}, {1, twoDimVert0},
79 {1, twoDimVert0}, {1, twoDimVert0},
80 {1, twoDimVert0}, {1, twoDimVert0},
81 {1, twoDimVert0}, {1, twoDimVert0},
82 {1, twoDimVert0}, {1, twoDimVert0},
83 {1, twoDimVert0}, {1, twoDimVert0},
84 {1, twoDimVert0}, {1, twoDimVert0},
85 {1, twoDimVert0}, {1, twoDimVert0},
86 {1, twoDimVert0}, {1, twoDimVert0},
87 {1, twoDimVert0}, {1, twoDimVert0},
88 {1, twoDimVert0}, {1, twoDimVert0},
89 {1, twoDimVert0}, {1, twoDimVert0},
90 {1, twoDimVert0}, {1, twoDimVert0},
91 {1, twoDimVert0}, {1, twoDimVert0},
92 {1, twoDimVert0}, {1, twoDimVert0},
93 {1, twoDimVert0}, {1, twoDimVert0},
94 {1, twoDimVert0}, {1, twoDimVert0},
95 {1, twoDimVert0}, {1, twoDimVert0},
96 {1, twoDimVert0}, {1, twoDimVert0},
97 {1, twoDimVert0}, {1, twoDimVert0},
98 {1, twoDimVert0}, {1, twoDimVert0}
99};
100
101//------------------------------------------------------------------------
102// white run lengths
103//------------------------------------------------------------------------
104
105// 11-12 bit codes (upper 7 bits are 0)
106static CCITTCode whiteTab1[32] = {
107 {-1, -1}, // 00000
108 {12, ccittEOL}, // 00001
109 {-1, -1}, {-1, -1}, // 0001x
110 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1},// 001xx
111 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1},// 010xx
112 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1},// 011xx
113 {11, 1792}, {11, 1792}, // 1000x
114 {12, 1984}, // 10010
115 {12, 2048}, // 10011
116 {12, 2112}, // 10100
117 {12, 2176}, // 10101
118 {12, 2240}, // 10110
119 {12, 2304}, // 10111
120 {11, 1856}, {11, 1856}, // 1100x
121 {11, 1920}, {11, 1920}, // 1101x
122 {12, 2368}, // 11100
123 {12, 2432}, // 11101
124 {12, 2496}, // 11110
125 {12, 2560} // 11111
126};
127
128// 1-9 bit codes
129static CCITTCode whiteTab2[512] = {
130 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1},// 0000000xx
131 {8, 29}, {8, 29}, // 00000010x
132 {8, 30}, {8, 30}, // 00000011x
133 {8, 45}, {8, 45}, // 00000100x
134 {8, 46}, {8, 46}, // 00000101x
135 {7, 22}, {7, 22}, {7, 22}, {7, 22}, // 0000011xx
136 {7, 23}, {7, 23}, {7, 23}, {7, 23}, // 0000100xx
137 {8, 47}, {8, 47}, // 00001010x
138 {8, 48}, {8, 48}, // 00001011x
139 {6, 13}, {6, 13}, {6, 13}, {6, 13}, // 000011xxx
140 {6, 13}, {6, 13}, {6, 13}, {6, 13},
141 {7, 20}, {7, 20}, {7, 20}, {7, 20}, // 0001000xx
142 {8, 33}, {8, 33}, // 00010010x
143 {8, 34}, {8, 34}, // 00010011x
144 {8, 35}, {8, 35}, // 00010100x
145 {8, 36}, {8, 36}, // 00010101x
146 {8, 37}, {8, 37}, // 00010110x
147 {8, 38}, {8, 38}, // 00010111x
148 {7, 19}, {7, 19}, {7, 19}, {7, 19}, // 0001100xx
149 {8, 31}, {8, 31}, // 00011010x
150 {8, 32}, {8, 32}, // 00011011x
151 {6, 1}, {6, 1}, {6, 1}, {6, 1}, // 000111xxx
152 {6, 1}, {6, 1}, {6, 1}, {6, 1},
153 {6, 12}, {6, 12}, {6, 12}, {6, 12}, // 001000xxx
154 {6, 12}, {6, 12}, {6, 12}, {6, 12},
155 {8, 53}, {8, 53}, // 00100100x
156 {8, 54}, {8, 54}, // 00100101x
157 {7, 26}, {7, 26}, {7, 26}, {7, 26}, // 0010011xx
158 {8, 39}, {8, 39}, // 00101000x
159 {8, 40}, {8, 40}, // 00101001x
160 {8, 41}, {8, 41}, // 00101010x
161 {8, 42}, {8, 42}, // 00101011x
162 {8, 43}, {8, 43}, // 00101100x
163 {8, 44}, {8, 44}, // 00101101x
164 {7, 21}, {7, 21}, {7, 21}, {7, 21}, // 0010111xx
165 {7, 28}, {7, 28}, {7, 28}, {7, 28}, // 0011000xx
166 {8, 61}, {8, 61}, // 00110010x
167 {8, 62}, {8, 62}, // 00110011x
168 {8, 63}, {8, 63}, // 00110100x
169 {8, 0}, {8, 0}, // 00110101x
170 {8, 320}, {8, 320}, // 00110110x
171 {8, 384}, {8, 384}, // 00110111x
172 {5, 10}, {5, 10}, {5, 10}, {5, 10}, // 00111xxxx
173 {5, 10}, {5, 10}, {5, 10}, {5, 10},
174 {5, 10}, {5, 10}, {5, 10}, {5, 10},
175 {5, 10}, {5, 10}, {5, 10}, {5, 10},
176 {5, 11}, {5, 11}, {5, 11}, {5, 11}, // 01000xxxx
177 {5, 11}, {5, 11}, {5, 11}, {5, 11},
178 {5, 11}, {5, 11}, {5, 11}, {5, 11},
179 {5, 11}, {5, 11}, {5, 11}, {5, 11},
180 {7, 27}, {7, 27}, {7, 27}, {7, 27}, // 0100100xx
181 {8, 59}, {8, 59}, // 01001010x
182 {8, 60}, {8, 60}, // 01001011x
183 {9, 1472}, // 010011000
184 {9, 1536}, // 010011001
185 {9, 1600}, // 010011010
186 {9, 1728}, // 010011011
187 {7, 18}, {7, 18}, {7, 18}, {7, 18}, // 0100111xx
188 {7, 24}, {7, 24}, {7, 24}, {7, 24}, // 0101000xx
189 {8, 49}, {8, 49}, // 01010010x
190 {8, 50}, {8, 50}, // 01010011x
191 {8, 51}, {8, 51}, // 01010100x
192 {8, 52}, {8, 52}, // 01010101x
193 {7, 25}, {7, 25}, {7, 25}, {7, 25}, // 0101011xx
194 {8, 55}, {8, 55}, // 01011000x
195 {8, 56}, {8, 56}, // 01011001x
196 {8, 57}, {8, 57}, // 01011010x
197 {8, 58}, {8, 58}, // 01011011x
198 {6, 192}, {6, 192}, {6, 192}, {6, 192},// 010111xxx
199 {6, 192}, {6, 192}, {6, 192}, {6, 192},
200 {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664},// 011000xxx
201 {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664},
202 {8, 448}, {8, 448}, // 01100100x
203 {8, 512}, {8, 512}, // 01100101x
204 {9, 704}, // 011001100
205 {9, 768}, // 011001101
206 {8, 640}, {8, 640}, // 01100111x
207 {8, 576}, {8, 576}, // 01101000x
208 {9, 832}, // 011010010
209 {9, 896}, // 011010011
210 {9, 960}, // 011010100
211 {9, 1024}, // 011010101
212 {9, 1088}, // 011010110
213 {9, 1152}, // 011010111
214 {9, 1216}, // 011011000
215 {9, 1280}, // 011011001
216 {9, 1344}, // 011011010
217 {9, 1408}, // 011011011
218 {7, 256}, {7, 256}, {7, 256}, {7, 256},// 0110111xx
219 {4, 2}, {4, 2}, {4, 2}, {4, 2}, // 0111xxxxx
220 {4, 2}, {4, 2}, {4, 2}, {4, 2},
221 {4, 2}, {4, 2}, {4, 2}, {4, 2},
222 {4, 2}, {4, 2}, {4, 2}, {4, 2},
223 {4, 2}, {4, 2}, {4, 2}, {4, 2},
224 {4, 2}, {4, 2}, {4, 2}, {4, 2},
225 {4, 2}, {4, 2}, {4, 2}, {4, 2},
226 {4, 2}, {4, 2}, {4, 2}, {4, 2},
227 {4, 3}, {4, 3}, {4, 3}, {4, 3}, // 1000xxxxx
228 {4, 3}, {4, 3}, {4, 3}, {4, 3},
229 {4, 3}, {4, 3}, {4, 3}, {4, 3},
230 {4, 3}, {4, 3}, {4, 3}, {4, 3},
231 {4, 3}, {4, 3}, {4, 3}, {4, 3},
232 {4, 3}, {4, 3}, {4, 3}, {4, 3},
233 {4, 3}, {4, 3}, {4, 3}, {4, 3},
234 {4, 3}, {4, 3}, {4, 3}, {4, 3},
235 {5, 128}, {5, 128}, {5, 128}, {5, 128},// 10010xxxx
236 {5, 128}, {5, 128}, {5, 128}, {5, 128},
237 {5, 128}, {5, 128}, {5, 128}, {5, 128},
238 {5, 128}, {5, 128}, {5, 128}, {5, 128},
239 {5, 8}, {5, 8}, {5, 8}, {5, 8}, // 10011xxxx
240 {5, 8}, {5, 8}, {5, 8}, {5, 8},
241 {5, 8}, {5, 8}, {5, 8}, {5, 8},
242 {5, 8}, {5, 8}, {5, 8}, {5, 8},
243 {5, 9}, {5, 9}, {5, 9}, {5, 9}, // 10100xxxx
244 {5, 9}, {5, 9}, {5, 9}, {5, 9},
245 {5, 9}, {5, 9}, {5, 9}, {5, 9},
246 {5, 9}, {5, 9}, {5, 9}, {5, 9},
247 {6, 16}, {6, 16}, {6, 16}, {6, 16}, // 101010xxx
248 {6, 16}, {6, 16}, {6, 16}, {6, 16},
249 {6, 17}, {6, 17}, {6, 17}, {6, 17}, // 101011xxx
250 {6, 17}, {6, 17}, {6, 17}, {6, 17},
251 {4, 4}, {4, 4}, {4, 4}, {4, 4}, // 1011xxxxx
252 {4, 4}, {4, 4}, {4, 4}, {4, 4},
253 {4, 4}, {4, 4}, {4, 4}, {4, 4},
254 {4, 4}, {4, 4}, {4, 4}, {4, 4},
255 {4, 4}, {4, 4}, {4, 4}, {4, 4},
256 {4, 4}, {4, 4}, {4, 4}, {4, 4},
257 {4, 4}, {4, 4}, {4, 4}, {4, 4},
258 {4, 4}, {4, 4}, {4, 4}, {4, 4},
259 {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 1100xxxxx
260 {4, 5}, {4, 5}, {4, 5}, {4, 5},
261 {4, 5}, {4, 5}, {4, 5}, {4, 5},
262 {4, 5}, {4, 5}, {4, 5}, {4, 5},
263 {4, 5}, {4, 5}, {4, 5}, {4, 5},
264 {4, 5}, {4, 5}, {4, 5}, {4, 5},
265 {4, 5}, {4, 5}, {4, 5}, {4, 5},
266 {4, 5}, {4, 5}, {4, 5}, {4, 5},
267 {6, 14}, {6, 14}, {6, 14}, {6, 14}, // 110100xxx
268 {6, 14}, {6, 14}, {6, 14}, {6, 14},
269 {6, 15}, {6, 15}, {6, 15}, {6, 15}, // 110101xxx
270 {6, 15}, {6, 15}, {6, 15}, {6, 15},
271 {5, 64}, {5, 64}, {5, 64}, {5, 64}, // 11011xxxx
272 {5, 64}, {5, 64}, {5, 64}, {5, 64},
273 {5, 64}, {5, 64}, {5, 64}, {5, 64},
274 {5, 64}, {5, 64}, {5, 64}, {5, 64},
275 {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 1110xxxxx
276 {4, 6}, {4, 6}, {4, 6}, {4, 6},
277 {4, 6}, {4, 6}, {4, 6}, {4, 6},
278 {4, 6}, {4, 6}, {4, 6}, {4, 6},
279 {4, 6}, {4, 6}, {4, 6}, {4, 6},
280 {4, 6}, {4, 6}, {4, 6}, {4, 6},
281 {4, 6}, {4, 6}, {4, 6}, {4, 6},
282 {4, 6}, {4, 6}, {4, 6}, {4, 6},
283 {4, 7}, {4, 7}, {4, 7}, {4, 7}, // 1111xxxxx
284 {4, 7}, {4, 7}, {4, 7}, {4, 7},
285 {4, 7}, {4, 7}, {4, 7}, {4, 7},
286 {4, 7}, {4, 7}, {4, 7}, {4, 7},
287 {4, 7}, {4, 7}, {4, 7}, {4, 7},
288 {4, 7}, {4, 7}, {4, 7}, {4, 7},
289 {4, 7}, {4, 7}, {4, 7}, {4, 7},
290 {4, 7}, {4, 7}, {4, 7}, {4, 7}
291};
292
293//------------------------------------------------------------------------
294// black run lengths
295//------------------------------------------------------------------------
296
297// 10-13 bit codes (upper 6 bits are 0)
298static CCITTCode blackTab1[128] = {
299 {-1, -1}, {-1, -1}, // 000000000000x
300 {12, ccittEOL}, {12, ccittEOL}, // 000000000001x
301 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000001xx
302 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000010xx
303 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000011xx
304 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000100xx
305 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000101xx
306 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000110xx
307 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000111xx
308 {11, 1792}, {11, 1792}, {11, 1792}, {11, 1792},// 00000001000xx
309 {12, 1984}, {12, 1984}, // 000000010010x
310 {12, 2048}, {12, 2048}, // 000000010011x
311 {12, 2112}, {12, 2112}, // 000000010100x
312 {12, 2176}, {12, 2176}, // 000000010101x
313 {12, 2240}, {12, 2240}, // 000000010110x
314 {12, 2304}, {12, 2304}, // 000000010111x
315 {11, 1856}, {11, 1856}, {11, 1856}, {11, 1856},// 00000001100xx
316 {11, 1920}, {11, 1920}, {11, 1920}, {11, 1920},// 00000001101xx
317 {12, 2368}, {12, 2368}, // 000000011100x
318 {12, 2432}, {12, 2432}, // 000000011101x
319 {12, 2496}, {12, 2496}, // 000000011110x
320 {12, 2560}, {12, 2560}, // 000000011111x
321 {10, 18}, {10, 18}, {10, 18}, {10, 18}, // 0000001000xxx
322 {10, 18}, {10, 18}, {10, 18}, {10, 18},
323 {12, 52}, {12, 52}, // 000000100100x
324 {13, 640}, // 0000001001010
325 {13, 704}, // 0000001001011
326 {13, 768}, // 0000001001100
327 {13, 832}, // 0000001001101
328 {12, 55}, {12, 55}, // 000000100111x
329 {12, 56}, {12, 56}, // 000000101000x
330 {13, 1280}, // 0000001010010
331 {13, 1344}, // 0000001010011
332 {13, 1408}, // 0000001010100
333 {13, 1472}, // 0000001010101
334 {12, 59}, {12, 59}, // 000000101011x
335 {12, 60}, {12, 60}, // 000000101100x
336 {13, 1536}, // 0000001011010
337 {13, 1600}, // 0000001011011
338 {11, 24}, {11, 24}, {11, 24}, {11, 24}, // 00000010111xx
339 {11, 25}, {11, 25}, {11, 25}, {11, 25}, // 00000011000xx
340 {13, 1664}, // 0000001100100
341 {13, 1728}, // 0000001100101
342 {12, 320}, {12, 320}, // 000000110011x
343 {12, 384}, {12, 384}, // 000000110100x
344 {12, 448}, {12, 448}, // 000000110101x
345 {13, 512}, // 0000001101100
346 {13, 576}, // 0000001101101
347 {12, 53}, {12, 53}, // 000000110111x
348 {12, 54}, {12, 54}, // 000000111000x
349 {13, 896}, // 0000001110010
350 {13, 960}, // 0000001110011
351 {13, 1024}, // 0000001110100
352 {13, 1088}, // 0000001110101
353 {13, 1152}, // 0000001110110
354 {13, 1216}, // 0000001110111
355 {10, 64}, {10, 64}, {10, 64}, {10, 64}, // 0000001111xxx
356 {10, 64}, {10, 64}, {10, 64}, {10, 64}
357};
358
359// 7-12 bit codes (upper 4 bits are 0)
360static CCITTCode blackTab2[192] = {
361 {8, 13}, {8, 13}, {8, 13}, {8, 13}, // 00000100xxxx
362 {8, 13}, {8, 13}, {8, 13}, {8, 13},
363 {8, 13}, {8, 13}, {8, 13}, {8, 13},
364 {8, 13}, {8, 13}, {8, 13}, {8, 13},
365 {11, 23}, {11, 23}, // 00000101000x
366 {12, 50}, // 000001010010
367 {12, 51}, // 000001010011
368 {12, 44}, // 000001010100
369 {12, 45}, // 000001010101
370 {12, 46}, // 000001010110
371 {12, 47}, // 000001010111
372 {12, 57}, // 000001011000
373 {12, 58}, // 000001011001
374 {12, 61}, // 000001011010
375 {12, 256}, // 000001011011
376 {10, 16}, {10, 16}, {10, 16}, {10, 16}, // 0000010111xx
377 {10, 17}, {10, 17}, {10, 17}, {10, 17}, // 0000011000xx
378 {12, 48}, // 000001100100
379 {12, 49}, // 000001100101
380 {12, 62}, // 000001100110
381 {12, 63}, // 000001100111
382 {12, 30}, // 000001101000
383 {12, 31}, // 000001101001
384 {12, 32}, // 000001101010
385 {12, 33}, // 000001101011
386 {12, 40}, // 000001101100
387 {12, 41}, // 000001101101
388 {11, 22}, {11, 22}, // 00000110111x
389 {8, 14}, {8, 14}, {8, 14}, {8, 14}, // 00000111xxxx
390 {8, 14}, {8, 14}, {8, 14}, {8, 14},
391 {8, 14}, {8, 14}, {8, 14}, {8, 14},
392 {8, 14}, {8, 14}, {8, 14}, {8, 14},
393 {7, 10}, {7, 10}, {7, 10}, {7, 10}, // 0000100xxxxx
394 {7, 10}, {7, 10}, {7, 10}, {7, 10},
395 {7, 10}, {7, 10}, {7, 10}, {7, 10},
396 {7, 10}, {7, 10}, {7, 10}, {7, 10},
397 {7, 10}, {7, 10}, {7, 10}, {7, 10},
398 {7, 10}, {7, 10}, {7, 10}, {7, 10},
399 {7, 10}, {7, 10}, {7, 10}, {7, 10},
400 {7, 10}, {7, 10}, {7, 10}, {7, 10},
401 {7, 11}, {7, 11}, {7, 11}, {7, 11}, // 0000101xxxxx
402 {7, 11}, {7, 11}, {7, 11}, {7, 11},
403 {7, 11}, {7, 11}, {7, 11}, {7, 11},
404 {7, 11}, {7, 11}, {7, 11}, {7, 11},
405 {7, 11}, {7, 11}, {7, 11}, {7, 11},
406 {7, 11}, {7, 11}, {7, 11}, {7, 11},
407 {7, 11}, {7, 11}, {7, 11}, {7, 11},
408 {7, 11}, {7, 11}, {7, 11}, {7, 11},
409 {9, 15}, {9, 15}, {9, 15}, {9, 15}, // 000011000xxx
410 {9, 15}, {9, 15}, {9, 15}, {9, 15},
411 {12, 128}, // 000011001000
412 {12, 192}, // 000011001001
413 {12, 26}, // 000011001010
414 {12, 27}, // 000011001011
415 {12, 28}, // 000011001100
416 {12, 29}, // 000011001101
417 {11, 19}, {11, 19}, // 00001100111x
418 {11, 20}, {11, 20}, // 00001101000x
419 {12, 34}, // 000011010010
420 {12, 35}, // 000011010011
421 {12, 36}, // 000011010100
422 {12, 37}, // 000011010101
423 {12, 38}, // 000011010110
424 {12, 39}, // 000011010111
425 {11, 21}, {11, 21}, // 00001101100x
426 {12, 42}, // 000011011010
427 {12, 43}, // 000011011011
428 {10, 0}, {10, 0}, {10, 0}, {10, 0}, // 0000110111xx
429 {7, 12}, {7, 12}, {7, 12}, {7, 12}, // 0000111xxxxx
430 {7, 12}, {7, 12}, {7, 12}, {7, 12},
431 {7, 12}, {7, 12}, {7, 12}, {7, 12},
432 {7, 12}, {7, 12}, {7, 12}, {7, 12},
433 {7, 12}, {7, 12}, {7, 12}, {7, 12},
434 {7, 12}, {7, 12}, {7, 12}, {7, 12},
435 {7, 12}, {7, 12}, {7, 12}, {7, 12},
436 {7, 12}, {7, 12}, {7, 12}, {7, 12}
437};
438
439// 2-6 bit codes
440static CCITTCode blackTab3[64] = {
441 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000xx
442 {6, 9}, // 000100
443 {6, 8}, // 000101
444 {5, 7}, {5, 7}, // 00011x
445 {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 0010xx
446 {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 0011xx
447 {3, 1}, {3, 1}, {3, 1}, {3, 1}, // 010xxx
448 {3, 1}, {3, 1}, {3, 1}, {3, 1},
449 {3, 4}, {3, 4}, {3, 4}, {3, 4}, // 011xxx
450 {3, 4}, {3, 4}, {3, 4}, {3, 4},
451 {2, 3}, {2, 3}, {2, 3}, {2, 3}, // 10xxxx
452 {2, 3}, {2, 3}, {2, 3}, {2, 3},
453 {2, 3}, {2, 3}, {2, 3}, {2, 3},
454 {2, 3}, {2, 3}, {2, 3}, {2, 3},
455 {2, 2}, {2, 2}, {2, 2}, {2, 2}, // 11xxxx
456 {2, 2}, {2, 2}, {2, 2}, {2, 2},
457 {2, 2}, {2, 2}, {2, 2}, {2, 2},
458 {2, 2}, {2, 2}, {2, 2}, {2, 2}
459};
diff --git a/noncore/unsupported/qpdf/xpdf/Stream.cc b/noncore/unsupported/qpdf/xpdf/Stream.cc
new file mode 100644
index 0000000..18490d4
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Stream.cc
@@ -0,0 +1,3467 @@
1//========================================================================
2//
3// Stream.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <stddef.h>
17#ifndef WIN32
18#include <unistd.h>
19#endif
20#include <string.h>
21#include <ctype.h>
22#include "gmem.h"
23#include "gfile.h"
24#include "config.h"
25#include "Error.h"
26#include "Object.h"
27#ifndef NO_DECRYPTION
28#include "Decrypt.h"
29#endif
30#include "Stream.h"
31#include "Stream-CCITT.h"
32
33#ifdef __DJGPP__
34static GBool setDJSYSFLAGS = gFalse;
35#endif
36
37#ifdef VMS
38#if (__VMS_VER < 70000000)
39extern "C" int unlink(char *filename);
40#endif
41#ifdef __GNUC__
42#define SEEK_SET 0
43#define SEEK_CUR 1
44#define SEEK_END 2
45#endif
46#endif
47
48#ifdef MACOS
49#include "StuffItEngineLib.h"
50#endif
51
52//------------------------------------------------------------------------
53// Stream (base class)
54//------------------------------------------------------------------------
55
56Stream::Stream() {
57 ref = 1;
58}
59
60Stream::~Stream() {
61}
62
63void Stream::close() {
64}
65
66int Stream::getRawChar() {
67 error(-1, "Internal: called getRawChar() on non-predictor stream");
68 return EOF;
69}
70
71char *Stream::getLine(char *buf, int size) {
72 int i;
73 int c;
74
75 if (lookChar() == EOF)
76 return NULL;
77 for (i = 0; i < size - 1; ++i) {
78 c = getChar();
79 if (c == EOF || c == '\n')
80 break;
81 if (c == '\r') {
82 if ((c = lookChar()) == '\n')
83 getChar();
84 break;
85 }
86 buf[i] = c;
87 }
88 buf[i] = '\0';
89 return buf;
90}
91
92GString *Stream::getPSFilter(char *indent) {
93 return new GString();
94}
95
96Stream *Stream::addFilters(Object *dict) {
97 Object obj, obj2;
98 Object params, params2;
99 Stream *str;
100 int i;
101
102 str = this;
103 dict->dictLookup("Filter", &obj);
104 if (obj.isNull()) {
105 obj.free();
106 dict->dictLookup("F", &obj);
107 }
108 dict->dictLookup("DecodeParms", &params);
109 if (params.isNull()) {
110 params.free();
111 dict->dictLookup("DP", &params);
112 }
113 if (obj.isName()) {
114 str = makeFilter(obj.getName(), str, &params);
115 } else if (obj.isArray()) {
116 for (i = 0; i < obj.arrayGetLength(); ++i) {
117 obj.arrayGet(i, &obj2);
118 if (params.isArray())
119 params.arrayGet(i, &params2);
120 else
121 params2.initNull();
122 if (obj2.isName()) {
123 str = makeFilter(obj2.getName(), str, &params2);
124 } else {
125 error(getPos(), "Bad filter name");
126 str = new EOFStream(str);
127 }
128 obj2.free();
129 params2.free();
130 }
131 } else if (!obj.isNull()) {
132 error(getPos(), "Bad 'Filter' attribute in stream");
133 }
134 obj.free();
135 params.free();
136
137 return str;
138}
139
140Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
141 int pred; // parameters
142 int colors;
143 int bits;
144 int early;
145 int encoding;
146 GBool endOfLine, byteAlign, endOfBlock, black;
147 int columns, rows;
148 Object obj;
149
150 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
151 str = new ASCIIHexStream(str);
152 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
153 str = new ASCII85Stream(str);
154 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
155 pred = 1;
156 columns = 1;
157 colors = 1;
158 bits = 8;
159 early = 1;
160 if (params->isDict()) {
161 params->dictLookup("Predictor", &obj);
162 if (obj.isInt())
163 pred = obj.getInt();
164 obj.free();
165 params->dictLookup("Columns", &obj);
166 if (obj.isInt())
167 columns = obj.getInt();
168 obj.free();
169 params->dictLookup("Colors", &obj);
170 if (obj.isInt())
171 colors = obj.getInt();
172 obj.free();
173 params->dictLookup("BitsPerComponent", &obj);
174 if (obj.isInt())
175 bits = obj.getInt();
176 obj.free();
177 params->dictLookup("EarlyChange", &obj);
178 if (obj.isInt())
179 early = obj.getInt();
180 obj.free();
181 }
182 str = new LZWStream(str, pred, columns, colors, bits, early);
183 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
184 str = new RunLengthStream(str);
185 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
186 encoding = 0;
187 endOfLine = gFalse;
188 byteAlign = gFalse;
189 columns = 1728;
190 rows = 0;
191 endOfBlock = gTrue;
192 black = gFalse;
193 if (params->isDict()) {
194 params->dictLookup("K", &obj);
195 if (obj.isInt()) {
196 encoding = obj.getInt();
197 }
198 obj.free();
199 params->dictLookup("EndOfLine", &obj);
200 if (obj.isBool()) {
201 endOfLine = obj.getBool();
202 }
203 obj.free();
204 params->dictLookup("EncodedByteAlign", &obj);
205 if (obj.isBool()) {
206 byteAlign = obj.getBool();
207 }
208 obj.free();
209 params->dictLookup("Columns", &obj);
210 if (obj.isInt()) {
211 columns = obj.getInt();
212 }
213 obj.free();
214 params->dictLookup("Rows", &obj);
215 if (obj.isInt()) {
216 rows = obj.getInt();
217 }
218 obj.free();
219 params->dictLookup("EndOfBlock", &obj);
220 if (obj.isBool()) {
221 endOfBlock = obj.getBool();
222 }
223 obj.free();
224 params->dictLookup("BlackIs1", &obj);
225 if (obj.isBool()) {
226 black = obj.getBool();
227 }
228 obj.free();
229 }
230 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
231 columns, rows, endOfBlock, black);
232 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
233 str = new DCTStream(str);
234 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
235 pred = 1;
236 columns = 1;
237 colors = 1;
238 bits = 8;
239 if (params->isDict()) {
240 params->dictLookup("Predictor", &obj);
241 if (obj.isInt())
242 pred = obj.getInt();
243 obj.free();
244 params->dictLookup("Columns", &obj);
245 if (obj.isInt())
246 columns = obj.getInt();
247 obj.free();
248 params->dictLookup("Colors", &obj);
249 if (obj.isInt())
250 colors = obj.getInt();
251 obj.free();
252 params->dictLookup("BitsPerComponent", &obj);
253 if (obj.isInt())
254 bits = obj.getInt();
255 obj.free();
256 }
257 str = new FlateStream(str, pred, columns, colors, bits);
258 } else {
259 error(getPos(), "Unknown filter '%s'", name);
260 str = new EOFStream(str);
261 }
262 return str;
263}
264
265//------------------------------------------------------------------------
266// BaseStream
267//------------------------------------------------------------------------
268
269BaseStream::BaseStream(Object *dictA) {
270 dict = *dictA;
271#ifndef NO_DECRYPTION
272 decrypt = NULL;
273#endif
274}
275
276BaseStream::~BaseStream() {
277 dict.free();
278#ifndef NO_DECRYPTION
279 if (decrypt)
280 delete decrypt;
281#endif
282}
283
284#ifndef NO_DECRYPTION
285void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
286 int objNum, int objGen) {
287 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
288}
289#endif
290
291//------------------------------------------------------------------------
292// FilterStream
293//------------------------------------------------------------------------
294
295FilterStream::FilterStream(Stream *strA) {
296 str = strA;
297}
298
299FilterStream::~FilterStream() {
300}
301
302void FilterStream::close() {
303 str->close();
304}
305
306void FilterStream::setPos(int pos) {
307 error(-1, "Internal: called setPos() on FilterStream");
308}
309
310//------------------------------------------------------------------------
311// ImageStream
312//------------------------------------------------------------------------
313
314ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
315 int imgLineSize;
316
317 str = strA;
318 width = widthA;
319 nComps = nCompsA;
320 nBits = nBitsA;
321
322 nVals = width * nComps;
323 if (nBits == 1) {
324 imgLineSize = (nVals + 7) & ~7;
325 } else {
326 imgLineSize = nVals;
327 }
328 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
329 imgIdx = nVals;
330}
331
332ImageStream::~ImageStream() {
333 gfree(imgLine);
334}
335
336void ImageStream::reset() {
337 str->reset();
338}
339
340GBool ImageStream::getPixel(Guchar *pix) {
341 Gulong buf, bitMask;
342 int bits;
343 int c;
344 int i;
345
346 if (imgIdx >= nVals) {
347
348 // read one line of image pixels
349 if (nBits == 1) {
350 for (i = 0; i < nVals; i += 8) {
351 c = str->getChar();
352 imgLine[i+0] = (Guchar)((c >> 7) & 1);
353 imgLine[i+1] = (Guchar)((c >> 6) & 1);
354 imgLine[i+2] = (Guchar)((c >> 5) & 1);
355 imgLine[i+3] = (Guchar)((c >> 4) & 1);
356 imgLine[i+4] = (Guchar)((c >> 3) & 1);
357 imgLine[i+5] = (Guchar)((c >> 2) & 1);
358 imgLine[i+6] = (Guchar)((c >> 1) & 1);
359 imgLine[i+7] = (Guchar)(c & 1);
360 }
361 } else if (nBits == 8) {
362 for (i = 0; i < nVals; ++i) {
363 imgLine[i] = str->getChar();
364 }
365 } else {
366 bitMask = (1 << nBits) - 1;
367 buf = 0;
368 bits = 0;
369 for (i = 0; i < nVals; ++i) {
370 if (bits < nBits) {
371 buf = (buf << 8) | (str->getChar() & 0xff);
372 bits += 8;
373 }
374 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
375 bits -= nBits;
376 }
377 }
378
379 // reset to start of line
380 imgIdx = 0;
381 }
382
383 for (i = 0; i < nComps; ++i)
384 pix[i] = imgLine[imgIdx++];
385 return gTrue;
386}
387
388void ImageStream::skipLine() {
389 int n, i;
390
391 n = (nVals * nBits + 7) >> 3;
392 for (i = 0; i < n; ++i) {
393 str->getChar();
394 }
395}
396
397//------------------------------------------------------------------------
398// StreamPredictor
399//------------------------------------------------------------------------
400
401StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
402 int widthA, int nCompsA, int nBitsA) {
403 str = strA;
404 predictor = predictorA;
405 width = widthA;
406 nComps = nCompsA;
407 nBits = nBitsA;
408
409 nVals = width * nComps;
410 pixBytes = (nComps * nBits + 7) >> 3;
411 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
412 predLine = (Guchar *)gmalloc(rowBytes);
413 memset(predLine, 0, rowBytes);
414 predIdx = rowBytes;
415}
416
417StreamPredictor::~StreamPredictor() {
418 gfree(predLine);
419}
420
421int StreamPredictor::lookChar() {
422 if (predIdx >= rowBytes) {
423 if (!getNextLine()) {
424 return EOF;
425 }
426 }
427 return predLine[predIdx];
428}
429
430int StreamPredictor::getChar() {
431 if (predIdx >= rowBytes) {
432 if (!getNextLine()) {
433 return EOF;
434 }
435 }
436 return predLine[predIdx++];
437}
438
439GBool StreamPredictor::getNextLine() {
440 int curPred;
441 Guchar upLeftBuf[4];
442 int left, up, upLeft, p, pa, pb, pc;
443 int c;
444 Gulong inBuf, outBuf, bitMask;
445 int inBits, outBits;
446 int i, j, k;
447
448 // get PNG optimum predictor number
449 if (predictor == 15) {
450 if ((curPred = str->getRawChar()) == EOF) {
451 return gFalse;
452 }
453 curPred += 10;
454 } else {
455 curPred = predictor;
456 }
457
458 // read the raw line, apply PNG (byte) predictor
459 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
460 for (i = pixBytes; i < rowBytes; ++i) {
461 upLeftBuf[3] = upLeftBuf[2];
462 upLeftBuf[2] = upLeftBuf[1];
463 upLeftBuf[1] = upLeftBuf[0];
464 upLeftBuf[0] = predLine[i];
465 if ((c = str->getRawChar()) == EOF) {
466 break;
467 }
468 switch (curPred) {
469 case 11: // PNG sub
470 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
471 break;
472 case 12: // PNG up
473 predLine[i] = predLine[i] + (Guchar)c;
474 break;
475 case 13: // PNG average
476 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
477 (Guchar)c;
478 break;
479 case 14: // PNG Paeth
480 left = predLine[i - pixBytes];
481 up = predLine[i];
482 upLeft = upLeftBuf[pixBytes];
483 p = left + up - upLeft;
484 if ((pa = p - left) < 0)
485 pa = -pa;
486 if ((pb = p - up) < 0)
487 pb = -pb;
488 if ((pc = p - upLeft) < 0)
489 pc = -pc;
490 if (pa <= pb && pa <= pc)
491 predLine[i] = left + (Guchar)c;
492 else if (pb <= pc)
493 predLine[i] = up + (Guchar)c;
494 else
495 predLine[i] = upLeft + (Guchar)c;
496 break;
497 case 10: // PNG none
498 default: // no predictor or TIFF predictor
499 predLine[i] = (Guchar)c;
500 break;
501 }
502 }
503
504 // apply TIFF (component) predictor
505 //~ this is completely untested
506 if (predictor == 2) {
507 if (nBits == 1) {
508 inBuf = predLine[pixBytes - 1];
509 for (i = pixBytes; i < rowBytes; i += 8) {
510 // 1-bit add is just xor
511 inBuf = (inBuf << 8) | predLine[i];
512 predLine[i] ^= inBuf >> nComps;
513 }
514 } else if (nBits == 8) {
515 for (i = pixBytes; i < rowBytes; ++i) {
516 predLine[i] += predLine[i - nComps];
517 }
518 } else {
519 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
520 bitMask = (1 << nBits) - 1;
521 inBuf = outBuf = 0;
522 inBits = outBits = 0;
523 j = k = pixBytes;
524 for (i = 0; i < nVals; ++i) {
525 if (inBits < nBits) {
526 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
527 inBits += 8;
528 }
529 upLeftBuf[3] = upLeftBuf[2];
530 upLeftBuf[2] = upLeftBuf[1];
531 upLeftBuf[1] = upLeftBuf[0];
532 upLeftBuf[0] = (upLeftBuf[nComps] +
533 (inBuf >> (inBits - nBits))) & bitMask;
534 outBuf = (outBuf << nBits) | upLeftBuf[0];
535 inBits -= nBits;
536 outBits += nBits;
537 if (outBits > 8) {
538 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
539 }
540 }
541 if (outBits > 0) {
542 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
543 }
544 }
545 }
546
547 // reset to start of line
548 predIdx = pixBytes;
549
550 return gTrue;
551}
552
553//------------------------------------------------------------------------
554// FileStream
555//------------------------------------------------------------------------
556
557FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA):
558 BaseStream(dictA) {
559 f = fA;
560 start = startA;
561 length = lengthA;
562 bufPtr = bufEnd = buf;
563 bufPos = start;
564 savePos = -1;
565}
566
567FileStream::~FileStream() {
568 close();
569}
570
571Stream *FileStream::makeSubStream(int startA, int lengthA, Object *dictA) {
572 return new FileStream(f, startA, lengthA, dictA);
573}
574
575void FileStream::reset() {
576 savePos = (int)ftell(f);
577 fseek(f, start, SEEK_SET);
578 bufPtr = bufEnd = buf;
579 bufPos = start;
580#ifndef NO_DECRYPTION
581 if (decrypt)
582 decrypt->reset();
583#endif
584}
585
586void FileStream::close() {
587 if (savePos >= 0) {
588 fseek(f, savePos, SEEK_SET);
589 savePos = -1;
590 }
591}
592
593GBool FileStream::fillBuf() {
594 int n;
595#ifndef NO_DECRYPTION
596 char *p;
597#endif
598
599 bufPos += bufEnd - buf;
600 bufPtr = bufEnd = buf;
601 if (length >= 0 && bufPos >= start + length) {
602 return gFalse;
603 }
604 if (length >= 0 && bufPos + fileStreamBufSize > start + length) {
605 n = start + length - bufPos;
606 } else {
607 n = fileStreamBufSize;
608 }
609 n = fread(buf, 1, n, f);
610 bufEnd = buf + n;
611 if (bufPtr >= bufEnd) {
612 return gFalse;
613 }
614#ifndef NO_DECRYPTION
615 if (decrypt) {
616 for (p = buf; p < bufEnd; ++p) {
617 *p = (char)decrypt->decryptByte((Guchar)*p);
618 }
619 }
620#endif
621 return gTrue;
622}
623
624void FileStream::setPos(int pos) {
625 long size;
626
627 if (pos >= 0) {
628 fseek(f, pos, SEEK_SET);
629 bufPos = pos;
630 } else {
631 fseek(f, 0, SEEK_END);
632 size = ftell(f);
633 if (pos < -size)
634 pos = (int)(-size);
635#ifdef __CYGWIN32__
636 //~ work around a bug in cygwin's implementation of fseek
637 rewind(f);
638#endif
639 fseek(f, pos, SEEK_END);
640 bufPos = (int)ftell(f);
641 }
642 bufPtr = bufEnd = buf;
643}
644
645void FileStream::moveStart(int delta) {
646 start += delta;
647 bufPtr = bufEnd = buf;
648 bufPos = start;
649}
650
651//------------------------------------------------------------------------
652// EmbedStream
653//------------------------------------------------------------------------
654
655EmbedStream::EmbedStream(Stream *strA, Object *dictA):
656 BaseStream(dictA) {
657 str = strA;
658}
659
660EmbedStream::~EmbedStream() {
661}
662
663Stream *EmbedStream::makeSubStream(int start, int length, Object *dictA) {
664 error(-1, "Internal: called makeSubStream() on EmbedStream");
665 return NULL;
666}
667
668void EmbedStream::setPos(int pos) {
669 error(-1, "Internal: called setPos() on EmbedStream");
670}
671
672int EmbedStream::getStart() {
673 error(-1, "Internal: called getStart() on EmbedStream");
674 return 0;
675}
676
677void EmbedStream::moveStart(int start) {
678 error(-1, "Internal: called moveStart() on EmbedStream");
679}
680
681//------------------------------------------------------------------------
682// ASCIIHexStream
683//------------------------------------------------------------------------
684
685ASCIIHexStream::ASCIIHexStream(Stream *strA):
686 FilterStream(strA) {
687 buf = EOF;
688 eof = gFalse;
689}
690
691ASCIIHexStream::~ASCIIHexStream() {
692 delete str;
693}
694
695void ASCIIHexStream::reset() {
696 str->reset();
697 buf = EOF;
698 eof = gFalse;
699}
700
701int ASCIIHexStream::lookChar() {
702 int c1, c2, x;
703
704 if (buf != EOF)
705 return buf;
706 if (eof) {
707 buf = EOF;
708 return EOF;
709 }
710 do {
711 c1 = str->getChar();
712 } while (isspace(c1));
713 if (c1 == '>') {
714 eof = gTrue;
715 buf = EOF;
716 return buf;
717 }
718 do {
719 c2 = str->getChar();
720 } while (isspace(c2));
721 if (c2 == '>') {
722 eof = gTrue;
723 c2 = '0';
724 }
725 if (c1 >= '0' && c1 <= '9') {
726 x = (c1 - '0') << 4;
727 } else if (c1 >= 'A' && c1 <= 'F') {
728 x = (c1 - 'A' + 10) << 4;
729 } else if (c1 >= 'a' && c1 <= 'f') {
730 x = (c1 - 'a' + 10) << 4;
731 } else if (c1 == EOF) {
732 eof = gTrue;
733 x = 0;
734 } else {
735 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
736 x = 0;
737 }
738 if (c2 >= '0' && c2 <= '9') {
739 x += c2 - '0';
740 } else if (c2 >= 'A' && c2 <= 'F') {
741 x += c2 - 'A' + 10;
742 } else if (c2 >= 'a' && c2 <= 'f') {
743 x += c2 - 'a' + 10;
744 } else if (c2 == EOF) {
745 eof = gTrue;
746 x = 0;
747 } else {
748 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
749 }
750 buf = x & 0xff;
751 return buf;
752}
753
754GString *ASCIIHexStream::getPSFilter(char *indent) {
755 GString *s;
756
757 if (!(s = str->getPSFilter(indent))) {
758 return NULL;
759 }
760 s->append(indent)->append("/ASCIIHexDecode filter\n");
761 return s;
762}
763
764GBool ASCIIHexStream::isBinary(GBool last) {
765 return str->isBinary(gFalse);
766}
767
768//------------------------------------------------------------------------
769// ASCII85Stream
770//------------------------------------------------------------------------
771
772ASCII85Stream::ASCII85Stream(Stream *strA):
773 FilterStream(strA) {
774 index = n = 0;
775 eof = gFalse;
776}
777
778ASCII85Stream::~ASCII85Stream() {
779 delete str;
780}
781
782void ASCII85Stream::reset() {
783 str->reset();
784 index = n = 0;
785 eof = gFalse;
786}
787
788int ASCII85Stream::lookChar() {
789 int k;
790 Gulong t;
791
792 if (index >= n) {
793 if (eof)
794 return EOF;
795 index = 0;
796 do {
797 c[0] = str->getChar();
798 } while (c[0] == '\n' || c[0] == '\r');
799 if (c[0] == '~' || c[0] == EOF) {
800 eof = gTrue;
801 n = 0;
802 return EOF;
803 } else if (c[0] == 'z') {
804 b[0] = b[1] = b[2] = b[3] = 0;
805 n = 4;
806 } else {
807 for (k = 1; k < 5; ++k) {
808 do {
809 c[k] = str->getChar();
810 } while (c[k] == '\n' || c[k] == '\r');
811 if (c[k] == '~' || c[k] == EOF)
812 break;
813 }
814 n = k - 1;
815 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
816 for (++k; k < 5; ++k)
817 c[k] = 0x21 + 84;
818 eof = gTrue;
819 }
820 t = 0;
821 for (k = 0; k < 5; ++k)
822 t = t * 85 + (c[k] - 0x21);
823 for (k = 3; k >= 0; --k) {
824 b[k] = (int)(t & 0xff);
825 t >>= 8;
826 }
827 }
828 }
829 return b[index];
830}
831
832GString *ASCII85Stream::getPSFilter(char *indent) {
833 GString *s;
834
835 if (!(s = str->getPSFilter(indent))) {
836 return NULL;
837 }
838 s->append(indent)->append("/ASCII85Decode filter\n");
839 return s;
840}
841
842GBool ASCII85Stream::isBinary(GBool last) {
843 return str->isBinary(gFalse);
844}
845
846//------------------------------------------------------------------------
847// LZWStream
848//------------------------------------------------------------------------
849
850LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
851 int bits, int earlyA):
852 FilterStream(strA) {
853 if (predictor != 1) {
854 pred = new StreamPredictor(this, predictor, columns, colors, bits);
855 } else {
856 pred = NULL;
857 }
858 early = earlyA;
859 zPipe = NULL;
860 bufPtr = bufEnd = buf;
861}
862
863LZWStream::~LZWStream() {
864 if (zPipe) {
865#ifdef HAVE_POPEN
866 pclose(zPipe);
867#else
868 fclose(zPipe);
869#endif
870 zPipe = NULL;
871 unlink(zName->getCString());
872 delete zName;
873 }
874 if (pred) {
875 delete pred;
876 }
877 delete str;
878}
879
880int LZWStream::getChar() {
881 if (pred) {
882 return pred->getChar();
883 }
884 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
885}
886
887int LZWStream::lookChar() {
888 if (pred) {
889 return pred->lookChar();
890 }
891 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
892}
893
894int LZWStream::getRawChar() {
895 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
896}
897
898void LZWStream::reset() {
899 FILE *f;
900 GString *zCmd;
901
902 //----- close old LZW stream
903 if (zPipe) {
904#ifdef HAVE_POPEN
905 pclose(zPipe);
906#else
907 fclose(zPipe);
908#endif
909 zPipe = NULL;
910 unlink(zName->getCString());
911 delete zName;
912 }
913
914 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
915 // to run gzip
916#if __DJGPP__
917 if (!setDJSYSFLAGS) {
918 setenv("DJSYSFLAGS", "0x0002", 0);
919 setDJSYSFLAGS = gTrue;
920 }
921#endif
922
923 //----- create the .Z file
924 if (!openTempFile(&zName, &f, "wb", ".Z")) {
925 error(getPos(), "Couldn't create temporary file for LZW stream");
926 return;
927 }
928 dumpFile(f);
929 fclose(f);
930
931 //----- execute uncompress / gzip
932 zCmd = new GString(uncompressCmd);
933 zCmd->append(' ');
934 zCmd->append(zName);
935#if defined(MACOS)
936 long magicCookie;
937 // first we open the engine up
938 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
939 // if we found it - let's use it!
940 if (!err && magicCookie) {
941 // make sure we have the correct version of the Engine
942 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
943 FSSpec myFSS;
944 Str255 pName;
945 strcpy((char *)pName, zName->getCString());
946 c2pstr((char *)pName);
947 FSMakeFSSpec(0, 0, pName, &myFSS);
948 short ftype = DetermineFileType(magicCookie, &myFSS);
949 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
950 NULL, NULL, kCreateFolderNever,
951 kDeleteOriginal, kTextConvertSmart);
952 }
953 }
954#elif defined(HAVE_POPEN)
955 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
956 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
957 unlink(zName->getCString());
958 delete zName;
959 return;
960 }
961#else // HAVE_POPEN
962#ifdef VMS
963 if (!system(zCmd->getCString())) {
964#else
965 if (system(zCmd->getCString())) {
966#endif
967 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
968 unlink(zName->getCString());
969 delete zName;
970 return;
971 }
972 zName->del(zName->getLength() - 2, 2);
973 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
974 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
975 unlink(zName->getCString());
976 delete zName;
977 return;
978 }
979#endif // HAVE_POPEN
980
981 //----- clean up
982 delete zCmd;
983
984 //----- initialize buffer
985 bufPtr = bufEnd = buf;
986}
987
988void LZWStream::dumpFile(FILE *f) {
989 int outCodeBits; // size of output code
990 int outBits; // max output code
991 int outBuf[8]; // output buffer
992 int outData; // temporary output buffer
993 int inCode, outCode; // input and output codes
994 int nextCode; // next code index
995 GBool eof; // set when EOF is reached
996 GBool clear; // set if table needs to be cleared
997 GBool first; // indicates first code word after clear
998 int i, j;
999
1000 str->reset();
1001
1002 // magic number
1003 fputc(0x1f, f);
1004 fputc(0x9d, f);
1005
1006 // max code length, block mode flag
1007 fputc(0x8c, f);
1008
1009 // init input side
1010 inCodeBits = 9;
1011 inputBuf = 0;
1012 inputBits = 0;
1013 eof = gFalse;
1014
1015 // init output side
1016 outCodeBits = 9;
1017
1018 // clear table
1019 first = gTrue;
1020 nextCode = 258;
1021
1022 clear = gFalse;
1023 do {
1024 for (i = 0; i < 8; ++i) {
1025 // check for table overflow
1026 if (nextCode + early > 0x1001) {
1027 inCode = 256;
1028
1029 // read input code
1030 } else {
1031 do {
1032 inCode = getCode();
1033 if (inCode == EOF) {
1034 eof = gTrue;
1035 inCode = 0;
1036 }
1037 } while (first && inCode == 256);
1038 }
1039
1040 // compute output code
1041 if (inCode < 256) {
1042 outCode = inCode;
1043 } else if (inCode == 256) {
1044 outCode = 256;
1045 clear = gTrue;
1046 } else if (inCode == 257) {
1047 outCode = 0;
1048 eof = gTrue;
1049 } else {
1050 outCode = inCode - 1;
1051 }
1052 outBuf[i] = outCode;
1053
1054 // next code index
1055 if (first)
1056 first = gFalse;
1057 else
1058 ++nextCode;
1059
1060 // check input code size
1061 if (nextCode + early == 0x200)
1062 inCodeBits = 10;
1063 else if (nextCode + early == 0x400) {
1064 inCodeBits = 11;
1065 } else if (nextCode + early == 0x800) {
1066 inCodeBits = 12;
1067 }
1068
1069 // check for eof/clear
1070 if (eof)
1071 break;
1072 if (clear) {
1073 i = 8;
1074 break;
1075 }
1076 }
1077
1078 // write output block
1079 outData = 0;
1080 outBits = 0;
1081 j = 0;
1082 while (j < i || outBits > 0) {
1083 if (outBits < 8 && j < i) {
1084 outData = outData | (outBuf[j++] << outBits);
1085 outBits += outCodeBits;
1086 }
1087 fputc(outData & 0xff, f);
1088 outData >>= 8;
1089 outBits -= 8;
1090 }
1091
1092 // check output code size
1093 if (nextCode - 1 == 512 ||
1094 nextCode - 1 == 1024 ||
1095 nextCode - 1 == 2048 ||
1096 nextCode - 1 == 4096) {
1097 outCodeBits = inCodeBits;
1098 }
1099
1100 // clear table if necessary
1101 if (clear) {
1102 inCodeBits = 9;
1103 outCodeBits = 9;
1104 first = gTrue;
1105 nextCode = 258;
1106 clear = gFalse;
1107 }
1108 } while (!eof);
1109}
1110
1111int LZWStream::getCode() {
1112 int c;
1113 int code;
1114
1115 while (inputBits < inCodeBits) {
1116 if ((c = str->getChar()) == EOF)
1117 return EOF;
1118 inputBuf = (inputBuf << 8) | (c & 0xff);
1119 inputBits += 8;
1120 }
1121 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1122 inputBits -= inCodeBits;
1123 return code;
1124}
1125
1126GBool LZWStream::fillBuf() {
1127 int n;
1128
1129 if (!zPipe)
1130 return gFalse;
1131 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1132#ifdef HAVE_POPEN
1133 pclose(zPipe);
1134#else
1135 fclose(zPipe);
1136#endif
1137 zPipe = NULL;
1138 unlink(zName->getCString());
1139 delete zName;
1140 }
1141 bufPtr = buf;
1142 bufEnd = buf + n;
1143 return n > 0;
1144}
1145
1146GString *LZWStream::getPSFilter(char *indent) {
1147 GString *s;
1148
1149 if (pred) {
1150 return NULL;
1151 }
1152 if (!(s = str->getPSFilter(indent))) {
1153 return NULL;
1154 }
1155 s->append(indent)->append("/LZWDecode filter\n");
1156 return s;
1157}
1158
1159GBool LZWStream::isBinary(GBool last) {
1160 return str->isBinary(gTrue);
1161}
1162
1163//------------------------------------------------------------------------
1164// RunLengthStream
1165//------------------------------------------------------------------------
1166
1167RunLengthStream::RunLengthStream(Stream *strA):
1168 FilterStream(strA) {
1169 bufPtr = bufEnd = buf;
1170 eof = gFalse;
1171}
1172
1173RunLengthStream::~RunLengthStream() {
1174 delete str;
1175}
1176
1177void RunLengthStream::reset() {
1178 str->reset();
1179 bufPtr = bufEnd = buf;
1180 eof = gFalse;
1181}
1182
1183GString *RunLengthStream::getPSFilter(char *indent) {
1184 GString *s;
1185
1186 if (!(s = str->getPSFilter(indent))) {
1187 return NULL;
1188 }
1189 s->append(indent)->append("/RunLengthDecode filter\n");
1190 return s;
1191}
1192
1193GBool RunLengthStream::isBinary(GBool last) {
1194 return str->isBinary(gTrue);
1195}
1196
1197GBool RunLengthStream::fillBuf() {
1198 int c;
1199 int n, i;
1200
1201 if (eof)
1202 return gFalse;
1203 c = str->getChar();
1204 if (c == 0x80 || c == EOF) {
1205 eof = gTrue;
1206 return gFalse;
1207 }
1208 if (c < 0x80) {
1209 n = c + 1;
1210 for (i = 0; i < n; ++i)
1211 buf[i] = (char)str->getChar();
1212 } else {
1213 n = 0x101 - c;
1214 c = str->getChar();
1215 for (i = 0; i < n; ++i)
1216 buf[i] = (char)c;
1217 }
1218 bufPtr = buf;
1219 bufEnd = buf + n;
1220 return gTrue;
1221}
1222
1223//------------------------------------------------------------------------
1224// CCITTFaxStream
1225//------------------------------------------------------------------------
1226
1227CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1228 GBool byteAlignA, int columnsA, int rowsA,
1229 GBool endOfBlockA, GBool blackA):
1230 FilterStream(strA) {
1231 encoding = encodingA;
1232 endOfLine = endOfLineA;
1233 byteAlign = byteAlignA;
1234 columns = columnsA;
1235 rows = rowsA;
1236 endOfBlock = endOfBlockA;
1237 black = blackA;
1238 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1239 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1240
1241 eof = gFalse;
1242 row = 0;
1243 nextLine2D = encoding < 0;
1244 inputBits = 0;
1245 codingLine[0] = 0;
1246 codingLine[1] = refLine[2] = columns;
1247 a0 = 1;
1248
1249 buf = EOF;
1250}
1251
1252CCITTFaxStream::~CCITTFaxStream() {
1253 delete str;
1254 gfree(refLine);
1255 gfree(codingLine);
1256}
1257
1258void CCITTFaxStream::reset() {
1259 int n;
1260
1261 str->reset();
1262 eof = gFalse;
1263 row = 0;
1264 nextLine2D = encoding < 0;
1265 inputBits = 0;
1266 codingLine[0] = 0;
1267 codingLine[1] = refLine[2] = columns;
1268 a0 = 1;
1269 buf = EOF;
1270
1271 // get initial end-of-line marker and 2D encoding tag
1272 if (endOfBlock) {
1273 if (lookBits(12) == 0x001) {
1274 eatBits(12);
1275 }
1276 } else {
1277 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1278 if (n == 11 && lookBits(12) == 0x001) {
1279 eatBits(12);
1280 }
1281 }
1282 if (encoding > 0) {
1283 nextLine2D = !lookBits(1);
1284 eatBits(1);
1285 }
1286}
1287
1288int CCITTFaxStream::lookChar() {
1289 short code1, code2, code3;
1290 int a0New;
1291#if 0
1292 GBool err;
1293#endif
1294 GBool gotEOL;
1295 int ret;
1296 int bits, i;
1297
1298 // if at eof just return EOF
1299 if (eof && codingLine[a0] >= columns) {
1300 return EOF;
1301 }
1302
1303 // read the next row
1304#if 0
1305 err = gFalse;
1306#endif
1307 if (codingLine[a0] >= columns) {
1308
1309 // 2-D encoding
1310 if (nextLine2D) {
1311 for (i = 0; codingLine[i] < columns; ++i)
1312 refLine[i] = codingLine[i];
1313 refLine[i] = refLine[i + 1] = columns;
1314 b1 = 1;
1315 a0New = codingLine[a0 = 0] = 0;
1316 do {
1317 code1 = getTwoDimCode();
1318 switch (code1) {
1319 case twoDimPass:
1320 if (refLine[b1] < columns) {
1321 a0New = refLine[b1 + 1];
1322 b1 += 2;
1323 }
1324 break;
1325 case twoDimHoriz:
1326 if ((a0 & 1) == 0) {
1327 code1 = code2 = 0;
1328 do {
1329 code1 += code3 = getWhiteCode();
1330 } while (code3 >= 64);
1331 do {
1332 code2 += code3 = getBlackCode();
1333 } while (code3 >= 64);
1334 } else {
1335 code1 = code2 = 0;
1336 do {
1337 code1 += code3 = getBlackCode();
1338 } while (code3 >= 64);
1339 do {
1340 code2 += code3 = getWhiteCode();
1341 } while (code3 >= 64);
1342 }
1343 codingLine[a0 + 1] = a0New + code1;
1344 ++a0;
1345 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1346 ++a0;
1347 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1348 b1 += 2;
1349 break;
1350 case twoDimVert0:
1351 a0New = codingLine[++a0] = refLine[b1];
1352 if (refLine[b1] < columns) {
1353 ++b1;
1354 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1355 b1 += 2;
1356 }
1357 break;
1358 case twoDimVertR1:
1359 a0New = codingLine[++a0] = refLine[b1] + 1;
1360 if (refLine[b1] < columns) {
1361 ++b1;
1362 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1363 b1 += 2;
1364 }
1365 break;
1366 case twoDimVertL1:
1367 a0New = codingLine[++a0] = refLine[b1] - 1;
1368 --b1;
1369 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1370 b1 += 2;
1371 break;
1372 case twoDimVertR2:
1373 a0New = codingLine[++a0] = refLine[b1] + 2;
1374 if (refLine[b1] < columns) {
1375 ++b1;
1376 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1377 b1 += 2;
1378 }
1379 break;
1380 case twoDimVertL2:
1381 a0New = codingLine[++a0] = refLine[b1] - 2;
1382 --b1;
1383 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1384 b1 += 2;
1385 break;
1386 case twoDimVertR3:
1387 a0New = codingLine[++a0] = refLine[b1] + 3;
1388 if (refLine[b1] < columns) {
1389 ++b1;
1390 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1391 b1 += 2;
1392 }
1393 break;
1394 case twoDimVertL3:
1395 a0New = codingLine[++a0] = refLine[b1] - 3;
1396 --b1;
1397 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1398 b1 += 2;
1399 break;
1400 case EOF:
1401 eof = gTrue;
1402 codingLine[a0 = 0] = columns;
1403 return EOF;
1404 default:
1405 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1406#if 0
1407 err = gTrue;
1408 break;
1409#else
1410 eof = gTrue;
1411 return EOF;
1412#endif
1413 }
1414 } while (codingLine[a0] < columns);
1415
1416 // 1-D encoding
1417 } else {
1418 codingLine[a0 = 0] = 0;
1419 while (1) {
1420 code1 = 0;
1421 do {
1422 code1 += code3 = getWhiteCode();
1423 } while (code3 >= 64);
1424 codingLine[a0+1] = codingLine[a0] + code1;
1425 ++a0;
1426 if (codingLine[a0] >= columns)
1427 break;
1428 code2 = 0;
1429 do {
1430 code2 += code3 = getBlackCode();
1431 } while (code3 >= 64);
1432 codingLine[a0+1] = codingLine[a0] + code2;
1433 ++a0;
1434 if (codingLine[a0] >= columns)
1435 break;
1436 }
1437 }
1438
1439 if (codingLine[a0] != columns) {
1440 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1441#if 0
1442 err = gTrue;
1443#endif
1444 }
1445
1446 // byte-align the row
1447 if (byteAlign) {
1448 inputBits &= ~7;
1449 }
1450
1451 // check for end-of-line marker, skipping over any extra zero bits
1452 gotEOL = gFalse;
1453 if (!endOfBlock && row == rows - 1) {
1454 eof = gTrue;
1455 } else {
1456 code1 = lookBits(12);
1457 while (code1 == 0) {
1458 eatBits(1);
1459 code1 = lookBits(12);
1460 }
1461 if (code1 == 0x001) {
1462 eatBits(12);
1463 gotEOL = gTrue;
1464 } else if (code1 == EOF) {
1465 eof = gTrue;
1466 }
1467 }
1468
1469 // get 2D encoding tag
1470 if (!eof && encoding > 0) {
1471 nextLine2D = !lookBits(1);
1472 eatBits(1);
1473 }
1474
1475 // check for end-of-block marker
1476 if (endOfBlock && gotEOL) {
1477 code1 = lookBits(12);
1478 if (code1 == 0x001) {
1479 eatBits(12);
1480 if (encoding > 0) {
1481 lookBits(1);
1482 eatBits(1);
1483 }
1484 if (encoding >= 0) {
1485 for (i = 0; i < 4; ++i) {
1486 code1 = lookBits(12);
1487 if (code1 != 0x001) {
1488 error(getPos(), "Bad RTC code in CCITTFax stream");
1489 }
1490 eatBits(12);
1491 if (encoding > 0) {
1492 lookBits(1);
1493 eatBits(1);
1494 }
1495 }
1496 }
1497 eof = gTrue;
1498 }
1499 }
1500
1501#if 0
1502 // This looks for an end-of-line marker after an error, however
1503 // some (most?) CCITT streams in PDF files don't use end-of-line
1504 // markers, and the just-plow-on technique works better in those
1505 // cases.
1506 else if (err) {
1507 do {
1508 if (code1 == EOF) {
1509 eof = gTrue;
1510 return EOF;
1511 }
1512 eatBits(1);
1513 code1 = look13Bits();
1514 } while ((code1 >> 1) != 0x001);
1515 eatBits(12);
1516 codingLine[++a0] = columns;
1517 if (encoding > 0) {
1518 eatBits(1);
1519 nextLine2D = !(code1 & 1);
1520 }
1521 }
1522#endif
1523
1524 a0 = 0;
1525 outputBits = codingLine[1] - codingLine[0];
1526 if (outputBits == 0) {
1527 a0 = 1;
1528 outputBits = codingLine[2] - codingLine[1];
1529 }
1530
1531 ++row;
1532 }
1533
1534 // get a byte
1535 if (outputBits >= 8) {
1536 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1537 if ((outputBits -= 8) == 0) {
1538 ++a0;
1539 if (codingLine[a0] < columns) {
1540 outputBits = codingLine[a0 + 1] - codingLine[a0];
1541 }
1542 }
1543 } else {
1544 bits = 8;
1545 ret = 0;
1546 do {
1547 if (outputBits > bits) {
1548 i = bits;
1549 bits = 0;
1550 if ((a0 & 1) == 0) {
1551 ret |= 0xff >> (8 - i);
1552 }
1553 outputBits -= i;
1554 } else {
1555 i = outputBits;
1556 bits -= outputBits;
1557 if ((a0 & 1) == 0) {
1558 ret |= (0xff >> (8 - i)) << bits;
1559 }
1560 outputBits = 0;
1561 ++a0;
1562 if (codingLine[a0] < columns) {
1563 outputBits = codingLine[a0 + 1] - codingLine[a0];
1564 }
1565 }
1566 } while (bits > 0 && codingLine[a0] < columns);
1567 }
1568 buf = black ? (ret ^ 0xff) : ret;
1569 return buf;
1570}
1571
1572short CCITTFaxStream::getTwoDimCode() {
1573 short code;
1574 CCITTCode *p;
1575 int n;
1576
1577 code = 0; // make gcc happy
1578 if (endOfBlock) {
1579 code = lookBits(7);
1580 p = &twoDimTab1[code];
1581 if (p->bits > 0) {
1582 eatBits(p->bits);
1583 return p->n;
1584 }
1585 } else {
1586 for (n = 1; n <= 7; ++n) {
1587 code = lookBits(n);
1588 if (n < 7) {
1589 code <<= 7 - n;
1590 }
1591 p = &twoDimTab1[code];
1592 if (p->bits == n) {
1593 eatBits(n);
1594 return p->n;
1595 }
1596 }
1597 }
1598 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1599 return EOF;
1600}
1601
1602short CCITTFaxStream::getWhiteCode() {
1603 short code;
1604 CCITTCode *p;
1605 int n;
1606
1607 code = 0; // make gcc happy
1608 if (endOfBlock) {
1609 code = lookBits(12);
1610 if ((code >> 5) == 0) {
1611 p = &whiteTab1[code];
1612 } else {
1613 p = &whiteTab2[code >> 3];
1614 }
1615 if (p->bits > 0) {
1616 eatBits(p->bits);
1617 return p->n;
1618 }
1619 } else {
1620 for (n = 1; n <= 9; ++n) {
1621 code = lookBits(n);
1622 if (n < 9) {
1623 code <<= 9 - n;
1624 }
1625 p = &whiteTab2[code];
1626 if (p->bits == n) {
1627 eatBits(n);
1628 return p->n;
1629 }
1630 }
1631 for (n = 11; n <= 12; ++n) {
1632 code = lookBits(n);
1633 if (n < 12) {
1634 code <<= 12 - n;
1635 }
1636 p = &whiteTab1[code];
1637 if (p->bits == n) {
1638 eatBits(n);
1639 return p->n;
1640 }
1641 }
1642 }
1643 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1644 // eat a bit and return a positive number so that the caller doesn't
1645 // go into an infinite loop
1646 eatBits(1);
1647 return 1;
1648}
1649
1650short CCITTFaxStream::getBlackCode() {
1651 short code;
1652 CCITTCode *p;
1653 int n;
1654
1655 code = 0; // make gcc happy
1656 if (endOfBlock) {
1657 code = lookBits(13);
1658 if ((code >> 7) == 0) {
1659 p = &blackTab1[code];
1660 } else if ((code >> 9) == 0) {
1661 p = &blackTab2[(code >> 1) - 64];
1662 } else {
1663 p = &blackTab3[code >> 7];
1664 }
1665 if (p->bits > 0) {
1666 eatBits(p->bits);
1667 return p->n;
1668 }
1669 } else {
1670 for (n = 2; n <= 6; ++n) {
1671 code = lookBits(n);
1672 if (n < 6) {
1673 code <<= 6 - n;
1674 }
1675 p = &blackTab3[code];
1676 if (p->bits == n) {
1677 eatBits(n);
1678 return p->n;
1679 }
1680 }
1681 for (n = 7; n <= 12; ++n) {
1682 code = lookBits(n);
1683 if (n < 12) {
1684 code <<= 12 - n;
1685 }
1686 if (code >= 64) {
1687 p = &blackTab2[code - 64];
1688 if (p->bits == n) {
1689 eatBits(n);
1690 return p->n;
1691 }
1692 }
1693 }
1694 for (n = 10; n <= 13; ++n) {
1695 code = lookBits(n);
1696 if (n < 13) {
1697 code <<= 13 - n;
1698 }
1699 p = &blackTab1[code];
1700 if (p->bits == n) {
1701 eatBits(n);
1702 return p->n;
1703 }
1704 }
1705 }
1706 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1707 // eat a bit and return a positive number so that the caller doesn't
1708 // go into an infinite loop
1709 eatBits(1);
1710 return 1;
1711}
1712
1713short CCITTFaxStream::lookBits(int n) {
1714 int c;
1715
1716 while (inputBits < n) {
1717 if ((c = str->getChar()) == EOF) {
1718 if (inputBits == 0) {
1719 return EOF;
1720 }
1721 // near the end of the stream, the caller may ask for more bits
1722 // than are available, but there may still be a valid code in
1723 // however many bits are available -- we need to return correct
1724 // data in this case
1725 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1726 }
1727 inputBuf = (inputBuf << 8) + c;
1728 inputBits += 8;
1729 }
1730 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1731}
1732
1733GString *CCITTFaxStream::getPSFilter(char *indent) {
1734 GString *s;
1735 char s1[50];
1736
1737 if (!(s = str->getPSFilter(indent))) {
1738 return NULL;
1739 }
1740 s->append(indent)->append("<< ");
1741 if (encoding != 0) {
1742 sprintf(s1, "/K %d ", encoding);
1743 s->append(s1);
1744 }
1745 if (endOfLine) {
1746 s->append("/EndOfLine true ");
1747 }
1748 if (byteAlign) {
1749 s->append("/EncodedByteAlign true ");
1750 }
1751 sprintf(s1, "/Columns %d ", columns);
1752 s->append(s1);
1753 if (rows != 0) {
1754 sprintf(s1, "/Rows %d ", rows);
1755 s->append(s1);
1756 }
1757 if (!endOfBlock) {
1758 s->append("/EndOfBlock false ");
1759 }
1760 if (black) {
1761 s->append("/BlackIs1 true ");
1762 }
1763 s->append(">> /CCITTFaxDecode filter\n");
1764 return s;
1765}
1766
1767GBool CCITTFaxStream::isBinary(GBool last) {
1768 return str->isBinary(gTrue);
1769}
1770
1771//------------------------------------------------------------------------
1772// DCTStream
1773//------------------------------------------------------------------------
1774
1775// IDCT constants (20.12 fixed point format)
1776#ifndef FP_IDCT
1777 #define dctCos1 4017 // cos(pi/16)
1778 #define dctSin1 799 // sin(pi/16)
1779 #define dctCos3 3406 // cos(3*pi/16)
1780 #define dctSin3 2276 // sin(3*pi/16)
1781 #define dctCos6 1567 // cos(6*pi/16)
1782 #define dctSin6 3784 // sin(6*pi/16)
1783 #define dctSqrt2 5793 // sqrt(2)
1784 #define dctSqrt1d2 2896 // sqrt(2) / 2
1785#endif
1786
1787// IDCT constants
1788#ifdef FP_IDCT
1789 #define dctCos1 0.98078528// cos(pi/16)
1790 #define dctSin1 0.19509032// sin(pi/16)
1791 #define dctCos3 0.83146961// cos(3*pi/16)
1792 #define dctSin3 0.55557023// sin(3*pi/16)
1793 #define dctCos6 0.38268343// cos(6*pi/16)
1794 #define dctSin6 0.92387953// sin(6*pi/16)
1795 #define dctSqrt2 1.41421356// sqrt(2)
1796 #define dctSqrt1d2 0.70710678// sqrt(2) / 2
1797#endif
1798
1799// color conversion parameters (16.16 fixed point format)
1800 #define dctCrToR 91881// 1.4020
1801 #define dctCbToG -22553// -0.3441363
1802 #define dctCrToG -46802// -0.71413636
1803 #define dctCbToB 116130// 1.772
1804
1805// clip [-256,511] --> [0,255]
1806#define dctClipOffset 256
1807static Guchar dctClip[768];
1808static int dctClipInit = 0;
1809
1810// zig zag decode map
1811static int dctZigZag[64] = {
1812 0,
1813 1, 8,
1814 16, 9, 2,
1815 3, 10, 17, 24,
1816 32, 25, 18, 11, 4,
1817 5, 12, 19, 26, 33, 40,
1818 48, 41, 34, 27, 20, 13, 6,
1819 7, 14, 21, 28, 35, 42, 49, 56,
1820 57, 50, 43, 36, 29, 22, 15,
1821 23, 30, 37, 44, 51, 58,
1822 59, 52, 45, 38, 31,
1823 39, 46, 53, 60,
1824 61, 54, 47,
1825 55, 62,
1826 63
1827};
1828
1829DCTStream::DCTStream(Stream *strA):
1830 FilterStream(strA) {
1831 int i, j;
1832
1833 width = height = 0;
1834 mcuWidth = mcuHeight = 0;
1835 numComps = 0;
1836 comp = 0;
1837 x = y = dy = 0;
1838 for (i = 0; i < 4; ++i)
1839 for (j = 0; j < 32; ++j)
1840 rowBuf[i][j] = NULL;
1841
1842 if (!dctClipInit) {
1843 for (i = -256; i < 0; ++i)
1844 dctClip[dctClipOffset + i] = 0;
1845 for (i = 0; i < 256; ++i)
1846 dctClip[dctClipOffset + i] = i;
1847 for (i = 256; i < 512; ++i)
1848 dctClip[dctClipOffset + i] = 255;
1849 dctClipInit = 1;
1850 }
1851}
1852
1853DCTStream::~DCTStream() {
1854 int i, j;
1855
1856 delete str;
1857 for (i = 0; i < numComps; ++i)
1858 for (j = 0; j < mcuHeight; ++j)
1859 gfree(rowBuf[i][j]);
1860}
1861
1862void DCTStream::reset() {
1863 str->reset();
1864 if (!readHeader()) {
1865 y = height;
1866 return;
1867 }
1868 restartMarker = 0xd0;
1869 restart();
1870}
1871
1872int DCTStream::getChar() {
1873 int c;
1874
1875 c = lookChar();
1876 if (c == EOF)
1877 return EOF;
1878 if (++comp == numComps) {
1879 comp = 0;
1880 if (++x == width) {
1881 x = 0;
1882 ++y;
1883 ++dy;
1884 }
1885 }
1886 if (y == height)
1887 readTrailer();
1888 return c;
1889}
1890
1891int DCTStream::lookChar() {
1892 if (y >= height)
1893 return EOF;
1894 if (dy >= mcuHeight) {
1895 if (!readMCURow()) {
1896 y = height;
1897 return EOF;
1898 }
1899 comp = 0;
1900 x = 0;
1901 dy = 0;
1902 }
1903 return rowBuf[comp][dy][x];
1904}
1905
1906void DCTStream::restart() {
1907 int i;
1908
1909 inputBits = 0;
1910 restartCtr = restartInterval;
1911 for (i = 0; i < numComps; ++i)
1912 compInfo[i].prevDC = 0;
1913}
1914
1915GBool DCTStream::readMCURow() {
1916 Guchar data[64];
1917 Guchar *p1, *p2;
1918 int pY, pCb, pCr, pR, pG, pB;
1919 int h, v, horiz, vert, hSub, vSub;
1920 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
1921 int c;
1922
1923 for (x1 = 0; x1 < width; x1 += mcuWidth) {
1924
1925 // deal with restart marker
1926 if (restartInterval > 0 && restartCtr == 0) {
1927 c = readMarker();
1928 if (c != restartMarker) {
1929 error(getPos(), "Bad DCT data: incorrect restart marker");
1930 return gFalse;
1931 }
1932 if (++restartMarker == 0xd8)
1933 restartMarker = 0xd0;
1934 restart();
1935 }
1936
1937 // read one MCU
1938 for (cc = 0; cc < numComps; ++cc) {
1939 h = compInfo[cc].hSample;
1940 v = compInfo[cc].vSample;
1941 horiz = mcuWidth / h;
1942 vert = mcuHeight / v;
1943 hSub = horiz / 8;
1944 vSub = vert / 8;
1945 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
1946 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
1947 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
1948 &acHuffTables[compInfo[cc].acHuffTable],
1949 quantTables[compInfo[cc].quantTable],
1950 &compInfo[cc].prevDC,
1951 data))
1952 return gFalse;
1953 if (hSub == 1 && vSub == 1) {
1954 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
1955 p1 = &rowBuf[cc][y2+y3][x1+x2];
1956 p1[0] = data[i];
1957 p1[1] = data[i+1];
1958 p1[2] = data[i+2];
1959 p1[3] = data[i+3];
1960 p1[4] = data[i+4];
1961 p1[5] = data[i+5];
1962 p1[6] = data[i+6];
1963 p1[7] = data[i+7];
1964 }
1965 } else if (hSub == 2 && vSub == 2) {
1966 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
1967 p1 = &rowBuf[cc][y2+y3][x1+x2];
1968 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
1969 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
1970 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
1971 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
1972 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
1973 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
1974 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
1975 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
1976 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
1977 }
1978 } else {
1979 i = 0;
1980 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
1981 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
1982 for (y5 = 0; y5 < vSub; ++y5)
1983 for (x5 = 0; x5 < hSub; ++x5)
1984 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
1985 ++i;
1986 }
1987 }
1988 }
1989 }
1990 }
1991 }
1992 --restartCtr;
1993
1994 // color space conversion
1995 if (colorXform) {
1996 // convert YCbCr to RGB
1997 if (numComps == 3) {
1998 for (y2 = 0; y2 < mcuHeight; ++y2) {
1999 for (x2 = 0; x2 < mcuWidth; ++x2) {
2000 pY = rowBuf[0][y2][x1+x2];
2001 pCb = rowBuf[1][y2][x1+x2] - 128;
2002 pCr = rowBuf[2][y2][x1+x2] - 128;
2003 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2004 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2005 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2006 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2007 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2008 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2009 }
2010 }
2011 // convert YCbCrK to CMYK (K is passed through unchanged)
2012 } else if (numComps == 4) {
2013 for (y2 = 0; y2 < mcuHeight; ++y2) {
2014 for (x2 = 0; x2 < mcuWidth; ++x2) {
2015 pY = rowBuf[0][y2][x1+x2];
2016 pCb = rowBuf[1][y2][x1+x2] - 128;
2017 pCr = rowBuf[2][y2][x1+x2] - 128;
2018 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2019 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2020 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2021 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2022 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2023 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2024 }
2025 }
2026 }
2027 }
2028 }
2029 return gTrue;
2030}
2031
2032// This IDCT algorithm is taken from:
2033// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2034// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2035// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2036// 988-991.
2037// The stage numbers mentioned in the comments refer to Figure 1 in this
2038// paper.
2039#ifndef FP_IDCT
2040GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2041 DCTHuffTable *acHuffTable,
2042 Guchar quantTable[64], int *prevDC,
2043 Guchar data[64]) {
2044 int tmp1[64];
2045 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2046 int run, size, amp;
2047 int c;
2048 int i, j;
2049
2050 // Huffman decode and dequantize
2051 size = readHuffSym(dcHuffTable);
2052 if (size == 9999)
2053 return gFalse;
2054 if (size > 0) {
2055 amp = readAmp(size);
2056 if (amp == 9999)
2057 return gFalse;
2058 } else {
2059 amp = 0;
2060 }
2061 tmp1[0] = (*prevDC += amp) * quantTable[0];
2062 for (i = 1; i < 64; ++i)
2063 tmp1[i] = 0;
2064 i = 1;
2065 while (i < 64) {
2066 run = 0;
2067 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2068 run += 0x10;
2069 if (c == 9999)
2070 return gFalse;
2071 if (c == 0x00) {
2072 break;
2073 } else {
2074 run += (c >> 4) & 0x0f;
2075 size = c & 0x0f;
2076 amp = readAmp(size);
2077 if (amp == 9999)
2078 return gFalse;
2079 i += run;
2080 j = dctZigZag[i++];
2081 tmp1[j] = amp * quantTable[j];
2082 }
2083 }
2084
2085 // inverse DCT on rows
2086 for (i = 0; i < 64; i += 8) {
2087
2088 // stage 4
2089 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2090 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2091 v2 = tmp1[i+2];
2092 v3 = tmp1[i+6];
2093 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2094 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2095 v5 = tmp1[i+3] << 4;
2096 v6 = tmp1[i+5] << 4;
2097
2098 // stage 3
2099 t = (v0 - v1+ 1) >> 1;
2100 v0 = (v0 + v1 + 1) >> 1;
2101 v1 = t;
2102 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2103 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2104 v3 = t;
2105 t = (v4 - v6 + 1) >> 1;
2106 v4 = (v4 + v6 + 1) >> 1;
2107 v6 = t;
2108 t = (v7 + v5 + 1) >> 1;
2109 v5 = (v7 - v5 + 1) >> 1;
2110 v7 = t;
2111
2112 // stage 2
2113 t = (v0 - v3 + 1) >> 1;
2114 v0 = (v0 + v3 + 1) >> 1;
2115 v3 = t;
2116 t = (v1 - v2 + 1) >> 1;
2117 v1 = (v1 + v2 + 1) >> 1;
2118 v2 = t;
2119 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2120 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2121 v7 = t;
2122 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2123 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2124 v6 = t;
2125
2126 // stage 1
2127 tmp1[i+0] = v0 + v7;
2128 tmp1[i+7] = v0 - v7;
2129 tmp1[i+1] = v1 + v6;
2130 tmp1[i+6] = v1 - v6;
2131 tmp1[i+2] = v2 + v5;
2132 tmp1[i+5] = v2 - v5;
2133 tmp1[i+3] = v3 + v4;
2134 tmp1[i+4] = v3 - v4;
2135 }
2136
2137 // inverse DCT on columns
2138 for (i = 0; i < 8; ++i) {
2139
2140 // stage 4
2141 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2142 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2143 v2 = tmp1[2*8+i];
2144 v3 = tmp1[6*8+i];
2145 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2146 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2147 v5 = tmp1[3*8+i];
2148 v6 = tmp1[5*8+i];
2149
2150 // stage 3
2151 t = (v0 - v1 + 1) >> 1;
2152 v0 = (v0 + v1 + 1) >> 1;
2153 v1 = t;
2154 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2155 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2156 v3 = t;
2157 t = (v4 - v6 + 1) >> 1;
2158 v4 = (v4 + v6 + 1) >> 1;
2159 v6 = t;
2160 t = (v7 + v5 + 1) >> 1;
2161 v5 = (v7 - v5 + 1) >> 1;
2162 v7 = t;
2163
2164 // stage 2
2165 t = (v0 - v3 + 1) >> 1;
2166 v0 = (v0 + v3 + 1) >> 1;
2167 v3 = t;
2168 t = (v1 - v2 + 1) >> 1;
2169 v1 = (v1 + v2 + 1) >> 1;
2170 v2 = t;
2171 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2172 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2173 v7 = t;
2174 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2175 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2176 v6 = t;
2177
2178 // stage 1
2179 tmp1[0*8+i] = v0 + v7;
2180 tmp1[7*8+i] = v0 - v7;
2181 tmp1[1*8+i] = v1 + v6;
2182 tmp1[6*8+i] = v1 - v6;
2183 tmp1[2*8+i] = v2 + v5;
2184 tmp1[5*8+i] = v2 - v5;
2185 tmp1[3*8+i] = v3 + v4;
2186 tmp1[4*8+i] = v3 - v4;
2187 }
2188
2189 // convert to 8-bit integers
2190 for (i = 0; i < 64; ++i)
2191 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2192
2193 return gTrue;
2194}
2195#endif
2196
2197#ifdef FP_IDCT
2198GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2199 DCTHuffTable *acHuffTable,
2200 Guchar quantTable[64], int *prevDC,
2201 Guchar data[64]) {
2202 fouble tmp1[64];
2203 fouble v0, v1, v2, v3, v4, v5, v6, v7, t;
2204 int run, size, amp;
2205 int c;
2206 int i, j;
2207
2208 // Huffman decode and dequantize
2209 size = readHuffSym(dcHuffTable);
2210 if (size == 9999)
2211 return gFalse;
2212 if (size > 0) {
2213 amp = readAmp(size);
2214 if (amp == 9999)
2215 return gFalse;
2216 } else {
2217 amp = 0;
2218 }
2219 tmp1[0] = (*prevDC += amp) * quantTable[0];
2220 for (i = 1; i < 64; ++i)
2221 tmp1[i] = 0;
2222 i = 1;
2223 while (i < 64) {
2224 run = 0;
2225 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2226 run += 0x10;
2227 if (c == 9999)
2228 return gFalse;
2229 if (c == 0x00) {
2230 break;
2231 } else {
2232 run += (c >> 4) & 0x0f;
2233 size = c & 0x0f;
2234 amp = readAmp(size);
2235 if (amp == 9999)
2236 return gFalse;
2237 i += run;
2238 j = dctZigZag[i++];
2239 tmp1[j] = amp * quantTable[j];
2240 }
2241 }
2242
2243 // inverse DCT on rows
2244 for (i = 0; i < 64; i += 8) {
2245
2246 // stage 4
2247 v0 = dctSqrt2 * tmp1[i+0];
2248 v1 = dctSqrt2 * tmp1[i+4];
2249 v2 = tmp1[i+2];
2250 v3 = tmp1[i+6];
2251 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2252 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2253 v5 = tmp1[i+3];
2254 v6 = tmp1[i+5];
2255
2256 // stage 3
2257 t = 0.5 * (v0 - v1);
2258 v0 = 0.5 * (v0 + v1);
2259 v1 = t;
2260 t = v2 * dctSin6 + v3 * dctCos6;
2261 v2 = v2 * dctCos6 - v3 * dctSin6;
2262 v3 = t;
2263 t = 0.5 * (v4 - v6);
2264 v4 = 0.5 * (v4 + v6);
2265 v6 = t;
2266 t = 0.5 * (v7 + v5);
2267 v5 = 0.5 * (v7 - v5);
2268 v7 = t;
2269
2270 // stage 2
2271 t = 0.5 * (v0 - v3);
2272 v0 = 0.5 * (v0 + v3);
2273 v3 = t;
2274 t = 0.5 * (v1 - v2);
2275 v1 = 0.5 * (v1 + v2);
2276 v2 = t;
2277 t = v4 * dctSin3 + v7 * dctCos3;
2278 v4 = v4 * dctCos3 - v7 * dctSin3;
2279 v7 = t;
2280 t = v5 * dctSin1 + v6 * dctCos1;
2281 v5 = v5 * dctCos1 - v6 * dctSin1;
2282 v6 = t;
2283
2284 // stage 1
2285 tmp1[i+0] = v0 + v7;
2286 tmp1[i+7] = v0 - v7;
2287 tmp1[i+1] = v1 + v6;
2288 tmp1[i+6] = v1 - v6;
2289 tmp1[i+2] = v2 + v5;
2290 tmp1[i+5] = v2 - v5;
2291 tmp1[i+3] = v3 + v4;
2292 tmp1[i+4] = v3 - v4;
2293 }
2294
2295 // inverse DCT on columns
2296 for (i = 0; i < 8; ++i) {
2297
2298 // stage 4
2299 v0 = dctSqrt2 * tmp1[0*8+i];
2300 v1 = dctSqrt2 * tmp1[4*8+i];
2301 v2 = tmp1[2*8+i];
2302 v3 = tmp1[6*8+i];
2303 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2304 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2305 v5 = tmp1[3*8+i];
2306 v6 = tmp1[5*8+i];
2307
2308 // stage 3
2309 t = 0.5 * (v0 - v1);
2310 v0 = 0.5 * (v0 + v1);
2311 v1 = t;
2312 t = v2 * dctSin6 + v3 * dctCos6;
2313 v2 = v2 * dctCos6 - v3 * dctSin6;
2314 v3 = t;
2315 t = 0.5 * (v4 - v6);
2316 v4 = 0.5 * (v4 + v6);
2317 v6 = t;
2318 t = 0.5 * (v7 + v5);
2319 v5 = 0.5 * (v7 - v5);
2320 v7 = t;
2321
2322 // stage 2
2323 t = 0.5 * (v0 - v3);
2324 v0 = 0.5 * (v0 + v3);
2325 v3 = t;
2326 t = 0.5 * (v1 - v2);
2327 v1 = 0.5 * (v1 + v2);
2328 v2 = t;
2329 t = v4 * dctSin3 + v7 * dctCos3;
2330 v4 = v4 * dctCos3 - v7 * dctSin3;
2331 v7 = t;
2332 t = v5 * dctSin1 + v6 * dctCos1;
2333 v5 = v5 * dctCos1 - v6 * dctSin1;
2334 v6 = t;
2335
2336 // stage 1
2337 tmp1[0*8+i] = v0 + v7;
2338 tmp1[7*8+i] = v0 - v7;
2339 tmp1[1*8+i] = v1 + v6;
2340 tmp1[6*8+i] = v1 - v6;
2341 tmp1[2*8+i] = v2 + v5;
2342 tmp1[5*8+i] = v2 - v5;
2343 tmp1[3*8+i] = v3 + v4;
2344 tmp1[4*8+i] = v3 - v4;
2345 }
2346
2347 // convert to 8-bit integers
2348 for (i = 0; i < 64; ++i)
2349 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2350
2351 return gTrue;
2352}
2353#endif
2354
2355int DCTStream::readHuffSym(DCTHuffTable *table) {
2356 Gushort code;
2357 int bit;
2358 int codeBits;
2359
2360 code = 0;
2361 codeBits = 0;
2362 do {
2363 // add a bit to the code
2364 if ((bit = readBit()) == EOF)
2365 return 9999;
2366 code = (code << 1) + bit;
2367 ++codeBits;
2368
2369 // look up code
2370 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2371 code -= table->firstCode[codeBits];
2372 return table->sym[table->firstSym[codeBits] + code];
2373 }
2374 } while (codeBits < 16);
2375
2376 error(getPos(), "Bad Huffman code in DCT stream");
2377 return 9999;
2378}
2379
2380int DCTStream::readAmp(int size) {
2381 int amp, bit;
2382 int bits;
2383
2384 amp = 0;
2385 for (bits = 0; bits < size; ++bits) {
2386 if ((bit = readBit()) == EOF)
2387 return 9999;
2388 amp = (amp << 1) + bit;
2389 }
2390 if (amp < (1 << (size - 1)))
2391 amp -= (1 << size) - 1;
2392 return amp;
2393}
2394
2395int DCTStream::readBit() {
2396 int bit;
2397 int c, c2;
2398
2399 if (inputBits == 0) {
2400 if ((c = str->getChar()) == EOF)
2401 return EOF;
2402 if (c == 0xff) {
2403 do {
2404 c2 = str->getChar();
2405 } while (c2 == 0xff);
2406 if (c2 != 0x00) {
2407 error(getPos(), "Bad DCT data: missing 00 after ff");
2408 return EOF;
2409 }
2410 }
2411 inputBuf = c;
2412 inputBits = 8;
2413 }
2414 bit = (inputBuf >> (inputBits - 1)) & 1;
2415 --inputBits;
2416 return bit;
2417}
2418
2419GBool DCTStream::readHeader() {
2420 GBool doScan;
2421 int minHSample, minVSample;
2422 int bufWidth;
2423 int n;
2424 int c = 0;
2425 int i, j;
2426
2427 width = height = 0;
2428 numComps = 0;
2429 numQuantTables = 0;
2430 numDCHuffTables = 0;
2431 numACHuffTables = 0;
2432 colorXform = 0;
2433 gotAdobeMarker = gFalse;
2434 restartInterval = 0;
2435
2436 // read headers
2437 doScan = gFalse;
2438 while (!doScan) {
2439 c = readMarker();
2440 switch (c) {
2441 case 0xc0: // SOF0
2442 if (!readFrameInfo())
2443 return gFalse;
2444 break;
2445 case 0xc4: // DHT
2446 if (!readHuffmanTables())
2447 return gFalse;
2448 break;
2449 case 0xd8: // SOI
2450 break;
2451 case 0xda: // SOS
2452 if (!readScanInfo())
2453 return gFalse;
2454 doScan = gTrue;
2455 break;
2456 case 0xdb: // DQT
2457 if (!readQuantTables())
2458 return gFalse;
2459 break;
2460 case 0xdd: // DRI
2461 if (!readRestartInterval())
2462 return gFalse;
2463 break;
2464 case 0xee: // APP14
2465 if (!readAdobeMarker())
2466 return gFalse;
2467 break;
2468 case EOF:
2469 error(getPos(), "Bad DCT header");
2470 return gFalse;
2471 default:
2472 // skip APPn / COM / etc.
2473 if (c >= 0xe0) {
2474 n = read16() - 2;
2475 for (i = 0; i < n; ++i)
2476 str->getChar();
2477 } else {
2478 error(getPos(), "Unknown DCT marker <%02x>", c);
2479 return gFalse;
2480 }
2481 break;
2482 }
2483 }
2484
2485 // compute MCU size
2486 mcuWidth = minHSample = compInfo[0].hSample;
2487 mcuHeight = minVSample = compInfo[0].vSample;
2488 for (i = 1; i < numComps; ++i) {
2489 if (compInfo[i].hSample < minHSample)
2490 minHSample = compInfo[i].hSample;
2491 if (compInfo[i].vSample < minVSample)
2492 minVSample = compInfo[i].vSample;
2493 if (compInfo[i].hSample > mcuWidth)
2494 mcuWidth = compInfo[i].hSample;
2495 if (compInfo[i].vSample > mcuHeight)
2496 mcuHeight = compInfo[i].vSample;
2497 }
2498 for (i = 0; i < numComps; ++i) {
2499 compInfo[i].hSample /= minHSample;
2500 compInfo[i].vSample /= minVSample;
2501 }
2502 mcuWidth = (mcuWidth / minHSample) * 8;
2503 mcuHeight = (mcuHeight / minVSample) * 8;
2504
2505 // allocate buffers
2506 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2507 for (i = 0; i < numComps; ++i)
2508 for (j = 0; j < mcuHeight; ++j)
2509 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2510
2511 // figure out color transform
2512 if (!gotAdobeMarker && numComps == 3) {
2513 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2514 colorXform = 1;
2515 }
2516 }
2517
2518 // initialize counters
2519 comp = 0;
2520 x = 0;
2521 y = 0;
2522 dy = mcuHeight;
2523
2524 return gTrue;
2525}
2526
2527GBool DCTStream::readFrameInfo() {
2528 int length;
2529 int prec;
2530 int i;
2531 int c;
2532
2533 length = read16() - 2;
2534 prec = str->getChar();
2535 height = read16();
2536 width = read16();
2537 numComps = str->getChar();
2538 length -= 6;
2539 if (prec != 8) {
2540 error(getPos(), "Bad DCT precision %d", prec);
2541 return gFalse;
2542 }
2543 for (i = 0; i < numComps; ++i) {
2544 compInfo[i].id = str->getChar();
2545 compInfo[i].inScan = gFalse;
2546 c = str->getChar();
2547 compInfo[i].hSample = (c >> 4) & 0x0f;
2548 compInfo[i].vSample = c & 0x0f;
2549 compInfo[i].quantTable = str->getChar();
2550 compInfo[i].dcHuffTable = 0;
2551 compInfo[i].acHuffTable = 0;
2552 }
2553 return gTrue;
2554}
2555
2556GBool DCTStream::readScanInfo() {
2557 int length;
2558 int scanComps, id, c;
2559 int i, j;
2560
2561 length = read16() - 2;
2562 scanComps = str->getChar();
2563 --length;
2564 if (length != 2 * scanComps + 3) {
2565 error(getPos(), "Bad DCT scan info block");
2566 return gFalse;
2567 }
2568 for (i = 0; i < scanComps; ++i) {
2569 id = str->getChar();
2570 for (j = 0; j < numComps; ++j) {
2571 if (id == compInfo[j].id)
2572 break;
2573 }
2574 if (j == numComps) {
2575 error(getPos(), "Bad DCT component ID in scan info block");
2576 return gFalse;
2577 }
2578 compInfo[j].inScan = gTrue;
2579 c = str->getChar();
2580 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2581 compInfo[j].acHuffTable = c & 0x0f;
2582 }
2583 str->getChar();
2584 str->getChar();
2585 str->getChar();
2586 return gTrue;
2587}
2588
2589GBool DCTStream::readQuantTables() {
2590 int length;
2591 int i;
2592 int index;
2593
2594 length = read16() - 2;
2595 while (length > 0) {
2596 index = str->getChar();
2597 if ((index & 0xf0) || index >= 4) {
2598 error(getPos(), "Bad DCT quantization table");
2599 return gFalse;
2600 }
2601 if (index == numQuantTables)
2602 numQuantTables = index + 1;
2603 for (i = 0; i < 64; ++i)
2604 quantTables[index][dctZigZag[i]] = str->getChar();
2605 length -= 65;
2606 }
2607 return gTrue;
2608}
2609
2610GBool DCTStream::readHuffmanTables() {
2611 DCTHuffTable *tbl;
2612 int length;
2613 int index;
2614 Gushort code;
2615 Guchar sym;
2616 int i;
2617 int c;
2618
2619 length = read16() - 2;
2620 while (length > 0) {
2621 index = str->getChar();
2622 --length;
2623 if ((index & 0x0f) >= 4) {
2624 error(getPos(), "Bad DCT Huffman table");
2625 return gFalse;
2626 }
2627 if (index & 0x10) {
2628 index &= 0x0f;
2629 if (index >= numACHuffTables)
2630 numACHuffTables = index+1;
2631 tbl = &acHuffTables[index];
2632 } else {
2633 if (index >= numDCHuffTables)
2634 numDCHuffTables = index+1;
2635 tbl = &dcHuffTables[index];
2636 }
2637 sym = 0;
2638 code = 0;
2639 for (i = 1; i <= 16; ++i) {
2640 c = str->getChar();
2641 tbl->firstSym[i] = sym;
2642 tbl->firstCode[i] = code;
2643 tbl->numCodes[i] = c;
2644 sym += c;
2645 code = (code + c) << 1;
2646 }
2647 length -= 16;
2648 for (i = 0; i < sym; ++i)
2649 tbl->sym[i] = str->getChar();
2650 length -= sym;
2651 }
2652 return gTrue;
2653}
2654
2655GBool DCTStream::readRestartInterval() {
2656 int length;
2657
2658 length = read16();
2659 if (length != 4) {
2660 error(getPos(), "Bad DCT restart interval");
2661 return gFalse;
2662 }
2663 restartInterval = read16();
2664 return gTrue;
2665}
2666
2667GBool DCTStream::readAdobeMarker() {
2668 int length, i;
2669 char buf[12];
2670 int c;
2671
2672 length = read16();
2673 if (length != 14)
2674 goto err;
2675 for (i = 0; i < 12; ++i) {
2676 if ((c = str->getChar()) == EOF)
2677 goto err;
2678 buf[i] = c;
2679 }
2680 if (strncmp(buf, "Adobe", 5))
2681 goto err;
2682 colorXform = buf[11];
2683 gotAdobeMarker = gTrue;
2684 return gTrue;
2685
2686 err:
2687 error(getPos(), "Bad DCT Adobe APP14 marker");
2688 return gFalse;
2689}
2690
2691GBool DCTStream::readTrailer() {
2692 int c;
2693
2694 c = readMarker();
2695 if (c != 0xd9) { // EOI
2696 error(getPos(), "Bad DCT trailer");
2697 return gFalse;
2698 }
2699 return gTrue;
2700}
2701
2702int DCTStream::readMarker() {
2703 int c;
2704
2705 do {
2706 do {
2707 c = str->getChar();
2708 } while (c != 0xff);
2709 do {
2710 c = str->getChar();
2711 } while (c == 0xff);
2712 } while (c == 0x00);
2713 return c;
2714}
2715
2716int DCTStream::read16() {
2717 int c1, c2;
2718
2719 if ((c1 = str->getChar()) == EOF)
2720 return EOF;
2721 if ((c2 = str->getChar()) == EOF)
2722 return EOF;
2723 return (c1 << 8) + c2;
2724}
2725
2726GString *DCTStream::getPSFilter(char *indent) {
2727 GString *s;
2728
2729 if (!(s = str->getPSFilter(indent))) {
2730 return NULL;
2731 }
2732 s->append(indent)->append("<< >> /DCTDecode filter\n");
2733 return s;
2734}
2735
2736GBool DCTStream::isBinary(GBool last) {
2737 return str->isBinary(gTrue);
2738}
2739
2740//------------------------------------------------------------------------
2741// FlateStream
2742//------------------------------------------------------------------------
2743
2744int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2745 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2746};
2747
2748FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2749 {0, 3},
2750 {0, 4},
2751 {0, 5},
2752 {0, 6},
2753 {0, 7},
2754 {0, 8},
2755 {0, 9},
2756 {0, 10},
2757 {1, 11},
2758 {1, 13},
2759 {1, 15},
2760 {1, 17},
2761 {2, 19},
2762 {2, 23},
2763 {2, 27},
2764 {2, 31},
2765 {3, 35},
2766 {3, 43},
2767 {3, 51},
2768 {3, 59},
2769 {4, 67},
2770 {4, 83},
2771 {4, 99},
2772 {4, 115},
2773 {5, 131},
2774 {5, 163},
2775 {5, 195},
2776 {5, 227},
2777 {0, 258}
2778};
2779
2780FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2781 { 0, 1},
2782 { 0, 2},
2783 { 0, 3},
2784 { 0, 4},
2785 { 1, 5},
2786 { 1, 7},
2787 { 2, 9},
2788 { 2, 13},
2789 { 3, 17},
2790 { 3, 25},
2791 { 4, 33},
2792 { 4, 49},
2793 { 5, 65},
2794 { 5, 97},
2795 { 6, 129},
2796 { 6, 193},
2797 { 7, 257},
2798 { 7, 385},
2799 { 8, 513},
2800 { 8, 769},
2801 { 9, 1025},
2802 { 9, 1537},
2803 {10, 2049},
2804 {10, 3073},
2805 {11, 4097},
2806 {11, 6145},
2807 {12, 8193},
2808 {12, 12289},
2809 {13, 16385},
2810 {13, 24577}
2811};
2812
2813FlateStream::FlateStream(Stream *strA, int predictor, int columns,
2814 int colors, int bits):
2815 FilterStream(strA) {
2816 if (predictor != 1) {
2817 pred = new StreamPredictor(this, predictor, columns, colors, bits);
2818 } else {
2819 pred = NULL;
2820 }
2821}
2822
2823FlateStream::~FlateStream() {
2824 if (pred) {
2825 delete pred;
2826 }
2827 delete str;
2828}
2829
2830void FlateStream::reset() {
2831 int cmf, flg;
2832
2833 index = 0;
2834 remain = 0;
2835 codeBuf = 0;
2836 codeSize = 0;
2837 compressedBlock = gFalse;
2838 endOfBlock = gTrue;
2839 eof = gTrue;
2840
2841 str->reset();
2842
2843 // read header
2844 //~ need to look at window size?
2845 endOfBlock = eof = gTrue;
2846 cmf = str->getChar();
2847 flg = str->getChar();
2848 if (cmf == EOF || flg == EOF)
2849 return;
2850 if ((cmf & 0x0f) != 0x08) {
2851 error(getPos(), "Unknown compression method in flate stream");
2852 return;
2853 }
2854 if ((((cmf << 8) + flg) % 31) != 0) {
2855 error(getPos(), "Bad FCHECK in flate stream");
2856 return;
2857 }
2858 if (flg & 0x20) {
2859 error(getPos(), "FDICT bit set in flate stream");
2860 return;
2861 }
2862
2863 eof = gFalse;
2864}
2865
2866int FlateStream::getChar() {
2867 int c;
2868
2869 if (pred) {
2870 return pred->getChar();
2871 }
2872 while (remain == 0) {
2873 if (endOfBlock && eof)
2874 return EOF;
2875 readSome();
2876 }
2877 c = buf[index];
2878 index = (index + 1) & flateMask;
2879 --remain;
2880 return c;
2881}
2882
2883int FlateStream::lookChar() {
2884 int c;
2885
2886 if (pred) {
2887 return pred->lookChar();
2888 }
2889 while (remain == 0) {
2890 if (endOfBlock && eof)
2891 return EOF;
2892 readSome();
2893 }
2894 c = buf[index];
2895 return c;
2896}
2897
2898int FlateStream::getRawChar() {
2899 int c;
2900
2901 while (remain == 0) {
2902 if (endOfBlock && eof)
2903 return EOF;
2904 readSome();
2905 }
2906 c = buf[index];
2907 index = (index + 1) & flateMask;
2908 --remain;
2909 return c;
2910}
2911
2912GString *FlateStream::getPSFilter(char *indent) {
2913 return NULL;
2914}
2915
2916GBool FlateStream::isBinary(GBool last) {
2917 return str->isBinary(gTrue);
2918}
2919
2920void FlateStream::readSome() {
2921 int code1, code2;
2922 int len, dist;
2923 int i, j, k;
2924 int c;
2925
2926 if (endOfBlock) {
2927 if (!startBlock())
2928 return;
2929 }
2930
2931 if (compressedBlock) {
2932 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
2933 goto err;
2934 if (code1 < 256) {
2935 buf[index] = code1;
2936 remain = 1;
2937 } else if (code1 == 256) {
2938 endOfBlock = gTrue;
2939 remain = 0;
2940 } else {
2941 code1 -= 257;
2942 code2 = lengthDecode[code1].bits;
2943 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2944 goto err;
2945 len = lengthDecode[code1].first + code2;
2946 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
2947 goto err;
2948 code2 = distDecode[code1].bits;
2949 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2950 goto err;
2951 dist = distDecode[code1].first + code2;
2952 i = index;
2953 j = (index - dist) & flateMask;
2954 for (k = 0; k < len; ++k) {
2955 buf[i] = buf[j];
2956 i = (i + 1) & flateMask;
2957 j = (j + 1) & flateMask;
2958 }
2959 remain = len;
2960 }
2961
2962 } else {
2963 len = (blockLen < flateWindow) ? blockLen : flateWindow;
2964 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
2965 if ((c = str->getChar()) == EOF) {
2966 endOfBlock = eof = gTrue;
2967 break;
2968 }
2969 buf[j] = c & 0xff;
2970 }
2971 remain = i;
2972 blockLen -= len;
2973 if (blockLen == 0)
2974 endOfBlock = gTrue;
2975 }
2976
2977 return;
2978
2979err:
2980 error(getPos(), "Unexpected end of file in flate stream");
2981 endOfBlock = eof = gTrue;
2982 remain = 0;
2983}
2984
2985GBool FlateStream::startBlock() {
2986 int blockHdr;
2987 int c;
2988 int check;
2989
2990 // read block header
2991 blockHdr = getCodeWord(3);
2992 if (blockHdr & 1)
2993 eof = gTrue;
2994 blockHdr >>= 1;
2995
2996 // uncompressed block
2997 if (blockHdr == 0) {
2998 compressedBlock = gFalse;
2999 if ((c = str->getChar()) == EOF)
3000 goto err;
3001 blockLen = c & 0xff;
3002 if ((c = str->getChar()) == EOF)
3003 goto err;
3004 blockLen |= (c & 0xff) << 8;
3005 if ((c = str->getChar()) == EOF)
3006 goto err;
3007 check = c & 0xff;
3008 if ((c = str->getChar()) == EOF)
3009 goto err;
3010 check |= (c & 0xff) << 8;
3011 if (check != (~blockLen & 0xffff))
3012 error(getPos(), "Bad uncompressed block length in flate stream");
3013 codeBuf = 0;
3014 codeSize = 0;
3015
3016 // compressed block with fixed codes
3017 } else if (blockHdr == 1) {
3018 compressedBlock = gTrue;
3019 loadFixedCodes();
3020
3021 // compressed block with dynamic codes
3022 } else if (blockHdr == 2) {
3023 compressedBlock = gTrue;
3024 if (!readDynamicCodes())
3025 goto err;
3026
3027 // unknown block type
3028 } else {
3029 goto err;
3030 }
3031
3032 endOfBlock = gFalse;
3033 return gTrue;
3034
3035err:
3036 error(getPos(), "Bad block header in flate stream");
3037 endOfBlock = eof = gTrue;
3038 return gFalse;
3039}
3040
3041void FlateStream::loadFixedCodes() {
3042 int i;
3043
3044 // set up code arrays
3045 litCodeTab.codes = allCodes;
3046 distCodeTab.codes = allCodes + flateMaxLitCodes;
3047
3048 // initialize literal code table
3049 for (i = 0; i <= 143; ++i)
3050 litCodeTab.codes[i].len = 8;
3051 for (i = 144; i <= 255; ++i)
3052 litCodeTab.codes[i].len = 9;
3053 for (i = 256; i <= 279; ++i)
3054 litCodeTab.codes[i].len = 7;
3055 for (i = 280; i <= 287; ++i)
3056 litCodeTab.codes[i].len = 8;
3057 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3058
3059 // initialize distance code table
3060 for (i = 0; i <= 5; ++i) {
3061 distCodeTab.start[i] = 0;
3062 }
3063 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3064 distCodeTab.start[i] = flateMaxDistCodes;
3065 }
3066 for (i = 0; i < flateMaxDistCodes; ++i) {
3067 distCodeTab.codes[i].len = 5;
3068 distCodeTab.codes[i].code = i;
3069 distCodeTab.codes[i].val = i;
3070 }
3071}
3072
3073GBool FlateStream::readDynamicCodes() {
3074 int numCodeLenCodes;
3075 int numLitCodes;
3076 int numDistCodes;
3077 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3078 FlateHuffmanTab codeLenCodeTab;
3079 int len, repeat, code;
3080 int i;
3081
3082 // read lengths
3083 if ((numLitCodes = getCodeWord(5)) == EOF)
3084 goto err;
3085 numLitCodes += 257;
3086 if ((numDistCodes = getCodeWord(5)) == EOF)
3087 goto err;
3088 numDistCodes += 1;
3089 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3090 goto err;
3091 numCodeLenCodes += 4;
3092 if (numLitCodes > flateMaxLitCodes ||
3093 numDistCodes > flateMaxDistCodes ||
3094 numCodeLenCodes > flateMaxCodeLenCodes)
3095 goto err;
3096
3097 // read code length code table
3098 codeLenCodeTab.codes = codeLenCodes;
3099 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3100 codeLenCodes[i].len = 0;
3101 for (i = 0; i < numCodeLenCodes; ++i) {
3102 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3103 goto err;
3104 }
3105 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3106
3107 // set up code arrays
3108 litCodeTab.codes = allCodes;
3109 distCodeTab.codes = allCodes + numLitCodes;
3110
3111 // read literal and distance code tables
3112 len = 0;
3113 repeat = 0;
3114 i = 0;
3115 while (i < numLitCodes + numDistCodes) {
3116 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3117 goto err;
3118 if (code == 16) {
3119 if ((repeat = getCodeWord(2)) == EOF)
3120 goto err;
3121 for (repeat += 3; repeat > 0; --repeat)
3122 allCodes[i++].len = len;
3123 } else if (code == 17) {
3124 if ((repeat = getCodeWord(3)) == EOF)
3125 goto err;
3126 len = 0;
3127 for (repeat += 3; repeat > 0; --repeat)
3128 allCodes[i++].len = 0;
3129 } else if (code == 18) {
3130 if ((repeat = getCodeWord(7)) == EOF)
3131 goto err;
3132 len = 0;
3133 for (repeat += 11; repeat > 0; --repeat)
3134 allCodes[i++].len = 0;
3135 } else {
3136 allCodes[i++].len = len = code;
3137 }
3138 }
3139 compHuffmanCodes(&litCodeTab, numLitCodes);
3140 compHuffmanCodes(&distCodeTab, numDistCodes);
3141
3142 return gTrue;
3143
3144err:
3145 error(getPos(), "Bad dynamic code table in flate stream");
3146 return gFalse;
3147}
3148
3149// On entry, the <tab->codes> array contains the lengths of each code,
3150// stored in code value order. This function computes the code words.
3151// The result is sorted in order of (1) code length and (2) code word.
3152// The length values are no longer valid. The <tab->start> array is
3153// filled with the indexes of the first code of each length.
3154void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3155 int numLengths[flateMaxHuffman+1];
3156 int nextCode[flateMaxHuffman+1];
3157 int nextIndex[flateMaxHuffman+2];
3158 int code;
3159 int i, j;
3160
3161 // count number of codes for each code length
3162 for (i = 0; i <= flateMaxHuffman; ++i)
3163 numLengths[i] = 0;
3164 for (i = 0; i < n; ++i)
3165 ++numLengths[tab->codes[i].len];
3166
3167 // compute first index for each length
3168 tab->start[0] = nextIndex[0] = 0;
3169 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3170 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3171
3172 // compute first code for each length
3173 code = 0;
3174 numLengths[0] = 0;
3175 for (i = 1; i <= flateMaxHuffman; ++i) {
3176 code = (code + numLengths[i-1]) << 1;
3177 nextCode[i] = code;
3178 }
3179
3180 // compute the codes -- this permutes the codes array from value
3181 // order to length/code order
3182 for (i = 0; i < n; ++i) {
3183 j = nextIndex[tab->codes[i].len]++;
3184 if (tab->codes[i].len == 0)
3185 tab->codes[j].code = 0;
3186 else
3187 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3188 tab->codes[j].val = i;
3189 }
3190}
3191
3192int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3193 int len;
3194 int code;
3195 int c;
3196 int i, j;
3197
3198 code = 0;
3199 for (len = 1; len <= flateMaxHuffman; ++len) {
3200
3201 // add a bit to the code
3202 if (codeSize == 0) {
3203 if ((c = str->getChar()) == EOF)
3204 return EOF;
3205 codeBuf = c & 0xff;
3206 codeSize = 8;
3207 }
3208 code = (code << 1) | (codeBuf & 1);
3209 codeBuf >>= 1;
3210 --codeSize;
3211
3212 // look for code
3213 i = tab->start[len];
3214 j = tab->start[len + 1];
3215 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3216 i += code - tab->codes[i].code;
3217 return tab->codes[i].val;
3218 }
3219 }
3220
3221 // not found
3222 error(getPos(), "Bad code (%04x) in flate stream", code);
3223 return EOF;
3224}
3225
3226int FlateStream::getCodeWord(int bits) {
3227 int c;
3228
3229 while (codeSize < bits) {
3230 if ((c = str->getChar()) == EOF)
3231 return EOF;
3232 codeBuf |= (c & 0xff) << codeSize;
3233 codeSize += 8;
3234 }
3235 c = codeBuf & ((1 << bits) - 1);
3236 codeBuf >>= bits;
3237 codeSize -= bits;
3238 return c;
3239}
3240
3241//------------------------------------------------------------------------
3242// EOFStream
3243//------------------------------------------------------------------------
3244
3245EOFStream::EOFStream(Stream *strA):
3246 FilterStream(strA) {
3247}
3248
3249EOFStream::~EOFStream() {
3250 delete str;
3251}
3252
3253//------------------------------------------------------------------------
3254// FixedLengthEncoder
3255//------------------------------------------------------------------------
3256
3257FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3258 FilterStream(strA) {
3259 length = lengthA;
3260 count = 0;
3261}
3262
3263FixedLengthEncoder::~FixedLengthEncoder() {
3264 if (str->isEncoder())
3265 delete str;
3266}
3267
3268void FixedLengthEncoder::reset() {
3269 str->reset();
3270 count = 0;
3271}
3272
3273void FixedLengthEncoder::close() {
3274}
3275
3276int FixedLengthEncoder::getChar() {
3277 if (length >= 0 && count >= length)
3278 return EOF;
3279 ++count;
3280 return str->getChar();
3281}
3282
3283int FixedLengthEncoder::lookChar() {
3284 if (length >= 0 && count >= length)
3285 return EOF;
3286 return str->getChar();
3287}
3288
3289//------------------------------------------------------------------------
3290// ASCII85Encoder
3291//------------------------------------------------------------------------
3292
3293ASCII85Encoder::ASCII85Encoder(Stream *strA):
3294 FilterStream(strA) {
3295 bufPtr = bufEnd = buf;
3296 lineLen = 0;
3297 eof = gFalse;
3298}
3299
3300ASCII85Encoder::~ASCII85Encoder() {
3301 if (str->isEncoder())
3302 delete str;
3303}
3304
3305void ASCII85Encoder::reset() {
3306 str->reset();
3307 bufPtr = bufEnd = buf;
3308 lineLen = 0;
3309 eof = gFalse;
3310}
3311
3312void ASCII85Encoder::close() {
3313}
3314
3315GBool ASCII85Encoder::fillBuf() {
3316 Gulong t;
3317 char buf1[5];
3318 int c;
3319 int n, i;
3320
3321 if (eof)
3322 return gFalse;
3323 t = 0;
3324 for (n = 0; n < 4; ++n) {
3325 if ((c = str->getChar()) == EOF)
3326 break;
3327 t = (t << 8) + c;
3328 }
3329 bufPtr = bufEnd = buf;
3330 if (n > 0) {
3331 if (n == 4 && t == 0) {
3332 *bufEnd++ = 'z';
3333 if (++lineLen == 65) {
3334 *bufEnd++ = '\n';
3335 lineLen = 0;
3336 }
3337 } else {
3338 if (n < 4)
3339 t <<= 8 * (4 - n);
3340 for (i = 4; i >= 0; --i) {
3341 buf1[i] = (char)(t % 85 + 0x21);
3342 t /= 85;
3343 }
3344 for (i = 0; i <= n; ++i) {
3345 *bufEnd++ = buf1[i];
3346 if (++lineLen == 65) {
3347 *bufEnd++ = '\n';
3348 lineLen = 0;
3349 }
3350 }
3351 }
3352 }
3353 if (n < 4) {
3354 *bufEnd++ = '~';
3355 *bufEnd++ = '>';
3356 eof = gTrue;
3357 }
3358 return bufPtr < bufEnd;
3359}
3360
3361//------------------------------------------------------------------------
3362// RunLengthEncoder
3363//------------------------------------------------------------------------
3364
3365RunLengthEncoder::RunLengthEncoder(Stream *strA):
3366 FilterStream(strA) {
3367 bufPtr = bufEnd = nextEnd = buf;
3368 eof = gFalse;
3369}
3370
3371RunLengthEncoder::~RunLengthEncoder() {
3372 if (str->isEncoder())
3373 delete str;
3374}
3375
3376void RunLengthEncoder::reset() {
3377 str->reset();
3378 bufPtr = bufEnd = nextEnd = buf;
3379 eof = gFalse;
3380}
3381
3382void RunLengthEncoder::close() {
3383}
3384
3385//
3386// When fillBuf finishes, buf[] looks like this:
3387// +-----+--------------+-----------------+--
3388// + tag | ... data ... | next 0, 1, or 2 |
3389// +-----+--------------+-----------------+--
3390// ^ ^ ^
3391// bufPtr bufEnd nextEnd
3392//
3393GBool RunLengthEncoder::fillBuf() {
3394 int c, c1, c2;
3395 int n;
3396
3397 // already hit EOF?
3398 if (eof)
3399 return gFalse;
3400
3401 // grab two bytes
3402 if (nextEnd < bufEnd + 1) {
3403 if ((c1 = str->getChar()) == EOF) {
3404 eof = gTrue;
3405 return gFalse;
3406 }
3407 } else {
3408 c1 = bufEnd[0] & 0xff;
3409 }
3410 if (nextEnd < bufEnd + 2) {
3411 if ((c2 = str->getChar()) == EOF) {
3412 eof = gTrue;
3413 buf[0] = 0;
3414 buf[1] = c1;
3415 bufPtr = buf;
3416 bufEnd = &buf[2];
3417 return gTrue;
3418 }
3419 } else {
3420 c2 = bufEnd[1] & 0xff;
3421 }
3422
3423 // check for repeat
3424 c = 0; // make gcc happy
3425 if (c1 == c2) {
3426 n = 2;
3427 while (n < 128 && (c = str->getChar()) == c1)
3428 ++n;
3429 buf[0] = (char)(257 - n);
3430 buf[1] = c1;
3431 bufEnd = &buf[2];
3432 if (c == EOF) {
3433 eof = gTrue;
3434 } else if (n < 128) {
3435 buf[2] = c;
3436 nextEnd = &buf[3];
3437 } else {
3438 nextEnd = bufEnd;
3439 }
3440
3441 // get up to 128 chars
3442 } else {
3443 buf[1] = c1;
3444 buf[2] = c2;
3445 n = 2;
3446 while (n < 128) {
3447 if ((c = str->getChar()) == EOF) {
3448 eof = gTrue;
3449 break;
3450 }
3451 ++n;
3452 buf[n] = c;
3453 if (buf[n] == buf[n-1])
3454 break;
3455 }
3456 if (buf[n] == buf[n-1]) {
3457 buf[0] = (char)(n-2-1);
3458 bufEnd = &buf[n-1];
3459 nextEnd = &buf[n+1];
3460 } else {
3461 buf[0] = (char)(n-1);
3462 bufEnd = nextEnd = &buf[n+1];
3463 }
3464 }
3465 bufPtr = buf;
3466 return gTrue;
3467}
diff --git a/noncore/unsupported/qpdf/xpdf/Stream.h b/noncore/unsupported/qpdf/xpdf/Stream.h
new file mode 100644
index 0000000..1f9c561
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Stream.h
@@ -0,0 +1,723 @@
1//========================================================================
2//
3// Stream.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef STREAM_H
10#define STREAM_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include <stdio.h>
17#include "gtypes.h"
18#include "Object.h"
19
20#ifndef NO_DECRYPTION
21class Decrypt;
22#endif
23class BaseStream;
24
25//------------------------------------------------------------------------
26
27enum StreamKind {
28 strFile,
29 strASCIIHex,
30 strASCII85,
31 strLZW,
32 strRunLength,
33 strCCITTFax,
34 strDCT,
35 strFlate,
36 strWeird // internal-use stream types
37};
38
39//------------------------------------------------------------------------
40// Stream (base class)
41//------------------------------------------------------------------------
42
43class Stream {
44public:
45
46 // Constructor.
47 Stream();
48
49 // Destructor.
50 virtual ~Stream();
51
52 // Reference counting.
53 int incRef() { return ++ref; }
54 int decRef() { return --ref; }
55
56 // Get kind of stream.
57 virtual StreamKind getKind() = 0;
58
59 // Reset stream to beginning.
60 virtual void reset() = 0;
61
62 // Close down the stream.
63 virtual void close();
64
65 // Get next char from stream.
66 virtual int getChar() = 0;
67
68 // Peek at next char in stream.
69 virtual int lookChar() = 0;
70
71 // Get next char from stream without using the predictor.
72 // This is only used by StreamPredictor.
73 virtual int getRawChar();
74
75 // Get next line from stream.
76 virtual char *getLine(char *buf, int size);
77
78 // Get current position in file.
79 virtual int getPos() = 0;
80
81 // Go to a position in the stream.
82 virtual void setPos(int pos) = 0;
83
84 // Get PostScript command for the filter(s).
85 virtual GString *getPSFilter(char *indent);
86
87 // Does this stream type potentially contain non-printable chars?
88 virtual GBool isBinary(GBool last = gTrue) = 0;
89
90 // Get the BaseStream or EmbedStream of this stream.
91 virtual BaseStream *getBaseStream() = 0;
92
93 // Get the dictionary associated with this stream.
94 virtual Dict *getDict() = 0;
95
96 // Is this an encoding filter?
97 virtual GBool isEncoder() { return gFalse; }
98
99 // Add filters to this stream according to the parameters in <dict>.
100 // Returns the new stream.
101 Stream *addFilters(Object *dict);
102
103private:
104
105 Stream *makeFilter(char *name, Stream *str, Object *params);
106
107 int ref; // reference count
108};
109
110//------------------------------------------------------------------------
111// BaseStream
112//
113// This is the base class for all streams that read directly from a file.
114//------------------------------------------------------------------------
115
116class BaseStream: public Stream {
117public:
118
119 BaseStream(Object *dictA);
120 virtual ~BaseStream();
121 virtual Stream *makeSubStream(int start, int length, Object *dict) = 0;
122 virtual void setPos(int pos) = 0;
123 virtual BaseStream *getBaseStream() { return this; }
124 virtual Dict *getDict() { return dict.getDict(); }
125
126 // Get/set position of first byte of stream within the file.
127 virtual int getStart() = 0;
128 virtual void moveStart(int delta) = 0;
129
130#ifndef NO_DECRYPTION
131 // Set decryption for this stream.
132 void doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen);
133#endif
134
135#ifndef NO_DECRYPTION
136protected:
137
138 Decrypt *decrypt;
139#endif
140
141private:
142
143 Object dict;
144};
145
146//------------------------------------------------------------------------
147// FilterStream
148//
149// This is the base class for all streams that filter another stream.
150//------------------------------------------------------------------------
151
152class FilterStream: public Stream {
153public:
154
155 FilterStream(Stream *strA);
156 virtual ~FilterStream();
157 virtual void close();
158 virtual int getPos() { return str->getPos(); }
159 virtual void setPos(int pos);
160 virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
161 virtual Dict *getDict() { return str->getDict(); }
162
163protected:
164
165 Stream *str;
166};
167
168//------------------------------------------------------------------------
169// ImageStream
170//------------------------------------------------------------------------
171
172class ImageStream {
173public:
174
175 // Create an image stream object for an image with the specified
176 // parameters. Note that these are the actual image parameters,
177 // which may be different from the predictor parameters.
178 ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
179
180 ~ImageStream();
181
182 // Reset the stream.
183 void reset();
184
185 // Gets the next pixel from the stream. <pix> should be able to hold
186 // at least nComps elements. Returns false at end of file.
187 GBool getPixel(Guchar *pix);
188
189 // Skip an entire line from the image.
190 void skipLine();
191
192private:
193
194 Stream *str; // base stream
195 int width; // pixels per line
196 int nComps; // components per pixel
197 int nBits; // bits per component
198 int nVals; // components per line
199 Guchar *imgLine; // line buffer
200 int imgIdx; // current index in imgLine
201};
202
203//------------------------------------------------------------------------
204// StreamPredictor
205//------------------------------------------------------------------------
206
207class StreamPredictor {
208public:
209
210 // Create a predictor object. Note that the parameters are for the
211 // predictor, and may not match the actual image parameters.
212 StreamPredictor(Stream *strA, int predictorA,
213 int widthA, int nCompsA, int nBitsA);
214
215 ~StreamPredictor();
216
217 int lookChar();
218 int getChar();
219
220private:
221
222 GBool getNextLine();
223
224 Stream *str; // base stream
225 int predictor; // predictor
226 int width; // pixels per line
227 int nComps; // components per pixel
228 int nBits; // bits per component
229 int nVals; // components per line
230 int pixBytes; // bytes per pixel
231 int rowBytes; // bytes per line
232 Guchar *predLine; // line buffer
233 int predIdx; // current index in predLine
234};
235
236//------------------------------------------------------------------------
237// FileStream
238//------------------------------------------------------------------------
239
240#define fileStreamBufSize 256
241
242class FileStream: public BaseStream {
243public:
244
245 FileStream(FILE *fA, int startA, int lengthA, Object *dictA);
246 virtual ~FileStream();
247 virtual Stream *makeSubStream(int startA, int lengthA, Object *dictA);
248 virtual StreamKind getKind() { return strFile; }
249 virtual void reset();
250 virtual void close();
251 virtual int getChar()
252 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
253 virtual int lookChar()
254 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
255 virtual int getPos() { return bufPos + (bufPtr - buf); }
256 virtual void setPos(int pos);
257 virtual GBool isBinary(GBool last = gTrue) { return last; }
258 virtual int getStart() { return start; }
259 virtual void moveStart(int delta);
260
261private:
262
263 GBool fillBuf();
264
265 FILE *f;
266 int start;
267 int length;
268 char buf[fileStreamBufSize];
269 char *bufPtr;
270 char *bufEnd;
271 int bufPos;
272 int savePos;
273};
274
275//------------------------------------------------------------------------
276// EmbedStream
277//
278// This is a special stream type used for embedded streams (inline
279// images). It reads directly from the base stream -- after the
280// EmbedStream is deleted, reads from the base stream will proceed where
281// the BaseStream left off. Note that this is very different behavior
282// that creating a new FileStream (using makeSubStream).
283//------------------------------------------------------------------------
284
285class EmbedStream: public BaseStream {
286public:
287
288 EmbedStream(Stream *strA, Object *dictA);
289 virtual ~EmbedStream();
290 virtual Stream *makeSubStream(int start, int length, Object *dictA);
291 virtual StreamKind getKind() { return str->getKind(); }
292 virtual void reset() {}
293 virtual int getChar() { return str->getChar(); }
294 virtual int lookChar() { return str->lookChar(); }
295 virtual int getPos() { return str->getPos(); }
296 virtual void setPos(int pos);
297 virtual GBool isBinary(GBool last = gTrue) { return last; }
298 virtual int getStart();
299 virtual void moveStart(int delta);
300
301private:
302
303 Stream *str;
304};
305
306//------------------------------------------------------------------------
307// ASCIIHexStream
308//------------------------------------------------------------------------
309
310class ASCIIHexStream: public FilterStream {
311public:
312
313 ASCIIHexStream(Stream *strA);
314 virtual ~ASCIIHexStream();
315 virtual StreamKind getKind() { return strASCIIHex; }
316 virtual void reset();
317 virtual int getChar()
318 { int c = lookChar(); buf = EOF; return c; }
319 virtual int lookChar();
320 virtual GString *getPSFilter(char *indent);
321 virtual GBool isBinary(GBool last = gTrue);
322
323private:
324
325 int buf;
326 GBool eof;
327};
328
329//------------------------------------------------------------------------
330// ASCII85Stream
331//------------------------------------------------------------------------
332
333class ASCII85Stream: public FilterStream {
334public:
335
336 ASCII85Stream(Stream *strA);
337 virtual ~ASCII85Stream();
338 virtual StreamKind getKind() { return strASCII85; }
339 virtual void reset();
340 virtual int getChar()
341 { int ch = lookChar(); ++index; return ch; }
342 virtual int lookChar();
343 virtual GString *getPSFilter(char *indent);
344 virtual GBool isBinary(GBool last = gTrue);
345
346private:
347
348 int c[5];
349 int b[4];
350 int index, n;
351 GBool eof;
352};
353
354//------------------------------------------------------------------------
355// LZWStream
356//------------------------------------------------------------------------
357
358class LZWStream: public FilterStream {
359public:
360
361 LZWStream(Stream *strA, int predictor, int columns, int colors,
362 int bits, int earlyA);
363 virtual ~LZWStream();
364 virtual StreamKind getKind() { return strLZW; }
365 virtual void reset();
366 virtual int getChar();
367 virtual int lookChar();
368 virtual int getRawChar();
369 virtual GString *getPSFilter(char *indent);
370 virtual GBool isBinary(GBool last = gTrue);
371
372private:
373
374 StreamPredictor *pred;// predictor
375 int early; // early parameter
376 FILE *zPipe; // uncompress pipe
377 GString *zName; // .Z file name
378 int inputBuf; // input buffer
379 int inputBits; // number of bits in input buffer
380 int inCodeBits; // size of input code
381 char buf[256]; // buffer
382 char *bufPtr; // next char to read
383 char *bufEnd; // end of buffer
384
385 void dumpFile(FILE *f);
386 int getCode();
387 GBool fillBuf();
388};
389
390//------------------------------------------------------------------------
391// RunLengthStream
392//------------------------------------------------------------------------
393
394class RunLengthStream: public FilterStream {
395public:
396
397 RunLengthStream(Stream *strA);
398 virtual ~RunLengthStream();
399 virtual StreamKind getKind() { return strRunLength; }
400 virtual void reset();
401 virtual int getChar()
402 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
403 virtual int lookChar()
404 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
405 virtual GString *getPSFilter(char *indent);
406 virtual GBool isBinary(GBool last = gTrue);
407
408private:
409
410 char buf[128]; // buffer
411 char *bufPtr; // next char to read
412 char *bufEnd; // end of buffer
413 GBool eof;
414
415 GBool fillBuf();
416};
417
418//------------------------------------------------------------------------
419// CCITTFaxStream
420//------------------------------------------------------------------------
421
422struct CCITTCodeTable;
423
424class CCITTFaxStream: public FilterStream {
425public:
426
427 CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
428 GBool byteAlignA, int columnsA, int rowsA,
429 GBool endOfBlockA, GBool blackA);
430 virtual ~CCITTFaxStream();
431 virtual StreamKind getKind() { return strCCITTFax; }
432 virtual void reset();
433 virtual int getChar()
434 { int c = lookChar(); buf = EOF; return c; }
435 virtual int lookChar();
436 virtual GString *getPSFilter(char *indent);
437 virtual GBool isBinary(GBool last = gTrue);
438
439private:
440
441 int encoding; // 'K' parameter
442 GBool endOfLine; // 'EndOfLine' parameter
443 GBool byteAlign; // 'EncodedByteAlign' parameter
444 int columns; // 'Columns' parameter
445 int rows; // 'Rows' parameter
446 GBool endOfBlock; // 'EndOfBlock' parameter
447 GBool black; // 'BlackIs1' parameter
448 GBool eof; // true if at eof
449 GBool nextLine2D; // true if next line uses 2D encoding
450 int row; // current row
451 int inputBuf; // input buffer
452 int inputBits; // number of bits in input buffer
453 short *refLine; // reference line changing elements
454 int b1; // index into refLine
455 short *codingLine; // coding line changing elements
456 int a0; // index into codingLine
457 int outputBits; // remaining ouput bits
458 int buf; // character buffer
459
460 short getTwoDimCode();
461 short getWhiteCode();
462 short getBlackCode();
463 short lookBits(int n);
464 void eatBits(int n) { inputBits -= n; }
465};
466
467//------------------------------------------------------------------------
468// DCTStream
469//------------------------------------------------------------------------
470
471// DCT component info
472struct DCTCompInfo {
473 int id; // component ID
474 GBool inScan; // is this component in the current scan?
475 int hSample, vSample; // horiz/vert sampling resolutions
476 int quantTable; // quantization table number
477 int dcHuffTable, acHuffTable;// Huffman table numbers
478 int prevDC; // DC coefficient accumulator
479};
480
481// DCT Huffman decoding table
482struct DCTHuffTable {
483 Guchar firstSym[17]; // first symbol for this bit length
484 Gushort firstCode[17];// first code for this bit length
485 Gushort numCodes[17]; // number of codes of this bit length
486 Guchar sym[256]; // symbols
487};
488
489class DCTStream: public FilterStream {
490public:
491
492 DCTStream(Stream *strA);
493 virtual ~DCTStream();
494 virtual StreamKind getKind() { return strDCT; }
495 virtual void reset();
496 virtual int getChar();
497 virtual int lookChar();
498 virtual GString *getPSFilter(char *indent);
499 virtual GBool isBinary(GBool last = gTrue);
500 Stream *getRawStream() { return str; }
501
502private:
503
504 int width, height; // image size
505 int mcuWidth, mcuHeight;// size of min coding unit, in data units
506 DCTCompInfo compInfo[4];// info for each component
507 int numComps; // number of components in image
508 int colorXform; // need YCbCr-to-RGB transform?
509 GBool gotAdobeMarker; // set if APP14 Adobe marker was present
510 int restartInterval; // restart interval, in MCUs
511 Guchar quantTables[4][64];// quantization tables
512 int numQuantTables; // number of quantization tables
513 DCTHuffTable dcHuffTables[4];// DC Huffman tables
514 DCTHuffTable acHuffTables[4];// AC Huffman tables
515 int numDCHuffTables; // number of DC Huffman tables
516 int numACHuffTables; // number of AC Huffman tables
517 Guchar *rowBuf[4][32];// buffer for one MCU
518 int comp, x, y, dy; // current position within image/MCU
519 int restartCtr; // MCUs left until restart
520 int restartMarker; // next restart marker
521 int inputBuf; // input buffer for variable length codes
522 int inputBits; // number of valid bits in input buffer
523
524 void restart();
525 GBool readMCURow();
526 GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable,
527 Guchar quantTable[64], int *prevDC, Guchar data[64]);
528 int readHuffSym(DCTHuffTable *table);
529 int readAmp(int size);
530 int readBit();
531 GBool readHeader();
532 GBool readFrameInfo();
533 GBool readScanInfo();
534 GBool readQuantTables();
535 GBool readHuffmanTables();
536 GBool readRestartInterval();
537 GBool readAdobeMarker();
538 GBool readTrailer();
539 int readMarker();
540 int read16();
541};
542
543//------------------------------------------------------------------------
544// FlateStream
545//------------------------------------------------------------------------
546
547#define flateWindow 32768 // buffer size
548#define flateMask (flateWindow-1)
549#define flateMaxHuffman 15 // max Huffman code length
550#define flateMaxCodeLenCodes 19 // max # code length codes
551#define flateMaxLitCodes 288 // max # literal codes
552#define flateMaxDistCodes 30 // max # distance codes
553
554// Huffman code table entry
555struct FlateCode {
556 int len; // code length in bits
557 int code; // code word
558 int val; // value represented by this code
559};
560
561// Huffman code table
562struct FlateHuffmanTab {
563 int start[flateMaxHuffman+2];// indexes of first code of each length
564 FlateCode *codes; // codes, sorted by length and code word
565};
566
567// Decoding info for length and distance code words
568struct FlateDecode {
569 int bits; // # extra bits
570 int first; // first length/distance
571};
572
573class FlateStream: public FilterStream {
574public:
575
576 FlateStream(Stream *strA, int predictor, int columns,
577 int colors, int bits);
578 virtual ~FlateStream();
579 virtual StreamKind getKind() { return strFlate; }
580 virtual void reset();
581 virtual int getChar();
582 virtual int lookChar();
583 virtual int getRawChar();
584 virtual GString *getPSFilter(char *indent);
585 virtual GBool isBinary(GBool last = gTrue);
586
587private:
588
589 StreamPredictor *pred;// predictor
590 Guchar buf[flateWindow];// output data buffer
591 int index; // current index into output buffer
592 int remain; // number valid bytes in output buffer
593 int codeBuf; // input buffer
594 int codeSize; // number of bits in input buffer
595 FlateCode // literal and distance codes
596 allCodes[flateMaxLitCodes + flateMaxDistCodes];
597 FlateHuffmanTab litCodeTab;// literal code table
598 FlateHuffmanTab distCodeTab;// distance code table
599 GBool compressedBlock;// set if reading a compressed block
600 int blockLen; // remaining length of uncompressed block
601 GBool endOfBlock; // set when end of block is reached
602 GBool eof; // set when end of stream is reached
603
604 static int // code length code reordering
605 codeLenCodeMap[flateMaxCodeLenCodes];
606 static FlateDecode // length decoding info
607 lengthDecode[flateMaxLitCodes-257];
608 static FlateDecode // distance decoding info
609 distDecode[flateMaxDistCodes];
610
611 void readSome();
612 GBool startBlock();
613 void loadFixedCodes();
614 GBool readDynamicCodes();
615 void compHuffmanCodes(FlateHuffmanTab *tab, int n);
616 int getHuffmanCodeWord(FlateHuffmanTab *tab);
617 int getCodeWord(int bits);
618};
619
620//------------------------------------------------------------------------
621// EOFStream
622//------------------------------------------------------------------------
623
624class EOFStream: public FilterStream {
625public:
626
627 EOFStream(Stream *strA);
628 virtual ~EOFStream();
629 virtual StreamKind getKind() { return strWeird; }
630 virtual void reset() {}
631 virtual int getChar() { return EOF; }
632 virtual int lookChar() { return EOF; }
633 virtual GString *getPSFilter(char *indent) { return NULL; }
634 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
635};
636
637//------------------------------------------------------------------------
638// FixedLengthEncoder
639//------------------------------------------------------------------------
640
641class FixedLengthEncoder: public FilterStream {
642public:
643
644 FixedLengthEncoder(Stream *strA, int lengthA);
645 ~FixedLengthEncoder();
646 virtual StreamKind getKind() { return strWeird; }
647 virtual void reset();
648 virtual void close();
649 virtual int getChar();
650 virtual int lookChar();
651 virtual GString *getPSFilter(char *indent) { return NULL; }
652 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
653 virtual GBool isEncoder() { return gTrue; }
654
655private:
656
657 int length;
658 int count;
659};
660
661//------------------------------------------------------------------------
662// ASCII85Encoder
663//------------------------------------------------------------------------
664
665class ASCII85Encoder: public FilterStream {
666public:
667
668 ASCII85Encoder(Stream *strA);
669 virtual ~ASCII85Encoder();
670 virtual StreamKind getKind() { return strWeird; }
671 virtual void reset();
672 virtual void close();
673 virtual int getChar()
674 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
675 virtual int lookChar()
676 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
677 virtual GString *getPSFilter(char *indent) { return NULL; }
678 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
679 virtual GBool isEncoder() { return gTrue; }
680
681private:
682
683 char buf[8];
684 char *bufPtr;
685 char *bufEnd;
686 int lineLen;
687 GBool eof;
688
689 GBool fillBuf();
690};
691
692//------------------------------------------------------------------------
693// RunLengthEncoder
694//------------------------------------------------------------------------
695
696class RunLengthEncoder: public FilterStream {
697public:
698
699 RunLengthEncoder(Stream *strA);
700 virtual ~RunLengthEncoder();
701 virtual StreamKind getKind() { return strWeird; }
702 virtual void reset();
703 virtual void close();
704 virtual int getChar()
705 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
706 virtual int lookChar()
707 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
708 virtual GString *getPSFilter(char *indent) { return NULL; }
709 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
710 virtual GBool isEncoder() { return gTrue; }
711
712private:
713
714 char buf[131];
715 char *bufPtr;
716 char *bufEnd;
717 char *nextEnd;
718 GBool eof;
719
720 GBool fillBuf();
721};
722
723#endif
diff --git a/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc b/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc
new file mode 100644
index 0000000..aa9366a
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc
@@ -0,0 +1,686 @@
1//========================================================================
2//
3// TextOutputDev.cc
4//
5// Copyright 1997 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <stddef.h>
17#include <math.h>
18#include <ctype.h>
19#include "GString.h"
20#include "gmem.h"
21#include "config.h"
22#include "Error.h"
23#include "GlobalParams.h"
24#include "UnicodeMap.h"
25#include "GfxState.h"
26#include "TextOutputDev.h"
27
28#ifdef MACOS
29// needed for setting type/creator of MacOS files
30#include "ICSupport.h"
31#endif
32
33//------------------------------------------------------------------------
34// TextString
35//------------------------------------------------------------------------
36
37TextString::TextString(GfxState *state, fouble fontSize) {
38 GfxFont *font;
39 fouble x, y;
40
41 state->transform(state->getCurX(), state->getCurY(), &x, &y);
42 if ((font = state->getFont())) {
43 yMin = y - font->getAscent() * fontSize;
44 yMax = y - font->getDescent() * fontSize;
45 } else {
46 // this means that the PDF file draws text without a current font,
47 // which should never happen
48 yMin = y - 0.95 * fontSize;
49 yMax = y + 0.35 * fontSize;
50 }
51 col = 0;
52 text = NULL;
53 xRight = NULL;
54 len = size = 0;
55 yxNext = NULL;
56 xyNext = NULL;
57}
58
59TextString::~TextString() {
60 gfree(text);
61 gfree(xRight);
62}
63
64void TextString::addChar(GfxState *state, fouble x, fouble y,
65 fouble dx, fouble dy, Unicode u) {
66 if (len == size) {
67 size += 16;
68 text = (Unicode *)grealloc(text, size * sizeof(Unicode));
69 xRight = (fouble *)grealloc(xRight, size * sizeof(fouble));
70 }
71 text[len] = u;
72 if (len == 0) {
73 xMin = x;
74 }
75 xMax = xRight[len] = x + dx;
76 ++len;
77}
78
79//------------------------------------------------------------------------
80// TextPage
81//------------------------------------------------------------------------
82
83TextPage::TextPage(GBool rawOrderA) {
84 rawOrder = rawOrderA;
85 curStr = NULL;
86 fontSize = 0;
87 yxStrings = NULL;
88 xyStrings = NULL;
89 yxCur1 = yxCur2 = NULL;
90 nest = 0;
91}
92
93TextPage::~TextPage() {
94 clear();
95}
96
97void TextPage::updateFont(GfxState *state) {
98 GfxFont *font;
99 fouble *fm;
100 char *name;
101 int code;
102
103 // adjust the font size
104 fontSize = state->getTransformedFontSize();
105 if ((font = state->getFont()) && font->getType() == fontType3) {
106 // This is a hack which makes it possible to deal with some Type 3
107 // fonts. The problem is that it's impossible to know what the
108 // base coordinate system used in the font is without actually
109 // rendering the font. This code tries to guess by looking at the
110 // width of the character 'm' (which breaks if the font is a
111 // subset that doesn't contain 'm').
112 for (code = 0; code < 256; ++code) {
113 if ((name = ((Gfx8BitFont *)font)->getCharName(code)) &&
114 name[0] == 'm' && name[1] == '\0') {
115 break;
116 }
117 }
118 if (code < 256) {
119 // 600 is a generic average 'm' width -- yes, this is a hack
120 fontSize *= ((Gfx8BitFont *)font)->getWidth(code) / 0.6;
121 }
122 fm = font->getFontMatrix();
123 if (fm[0] != 0) {
124 fontSize *= fabs(fm[3] / fm[0]);
125 }
126 }
127}
128
129void TextPage::beginString(GfxState *state) {
130 // This check is needed because Type 3 characters can contain
131 // text-drawing operations.
132 if (curStr) {
133 ++nest;
134 return;
135 }
136
137 curStr = new TextString(state, fontSize);
138}
139
140void TextPage::addChar(GfxState *state, fouble x, fouble y,
141 fouble dx, fouble dy, Unicode *u, int uLen) {
142 fouble x1, y1, w1, h1, dx2, dy2;
143 int n, i;
144
145 state->transform(x, y, &x1, &y1);
146 n = curStr->len;
147 if (n > 0 &&
148 x1 - curStr->xRight[n-1] > 0.1 * (curStr->yMax - curStr->yMin)) {
149 endString();
150 beginString(state);
151 }
152 state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(),
153 0, &dx2, &dy2);
154 dx -= dx2;
155 dy -= dy2;
156 state->transformDelta(dx, dy, &w1, &h1);
157 w1 /= uLen;
158 h1 /= uLen;
159 for (i = 0; i < uLen; ++i) {
160 curStr->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]);
161 }
162}
163
164void TextPage::endString() {
165 TextString *p1, *p2;
166 fouble h, y1, y2;
167
168 // This check is needed because Type 3 characters can contain
169 // text-drawing operations.
170 if (nest > 0) {
171 --nest;
172 return;
173 }
174
175 // throw away zero-length strings -- they don't have valid xMin/xMax
176 // values, and they're useless anyway
177 if (curStr->len == 0) {
178 delete curStr;
179 curStr = NULL;
180 return;
181 }
182
183 // insert string in y-major list
184 h = curStr->yMax - curStr->yMin;
185 y1 = curStr->yMin + 0.5 * h;
186 y2 = curStr->yMin + 0.8 * h;
187 if (rawOrder) {
188 p1 = yxCur1;
189 p2 = NULL;
190 } else if ((!yxCur1 ||
191 (y1 >= yxCur1->yMin &&
192 (y2 >= yxCur1->yMax || curStr->xMax >= yxCur1->xMin))) &&
193 (!yxCur2 ||
194 (y1 < yxCur2->yMin ||
195 (y2 < yxCur2->yMax && curStr->xMax < yxCur2->xMin)))) {
196 p1 = yxCur1;
197 p2 = yxCur2;
198 } else {
199 for (p1 = NULL, p2 = yxStrings; p2; p1 = p2, p2 = p2->yxNext) {
200 if (y1 < p2->yMin || (y2 < p2->yMax && curStr->xMax < p2->xMin)) {
201 break;
202 }
203 }
204 yxCur2 = p2;
205 }
206 yxCur1 = curStr;
207 if (p1) {
208 p1->yxNext = curStr;
209 } else {
210 yxStrings = curStr;
211 }
212 curStr->yxNext = p2;
213 curStr = NULL;
214}
215
216void TextPage::coalesce() {
217 TextString *str1, *str2;
218 fouble space, d;
219 GBool addSpace;
220 int n, i;
221
222#if 0 //~ for debugging
223 for (str1 = yxStrings; str1; str1 = str1->yxNext) {
224 printf("x=%3d..%3d y=%3d..%3d size=%2d '",
225 (int)str1->xMin, (int)str1->xMax, (int)str1->yMin, (int)str1->yMax,
226 (int)(str1->yMax - str1->yMin));
227 for (i = 0; i < str1->len; ++i) {
228 fputc(str1->text[i] & 0xff, stdout);
229 }
230 printf("'\n");
231 }
232 printf("\n------------------------------------------------------------\n\n");
233#endif
234 str1 = yxStrings;
235 while (str1 && (str2 = str1->yxNext)) {
236 space = str1->yMax - str1->yMin;
237 d = str2->xMin - str1->xMax;
238 if (((rawOrder &&
239 ((str2->yMin >= str1->yMin && str2->yMin <= str1->yMax) ||
240 (str2->yMax >= str1->yMin && str2->yMax <= str1->yMax))) ||
241 (!rawOrder && str2->yMin < str1->yMax)) &&
242 d > -0.5 * space && d < space) {
243 n = str1->len + str2->len;
244 if ((addSpace = d > 0.1 * space)) {
245 ++n;
246 }
247 str1->size = (n + 15) & ~15;
248 str1->text = (Unicode *)grealloc(str1->text,
249 str1->size * sizeof(Unicode));
250 str1->xRight = (fouble *)grealloc(str1->xRight,
251 str1->size * sizeof(fouble));
252 if (addSpace) {
253 str1->text[str1->len] = 0x20;
254 str1->xRight[str1->len] = str2->xMin;
255 ++str1->len;
256 }
257 for (i = 0; i < str2->len; ++i) {
258 str1->text[str1->len] = str2->text[i];
259 str1->xRight[str1->len] = str2->xRight[i];
260 ++str1->len;
261 }
262 if (str2->xMax > str1->xMax) {
263 str1->xMax = str2->xMax;
264 }
265 if (str2->yMax > str1->yMax) {
266 str1->yMax = str2->yMax;
267 }
268 str1->yxNext = str2->yxNext;
269 delete str2;
270 } else {
271 str1 = str2;
272 }
273 }
274}
275
276GBool TextPage::findText(Unicode *s, int len,
277 GBool top, GBool bottom,
278 fouble *xMin, fouble *yMin,
279 fouble *xMax, fouble *yMax) {
280 TextString *str;
281 Unicode *p;
282 Unicode u1, u2;
283 int m, i, j;
284 fouble x;
285
286 // scan all strings on page
287 for (str = yxStrings; str; str = str->yxNext) {
288
289 // check: above top limit?
290 if (!top && (str->yMax < *yMin ||
291 (str->yMin < *yMin && str->xMax <= *xMin))) {
292 continue;
293 }
294
295 // check: below bottom limit?
296 if (!bottom && (str->yMin > *yMax ||
297 (str->yMax > *yMax && str->xMin >= *xMax))) {
298 return gFalse;
299 }
300
301 // search each position in this string
302 m = str->len;
303 for (i = 0, p = str->text; i <= m - len; ++i, ++p) {
304
305 // check: above top limit?
306 if (!top && str->yMin < *yMin) {
307 x = (((i == 0) ? str->xMin : str->xRight[i-1]) + str->xRight[i]) / 2;
308 if (x < *xMin) {
309 continue;
310 }
311 }
312
313 // check: below bottom limit?
314 if (!bottom && str->yMax > *yMax) {
315 x = (((i == 0) ? str->xMin : str->xRight[i-1]) + str->xRight[i]) / 2;
316 if (x > *xMax) {
317 return gFalse;
318 }
319 }
320
321 // compare the strings
322 for (j = 0; j < len; ++j) {
323#if 1 //~ this lowercases Latin A-Z only -- this will eventually be
324 //~ extended to handle other character sets
325 if (p[j] >= 0x41 && p[j] <= 0x5a) {
326 u1 = p[j] + 0x20;
327 } else {
328 u1 = p[j];
329 }
330 if (s[j] >= 0x41 && s[j] <= 0x5a) {
331 u2 = s[j] + 0x20;
332 } else {
333 u2 = s[j];
334 }
335#endif
336 if (u1 != u2) {
337 break;
338 }
339 }
340
341 // found it
342 if (j == len) {
343 *xMin = (i == 0) ? str->xMin : str->xRight[i-1];
344 *xMax = str->xRight[i + len - 1];
345 *yMin = str->yMin;
346 *yMax = str->yMax;
347 return gTrue;
348 }
349 }
350 }
351 return gFalse;
352}
353
354GString *TextPage::getText(fouble xMin, fouble yMin,
355 fouble xMax, fouble yMax) {
356 GString *s;
357 UnicodeMap *uMap;
358 char space[8], eol[16], buf[8];
359 int spaceLen, eolLen, n;
360 TextString *str1;
361 fouble x0, x1, x2, y;
362 fouble xPrev, yPrev;
363 int i1, i2, i;
364 GBool multiLine;
365
366 s = new GString();
367 if (!(uMap = globalParams->getTextEncoding())) {
368 return s;
369 }
370 spaceLen = uMap->mapUnicode(0x20, space, sizeof(space));
371 eolLen = 0; // make gcc happy
372 switch (globalParams->getTextEOL()) {
373 case eolUnix:
374 eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol));
375 break;
376 case eolDOS:
377 eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
378 eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen);
379 break;
380 case eolMac:
381 eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
382 break;
383 }
384 xPrev = yPrev = 0;
385 multiLine = gFalse;
386 for (str1 = yxStrings; str1; str1 = str1->yxNext) {
387 y = 0.5 * (str1->yMin + str1->yMax);
388 if (y > yMax) {
389 break;
390 }
391 if (y > yMin && str1->xMin < xMax && str1->xMax > xMin) {
392 x0 = x1 = x2 = str1->xMin;
393 for (i1 = 0; i1 < str1->len; ++i1) {
394 x0 = (i1==0) ? str1->xMin : str1->xRight[i1-1];
395 x1 = str1->xRight[i1];
396 if (0.5 * (x0 + x1) >= xMin) {
397 break;
398 }
399 }
400 for (i2 = str1->len - 1; i2 > i1; --i2) {
401 x1 = (i2==0) ? str1->xMin : str1->xRight[i2-1];
402 x2 = str1->xRight[i2];
403 if (0.5 * (x1 + x2) <= xMax) {
404 break;
405 }
406 }
407 if (s->getLength() > 0) {
408 if (x0 < xPrev || str1->yMin > yPrev) {
409 s->append(eol, eolLen);
410 multiLine = gTrue;
411 } else {
412 for (i = 0; i < 4; ++i) {
413 s->append(space, spaceLen);
414 }
415 }
416 }
417 for (i = i1; i <= i2; ++i) {
418 n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf));
419 s->append(buf, n);
420 }
421 xPrev = x2;
422 yPrev = str1->yMax;
423 }
424 }
425 if (multiLine) {
426 s->append(eol, eolLen);
427 }
428 uMap->decRefCnt();
429 return s;
430}
431
432void TextPage::dump(FILE *f) {
433 UnicodeMap *uMap;
434 char space[8], eol[16], eop[8], buf[8];
435 int spaceLen, eolLen, eopLen, n;
436 TextString *str1, *str2, *str3;
437 fouble yMin, yMax;
438 int col1, col2, d, i;
439
440 // get the output encoding
441 if (!(uMap = globalParams->getTextEncoding())) {
442 return;
443 }
444 spaceLen = uMap->mapUnicode(0x20, space, sizeof(space));
445 eolLen = 0; // make gcc happy
446 switch (globalParams->getTextEOL()) {
447 case eolUnix:
448 eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol));
449 break;
450 case eolDOS:
451 eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
452 eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen);
453 break;
454 case eolMac:
455 eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
456 break;
457 }
458 eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop));
459
460 // build x-major list
461 xyStrings = NULL;
462 for (str1 = yxStrings; str1; str1 = str1->yxNext) {
463 for (str2 = NULL, str3 = xyStrings;
464 str3;
465 str2 = str3, str3 = str3->xyNext) {
466 if (str1->xMin < str3->xMin ||
467 (str1->xMin == str3->xMin && str1->yMin < str3->yMin)) {
468 break;
469 }
470 }
471 if (str2) {
472 str2->xyNext = str1;
473 } else {
474 xyStrings = str1;
475 }
476 str1->xyNext = str3;
477 }
478
479 // do column assignment
480 for (str1 = xyStrings; str1; str1 = str1->xyNext) {
481 col1 = 0;
482 for (str2 = xyStrings; str2 != str1; str2 = str2->xyNext) {
483 if (str1->xMin >= str2->xMax) {
484 col2 = str2->col + str2->len + 4;
485 if (col2 > col1) {
486 col1 = col2;
487 }
488 } else if (str1->xMin > str2->xMin) {
489 col2 = str2->col +
490 (int)(((str1->xMin - str2->xMin) / (str2->xMax - str2->xMin)) *
491 str2->len);
492 if (col2 > col1) {
493 col1 = col2;
494 }
495 }
496 }
497 str1->col = col1;
498 }
499
500#if 0 //~ for debugging
501 fprintf(f, "~~~~~~~~~~\n");
502 for (str1 = yxStrings; str1; str1 = str1->yxNext) {
503 fprintf(f, "(%4d,%4d) - (%4d,%4d) [%3d] '",
504 (int)str1->xMin, (int)str1->yMin,
505 (int)str1->xMax, (int)str1->yMax, str1->col);
506 for (i = 0; i < str1->len; ++i) {
507 fputc(str1->text[i] & 0xff, stdout);
508 }
509 printf("'\n");
510 }
511 fprintf(f, "~~~~~~~~~~\n");
512#endif
513
514 // output
515 col1 = 0;
516 yMax = yxStrings ? yxStrings->yMax : fouble(0);
517 for (str1 = yxStrings; str1; str1 = str1->yxNext) {
518
519 // line this string up with the correct column
520 if (rawOrder && col1 == 0) {
521 col1 = str1->col;
522 } else {
523 for (; col1 < str1->col; ++col1) {
524 fwrite(space, 1, spaceLen, f);
525 }
526 }
527
528 // print the string
529 for (i = 0; i < str1->len; ++i) {
530 if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) {
531 fwrite(buf, 1, n, f);
532 }
533 }
534
535 // increment column
536 col1 += str1->len;
537
538 // update yMax for this line
539 if (str1->yMax > yMax) {
540 yMax = str1->yMax;
541 }
542
543 // if we've hit the end of the line...
544 if (!(str1->yxNext &&
545 !(rawOrder && str1->yxNext->yMax < str1->yMin) &&
546 str1->yxNext->yMin < 0.2*str1->yMin + 0.8*str1->yMax &&
547 str1->yxNext->xMin >= str1->xMax)) {
548
549 // print a return
550 fwrite(eol, 1, eolLen, f);
551
552 // print extra vertical space if necessary
553 if (str1->yxNext) {
554
555 // find yMin for next line
556 yMin = str1->yxNext->yMin;
557 for (str2 = str1->yxNext; str2; str2 = str2->yxNext) {
558 if (str2->yMin < yMin) {
559 yMin = str2->yMin;
560 }
561 if (!(str2->yxNext && str2->yxNext->yMin < str2->yMax &&
562 str2->yxNext->xMin >= str2->xMax))
563 break;
564 }
565
566 // print the space
567 d = (int)((yMin - yMax) / (str1->yMax - str1->yMin) + 0.5);
568 // various things (weird font matrices) can result in bogus
569 // values here, so do a sanity check
570 if (rawOrder && d > 2) {
571 d = 2;
572 } else if (!rawOrder && d > 5) {
573 d = 5;
574 }
575 for (; d > 0; --d) {
576 fwrite(eol, 1, eolLen, f);
577 }
578 }
579
580 // set up for next line
581 col1 = 0;
582 yMax = str1->yxNext ? str1->yxNext->yMax : fouble(0);
583 }
584 }
585
586 // end of page
587 fwrite(eol, 1, eolLen, f);
588 fwrite(eop, 1, eopLen, f);
589 fwrite(eol, 1, eolLen, f);
590
591 uMap->decRefCnt();
592}
593
594void TextPage::clear() {
595 TextString *p1, *p2;
596
597 if (curStr) {
598 delete curStr;
599 curStr = NULL;
600 }
601 for (p1 = yxStrings; p1; p1 = p2) {
602 p2 = p1->yxNext;
603 delete p1;
604 }
605 yxStrings = NULL;
606 xyStrings = NULL;
607 yxCur1 = yxCur2 = NULL;
608}
609
610//------------------------------------------------------------------------
611// TextOutputDev
612//------------------------------------------------------------------------
613
614TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) {
615 text = NULL;
616 rawOrder = rawOrderA;
617 ok = gTrue;
618
619 // open file
620 needClose = gFalse;
621 if (fileName) {
622 if (!strcmp(fileName, "-")) {
623 f = stdout;
624 } else if ((f = fopen(fileName, append ? "a" : "w"))) {
625 needClose = gTrue;
626 } else {
627 error(-1, "Couldn't open text file '%s'", fileName);
628 ok = gFalse;
629 return;
630 }
631 } else {
632 f = NULL;
633 }
634
635 // set up text object
636 text = new TextPage(rawOrder);
637}
638
639TextOutputDev::~TextOutputDev() {
640 if (needClose) {
641#ifdef MACOS
642 ICS_MapRefNumAndAssign((short)f->handle);
643#endif
644 fclose(f);
645 }
646 if (text) {
647 delete text;
648 }
649}
650
651void TextOutputDev::startPage(int pageNum, GfxState *state) {
652 text->clear();
653}
654
655void TextOutputDev::endPage() {
656 text->coalesce();
657 if (f) {
658 text->dump(f);
659 }
660}
661
662void TextOutputDev::updateFont(GfxState *state) {
663 text->updateFont(state);
664}
665
666void TextOutputDev::beginString(GfxState *state, GString *s) {
667 text->beginString(state);
668}
669
670void TextOutputDev::endString(GfxState *state) {
671 text->endString();
672}
673
674void TextOutputDev::drawChar(GfxState *state, fouble x, fouble y,
675 fouble dx, fouble dy,
676 fouble originX, fouble originY,
677 CharCode c, Unicode *u, int uLen) {
678 text->addChar(state, x, y, dx, dy, u, uLen);
679}
680
681GBool TextOutputDev::findText(Unicode *s, int len,
682 GBool top, GBool bottom,
683 fouble *xMin, fouble *yMin,
684 fouble *xMax, fouble *yMax) {
685 return text->findText(s, len, top, bottom, xMin, yMin, xMax, yMax);
686}
diff --git a/noncore/unsupported/qpdf/xpdf/TextOutputDev.h b/noncore/unsupported/qpdf/xpdf/TextOutputDev.h
new file mode 100644
index 0000000..4c71e5e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/TextOutputDev.h
@@ -0,0 +1,189 @@
1//========================================================================
2//
3// TextOutputDev.h
4//
5// Copyright 1997 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef TEXTOUTPUTDEV_H
10#define TEXTOUTPUTDEV_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include <stdio.h>
17#include "gtypes.h"
18#include "GfxFont.h"
19#include "OutputDev.h"
20
21class GfxState;
22class GString;
23
24//------------------------------------------------------------------------
25// TextString
26//------------------------------------------------------------------------
27
28class TextString {
29public:
30
31 // Constructor.
32 TextString(GfxState *state, fouble fontSize);
33
34 // Destructor.
35 ~TextString();
36
37 // Add a character to the string.
38 void addChar(GfxState *state, fouble x, fouble y,
39 fouble dx, fouble dy, Unicode u);
40
41private:
42
43 fouble xMin, xMax; // bounding box x coordinates
44 fouble yMin, yMax; // bounding box y coordinates
45 int col; // starting column
46 Unicode *text; // the text
47 fouble *xRight; // right-hand x coord of each char
48 int len; // length of text and xRight
49 int size; // size of text and xRight arrays
50 TextString *yxNext; // next string in y-major order
51 TextString *xyNext; // next string in x-major order
52
53 friend class TextPage;
54};
55
56//------------------------------------------------------------------------
57// TextPage
58//------------------------------------------------------------------------
59
60class TextPage {
61public:
62
63 // Constructor.
64 TextPage(GBool rawOrderA);
65
66 // Destructor.
67 ~TextPage();
68
69 // Update the current font.
70 void updateFont(GfxState *state);
71
72 // Begin a new string.
73 void beginString(GfxState *state);
74
75 // Add a character to the current string.
76 void addChar(GfxState *state, fouble x, fouble y,
77 fouble dx, fouble dy, Unicode *u, int uLen);
78
79 // End the current string, sorting it into the list of strings.
80 void endString();
81
82 // Coalesce strings that look like parts of the same line.
83 void coalesce();
84
85 // Find a string. If <top> is true, starts looking at top of page;
86 // otherwise starts looking at <xMin>,<yMin>. If <bottom> is true,
87 // stops looking at bottom of page; otherwise stops looking at
88 // <xMax>,<yMax>. If found, sets the text bounding rectange and
89 // returns true; otherwise returns false.
90 GBool findText(Unicode *s, int len,
91 GBool top, GBool bottom,
92 fouble *xMin, fouble *yMin,
93 fouble *xMax, fouble *yMax);
94
95 // Get the text which is inside the specified rectangle.
96 GString *getText(fouble xMin, fouble yMin,
97 fouble xMax, fouble yMax);
98
99 // Dump contents of page to a file.
100 void dump(FILE *f);
101
102 // Clear the page.
103 void clear();
104
105private:
106
107 GBool rawOrder; // keep strings in content stream order
108
109 TextString *curStr; // currently active string
110 fouble fontSize; // current font size
111
112 TextString *yxStrings;// strings in y-major order
113 TextString *xyStrings;// strings in x-major order
114 TextString *yxCur1, *yxCur2;// cursors for yxStrings list
115
116 int nest; // current nesting level (for Type 3 fonts)
117};
118
119//------------------------------------------------------------------------
120// TextOutputDev
121//------------------------------------------------------------------------
122
123class TextOutputDev: public OutputDev {
124public:
125
126 // Open a text output file. If <fileName> is NULL, no file is
127 // written (this is useful, e.g., for searching text). If
128 // <rawOrder> is true, the text is kept in content stream order.
129 TextOutputDev(char *fileName, GBool rawOrderA, GBool append);
130
131 // Destructor.
132 virtual ~TextOutputDev();
133
134 // Check if file was successfully created.
135 virtual GBool isOk() { return ok; }
136
137 //---- get info about output device
138
139 // Does this device use upside-down coordinates?
140 // (Upside-down means (0,0) is the top left corner of the page.)
141 virtual GBool upsideDown() { return gTrue; }
142
143 // Does this device use drawChar() or drawString()?
144 virtual GBool useDrawChar() { return gTrue; }
145
146 // Does this device need non-text content?
147 virtual GBool needNonText() { return gFalse; }
148
149 //----- initialization and control
150
151 // Start a page.
152 virtual void startPage(int pageNum, GfxState *state);
153
154 // End a page.
155 virtual void endPage();
156
157 //----- update text state
158 virtual void updateFont(GfxState *state);
159
160 //----- text drawing
161 virtual void beginString(GfxState *state, GString *s);
162 virtual void endString(GfxState *state);
163 virtual void drawChar(GfxState *state, fouble x, fouble y,
164 fouble dx, fouble dy,
165 fouble originX, fouble originY,
166 CharCode c, Unicode *u, int uLen);
167
168 //----- special access
169
170 // Find a string. If <top> is true, starts looking at top of page;
171 // otherwise starts looking at <xMin>,<yMin>. If <bottom> is true,
172 // stops looking at bottom of page; otherwise stops looking at
173 // <xMax>,<yMax>. If found, sets the text bounding rectange and
174 // returns true; otherwise returns false.
175 GBool findText(Unicode *s, int len,
176 GBool top, GBool bottom,
177 fouble *xMin, fouble *yMin,
178 fouble *xMax, fouble *yMax);
179
180private:
181
182 FILE *f; // text file
183 GBool needClose; // need to close the file?
184 TextPage *text; // text for the current page
185 GBool rawOrder; // keep text in content stream order
186 GBool ok; // set up ok?
187};
188
189#endif
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc b/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
new file mode 100644
index 0000000..ab823b1
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
@@ -0,0 +1,260 @@
1//========================================================================
2//
3// UnicodeMap.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <string.h>
16#include "gmem.h"
17#include "gfile.h"
18#include "GString.h"
19#include "GList.h"
20#include "Error.h"
21#include "GlobalParams.h"
22#include "UnicodeMap.h"
23
24//------------------------------------------------------------------------
25
26#define maxExtCode 16
27
28struct UnicodeMapExt {
29 Unicode u; // Unicode char
30 char code[maxExtCode];
31 Guint nBytes;
32};
33
34//------------------------------------------------------------------------
35
36UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
37 FILE *f;
38 UnicodeMap *map;
39 UnicodeMapRange *range;
40 UnicodeMapExt *eMap;
41 int size, eMapsSize;
42 char buf[256];
43 int line, nBytes, i, x;
44 char *tok1, *tok2, *tok3;
45
46 if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
47 error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
48 encodingNameA->getCString());
49 return NULL;
50 }
51
52 map = new UnicodeMap(encodingNameA->copy());
53
54 size = 8;
55 map->ranges = (UnicodeMapRange *)gmalloc(size * sizeof(UnicodeMapRange));
56 eMapsSize = 0;
57
58 line = 1;
59 while (getLine(buf, sizeof(buf), f)) {
60 if ((tok1 = strtok(buf, " \t\r\n")) &&
61 (tok2 = strtok(NULL, " \t\r\n"))) {
62 if (!(tok3 = strtok(NULL, " \t\r\n"))) {
63 tok3 = tok2;
64 tok2 = tok1;
65 }
66 nBytes = strlen(tok3) / 2;
67 if (nBytes <= 4) {
68 if (map->len == size) {
69 size *= 2;
70 map->ranges = (UnicodeMapRange *)
71 grealloc(map->ranges, size * sizeof(UnicodeMapRange));
72 }
73 range = &map->ranges[map->len];
74 sscanf(tok1, "%x", &range->start);
75 sscanf(tok2, "%x", &range->end);
76 sscanf(tok3, "%x", &range->code);
77 range->nBytes = nBytes;
78 ++map->len;
79 } else if (tok2 == tok1) {
80 if (map->eMapsLen == eMapsSize) {
81 eMapsSize += 16;
82 map->eMaps = (UnicodeMapExt *)
83 grealloc(map->eMaps, eMapsSize * sizeof(UnicodeMapExt));
84 }
85 eMap = &map->eMaps[map->eMapsLen];
86 sscanf(tok1, "%x", &eMap->u);
87 for (i = 0; i < nBytes; ++i) {
88 sscanf(tok3 + i*2, "%2x", &x);
89 eMap->code[i] = (char)x;
90 }
91 eMap->nBytes = nBytes;
92 ++map->eMapsLen;
93 } else {
94 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
95 line, encodingNameA->getCString());
96 }
97 } else {
98 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
99 line, encodingNameA->getCString());
100 }
101 ++line;
102 }
103
104 return map;
105}
106
107UnicodeMap::UnicodeMap(GString *encodingNameA) {
108 encodingName = encodingNameA;
109 kind = unicodeMapUser;
110 ranges = NULL;
111 len = 0;
112 eMaps = NULL;
113 eMapsLen = 0;
114 refCnt = 1;
115}
116
117UnicodeMap::UnicodeMap(char *encodingNameA,
118 UnicodeMapRange *rangesA, int lenA) {
119 encodingName = new GString(encodingNameA);
120 kind = unicodeMapResident;
121 ranges = rangesA;
122 len = lenA;
123 eMaps = NULL;
124 eMapsLen = 0;
125 refCnt = 1;
126}
127
128UnicodeMap::UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA) {
129 encodingName = new GString(encodingNameA);
130 kind = unicodeMapFunc;
131 func = funcA;
132 eMaps = NULL;
133 eMapsLen = 0;
134 refCnt = 1;
135}
136
137UnicodeMap::~UnicodeMap() {
138 delete encodingName;
139 if (kind == unicodeMapUser && ranges) {
140 gfree(ranges);
141 }
142 if (eMaps) {
143 gfree(eMaps);
144 }
145}
146
147void UnicodeMap::incRefCnt() {
148 ++refCnt;
149}
150
151void UnicodeMap::decRefCnt() {
152 if (--refCnt == 0) {
153 delete this;
154 }
155}
156
157GBool UnicodeMap::match(GString *encodingNameA) {
158 return !encodingName->cmp(encodingNameA);
159}
160
161int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
162 int a, b, m, n, i, j;
163 Guint code;
164
165 if (kind == unicodeMapFunc) {
166 return (*func)(u, buf, bufSize);
167 }
168
169 a = 0;
170 b = len;
171 if (u < ranges[a].start) {
172 return 0;
173 }
174 // invariant: ranges[a].start <= u < ranges[b].start
175 while (b - a > 1) {
176 m = (a + b) / 2;
177 if (u >= ranges[m].start) {
178 a = m;
179 } else if (u < ranges[m].start) {
180 b = m;
181 }
182 }
183 if (u <= ranges[a].end) {
184 n = ranges[a].nBytes;
185 if (n > bufSize) {
186 return 0;
187 }
188 code = ranges[a].code + (u - ranges[a].start);
189 for (i = n - 1; i >= 0; --i) {
190 buf[i] = (char)(code & 0xff);
191 code >>= 8;
192 }
193 return n;
194 }
195
196 for (i = 0; i < eMapsLen; ++i) {
197 if (eMaps[i].u == u) {
198 n = eMaps[i].nBytes;
199 for (j = 0; j < n; ++j) {
200 buf[j] = eMaps[i].code[j];
201 }
202 return n;
203 }
204 }
205
206 return 0;
207}
208
209//------------------------------------------------------------------------
210
211UnicodeMapCache::UnicodeMapCache() {
212 int i;
213
214 for (i = 0; i < unicodeMapCacheSize; ++i) {
215 cache[i] = NULL;
216 }
217}
218
219UnicodeMapCache::~UnicodeMapCache() {
220 int i;
221
222 for (i = 0; i < unicodeMapCacheSize; ++i) {
223 if (cache[i]) {
224 cache[i]->decRefCnt();
225 }
226 }
227}
228
229UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
230 UnicodeMap *map;
231 int i, j;
232
233 if (cache[0] && cache[0]->match(encodingName)) {
234 cache[0]->incRefCnt();
235 return cache[0];
236 }
237 for (i = 1; i < unicodeMapCacheSize; ++i) {
238 if (cache[i] && cache[i]->match(encodingName)) {
239 map = cache[i];
240 for (j = i; j >= 1; --j) {
241 cache[j] = cache[j - 1];
242 }
243 cache[0] = map;
244 map->incRefCnt();
245 return map;
246 }
247 }
248 if ((map = UnicodeMap::parse(encodingName))) {
249 if (cache[unicodeMapCacheSize - 1]) {
250 cache[unicodeMapCacheSize - 1]->decRefCnt();
251 }
252 for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
253 cache[j] = cache[j - 1];
254 }
255 cache[0] = map;
256 map->incRefCnt();
257 return map;
258 }
259 return NULL;
260}
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMap.h b/noncore/unsupported/qpdf/xpdf/UnicodeMap.h
new file mode 100644
index 0000000..4d982c8
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMap.h
@@ -0,0 +1,110 @@
1//========================================================================
2//
3// UnicodeMap.h
4//
5// Mapping from Unicode to an encoding.
6//
7// Copyright 2001 Derek B. Noonburg
8//
9//========================================================================
10
11#ifndef UNICODEMAP_H
12#define UNICODEMAP_H
13
14#ifdef __GNUC__
15#pragma interface
16#endif
17
18#include "gtypes.h"
19#include "CharTypes.h"
20
21class GString;
22
23//------------------------------------------------------------------------
24
25enum UnicodeMapKind {
26 unicodeMapUser, // read from a file
27 unicodeMapResident, // static list of ranges
28 unicodeMapFunc // function pointer
29};
30
31typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize);
32
33struct UnicodeMapRange {
34 Unicode start, end; // range of Unicode chars
35 Guint code, nBytes; // first output code
36};
37
38struct UnicodeMapExt;
39
40//------------------------------------------------------------------------
41
42class UnicodeMap {
43public:
44
45 // Create the UnicodeMap specified by <encodingName>. Sets the
46 // initial reference count to 1. Returns NULL on failure.
47 static UnicodeMap *parse(GString *encodingNameA);
48
49 // Create a resident UnicodeMap.
50 UnicodeMap(char *encodingNameA,
51 UnicodeMapRange *rangesA, int lenA);
52
53 // Create a resident UnicodeMap that uses a function instead of a
54 // list of ranges.
55 UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA);
56
57 ~UnicodeMap();
58
59 void incRefCnt();
60 void decRefCnt();
61
62 GString *getEncodingName() { return encodingName; }
63
64 // Return true if this UnicodeMap matches the specified
65 // <encodingNameA>.
66 GBool match(GString *encodingNameA);
67
68 // Map Unicode to the target encoding. Fills in <buf> with the
69 // output and returns the number of bytes used. Output will be
70 // truncated at <bufSize> bytes. No string terminator is written.
71 // Returns 0 if no mapping is found.
72 int mapUnicode(Unicode u, char *buf, int bufSize);
73
74private:
75
76 UnicodeMap(GString *encodingNameA);
77
78 GString *encodingName;
79 UnicodeMapKind kind;
80 union {
81 UnicodeMapRange *ranges;// (user, resident)
82 UnicodeMapFunc func;// (func)
83 };
84 int len; // (user, resident)
85 UnicodeMapExt *eMaps; // (user)
86 int eMapsLen; // (user)
87 int refCnt;
88};
89
90//------------------------------------------------------------------------
91
92#define unicodeMapCacheSize 4
93
94class UnicodeMapCache {
95public:
96
97 UnicodeMapCache();
98 ~UnicodeMapCache();
99
100 // Get the UnicodeMap for <encodingName>. Increments its reference
101 // count; there will be one reference for the cache plus one for the
102 // caller of this function. Returns NULL on failure.
103 UnicodeMap *getUnicodeMap(GString *encodingName);
104
105private:
106
107 UnicodeMap *cache[unicodeMapCacheSize];
108};
109
110#endif
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h b/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h
new file mode 100644
index 0000000..6fcd44e
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h
@@ -0,0 +1,303 @@
1//========================================================================
2//
3// UnicodeMapTables.h
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9static UnicodeMapRange latin1UnicodeMapRanges[] = {
10 { 0x000a, 0x000a, 0x0a, 1 },
11 { 0x000c, 0x000d, 0x0c, 1 },
12 { 0x0020, 0x007e, 0x20, 1 },
13 { 0x00a0, 0x00a0, 0x20, 1 },
14 { 0x00a1, 0x00ac, 0xa1, 1 },
15 { 0x00ae, 0x00ff, 0xae, 1 },
16 { 0x0131, 0x0131, 0x69, 1 },
17 { 0x0141, 0x0141, 0x4c, 1 },
18 { 0x0142, 0x0142, 0x6c, 1 },
19 { 0x0152, 0x0152, 0x4f45, 2 },
20 { 0x0153, 0x0153, 0x6f65, 2 },
21 { 0x0160, 0x0160, 0x53, 1 },
22 { 0x0161, 0x0161, 0x73, 1 },
23 { 0x0178, 0x0178, 0x59, 1 },
24 { 0x017d, 0x017d, 0x5a, 1 },
25 { 0x017e, 0x017e, 0x7a, 1 },
26 { 0x02c6, 0x02c6, 0x5e, 1 },
27 { 0x02da, 0x02da, 0xb0, 1 },
28 { 0x02dc, 0x02dc, 0x7e, 1 },
29 { 0x2013, 0x2013, 0xad, 1 },
30 { 0x2014, 0x2014, 0x2d2d, 2 },
31 { 0x2018, 0x2018, 0x60, 1 },
32 { 0x2019, 0x2019, 0x27, 1 },
33 { 0x201a, 0x201a, 0x2c, 1 },
34 { 0x201c, 0x201c, 0x22, 1 },
35 { 0x201d, 0x201d, 0x22, 1 },
36 { 0x201e, 0x201e, 0x2c2c, 2 },
37 { 0x2022, 0x2022, 0xb7, 1 },
38 { 0x2026, 0x2026, 0x2e2e2e, 3 },
39 { 0x2039, 0x2039, 0x3c, 1 },
40 { 0x203a, 0x203a, 0x3e, 1 },
41 { 0x2044, 0x2044, 0x2f, 1 },
42 { 0x2122, 0x2122, 0x544d, 2 },
43 { 0x2212, 0x2212, 0x2d, 1 },
44 { 0xfb00, 0xfb00, 0x6666, 2 },
45 { 0xfb01, 0xfb01, 0x6669, 2 },
46 { 0xfb02, 0xfb02, 0x666c, 2 },
47 { 0xfb03, 0xfb03, 0x666669, 3 },
48 { 0xfb04, 0xfb04, 0x66666c, 3 }
49};
50#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange))
51
52static UnicodeMapRange ascii7UnicodeMapRanges[] = {
53 { 0x000a, 0x000a, 0x0a, 1 },
54 { 0x000c, 0x000d, 0x0c, 1 },
55 { 0x0020, 0x005f, 0x20, 1 },
56 { 0x0061, 0x007e, 0x61, 1 },
57 { 0x00a6, 0x00a6, 0x7c, 1 },
58 { 0x00a9, 0x00a9, 0x286329, 3 },
59 { 0x00ae, 0x00ae, 0x285229, 3 },
60 { 0x00b7, 0x00b7, 0x2a, 1 },
61 { 0x00bc, 0x00bc, 0x312f34, 3 },
62 { 0x00bd, 0x00bd, 0x312f32, 3 },
63 { 0x00be, 0x00be, 0x332f34, 3 },
64 { 0x00c0, 0x00c0, 0x41, 1 },
65 { 0x00c1, 0x00c1, 0x41, 1 },
66 { 0x00c2, 0x00c2, 0x41, 1 },
67 { 0x00c3, 0x00c3, 0x41, 1 },
68 { 0x00c4, 0x00c4, 0x41, 1 },
69 { 0x00c5, 0x00c5, 0x41, 1 },
70 { 0x00c6, 0x00c6, 0x4145, 2 },
71 { 0x00c7, 0x00c7, 0x43, 1 },
72 { 0x00c8, 0x00c8, 0x45, 1 },
73 { 0x00c9, 0x00c9, 0x45, 1 },
74 { 0x00ca, 0x00ca, 0x45, 1 },
75 { 0x00cb, 0x00cb, 0x45, 1 },
76 { 0x00cc, 0x00cc, 0x49, 1 },
77 { 0x00cd, 0x00cd, 0x49, 1 },
78 { 0x00ce, 0x00ce, 0x49, 1 },
79 { 0x00cf, 0x00cf, 0x49, 1 },
80 { 0x00d1, 0x00d2, 0x4e, 1 },
81 { 0x00d3, 0x00d3, 0x4f, 1 },
82 { 0x00d4, 0x00d4, 0x4f, 1 },
83 { 0x00d5, 0x00d5, 0x4f, 1 },
84 { 0x00d6, 0x00d6, 0x4f, 1 },
85 { 0x00d7, 0x00d7, 0x78, 1 },
86 { 0x00d8, 0x00d8, 0x4f, 1 },
87 { 0x00d9, 0x00d9, 0x55, 1 },
88 { 0x00da, 0x00da, 0x55, 1 },
89 { 0x00db, 0x00db, 0x55, 1 },
90 { 0x00dc, 0x00dc, 0x55, 1 },
91 { 0x00dd, 0x00dd, 0x59, 1 },
92 { 0x00e0, 0x00e0, 0x61, 1 },
93 { 0x00e1, 0x00e1, 0x61, 1 },
94 { 0x00e2, 0x00e2, 0x61, 1 },
95 { 0x00e3, 0x00e3, 0x61, 1 },
96 { 0x00e4, 0x00e4, 0x61, 1 },
97 { 0x00e5, 0x00e5, 0x61, 1 },
98 { 0x00e6, 0x00e6, 0x6165, 2 },
99 { 0x00e7, 0x00e7, 0x63, 1 },
100 { 0x00e8, 0x00e8, 0x65, 1 },
101 { 0x00e9, 0x00e9, 0x65, 1 },
102 { 0x00ea, 0x00ea, 0x65, 1 },
103 { 0x00eb, 0x00eb, 0x65, 1 },
104 { 0x00ec, 0x00ec, 0x69, 1 },
105 { 0x00ed, 0x00ed, 0x69, 1 },
106 { 0x00ee, 0x00ee, 0x69, 1 },
107 { 0x00ef, 0x00ef, 0x69, 1 },
108 { 0x00f1, 0x00f2, 0x6e, 1 },
109 { 0x00f3, 0x00f3, 0x6f, 1 },
110 { 0x00f4, 0x00f4, 0x6f, 1 },
111 { 0x00f5, 0x00f5, 0x6f, 1 },
112 { 0x00f6, 0x00f6, 0x6f, 1 },
113 { 0x00f7, 0x00f7, 0x2f, 1 },
114 { 0x00f8, 0x00f8, 0x6f, 1 },
115 { 0x00f9, 0x00f9, 0x75, 1 },
116 { 0x00fa, 0x00fa, 0x75, 1 },
117 { 0x00fb, 0x00fb, 0x75, 1 },
118 { 0x00fc, 0x00fc, 0x75, 1 },
119 { 0x00fd, 0x00fd, 0x79, 1 },
120 { 0x00ff, 0x00ff, 0x79, 1 },
121 { 0x0131, 0x0131, 0x69, 1 },
122 { 0x0141, 0x0141, 0x4c, 1 },
123 { 0x0152, 0x0152, 0x4f45, 2 },
124 { 0x0153, 0x0153, 0x6f65, 2 },
125 { 0x0160, 0x0160, 0x53, 1 },
126 { 0x0178, 0x0178, 0x59, 1 },
127 { 0x017d, 0x017d, 0x5a, 1 },
128 { 0x2013, 0x2013, 0x2d, 1 },
129 { 0x2014, 0x2014, 0x2d2d, 2 },
130 { 0x2018, 0x2018, 0x60, 1 },
131 { 0x2019, 0x2019, 0x27, 1 },
132 { 0x201c, 0x201c, 0x22, 1 },
133 { 0x201d, 0x201d, 0x22, 1 },
134 { 0x2022, 0x2022, 0x2a, 1 },
135 { 0x2026, 0x2026, 0x2e2e2e, 3 },
136 { 0x2122, 0x2122, 0x544d, 2 },
137 { 0x2212, 0x2212, 0x2d, 1 },
138 { 0xfb00, 0xfb00, 0x6666, 2 },
139 { 0xfb01, 0xfb01, 0x6669, 2 },
140 { 0xfb02, 0xfb02, 0x666c, 2 },
141 { 0xfb03, 0xfb03, 0x666669, 3 },
142 { 0xfb04, 0xfb04, 0x66666c, 3 }
143};
144#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange))
145
146static UnicodeMapRange symbolUnicodeMapRanges[] = {
147 { 0x0020, 0x0021, 0x20, 1 },
148 { 0x0023, 0x0023, 0x23, 1 },
149 { 0x0025, 0x0026, 0x25, 1 },
150 { 0x0028, 0x0029, 0x28, 1 },
151 { 0x002b, 0x002c, 0x2b, 1 },
152 { 0x002e, 0x003f, 0x2e, 1 },
153 { 0x005b, 0x005b, 0x5b, 1 },
154 { 0x005d, 0x005d, 0x5d, 1 },
155 { 0x005f, 0x005f, 0x5f, 1 },
156 { 0x007b, 0x007d, 0x7b, 1 },
157 { 0x00ac, 0x00ac, 0xd8, 1 },
158 { 0x00b0, 0x00b1, 0xb0, 1 },
159 { 0x00b5, 0x00b5, 0x6d, 1 },
160 { 0x00d7, 0x00d7, 0xb4, 1 },
161 { 0x00f7, 0x00f7, 0xb8, 1 },
162 { 0x0192, 0x0192, 0xa6, 1 },
163 { 0x0391, 0x0392, 0x41, 1 },
164 { 0x0393, 0x0393, 0x47, 1 },
165 { 0x0395, 0x0395, 0x45, 1 },
166 { 0x0396, 0x0396, 0x5a, 1 },
167 { 0x0397, 0x0397, 0x48, 1 },
168 { 0x0398, 0x0398, 0x51, 1 },
169 { 0x0399, 0x0399, 0x49, 1 },
170 { 0x039a, 0x039d, 0x4b, 1 },
171 { 0x039e, 0x039e, 0x58, 1 },
172 { 0x039f, 0x03a0, 0x4f, 1 },
173 { 0x03a1, 0x03a1, 0x52, 1 },
174 { 0x03a3, 0x03a5, 0x53, 1 },
175 { 0x03a6, 0x03a6, 0x46, 1 },
176 { 0x03a7, 0x03a7, 0x43, 1 },
177 { 0x03a8, 0x03a8, 0x59, 1 },
178 { 0x03b1, 0x03b2, 0x61, 1 },
179 { 0x03b3, 0x03b3, 0x67, 1 },
180 { 0x03b4, 0x03b5, 0x64, 1 },
181 { 0x03b6, 0x03b6, 0x7a, 1 },
182 { 0x03b7, 0x03b7, 0x68, 1 },
183 { 0x03b8, 0x03b8, 0x71, 1 },
184 { 0x03b9, 0x03b9, 0x69, 1 },
185 { 0x03ba, 0x03bb, 0x6b, 1 },
186 { 0x03bd, 0x03bd, 0x6e, 1 },
187 { 0x03be, 0x03be, 0x78, 1 },
188 { 0x03bf, 0x03c0, 0x6f, 1 },
189 { 0x03c1, 0x03c1, 0x72, 1 },
190 { 0x03c2, 0x03c2, 0x56, 1 },
191 { 0x03c3, 0x03c5, 0x73, 1 },
192 { 0x03c6, 0x03c6, 0x66, 1 },
193 { 0x03c7, 0x03c7, 0x63, 1 },
194 { 0x03c8, 0x03c8, 0x79, 1 },
195 { 0x03c9, 0x03c9, 0x77, 1 },
196 { 0x03d1, 0x03d1, 0x4a, 1 },
197 { 0x03d2, 0x03d2, 0xa1, 1 },
198 { 0x03d5, 0x03d5, 0x6a, 1 },
199 { 0x03d6, 0x03d6, 0x76, 1 },
200 { 0x2022, 0x2022, 0xb7, 1 },
201 { 0x2026, 0x2026, 0xbc, 1 },
202 { 0x2032, 0x2032, 0xa2, 1 },
203 { 0x2033, 0x2033, 0xb2, 1 },
204 { 0x2044, 0x2044, 0xa4, 1 },
205 { 0x2111, 0x2111, 0xc1, 1 },
206 { 0x2118, 0x2118, 0xc3, 1 },
207 { 0x211c, 0x211c, 0xc2, 1 },
208 { 0x2126, 0x2126, 0x57, 1 },
209 { 0x2135, 0x2135, 0xc0, 1 },
210 { 0x2190, 0x2193, 0xac, 1 },
211 { 0x2194, 0x2194, 0xab, 1 },
212 { 0x21b5, 0x21b5, 0xbf, 1 },
213 { 0x21d0, 0x21d3, 0xdc, 1 },
214 { 0x21d4, 0x21d4, 0xdb, 1 },
215 { 0x2200, 0x2200, 0x22, 1 },
216 { 0x2202, 0x2202, 0xb6, 1 },
217 { 0x2203, 0x2203, 0x24, 1 },
218 { 0x2205, 0x2205, 0xc6, 1 },
219 { 0x2206, 0x2206, 0x44, 1 },
220 { 0x2207, 0x2207, 0xd1, 1 },
221 { 0x2208, 0x2209, 0xce, 1 },
222 { 0x220b, 0x220b, 0x27, 1 },
223 { 0x220f, 0x220f, 0xd5, 1 },
224 { 0x2211, 0x2211, 0xe5, 1 },
225 { 0x2212, 0x2212, 0x2d, 1 },
226 { 0x2217, 0x2217, 0x2a, 1 },
227 { 0x221a, 0x221a, 0xd6, 1 },
228 { 0x221d, 0x221d, 0xb5, 1 },
229 { 0x221e, 0x221e, 0xa5, 1 },
230 { 0x2220, 0x2220, 0xd0, 1 },
231 { 0x2227, 0x2228, 0xd9, 1 },
232 { 0x2229, 0x222a, 0xc7, 1 },
233 { 0x222b, 0x222b, 0xf2, 1 },
234 { 0x2234, 0x2234, 0x5c, 1 },
235 { 0x223c, 0x223c, 0x7e, 1 },
236 { 0x2245, 0x2245, 0x40, 1 },
237 { 0x2248, 0x2248, 0xbb, 1 },
238 { 0x2260, 0x2261, 0xb9, 1 },
239 { 0x2264, 0x2264, 0xa3, 1 },
240 { 0x2265, 0x2265, 0xb3, 1 },
241 { 0x2282, 0x2282, 0xcc, 1 },
242 { 0x2283, 0x2283, 0xc9, 1 },
243 { 0x2284, 0x2284, 0xcb, 1 },
244 { 0x2286, 0x2286, 0xcd, 1 },
245 { 0x2287, 0x2287, 0xca, 1 },
246 { 0x2295, 0x2295, 0xc5, 1 },
247 { 0x2297, 0x2297, 0xc4, 1 },
248 { 0x22a5, 0x22a5, 0x5e, 1 },
249 { 0x22c5, 0x22c5, 0xd7, 1 },
250 { 0x2320, 0x2320, 0xf3, 1 },
251 { 0x2321, 0x2321, 0xf5, 1 },
252 { 0x2329, 0x2329, 0xe1, 1 },
253 { 0x232a, 0x232a, 0xf1, 1 },
254 { 0x25ca, 0x25ca, 0xe0, 1 },
255 { 0x2660, 0x2660, 0xaa, 1 },
256 { 0x2663, 0x2663, 0xa7, 1 },
257 { 0x2665, 0x2665, 0xa9, 1 },
258 { 0x2666, 0x2666, 0xa8, 1 },
259 { 0xf6d9, 0xf6d9, 0xd3, 1 },
260 { 0xf6da, 0xf6da, 0xd2, 1 },
261 { 0xf6db, 0xf6db, 0xd4, 1 },
262 { 0xf8e5, 0xf8e5, 0x60, 1 },
263 { 0xf8e6, 0xf8e7, 0xbd, 1 },
264 { 0xf8e8, 0xf8ea, 0xe2, 1 },
265 { 0xf8eb, 0xf8f4, 0xe6, 1 },
266 { 0xf8f5, 0xf8f5, 0xf4, 1 },
267 { 0xf8f6, 0xf8fe, 0xf6, 1 }
268};
269#define symbolUnicodeMapLen (sizeof(symbolUnicodeMapRanges) / sizeof(UnicodeMapRange))
270
271static UnicodeMapRange zapfDingbatsUnicodeMapRanges[] = {
272 { 0x0020, 0x0020, 0x20, 1 },
273 { 0x2192, 0x2192, 0xd5, 1 },
274 { 0x2194, 0x2195, 0xd6, 1 },
275 { 0x2460, 0x2469, 0xac, 1 },
276 { 0x25a0, 0x25a0, 0x6e, 1 },
277 { 0x25b2, 0x25b2, 0x73, 1 },
278 { 0x25bc, 0x25bc, 0x74, 1 },
279 { 0x25c6, 0x25c6, 0x75, 1 },
280 { 0x25cf, 0x25cf, 0x6c, 1 },
281 { 0x25d7, 0x25d7, 0x77, 1 },
282 { 0x2605, 0x2605, 0x48, 1 },
283 { 0x260e, 0x260e, 0x25, 1 },
284 { 0x261b, 0x261b, 0x2a, 1 },
285 { 0x261e, 0x261e, 0x2b, 1 },
286 { 0x2660, 0x2660, 0xab, 1 },
287 { 0x2663, 0x2663, 0xa8, 1 },
288 { 0x2665, 0x2665, 0xaa, 1 },
289 { 0x2666, 0x2666, 0xa9, 1 },
290 { 0x2701, 0x2704, 0x21, 1 },
291 { 0x2706, 0x2709, 0x26, 1 },
292 { 0x270c, 0x2727, 0x2c, 1 },
293 { 0x2729, 0x274b, 0x49, 1 },
294 { 0x274d, 0x274d, 0x6d, 1 },
295 { 0x274f, 0x2752, 0x6f, 1 },
296 { 0x2756, 0x2756, 0x76, 1 },
297 { 0x2758, 0x275e, 0x78, 1 },
298 { 0x2761, 0x2767, 0xa1, 1 },
299 { 0x2776, 0x2794, 0xb6, 1 },
300 { 0x2798, 0x27af, 0xd8, 1 },
301 { 0x27b1, 0x27be, 0xf1, 1 }
302};
303#define zapfDingbatsUnicodeMapLen (sizeof(zapfDingbatsUnicodeMapRanges) / sizeof(UnicodeMapRange))
diff --git a/noncore/unsupported/qpdf/xpdf/XRef.cc b/noncore/unsupported/qpdf/xpdf/XRef.cc
new file mode 100644
index 0000000..5d526e9
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/XRef.cc
@@ -0,0 +1,641 @@
1//========================================================================
2//
3// XRef.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdlib.h>
15#include <stddef.h>
16#include <string.h>
17#include <ctype.h>
18#include "gmem.h"
19#include "Object.h"
20#include "Stream.h"
21#include "Lexer.h"
22#include "Parser.h"
23#include "Dict.h"
24#ifndef NO_DECRYPTION
25#include "Decrypt.h"
26#endif
27#include "Error.h"
28#include "XRef.h"
29
30//------------------------------------------------------------------------
31
32 #define xrefSearchSize 1024// read this many bytes at end of file
33 // to look for 'startxref'
34
35#ifndef NO_DECRYPTION
36//------------------------------------------------------------------------
37// Permission bits
38//------------------------------------------------------------------------
39
40#define permPrint (1<<2)
41#define permChange (1<<3)
42#define permCopy (1<<4)
43#define permNotes (1<<5)
44#define defPermFlags 0xfffc
45#endif
46
47//------------------------------------------------------------------------
48// XRef
49//------------------------------------------------------------------------
50
51XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
52 int pos;
53 int i;
54
55 ok = gTrue;
56 size = 0;
57 entries = NULL;
58 streamEnds = NULL;
59 streamEndsLen = 0;
60
61 // read the trailer
62 str = strA;
63 start = str->getStart();
64 pos = readTrailer();
65
66 // if there was a problem with the trailer,
67 // try to reconstruct the xref table
68 if (pos == 0) {
69 if (!(ok = constructXRef())) {
70 return;
71 }
72
73 // trailer is ok - read the xref table
74 } else {
75 entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
76 for (i = 0; i < size; ++i) {
77 entries[i].offset = -1;
78 entries[i].used = gFalse;
79 }
80 while (readXRef(&pos)) ;
81
82 // if there was a problem with the xref table,
83 // try to reconstruct it
84 if (!ok) {
85 gfree(entries);
86 size = 0;
87 entries = NULL;
88 if (!(ok = constructXRef())) {
89 return;
90 }
91 }
92 }
93
94 // now set the trailer dictionary's xref pointer so we can fetch
95 // indirect objects from it
96 trailerDict.getDict()->setXRef(this);
97
98 // check for encryption
99#ifndef NO_DECRYPTION
100 encrypted = gFalse;
101#endif
102 if (checkEncrypted(ownerPassword, userPassword)) {
103 ok = gFalse;
104 return;
105 }
106}
107
108XRef::~XRef() {
109 gfree(entries);
110 trailerDict.free();
111 if (streamEnds) {
112 gfree(streamEnds);
113 }
114}
115
116// Read startxref position, xref table size, and root. Returns
117// first xref position.
118int XRef::readTrailer() {
119 Parser *parser;
120 Object obj;
121 char buf[xrefSearchSize+1];
122 int n, pos, pos1;
123 char *p;
124 int c;
125 int i;
126
127 // read last xrefSearchSize bytes
128 str->setPos(-xrefSearchSize);
129 for (n = 0; n < xrefSearchSize; ++n) {
130 if ((c = str->getChar()) == EOF)
131 break;
132 buf[n] = c;
133 }
134 buf[n] = '\0';
135
136 // find startxref
137 for (i = n - 9; i >= 0; --i) {
138 if (!strncmp(&buf[i], "startxref", 9))
139 break;
140 }
141 if (i < 0)
142 return 0;
143 for (p = &buf[i+9]; isspace(*p); ++p) ;
144 pos = lastXRefPos = atoi(p);
145
146 // find trailer dict by looking after first xref table
147 // (NB: we can't just use the trailer dict at the end of the file --
148 // this won't work for linearized files.)
149 str->setPos(start + pos);
150 for (i = 0; i < 4; ++i)
151 buf[i] = str->getChar();
152 if (strncmp(buf, "xref", 4))
153 return 0;
154 pos1 = pos + 4;
155 while (1) {
156 str->setPos(start + pos1);
157 for (i = 0; i < 35; ++i) {
158 if ((c = str->getChar()) == EOF)
159 return 0;
160 buf[i] = c;
161 }
162 if (!strncmp(buf, "trailer", 7))
163 break;
164 p = buf;
165 while (isspace(*p)) ++p;
166 while ('0' <= *p && *p <= '9') ++p;
167 while (isspace(*p)) ++p;
168 n = atoi(p);
169 while ('0' <= *p && *p <= '9') ++p;
170 while (isspace(*p)) ++p;
171 if (p == buf)
172 return 0;
173 pos1 += (p - buf) + n * 20;
174 }
175 pos1 += 7;
176
177 // read trailer dict
178 obj.initNull();
179 parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(start + pos1,
180 -1, &obj)));
181 parser->getObj(&trailerDict);
182 if (trailerDict.isDict()) {
183 trailerDict.dictLookupNF("Size", &obj);
184 if (obj.isInt())
185 size = obj.getInt();
186 else
187 pos = 0;
188 obj.free();
189 trailerDict.dictLookupNF("Root", &obj);
190 if (obj.isRef()) {
191 rootNum = obj.getRefNum();
192 rootGen = obj.getRefGen();
193 } else {
194 pos = 0;
195 }
196 obj.free();
197 } else {
198 pos = 0;
199 }
200 delete parser;
201
202 // return first xref position
203 return pos;
204}
205
206// Read an xref table and the prev pointer from the trailer.
207GBool XRef::readXRef(int *pos) {
208 Parser *parser;
209 Object obj, obj2;
210 char s[20];
211 GBool more;
212 int first, newSize, n, i, j;
213 int c;
214
215 // seek to xref in stream
216 str->setPos(start + *pos);
217
218 // make sure it's an xref table
219 while ((c = str->getChar()) != EOF && isspace(c)) ;
220 s[0] = (char)c;
221 s[1] = (char)str->getChar();
222 s[2] = (char)str->getChar();
223 s[3] = (char)str->getChar();
224 if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) {
225 goto err2;
226 }
227
228 // read xref
229 while (1) {
230 while ((c = str->lookChar()) != EOF && isspace(c)) {
231 str->getChar();
232 }
233 if (c == 't') {
234 break;
235 }
236 for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
237 s[i] = (char)c;
238 }
239 if (i == 0) {
240 goto err2;
241 }
242 s[i] = '\0';
243 first = atoi(s);
244 while ((c = str->lookChar()) != EOF && isspace(c)) {
245 str->getChar();
246 }
247 for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
248 s[i] = (char)c;
249 }
250 if (i == 0) {
251 goto err2;
252 }
253 s[i] = '\0';
254 n = atoi(s);
255 while ((c = str->lookChar()) != EOF && isspace(c)) {
256 str->getChar();
257 }
258 // check for buggy PDF files with an incorrect (too small) xref
259 // table size
260 if (first + n > size) {
261 newSize = size + 256;
262 entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
263 for (i = size; i < newSize; ++i) {
264 entries[i].offset = -1;
265 entries[i].used = gFalse;
266 }
267 size = newSize;
268 }
269 for (i = first; i < first + n; ++i) {
270 for (j = 0; j < 20; ++j) {
271 if ((c = str->getChar()) == EOF) {
272 goto err2;
273 }
274 s[j] = (char)c;
275 }
276 if (entries[i].offset < 0) {
277 s[10] = '\0';
278 entries[i].offset = atoi(s);
279 s[16] = '\0';
280 entries[i].gen = atoi(&s[11]);
281 if (s[17] == 'n') {
282 entries[i].used = gTrue;
283 } else if (s[17] == 'f') {
284 entries[i].used = gFalse;
285 } else {
286 goto err2;
287 }
288 // PDF files of patents from the IBM Intellectual Property
289 // Network have a bug: the xref table claims to start at 1
290 // instead of 0.
291 if (i == 1 && first == 1 &&
292 entries[1].offset == 0 && entries[1].gen == 65535 &&
293 !entries[1].used) {
294 i = first = 0;
295 entries[0] = entries[1];
296 entries[1].offset = -1;
297 }
298 }
299 }
300 }
301
302 // read prev pointer from trailer dictionary
303 obj.initNull();
304 parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(str->getPos(),
305 -1, &obj)));
306 parser->getObj(&obj);
307 if (!obj.isCmd("trailer")) {
308 goto err1;
309 }
310 obj.free();
311 parser->getObj(&obj);
312 if (!obj.isDict()) {
313 goto err1;
314 }
315 obj.getDict()->lookupNF("Prev", &obj2);
316 if (obj2.isInt()) {
317 *pos = obj2.getInt();
318 more = gTrue;
319 } else {
320 more = gFalse;
321 }
322 obj.free();
323 obj2.free();
324
325 delete parser;
326 return more;
327
328 err1:
329 obj.free();
330 err2:
331 ok = gFalse;
332 return gFalse;
333}
334
335// Attempt to construct an xref table for a damaged file.
336GBool XRef::constructXRef() {
337 Parser *parser;
338 Object obj;
339 char buf[256];
340 int pos;
341 int num, gen;
342 int newSize;
343 int streamEndsSize;
344 char *p;
345 int i;
346 GBool gotRoot;
347
348 error(0, "PDF file is damaged - attempting to reconstruct xref table...");
349 gotRoot = gFalse;
350 streamEndsLen = streamEndsSize = 0;
351
352 str->reset();
353 while (1) {
354 pos = str->getPos();
355 if (!str->getLine(buf, 256)) {
356 break;
357 }
358 p = buf;
359
360 // got trailer dictionary
361 if (!strncmp(p, "trailer", 7)) {
362 obj.initNull();
363 parser = new Parser(NULL, new Lexer(NULL,
364 str->makeSubStream(start + pos + 7, -1, &obj)));
365 if (!trailerDict.isNone())
366 trailerDict.free();
367 parser->getObj(&trailerDict);
368 if (trailerDict.isDict()) {
369 trailerDict.dictLookupNF("Root", &obj);
370 if (obj.isRef()) {
371 rootNum = obj.getRefNum();
372 rootGen = obj.getRefGen();
373 gotRoot = gTrue;
374 }
375 obj.free();
376 } else {
377 pos = 0;
378 }
379 delete parser;
380
381 // look for object
382 } else if (isdigit(*p)) {
383 num = atoi(p);
384 do {
385 ++p;
386 } while (*p && isdigit(*p));
387 if (isspace(*p)) {
388 do {
389 ++p;
390 } while (*p && isspace(*p));
391 if (isdigit(*p)) {
392 gen = atoi(p);
393 do {
394 ++p;
395 } while (*p && isdigit(*p));
396 if (isspace(*p)) {
397 do {
398 ++p;
399 } while (*p && isspace(*p));
400 if (!strncmp(p, "obj", 3)) {
401 if (num >= size) {
402 newSize = (num + 1 + 255) & ~255;
403 entries = (XRefEntry *)
404 grealloc(entries, newSize * sizeof(XRefEntry));
405 for (i = size; i < newSize; ++i) {
406 entries[i].offset = -1;
407 entries[i].used = gFalse;
408 }
409 size = newSize;
410 }
411 if (!entries[num].used || gen >= entries[num].gen) {
412 entries[num].offset = pos - start;
413 entries[num].gen = gen;
414 entries[num].used = gTrue;
415 }
416 }
417 }
418 }
419 }
420
421 } else if (!strncmp(p, "endstream", 9)) {
422 if (streamEndsLen == streamEndsSize) {
423 streamEndsSize += 64;
424 streamEnds = (int *)grealloc(streamEnds, streamEndsSize * sizeof(int));
425 }
426 streamEnds[streamEndsLen++] = pos;
427 }
428 }
429
430 if (gotRoot)
431 return gTrue;
432
433 error(-1, "Couldn't find trailer dictionary");
434 return gFalse;
435}
436
437#ifndef NO_DECRYPTION
438GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
439 Object encrypt, filterObj, versionObj, revisionObj, lengthObj;
440 Object ownerKey, userKey, permissions, fileID, fileID1;
441 GBool encrypted1;
442 GBool ret;
443
444 ret = gFalse;
445
446 permFlags = defPermFlags;
447 trailerDict.dictLookup("Encrypt", &encrypt);
448 if ((encrypted1 = encrypt.isDict())) {
449 ret = gTrue;
450 encrypt.dictLookup("Filter", &filterObj);
451 if (filterObj.isName("Standard")) {
452 encrypt.dictLookup("V", &versionObj);
453 encrypt.dictLookup("R", &revisionObj);
454 encrypt.dictLookup("Length", &lengthObj);
455 encrypt.dictLookup("O", &ownerKey);
456 encrypt.dictLookup("U", &userKey);
457 encrypt.dictLookup("P", &permissions);
458 trailerDict.dictLookup("ID", &fileID);
459 if (versionObj.isInt() &&
460 revisionObj.isInt() &&
461 ownerKey.isString() && ownerKey.getString()->getLength() == 32 &&
462 userKey.isString() && userKey.getString()->getLength() == 32 &&
463 permissions.isInt() &&
464 fileID.isArray()) {
465 encVersion = versionObj.getInt();
466 encRevision = revisionObj.getInt();
467 if (lengthObj.isInt()) {
468 keyLength = lengthObj.getInt() / 8;
469 } else {
470 keyLength = 5;
471 }
472 permFlags = permissions.getInt();
473 if (encVersion >= 1 && encVersion <= 2 &&
474 encRevision >= 2 && encRevision <= 3) {
475 fileID.arrayGet(0, &fileID1);
476 if (fileID1.isString()) {
477 if (Decrypt::makeFileKey(encVersion, encRevision, keyLength,
478 ownerKey.getString(), userKey.getString(),
479 permFlags, fileID1.getString(),
480 ownerPassword, userPassword, fileKey,
481 &ownerPasswordOk)) {
482 if (ownerPassword && !ownerPasswordOk) {
483 error(-1, "Incorrect owner password");
484 }
485 ret = gFalse;
486 } else {
487 error(-1, "Incorrect password");
488 }
489 } else {
490 error(-1, "Weird encryption info");
491 }
492 fileID1.free();
493 } else {
494 error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
495 encVersion, encRevision);
496 }
497 } else {
498 error(-1, "Weird encryption info");
499 }
500 fileID.free();
501 permissions.free();
502 userKey.free();
503 ownerKey.free();
504 lengthObj.free();
505 revisionObj.free();
506 versionObj.free();
507 } else {
508 error(-1, "Unknown security handler '%s'",
509 filterObj.isName() ? filterObj.getName() : "???");
510 }
511 filterObj.free();
512 }
513 encrypt.free();
514
515 // this flag has to be set *after* we read the O/U/P strings
516 encrypted = encrypted1;
517
518 return ret;
519}
520#else
521GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
522 Object obj;
523 GBool encrypted;
524
525 trailerDict.dictLookup("Encrypt", &obj);
526 if ((encrypted = !obj.isNull())) {
527 error(-1, "PDF file is encrypted and this version of the Xpdf tools");
528 error(-1, "was built without decryption support.");
529 }
530 obj.free();
531 return encrypted;
532}
533#endif
534
535GBool XRef::okToPrint(GBool ignoreOwnerPW) {
536#ifndef NO_DECRYPTION
537 if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permPrint)) {
538 return gFalse;
539 }
540#endif
541 return gTrue;
542}
543
544GBool XRef::okToChange(GBool ignoreOwnerPW) {
545#ifndef NO_DECRYPTION
546 if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permChange)) {
547 return gFalse;
548 }
549#endif
550 return gTrue;
551}
552
553GBool XRef::okToCopy(GBool ignoreOwnerPW) {
554#ifndef NO_DECRYPTION
555 if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permCopy)) {
556 return gFalse;
557 }
558#endif
559 return gTrue;
560}
561
562GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
563#ifndef NO_DECRYPTION
564 if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permNotes)) {
565 return gFalse;
566 }
567#endif
568 return gTrue;
569}
570
571Object *XRef::fetch(int num, int gen, Object *obj) {
572 XRefEntry *e;
573 Parser *parser;
574 Object obj1, obj2, obj3;
575
576 // check for bogus ref - this can happen in corrupted PDF files
577 if (num < 0 || num >= size) {
578 obj->initNull();
579 return obj;
580 }
581
582 e = &entries[num];
583 if (e->gen == gen && e->offset >= 0) {
584 obj1.initNull();
585 parser = new Parser(this, new Lexer(this,
586 str->makeSubStream(start + e->offset, -1, &obj1)));
587 parser->getObj(&obj1);
588 parser->getObj(&obj2);
589 parser->getObj(&obj3);
590 if (obj1.isInt() && obj1.getInt() == num &&
591 obj2.isInt() && obj2.getInt() == gen &&
592 obj3.isCmd("obj")) {
593#ifndef NO_DECRYPTION
594 parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
595 num, gen);
596#else
597 parser->getObj(obj);
598#endif
599 } else {
600 obj->initNull();
601 }
602 obj1.free();
603 obj2.free();
604 obj3.free();
605 delete parser;
606 } else {
607 obj->initNull();
608 }
609 return obj;
610}
611
612Object *XRef::getDocInfo(Object *obj) {
613 return trailerDict.dictLookup("Info", obj);
614}
615
616// Added for the pdftex project.
617Object *XRef::getDocInfoNF(Object *obj) {
618 return trailerDict.dictLookupNF("Info", obj);
619}
620
621int XRef::getStreamEnd(int streamStart) {
622 int a, b, m;
623
624 if (streamEndsLen == 0 ||
625 streamStart > streamEnds[streamEndsLen - 1]) {
626 return -1;
627 }
628
629 a = -1;
630 b = streamEndsLen - 1;
631 // invariant: streamEnds[a] < streamStart <= streamEnds[b]
632 while (b - a > 1) {
633 m = (a + b) / 2;
634 if (streamStart <= streamEnds[m]) {
635 b = m;
636 } else {
637 a = m;
638 }
639 }
640 return streamEnds[b];
641}
diff --git a/noncore/unsupported/qpdf/xpdf/XRef.h b/noncore/unsupported/qpdf/xpdf/XRef.h
new file mode 100644
index 0000000..a44c495
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/XRef.h
@@ -0,0 +1,111 @@
1//========================================================================
2//
3// XRef.h
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef XREF_H
10#define XREF_H
11
12#ifdef __GNUC__
13#pragma interface
14#endif
15
16#include "gtypes.h"
17#include "Object.h"
18
19class Dict;
20class Stream;
21
22//------------------------------------------------------------------------
23// XRef
24//------------------------------------------------------------------------
25
26struct XRefEntry {
27 int offset;
28 int gen;
29 GBool used;
30};
31
32class XRef {
33public:
34
35 // Constructor. Read xref table from stream.
36 XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword);
37
38 // Destructor.
39 ~XRef();
40
41 // Is xref table valid?
42 GBool isOk() { return ok; }
43
44 // Is the file encrypted?
45#ifndef NO_DECRYPTION
46 GBool isEncrypted() { return encrypted; }
47#else
48 GBool isEncrypted() { return gFalse; }
49#endif
50
51 // Check various permissions.
52 GBool okToPrint(GBool ignoreOwnerPW = gFalse);
53 GBool okToChange(GBool ignoreOwnerPW = gFalse);
54 GBool okToCopy(GBool ignoreOwnerPW = gFalse);
55 GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
56
57 // Get catalog object.
58 Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
59
60 // Fetch an indirect reference.
61 Object *fetch(int num, int gen, Object *obj);
62
63 // Return the document's Info dictionary (if any).
64 Object *getDocInfo(Object *obj);
65 Object *getDocInfoNF(Object *obj);
66
67 // Return the number of objects in the xref table.
68 int getNumObjects() { return size; }
69
70 // Return the offset of the last xref table.
71 int getLastXRefPos() { return lastXRefPos; }
72
73 // Return the catalog object reference.
74 int getRootNum() { return rootNum; }
75 int getRootGen() { return rootGen; }
76
77 // Get end position for a stream in a damaged file.
78 // Returns -1 if unknown or file is not damaged.
79 int getStreamEnd(int streamStart);
80
81private:
82
83 BaseStream *str; // input stream
84 int start; // offset in file (to allow for garbage
85 // at beginning of file)
86 XRefEntry *entries; // xref entries
87 int size; // size of <entries> array
88 int rootNum, rootGen; // catalog dict
89 GBool ok; // true if xref table is valid
90 Object trailerDict; // trailer dictionary
91 int lastXRefPos; // offset of last xref table
92 int *streamEnds; // 'endstream' positions - only used in
93 // damaged files
94 int streamEndsLen; // number of valid entries in streamEnds
95#ifndef NO_DECRYPTION
96 GBool encrypted; // true if file is encrypted
97 int encVersion; // encryption algorithm
98 int encRevision; // security handler revision
99 int keyLength; // length of key, in bytes
100 int permFlags; // permission bits
101 Guchar fileKey[16]; // file decryption key
102 GBool ownerPasswordOk;// true if owner password is correct
103#endif
104
105 int readTrailer();
106 GBool readXRef(int *pos);
107 GBool constructXRef();
108 GBool checkEncrypted(GString *ownerPassword, GString *userPassword);
109};
110
111#endif
diff --git a/noncore/unsupported/qpdf/xpdf/config.h b/noncore/unsupported/qpdf/xpdf/config.h
new file mode 100644
index 0000000..2cd2489
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/config.h
@@ -0,0 +1,126 @@
1//========================================================================
2//
3// config.h
4//
5// Copyright 1996-2002 Derek B. Noonburg
6//
7//========================================================================
8
9#ifndef CONFIG_H
10#define CONFIG_H
11
12//------------------------------------------------------------------------
13// version
14//------------------------------------------------------------------------
15
16// xpdf version
17#define xpdfVersion "1.00"
18
19// supported PDF version
20#define supportedPDFVersionStr "1.4"
21#define supportedPDFVersionNum 1.4
22
23// copyright notice
24#define xpdfCopyright "Copyright 1996-2002 Derek B. Noonburg"
25
26//------------------------------------------------------------------------
27// paper size
28//------------------------------------------------------------------------
29
30// default paper size (in points) for PostScript output
31#ifdef A4_PAPER
32#define defPaperWidth 595 // ISO A4 (210x297 mm)
33#define defPaperHeight 842
34#else
35#define defPaperWidth 612 // American letter (8.5x11")
36#define defPaperHeight 792
37#endif
38
39//------------------------------------------------------------------------
40// config file (xpdfrc) path
41//------------------------------------------------------------------------
42
43// user config file name, relative to the user's home directory
44#if defined(VMS) || (defined(WIN32) && !defined(__CYGWIN32__))
45#define xpdfUserConfigFile "xpdfrc"
46#else
47#define xpdfUserConfigFile ".xpdfrc"
48#endif
49
50// system config file name (set via the configure script)
51#ifdef SYSTEM_XPDFRC
52#define xpdfSysConfigFile SYSTEM_XPDFRC
53#else
54// under Windows, we get the directory with the executable and then
55// append this file name
56#define xpdfSysConfigFile "xpdfrc"
57#endif
58
59//------------------------------------------------------------------------
60// X-related constants
61//------------------------------------------------------------------------
62
63// default maximum size of color cube to allocate
64#define defaultRGBCube 5
65
66// number of fonts (combined t1lib, FreeType, X server) to cache
67#define xOutFontCacheSize 64
68
69//------------------------------------------------------------------------
70// popen
71//------------------------------------------------------------------------
72
73#ifdef _MSC_VER
74#define popen _popen
75#define pclose _pclose
76#endif
77
78#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(__CYGWIN32__) || defined(MACOS)
79#define POPEN_READ_MODE "rb"
80#else
81#define POPEN_READ_MODE "r"
82#endif
83
84//------------------------------------------------------------------------
85// uncompress program
86//------------------------------------------------------------------------
87
88#ifdef HAVE_POPEN
89
90// command to uncompress to stdout
91# ifdef USE_GZIP
92# define uncompressCmd "gzip -d -c -q"
93# else
94# ifdef __EMX__
95# define uncompressCmd "compress -d -c"
96# else
97# define uncompressCmd "uncompress -c"
98# endif // __EMX__
99# endif // USE_GZIP
100
101#else // HAVE_POPEN
102
103// command to uncompress a file
104# ifdef USE_GZIP
105# define uncompressCmd "gzip -d -q"
106# else
107# define uncompressCmd "uncompress"
108# endif // USE_GZIP
109
110#endif // HAVE_POPEN
111
112//------------------------------------------------------------------------
113// Win32 stuff
114//------------------------------------------------------------------------
115
116#ifdef CDECL
117#undef CDECL
118#endif
119
120#ifdef _MSC_VER
121#define CDECL __cdecl
122#else
123#define CDECL
124#endif
125
126#endif