author | sandman <sandman> | 2002-04-13 00:47:20 (UTC) |
---|---|---|
committer | sandman <sandman> | 2002-04-13 00:47:20 (UTC) |
commit | 98a1e3f36567639344f12932b629e526a8783aa8 (patch) (unidiff) | |
tree | 0433d296857faceeafc54f7deabddb621f45a933 | |
parent | 7e31b1fba119f69929d6744d7295555ff1727f4f (diff) | |
download | opie-98a1e3f36567639344f12932b629e526a8783aa8.zip opie-98a1e3f36567639344f12932b629e526a8783aa8.tar.gz opie-98a1e3f36567639344f12932b629e526a8783aa8.tar.bz2 |
CVS import of QPdf
90 files changed, 33305 insertions, 0 deletions
diff --git a/apps/Applications/qpdf.desktop b/apps/Applications/qpdf.desktop new file mode 100644 index 0000000..3b4b9be --- a/dev/null +++ b/apps/Applications/qpdf.desktop | |||
@@ -0,0 +1,7 @@ | |||
1 | [Desktop Entry] | ||
2 | Comment=PDF Viewer | ||
3 | Exec=qpdf | ||
4 | Icon=qpdf_icon | ||
5 | Type=Application | ||
6 | MimeType=application/pdf | ||
7 | Name=PDF Viewer | ||
diff --git a/i18n/de/qpdf.ts b/i18n/de/qpdf.ts new file mode 100644 index 0000000..1135c8a --- a/dev/null +++ b/i18n/de/qpdf.ts | |||
@@ -0,0 +1,101 @@ | |||
1 | <!DOCTYPE TS><TS> | ||
2 | <context> | ||
3 | <name>QPdfDlg</name> | ||
4 | <message> | ||
5 | <source>QPdf</source> | ||
6 | <translation type="unfinished"></translation> | ||
7 | </message> | ||
8 | <message> | ||
9 | <source>Zoom</source> | ||
10 | <translation>Ansicht</translation> | ||
11 | </message> | ||
12 | <message> | ||
13 | <source>Fit to width</source> | ||
14 | <translation>Seitenbreite</translation> | ||
15 | </message> | ||
16 | <message> | ||
17 | <source>Fit to page</source> | ||
18 | <translation>Ganze Seite</translation> | ||
19 | </message> | ||
20 | <message> | ||
21 | <source>50%</source> | ||
22 | <translation type="unfinished"></translation> | ||
23 | </message> | ||
24 | <message> | ||
25 | <source>75%</source> | ||
26 | <translation type="unfinished"></translation> | ||
27 | </message> | ||
28 | <message> | ||
29 | <source>100%</source> | ||
30 | <translation type="unfinished"></translation> | ||
31 | </message> | ||
32 | <message> | ||
33 | <source>125%</source> | ||
34 | <translation type="unfinished"></translation> | ||
35 | </message> | ||
36 | <message> | ||
37 | <source>150%</source> | ||
38 | <translation type="unfinished"></translation> | ||
39 | </message> | ||
40 | <message> | ||
41 | <source>200%</source> | ||
42 | <translation type="unfinished"></translation> | ||
43 | </message> | ||
44 | <message> | ||
45 | <source>Open...</source> | ||
46 | <translation>Öffnen...</translation> | ||
47 | </message> | ||
48 | <message> | ||
49 | <source>Find...</source> | ||
50 | <translation>Suchen...</translation> | ||
51 | </message> | ||
52 | <message> | ||
53 | <source>Fullscreen</source> | ||
54 | <translation>Vollbildmodus</translation> | ||
55 | </message> | ||
56 | <message> | ||
57 | <source>First page</source> | ||
58 | <translation>Erste Seite</translation> | ||
59 | </message> | ||
60 | <message> | ||
61 | <source>Previous page</source> | ||
62 | <translation>Vorherige Seite</translation> | ||
63 | </message> | ||
64 | <message> | ||
65 | <source>Goto page...</source> | ||
66 | <translation>Gehe zu Seite...</translation> | ||
67 | </message> | ||
68 | <message> | ||
69 | <source>Next page</source> | ||
70 | <translation>Nächste Seite</translation> | ||
71 | </message> | ||
72 | <message> | ||
73 | <source>Last page</source> | ||
74 | <translation>Letzte Seite</translation> | ||
75 | </message> | ||
76 | <message> | ||
77 | <source>Next</source> | ||
78 | <translation>Weitersuchen</translation> | ||
79 | </message> | ||
80 | <message> | ||
81 | <source>Goto page</source> | ||
82 | <translation>Gehe zu Seite</translation> | ||
83 | </message> | ||
84 | <message> | ||
85 | <source>Select from 1 .. %1:</source> | ||
86 | <translation>Auswahl im Bereich 1 .. %1:</translation> | ||
87 | </message> | ||
88 | <message> | ||
89 | <source>'%1' could not be found.</source> | ||
90 | <translation type="unfinished">Kann '%1' nicht finden.</translation> | ||
91 | </message> | ||
92 | <message> | ||
93 | <source>Error</source> | ||
94 | <translation>Fehler</translation> | ||
95 | </message> | ||
96 | <message> | ||
97 | <source>File does not exist !</source> | ||
98 | <translation type="unfinished">Datei existiert nicht !</translation> | ||
99 | </message> | ||
100 | </context> | ||
101 | </TS> | ||
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 | |||
50 | static 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 | |||
57 | static 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 | |||
67 | struct QOutFontSubst { | ||
68 | char * m_name; | ||
69 | char * m_sname; | ||
70 | bool m_bold; | ||
71 | bool m_italic; | ||
72 | QFont::StyleHint m_hint; | ||
73 | }; | ||
74 | |||
75 | static 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 | |||
101 | QFont 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 | |||
183 | QOutputDev::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 | |||
192 | QOutputDev::~QOutputDev ( ) | ||
193 | { | ||
194 | delete m_painter; | ||
195 | delete m_pixmap; | ||
196 | delete m_text; | ||
197 | } | ||
198 | |||
199 | |||
200 | void 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 | |||
218 | void 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 | |||
228 | void 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 | |||
247 | void 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 | |||
254 | void 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 | |||
263 | void 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 | |||
273 | void 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 | |||
278 | void QOutputDev::updateLineDash ( GfxState *state ) | ||
279 | { | ||
280 | updateLineAttrs ( state, gTrue ); | ||
281 | } | ||
282 | |||
283 | void QOutputDev::updateFlatness ( GfxState */*state*/ ) | ||
284 | { | ||
285 | // not supported | ||
286 | //qDebug ( "updateFlatness not supported !\n" ); | ||
287 | } | ||
288 | |||
289 | void QOutputDev::updateLineJoin ( GfxState *state ) | ||
290 | { | ||
291 | updateLineAttrs ( state, gFalse ); | ||
292 | } | ||
293 | |||
294 | void QOutputDev::updateLineCap ( GfxState *state ) | ||
295 | { | ||
296 | updateLineAttrs ( state, gFalse ); | ||
297 | } | ||
298 | |||
299 | // unimplemented | ||
300 | void QOutputDev::updateMiterLimit ( GfxState */*state*/ ) | ||
301 | { | ||
302 | //qDebug ( "updateMiterLimit not supported !\n" ); | ||
303 | } | ||
304 | |||
305 | void QOutputDev::updateLineWidth ( GfxState *state ) | ||
306 | { | ||
307 | updateLineAttrs ( state, gFalse ); | ||
308 | } | ||
309 | |||
310 | void 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 | |||
368 | void QOutputDev::updateFillColor ( GfxState *state ) | ||
369 | { | ||
370 | GfxRGB rgb; | ||
371 | state-> getFillRGB ( &rgb ); | ||
372 | |||
373 | m_painter-> setBrush ( q_col ( rgb )); | ||
374 | } | ||
375 | |||
376 | void 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 | |||
386 | void 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 | |||
404 | void 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 | |||
432 | void QOutputDev::fill ( GfxState *state ) | ||
433 | { | ||
434 | doFill ( state, true ); | ||
435 | } | ||
436 | |||
437 | void 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 | // | ||
451 | void 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 | |||
484 | void QOutputDev::clip ( GfxState *state ) | ||
485 | { | ||
486 | doClip ( state, true ); | ||
487 | } | ||
488 | |||
489 | void QOutputDev::eoClip ( GfxState *state ) | ||
490 | { | ||
491 | doClip ( state, false ); | ||
492 | } | ||
493 | |||
494 | void 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 | // | ||
547 | int 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 | // | ||
567 | int 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 | |||
612 | void QOutputDev::beginString ( GfxState *state, GString */*s*/ ) | ||
613 | { | ||
614 | m_text-> beginString ( state ); | ||
615 | } | ||
616 | |||
617 | void QOutputDev::endString ( GfxState */*state*/ ) | ||
618 | { | ||
619 | m_text-> endString ( ); | ||
620 | } | ||
621 | |||
622 | void 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 | |||
721 | void 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 | |||
835 | void 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 | |||
967 | bool 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 | |||
978 | bool 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 | |||
1004 | GBool 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 | |||
1022 | QString 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 | |||
1030 | QString QOutputDev::getText ( const QRect &r ) | ||
1031 | { | ||
1032 | return getText ( r. left ( ), r. top ( ), r. width ( ), r. height ( )); | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | |||
1037 | void 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 | |||
22 | class Object; | ||
23 | |||
24 | #include "config.h" | ||
25 | #include "CharTypes.h" | ||
26 | #include "GlobalParams.h" | ||
27 | #include "OutputDev.h" | ||
28 | |||
29 | class GString; | ||
30 | class GList; | ||
31 | struct GfxRGB; | ||
32 | class GfxFont; | ||
33 | class GfxSubpath; | ||
34 | class TextPage; | ||
35 | class XOutputFontCache; | ||
36 | class Link; | ||
37 | class Catalog; | ||
38 | class DisplayFontParam; | ||
39 | class UnicodeMap; | ||
40 | class CharCodeToUnicode; | ||
41 | |||
42 | |||
43 | class QPainter; | ||
44 | class QPixmap; | ||
45 | class QPointArray; | ||
46 | |||
47 | |||
48 | typedef fouble fp_t; | ||
49 | |||
50 | //------------------------------------------------------------------------ | ||
51 | // Constants | ||
52 | //------------------------------------------------------------------------ | ||
53 | |||
54 | |||
55 | //------------------------------------------------------------------------ | ||
56 | // Misc types | ||
57 | //------------------------------------------------------------------------ | ||
58 | |||
59 | |||
60 | //------------------------------------------------------------------------ | ||
61 | // XOutputDev | ||
62 | //------------------------------------------------------------------------ | ||
63 | |||
64 | class QOutputDev : public QScrollView, public OutputDev { | ||
65 | public: | ||
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 | |||
154 | protected: | ||
155 | virtual void drawContents ( QPainter *p, int, int, int, int ); | ||
156 | |||
157 | private: | ||
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 | |||
10 | QPEOutputDev::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 | |||
28 | void QPEOutputDev::startPage ( int pn, GfxState *st ) | ||
29 | { | ||
30 | m_selection = QRect ( ); | ||
31 | m_selectiondrag = false; | ||
32 | |||
33 | QOutputDev::startPage ( pn, st ); | ||
34 | } | ||
35 | |||
36 | |||
37 | void QPEOutputDev::setPageCount ( int actp, int maxp ) | ||
38 | { | ||
39 | m_counter-> setText ( QString ( "%1 / %2" ). arg ( actp ). arg ( maxp )); | ||
40 | } | ||
41 | |||
42 | void 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 | |||
59 | bool QPEOutputDev::isBusy ( ) const | ||
60 | { | ||
61 | return m_isbusy; | ||
62 | } | ||
63 | |||
64 | void 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 | |||
74 | void 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 | |||
96 | void 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 | |||
114 | QRect QPEOutputDev::selection ( ) const | ||
115 | { | ||
116 | return m_selection; | ||
117 | } | ||
118 | |||
119 | |||
120 | void 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 | |||
141 | void 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 | |||
152 | void 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 | |||
168 | void 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 | |||
6 | class QLabel; | ||
7 | class QBusyBar; | ||
8 | |||
9 | class QPEOutputDev : public QOutputDev { | ||
10 | Q_OBJECT | ||
11 | |||
12 | public: | ||
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 | |||
25 | signals: | ||
26 | void selectionChanged ( const QRect &sel ); | ||
27 | |||
28 | protected: | ||
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 | |||
38 | private: | ||
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 | |||
2 | QPDF - a PDF viewer for the Qtopia environment | ||
3 | |||
4 | This tool is based on xpdf (currently 1.00). It uses the (mostly unmodified - | ||
5 | see below) xpdf PDF rendering engine. The Qtopia adaption was done with a new | ||
6 | OutputDev which renders directly to a QPixmap via QPainter calls. | ||
7 | |||
8 | Changes in 20020406: | ||
9 | - Font substitution handling improved. | ||
10 | - Unknown characters are simply ignored now. | ||
11 | - Fullscreen view added. | ||
12 | |||
13 | Changes in 20020407: | ||
14 | - Crash with FontName == 0 fixed | ||
15 | - Cleanup | ||
16 | - Prepare for CVS import | ||
17 | |||
18 | Changes 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 | |||
23 | Changed 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 | |||
30 | Changes 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 | |||
46 | ToDo: | ||
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 | |||
54 | Install: | ||
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 | |||
86 | Have fun ;) | ||
87 | |||
88 | Robert (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 | |||
13 | static 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 | |||
21 | typedef 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 | |||
8 | template <unsigned int SH> class fixed { | ||
9 | public: | ||
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_ | ||
78 | public: | ||
79 | #else | ||
80 | private: | ||
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 | |||
127 | template <unsigned int SH> inline fixed<SH> operator + ( int i, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::i2f( i ) + f. m_f, true ); } | ||
128 | template <unsigned int SH> inline fixed<SH> operator - ( int i, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::i2f( i ) - f. m_f, true ); } | ||
129 | template <unsigned int SH> inline fixed<SH> operator * ( int i, const fixed<SH> &f ) { return fixed<SH> ( i * f. m_f, true ); } | ||
130 | template <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 | |||
133 | template <unsigned int SH> inline fixed<SH> operator + ( double d, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::d2f( d ) + f. m_f, true ); } | ||
134 | template <unsigned int SH> inline fixed<SH> operator - ( double d, const fixed<SH> &f ) { return fixed<SH> ( fixed<SH>::d2f( d ) - f. m_f, true ); } | ||
135 | template <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 ); } | ||
136 | template <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 | |||
138 | template <unsigned int SH> inline bool operator < ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) < f. m_f; } | ||
139 | template <unsigned int SH> inline bool operator > ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) > f. m_f; } | ||
140 | template <unsigned int SH> inline bool operator <= ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) <= f. m_f; } | ||
141 | template <unsigned int SH> inline bool operator >= ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) >= f. m_f; } | ||
142 | template <unsigned int SH> inline bool operator == ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) == f. m_f; } | ||
143 | template <unsigned int SH> inline bool operator != ( double d, const fixed<SH> &f ) { return fixed<SH>::d2f( d ) != f. m_f; } | ||
144 | |||
145 | template <unsigned int SH> inline bool operator < ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) < f. m_f; } | ||
146 | template <unsigned int SH> inline bool operator > ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) > f. m_f; } | ||
147 | template <unsigned int SH> inline bool operator <= ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) <= f. m_f; } | ||
148 | template <unsigned int SH> inline bool operator >= ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) >= f. m_f; } | ||
149 | template <unsigned int SH> inline bool operator == ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) == f. m_f; } | ||
150 | template <unsigned int SH> inline bool operator != ( int i, const fixed<SH> &f ) { return fixed<SH>::i2f( i ) != f. m_f; } | ||
151 | |||
152 | |||
153 | template <unsigned int SH> inline fixed<SH> sqrt ( const fixed<SH> &f ) | ||
154 | { | ||
155 | return fixed<SH> ( double( sqrt ( double( f )))); | ||
156 | } | ||
157 | |||
158 | template <unsigned int SH> inline fixed<SH> fabs ( const fixed<SH> &f ) | ||
159 | { | ||
160 | return ( f < 0 ) ? -f : f; | ||
161 | } | ||
162 | |||
163 | template <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 | |||
20 | struct GHashBucket { | ||
21 | GString *key; | ||
22 | void *val; | ||
23 | GHashBucket *next; | ||
24 | }; | ||
25 | |||
26 | struct GHashIter { | ||
27 | int h; | ||
28 | GHashBucket *p; | ||
29 | }; | ||
30 | |||
31 | //------------------------------------------------------------------------ | ||
32 | |||
33 | GHash::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 | |||
45 | GHash::~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 | |||
62 | void 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 | |||
98 | void *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 | |||
108 | void *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 | |||
118 | void *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 | |||
141 | void *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 | |||
164 | void GHash::startIter(GHashIter **iter) { | ||
165 | *iter = new GHashIter; | ||
166 | (*iter)->h = -1; | ||
167 | (*iter)->p = NULL; | ||
168 | } | ||
169 | |||
170 | GBool 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 | |||
190 | void GHash::killIter(GHashIter **iter) { | ||
191 | delete *iter; | ||
192 | *iter = NULL; | ||
193 | } | ||
194 | |||
195 | GHashBucket *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 | |||
207 | GHashBucket *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 | |||
219 | int 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 | |||
231 | int 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 | |||
18 | class GString; | ||
19 | struct GHashBucket; | ||
20 | struct GHashIter; | ||
21 | |||
22 | //------------------------------------------------------------------------ | ||
23 | |||
24 | class GHash { | ||
25 | public: | ||
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 | |||
39 | private: | ||
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 | |||
22 | GList::GList() { | ||
23 | size = 8; | ||
24 | data = (void **)gmalloc(size * sizeof(void*)); | ||
25 | length = 0; | ||
26 | inc = 0; | ||
27 | } | ||
28 | |||
29 | GList::GList(int sizeA) { | ||
30 | size = sizeA; | ||
31 | data = (void **)gmalloc(size * sizeof(void*)); | ||
32 | length = 0; | ||
33 | inc = 0; | ||
34 | } | ||
35 | |||
36 | GList::~GList() { | ||
37 | gfree(data); | ||
38 | } | ||
39 | |||
40 | void GList::append(void *p) { | ||
41 | if (length >= size) { | ||
42 | expand(); | ||
43 | } | ||
44 | data[length++] = p; | ||
45 | } | ||
46 | |||
47 | void 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 | |||
58 | void 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 | |||
69 | void *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 | |||
83 | void GList::expand() { | ||
84 | size += (inc > 0) ? inc : size; | ||
85 | data = (void **)grealloc(data, size * sizeof(void*)); | ||
86 | } | ||
87 | |||
88 | void 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 | |||
22 | class GList { | ||
23 | public: | ||
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 | |||
66 | private: | ||
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 | |||
23 | static inline int size(int len) { | ||
24 | int delta; | ||
25 | |||
26 | delta = len < 256 ? 7 : 255; | ||
27 | return ((len + 1) + delta) & ~delta; | ||
28 | } | ||
29 | |||
30 | inline 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 | |||
43 | GString::GString() { | ||
44 | s = NULL; | ||
45 | resize(length = 0); | ||
46 | s[0] = '\0'; | ||
47 | } | ||
48 | |||
49 | GString::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 | |||
57 | GString::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 | |||
64 | GString::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 | |||
71 | GString::GString(GString *str) { | ||
72 | s = NULL; | ||
73 | resize(length = str->getLength()); | ||
74 | memcpy(s, str->getCString(), length + 1); | ||
75 | } | ||
76 | |||
77 | GString::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 | |||
87 | GString *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 | |||
113 | GString::~GString() { | ||
114 | delete[] s; | ||
115 | } | ||
116 | |||
117 | GString *GString::clear() { | ||
118 | s[length = 0] = '\0'; | ||
119 | resize(0); | ||
120 | return this; | ||
121 | } | ||
122 | |||
123 | GString *GString::append(char c) { | ||
124 | resize(length + 1); | ||
125 | s[length++] = c; | ||
126 | s[length] = '\0'; | ||
127 | return this; | ||
128 | } | ||
129 | |||
130 | GString *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 | |||
139 | GString *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 | |||
148 | GString *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 | |||
156 | GString *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 | |||
167 | GString *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 | |||
179 | GString *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 | |||
191 | GString *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 | |||
202 | GString *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 | |||
213 | GString *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 | |||
223 | GString *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 | |||
20 | class GString { | ||
21 | public: | ||
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 | |||
90 | private: | ||
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 | |||
51 | class GString; | ||
52 | |||
53 | //------------------------------------------------------------------------ | ||
54 | |||
55 | // Get home directory path. | ||
56 | extern GString *getHomeDir(); | ||
57 | |||
58 | // Get current directory. | ||
59 | extern 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>. | ||
63 | extern 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. | ||
67 | extern GString *grabPath(char *fileName); | ||
68 | |||
69 | // Is this an absolute path or file name? | ||
70 | extern 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 '~'). | ||
74 | extern GString *makePathAbsolute(GString *path); | ||
75 | |||
76 | // Get the modification time for <fileName>. Returns 0 if there is an | ||
77 | // error. | ||
78 | extern 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. | ||
86 | extern 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. | ||
90 | extern char *getLine(char *buf, int size, FILE *f); | ||
91 | |||
92 | //------------------------------------------------------------------------ | ||
93 | // GDir and GDirEntry | ||
94 | //------------------------------------------------------------------------ | ||
95 | |||
96 | class GDirEntry { | ||
97 | public: | ||
98 | |||
99 | GDirEntry(char *dirPath, char *nameA, GBool doStat); | ||
100 | ~GDirEntry(); | ||
101 | GString *getName() { return name; } | ||
102 | GBool isDir() { return dir; } | ||
103 | |||
104 | private: | ||
105 | |||
106 | GString *name; // dir/file name | ||
107 | GBool dir; // is it a directory? | ||
108 | }; | ||
109 | |||
110 | class GDir { | ||
111 | public: | ||
112 | |||
113 | GDir(char *name, GBool doStatA = gTrue); | ||
114 | ~GDir(); | ||
115 | GDirEntry *getNextEntry(); | ||
116 | void rewind(); | ||
117 | |||
118 | private: | ||
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 | ||
15 | extern "C" { | ||
16 | #endif | ||
17 | |||
18 | /* | ||
19 | * Same as malloc, but prints error message and exits if malloc() | ||
20 | * returns NULL. | ||
21 | */ | ||
22 | extern 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 | */ | ||
28 | extern void *grealloc(void *p, int size); | ||
29 | |||
30 | /* | ||
31 | * Same as free, but checks for and ignores NULL pointers. | ||
32 | */ | ||
33 | extern void gfree(void *p); | ||
34 | |||
35 | #ifdef DEBUG_MEM | ||
36 | /* | ||
37 | * Report on unfreed memory. | ||
38 | */ | ||
39 | extern void gMemReport(FILE *f); | ||
40 | #else | ||
41 | #define gMemReport(f) | ||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * Allocate memory and copy a string into it. | ||
46 | */ | ||
47 | extern 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 | */ | ||
16 | typedef 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 | */ | ||
24 | typedef unsigned char Guchar; | ||
25 | typedef unsigned short Gushort; | ||
26 | typedef unsigned int Guint; | ||
27 | typedef 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 | |||
2 | extern "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 | |||
22 | void *gmalloc ( int size ) { return malloc ( size ); } | ||
23 | void *grealloc ( void *p, int size ) { return realloc ( p, size ); } | ||
24 | void gfree ( void *p ) { free ( p ); } | ||
25 | char *copyString ( char *str ) { return strdup ( str ); } | ||
26 | char *getLine(char *buf, int size, FILE *f) { return fgets ( buf, size, f ); } | ||
27 | GString *getHomeDir ( ) { return new GString ( QDir::home ( ). absPath ( ). local8Bit ( )); } | ||
28 | GString *appendToPath ( GString *path, char *fileName ) { return new GString ( QDir ( path-> getCString ( )). absFilePath ( fileName ). local8Bit ( )); } | ||
29 | |||
30 | // mostly taken from XPDF, but simplified... | ||
31 | |||
32 | GBool 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 @@ | |||
1 | Files: bin/qpdf apps/Applications/qpdf.desktop pics/qpdf_icon.png | ||
2 | Package: opie-qpdf | ||
3 | Priority: optional | ||
4 | Section: opie/applications | ||
5 | Maintainer: Robert Griebl <sandman@handhelds.org> | ||
6 | Architecture: arm | ||
7 | Version: $QPE_VERSION-$SUB_VERSION | ||
8 | Depends: opie-base ($QPE_VERSION), gzip | ||
9 | Description: 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 | |||
9 | QBusyBar::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, >, &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 | |||
54 | QBusyBar::~QBusyBar ( ) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | bool QBusyBar::isBusy ( ) const | ||
59 | { | ||
60 | return m_busy; | ||
61 | } | ||
62 | |||
63 | void QBusyBar::beginBusy ( ) | ||
64 | { | ||
65 | setBusy ( true ); | ||
66 | } | ||
67 | |||
68 | void QBusyBar::endBusy ( ) | ||
69 | { | ||
70 | setBusy ( false ); | ||
71 | } | ||
72 | |||
73 | void 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 | |||
93 | void QBusyBar::slotTimeout ( ) | ||
94 | { | ||
95 | m_pos++; | ||
96 | m_pos %= ( 2 * ( m_fade + m_div )); | ||
97 | |||
98 | update ( ); | ||
99 | } | ||
100 | |||
101 | void 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 | |||
6 | class QColor; | ||
7 | class QTimer; | ||
8 | |||
9 | class QBusyBar : public QWidget { | ||
10 | Q_OBJECT | ||
11 | |||
12 | public: | ||
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 | |||
20 | public slots: | ||
21 | void beginBusy ( ); | ||
22 | void endBusy ( ); | ||
23 | |||
24 | void setBusy ( bool b ); | ||
25 | |||
26 | protected: | ||
27 | virtual void paintEvent ( QPaintEvent *e ); | ||
28 | |||
29 | private slots: | ||
30 | void slotTimeout ( ); | ||
31 | |||
32 | private: | ||
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 | |||
41 | int 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 | |||
59 | QPdfDlg::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 | |||
140 | QPdfDlg::~QPdfDlg ( ) | ||
141 | { | ||
142 | delete m_doc; | ||
143 | } | ||
144 | |||
145 | // vv Fullscreen handling (for broken QT-lib) [David Hedbor, www.eongames.com] | ||
146 | |||
147 | void QPdfDlg::resizeEvent ( QResizeEvent * ) | ||
148 | { | ||
149 | if ( m_fullscreen && ( size ( ) != qApp-> desktop ( )-> size ( ))) | ||
150 | setFullscreen ( true ); | ||
151 | } | ||
152 | |||
153 | void QPdfDlg::focusInEvent ( QFocusEvent * ) | ||
154 | { | ||
155 | if ( m_fullscreen ) | ||
156 | setFullscreen ( true ); | ||
157 | } | ||
158 | |||
159 | void 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 | |||
168 | void 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 | |||
192 | void 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 | |||
202 | bool QPdfDlg::busy ( ) const | ||
203 | { | ||
204 | return m_busy; | ||
205 | } | ||
206 | |||
207 | |||
208 | void 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 | |||
220 | void 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 | |||
259 | void 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 | |||
282 | void 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 | |||
297 | void 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 | |||
360 | foundPage: | ||
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 | |||
370 | found: | ||
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 | |||
383 | void QPdfDlg::findText ( ) | ||
384 | { | ||
385 | findText ( m_findedit-> text ( )); | ||
386 | } | ||
387 | |||
388 | void 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 | |||
394 | void QPdfDlg::firstPage ( ) | ||
395 | { | ||
396 | gotoPage ( 1 ); | ||
397 | } | ||
398 | |||
399 | void QPdfDlg::prevPage ( ) | ||
400 | { | ||
401 | gotoPage ( m_currentpage - 1 ); | ||
402 | } | ||
403 | |||
404 | void QPdfDlg::nextPage ( ) | ||
405 | { | ||
406 | gotoPage ( m_currentpage + 1 ); | ||
407 | } | ||
408 | |||
409 | void QPdfDlg::lastPage ( ) | ||
410 | { | ||
411 | gotoPage ( m_pages ); | ||
412 | } | ||
413 | |||
414 | void 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 | |||
428 | void 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 | |||
443 | void QPdfDlg::closeFileSelector ( ) | ||
444 | { | ||
445 | m_tb_menu-> show ( ); | ||
446 | m_tb_tool-> show ( ); | ||
447 | m_stack-> raiseWidget ( m_outdev ); | ||
448 | } | ||
449 | |||
450 | void 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 | |||
458 | void 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 | |||
468 | void 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 | |||
502 | void 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 | |||
512 | void 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 | |||
9 | class QPEOutputDev; | ||
10 | class PDFDoc; | ||
11 | |||
12 | class DocLnk; | ||
13 | class FileSelector; | ||
14 | class QWidgetStack; | ||
15 | class QLineEdit; | ||
16 | |||
17 | |||
18 | class QPdfDlg : public QMainWindow { | ||
19 | Q_OBJECT | ||
20 | |||
21 | public: | ||
22 | QPdfDlg ( ); | ||
23 | virtual ~QPdfDlg ( ); | ||
24 | |||
25 | public 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 | |||
49 | private slots: | ||
50 | void delayedInit ( ); | ||
51 | void closeFileSelector ( ); | ||
52 | |||
53 | void updateCaption ( ); | ||
54 | |||
55 | void copyToClipboard ( const QRect & ); | ||
56 | |||
57 | protected: | ||
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 | |||
68 | private: | ||
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 @@ | |||
1 | TEMPLATE = app | ||
2 | |||
3 | CONFIG *= qt embedded release warn_off | ||
4 | CONFIG -= warn_on | ||
5 | |||
6 | SOURCES = 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 | |||
43 | HEADERS = QOutputDev.h \ | ||
44 | QPEOutputDev.h \ | ||
45 | qbusybar.h \ | ||
46 | qpdf.h | ||
47 | |||
48 | INCLUDEPATH += . \ | ||
49 | .. \ | ||
50 | xpdf \ | ||
51 | $(OPIEDIR)/include \ | ||
52 | ../goo \ | ||
53 | goo | ||
54 | |||
55 | LIBS += -L $(OPIEDIR)/lib -lqpe -lstdc++ | ||
56 | |||
57 | DESTDIR = $(OPIEDIR)/bin | ||
58 | TARGET = qpdf | ||
59 | |||
60 | TRANSLATIONS = ../../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 | |||
23 | Array::Array(XRef *xrefA) { | ||
24 | xref = xrefA; | ||
25 | elems = NULL; | ||
26 | size = length = 0; | ||
27 | ref = 1; | ||
28 | } | ||
29 | |||
30 | Array::~Array() { | ||
31 | int i; | ||
32 | |||
33 | for (i = 0; i < length; ++i) | ||
34 | elems[i].free(); | ||
35 | gfree(elems); | ||
36 | } | ||
37 | |||
38 | void 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 | |||
47 | Object *Array::get(int i, Object *obj) { | ||
48 | return elems[i].fetch(xref, obj); | ||
49 | } | ||
50 | |||
51 | Object *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 | |||
18 | class XRef; | ||
19 | |||
20 | //------------------------------------------------------------------------ | ||
21 | // Array | ||
22 | //------------------------------------------------------------------------ | ||
23 | |||
24 | class Array { | ||
25 | public: | ||
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 | |||
47 | private: | ||
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 | |||
22 | BuiltinFontWidths::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 | |||
37 | BuiltinFontWidths::~BuiltinFontWidths() { | ||
38 | gfree(tab); | ||
39 | } | ||
40 | |||
41 | GBool 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 | |||
55 | int 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 | |||
18 | struct BuiltinFont; | ||
19 | class BuiltinFontWidths; | ||
20 | |||
21 | //------------------------------------------------------------------------ | ||
22 | |||
23 | struct BuiltinFont { | ||
24 | char *name; | ||
25 | char **defaultBaseEnc; | ||
26 | short ascent; | ||
27 | short descent; | ||
28 | short bbox[4]; | ||
29 | BuiltinFontWidths *widths; | ||
30 | }; | ||
31 | |||
32 | //------------------------------------------------------------------------ | ||
33 | |||
34 | struct BuiltinFontWidth { | ||
35 | char *name; | ||
36 | Gushort width; | ||
37 | BuiltinFontWidth *next; | ||
38 | }; | ||
39 | |||
40 | class BuiltinFontWidths { | ||
41 | public: | ||
42 | |||
43 | BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA); | ||
44 | ~BuiltinFontWidths(); | ||
45 | GBool getWidth(char *name, Gushort *width); | ||
46 | |||
47 | private: | ||
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 | |||
14 | static 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 | |||
277 | static 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 | |||
540 | static 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 | |||
803 | static 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 | |||
1066 | static 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 | |||
1297 | static 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 | |||
1528 | static 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 | |||
1759 | static 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 | |||
1990 | static 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 | |||
2182 | static 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 | |||
2413 | static 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 | |||
2644 | static 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 | |||
2875 | static 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 | |||
3106 | static 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 | |||
3311 | BuiltinFont 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 | |||
3328 | BuiltinFont *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 | |||
3343 | void 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 | |||
3360 | void 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 | |||
17 | extern BuiltinFont builtinFonts[nBuiltinFonts]; | ||
18 | extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts]; | ||
19 | |||
20 | extern void initBuiltinFontTables(); | ||
21 | extern 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 | |||
27 | struct CMapVectorEntry { | ||
28 | GBool isVector; | ||
29 | union { | ||
30 | CMapVectorEntry *vector; | ||
31 | CID cid; | ||
32 | }; | ||
33 | }; | ||
34 | |||
35 | //------------------------------------------------------------------------ | ||
36 | |||
37 | CMap *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 | |||
114 | CMap::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 | |||
128 | CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) { | ||
129 | collection = collectionA; | ||
130 | cMapName = cMapNameA; | ||
131 | wMode = wModeA; | ||
132 | vector = NULL; | ||
133 | refCnt = 1; | ||
134 | } | ||
135 | |||
136 | void 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 | |||
150 | void 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 | |||
175 | void 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 | |||
200 | void 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 | |||
228 | CMap::~CMap() { | ||
229 | delete collection; | ||
230 | delete cMapName; | ||
231 | if (vector) { | ||
232 | freeCMapVector(vector); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | void 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 | |||
247 | void CMap::incRefCnt() { | ||
248 | ++refCnt; | ||
249 | } | ||
250 | |||
251 | void CMap::decRefCnt() { | ||
252 | if (--refCnt == 0) { | ||
253 | delete this; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | GBool CMap::match(GString *collectionA, GString *cMapNameA) { | ||
258 | return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA); | ||
259 | } | ||
260 | |||
261 | CID 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 | |||
290 | CMapCache::CMapCache() { | ||
291 | int i; | ||
292 | |||
293 | for (i = 0; i < cMapCacheSize; ++i) { | ||
294 | cache[i] = NULL; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | CMapCache::~CMapCache() { | ||
299 | int i; | ||
300 | |||
301 | for (i = 0; i < cMapCacheSize; ++i) { | ||
302 | if (cache[i]) { | ||
303 | cache[i]->decRefCnt(); | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | |||
308 | CMap *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 | |||
19 | class GString; | ||
20 | struct CMapVectorEntry; | ||
21 | class CMapCache; | ||
22 | |||
23 | //------------------------------------------------------------------------ | ||
24 | |||
25 | class CMap { | ||
26 | public: | ||
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 | |||
53 | private: | ||
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 | |||
76 | class CMapCache { | ||
77 | public: | ||
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 | |||
88 | private: | ||
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 | |||
29 | Catalog::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 | |||
117 | Catalog::~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 | |||
138 | GString *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 | |||
162 | int 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 | |||
233 | int 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 | |||
243 | LinkDest *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 | |||
283 | Object *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 | |||
16 | class XRef; | ||
17 | class Object; | ||
18 | class Page; | ||
19 | class PageAttrs; | ||
20 | struct Ref; | ||
21 | class LinkDest; | ||
22 | |||
23 | //------------------------------------------------------------------------ | ||
24 | // Catalog | ||
25 | //------------------------------------------------------------------------ | ||
26 | |||
27 | class Catalog { | ||
28 | public: | ||
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 | |||
66 | private: | ||
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 | |||
27 | struct CharCodeToUnicodeString { | ||
28 | CharCode c; | ||
29 | Unicode u[maxUnicodeString]; | ||
30 | int len; | ||
31 | }; | ||
32 | |||
33 | //------------------------------------------------------------------------ | ||
34 | |||
35 | CharCodeToUnicode *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 | |||
74 | CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) { | ||
75 | return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0); | ||
76 | } | ||
77 | |||
78 | static 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 | |||
103 | CharCodeToUnicode *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 | |||
114 | void 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 | |||
267 | CharCodeToUnicode::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 | |||
281 | CharCodeToUnicode::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 | |||
298 | CharCodeToUnicode::~CharCodeToUnicode() { | ||
299 | if (collection) { | ||
300 | delete collection; | ||
301 | } | ||
302 | gfree(map); | ||
303 | if (sMap) { | ||
304 | gfree(sMap); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | void CharCodeToUnicode::incRefCnt() { | ||
309 | ++refCnt; | ||
310 | } | ||
311 | |||
312 | void CharCodeToUnicode::decRefCnt() { | ||
313 | if (--refCnt == 0) { | ||
314 | delete this; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | GBool CharCodeToUnicode::match(GString *collectionA) { | ||
319 | return collection && !collection->cmp(collectionA); | ||
320 | } | ||
321 | |||
322 | int 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 | |||
345 | CIDToUnicodeCache::CIDToUnicodeCache() { | ||
346 | int i; | ||
347 | |||
348 | for (i = 0; i < cidToUnicodeCacheSize; ++i) { | ||
349 | cache[i] = NULL; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | CIDToUnicodeCache::~CIDToUnicodeCache() { | ||
354 | int i; | ||
355 | |||
356 | for (i = 0; i < cidToUnicodeCacheSize; ++i) { | ||
357 | if (cache[i]) { | ||
358 | cache[i]->decRefCnt(); | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | |||
363 | CharCodeToUnicode *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 | |||
20 | struct CharCodeToUnicodeString; | ||
21 | |||
22 | //------------------------------------------------------------------------ | ||
23 | |||
24 | class CharCodeToUnicode { | ||
25 | public: | ||
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 | |||
51 | private: | ||
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 | |||
72 | class CIDToUnicodeCache { | ||
73 | public: | ||
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 | |||
84 | private: | ||
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. | ||
13 | typedef unsigned int Unicode; | ||
14 | |||
15 | // Character ID for CID character collections. | ||
16 | typedef 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 | ||
22 | typedef 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 | |||
17 | static void rc4InitKey(Guchar *key, int keyLen, Guchar *state); | ||
18 | static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); | ||
19 | static void md5(Guchar *msg, int msgLen, Guchar *digest); | ||
20 | |||
21 | static 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 | |||
32 | Decrypt::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 | |||
54 | void Decrypt::reset() { | ||
55 | x = y = 0; | ||
56 | rc4InitKey(objKey, objKeyLength, state); | ||
57 | } | ||
58 | |||
59 | Guchar Decrypt::decryptByte(Guchar c) { | ||
60 | return rc4DecryptByte(state, &x, &y, c); | ||
61 | } | ||
62 | |||
63 | GBool 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 | |||
112 | GBool 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 | |||
186 | static 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 | |||
203 | static 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 | ||
220 | static inline Gulong rotateLeft(Gulong x, int r) { | ||
221 | x &= 0xffffffff; | ||
222 | return ((x << r) | (x >> (32 - r))) & 0xffffffff; | ||
223 | } | ||
224 | |||
225 | static 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 | |||
230 | static 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 | |||
235 | static 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 | |||
240 | static 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 | |||
245 | static 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 | |||
23 | class Decrypt { | ||
24 | public: | ||
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 | |||
46 | private: | ||
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 | |||
25 | Dict::Dict(XRef *xrefA) { | ||
26 | xref = xrefA; | ||
27 | entries = NULL; | ||
28 | size = length = 0; | ||
29 | ref = 1; | ||
30 | } | ||
31 | |||
32 | Dict::~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 | |||
42 | void 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 | |||
52 | inline 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 | |||
62 | GBool Dict::is(char *type) { | ||
63 | DictEntry *e; | ||
64 | |||
65 | return (e = find("Type")) && e->val.isName(type); | ||
66 | } | ||
67 | |||
68 | Object *Dict::lookup(char *key, Object *obj) { | ||
69 | DictEntry *e; | ||
70 | |||
71 | return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull(); | ||
72 | } | ||
73 | |||
74 | Object *Dict::lookupNF(char *key, Object *obj) { | ||
75 | DictEntry *e; | ||
76 | |||
77 | return (e = find(key)) ? e->val.copy(obj) : obj->initNull(); | ||
78 | } | ||
79 | |||
80 | char *Dict::getKey(int i) { | ||
81 | return entries[i].key; | ||
82 | } | ||
83 | |||
84 | Object *Dict::getVal(int i, Object *obj) { | ||
85 | return entries[i].val.fetch(xref, obj); | ||
86 | } | ||
87 | |||
88 | Object *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 | |||
22 | struct DictEntry { | ||
23 | char *key; | ||
24 | Object val; | ||
25 | }; | ||
26 | |||
27 | class Dict { | ||
28 | public: | ||
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 | |||
64 | private: | ||
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 | |||
9 | static 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 | |||
20 | void 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 | |||
19 | extern 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 | |||
13 | char *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 | |||
272 | char *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 | |||
531 | char *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 | |||
790 | char *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 | |||
1049 | char *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 | |||
1308 | char *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 | |||
1567 | char *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 | |||
12 | extern char *macRomanEncoding[]; | ||
13 | extern char *macExpertEncoding[]; | ||
14 | extern char *winAnsiEncoding[]; | ||
15 | extern char *standardEncoding[]; | ||
16 | extern char *expertEncoding[]; | ||
17 | extern char *symbolEncoding[]; | ||
18 | extern 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 | |||
6 | typedef 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 | |||
23 | FormWidget::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 | |||
80 | FormWidget::~FormWidget() { | ||
81 | appearance.free(); | ||
82 | } | ||
83 | |||
84 | void 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 | |||
97 | FormWidgets::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 | |||
132 | FormWidgets::~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 | |||
16 | class XRef; | ||
17 | class Gfx; | ||
18 | |||
19 | //------------------------------------------------------------------------ | ||
20 | // FormWidget | ||
21 | //------------------------------------------------------------------------ | ||
22 | |||
23 | class FormWidget { | ||
24 | public: | ||
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 | |||
35 | private: | ||
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 | |||
49 | class FormWidgets { | ||
50 | public: | ||
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 | |||
61 | private: | ||
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 | |||
29 | Function::Function() { | ||
30 | } | ||
31 | |||
32 | Function::~Function() { | ||
33 | } | ||
34 | |||
35 | Function *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 | |||
80 | GBool 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 | |||
156 | IdentityFunction::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 | |||
170 | IdentityFunction::~IdentityFunction() { | ||
171 | } | ||
172 | |||
173 | void 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 | |||
185 | SampledFunction::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 | |||
337 | SampledFunction::~SampledFunction() { | ||
338 | if (samples) { | ||
339 | gfree(samples); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | SampledFunction::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 | |||
356 | void 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 | |||
412 | ExponentialFunction::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 | |||
494 | ExponentialFunction::~ExponentialFunction() { | ||
495 | } | ||
496 | |||
497 | ExponentialFunction::ExponentialFunction(ExponentialFunction *func) { | ||
498 | memcpy(this, func, sizeof(ExponentialFunction)); | ||
499 | } | ||
500 | |||
501 | void 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 | |||
529 | StitchingFunction::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 | |||
615 | StitchingFunction::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 | |||
626 | StitchingFunction::~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 | |||
639 | void 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 | |||
664 | enum 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. | ||
713 | char *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 | |||
758 | enum 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 | |||
788 | struct 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 | |||
801 | class PSStack { | ||
802 | public: | ||
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 | |||
827 | private: | ||
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 | |||
837 | GBool 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 | |||
845 | GBool PSStack::checkUnderflow() { | ||
846 | if (sp == psStackSize) { | ||
847 | error(-1, "Stack underflow in PostScript function"); | ||
848 | return gFalse; | ||
849 | } | ||
850 | return gTrue; | ||
851 | } | ||
852 | |||
853 | GBool 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 | |||
861 | void PSStack::pushBool(GBool booln) { | ||
862 | if (checkOverflow()) { | ||
863 | stack[--sp].type = psBool; | ||
864 | stack[sp].booln = booln; | ||
865 | } | ||
866 | } | ||
867 | |||
868 | void PSStack::pushInt(int intg) { | ||
869 | if (checkOverflow()) { | ||
870 | stack[--sp].type = psInt; | ||
871 | stack[sp].intg = intg; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | void PSStack::pushReal(fouble real) { | ||
876 | if (checkOverflow()) { | ||
877 | stack[--sp].type = psReal; | ||
878 | stack[sp].real = real; | ||
879 | } | ||
880 | } | ||
881 | |||
882 | GBool PSStack::popBool() { | ||
883 | if (checkUnderflow() && checkType(psBool, psBool)) { | ||
884 | return stack[sp++].booln; | ||
885 | } | ||
886 | return gFalse; | ||
887 | } | ||
888 | |||
889 | int PSStack::popInt() { | ||
890 | if (checkUnderflow() && checkType(psInt, psInt)) { | ||
891 | return stack[sp++].intg; | ||
892 | } | ||
893 | return 0; | ||
894 | } | ||
895 | |||
896 | fouble 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 | |||
907 | void 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 | |||
919 | void 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 | |||
943 | void PSStack::index(int i) { | ||
944 | if (!checkOverflow()) { | ||
945 | return; | ||
946 | } | ||
947 | --sp; | ||
948 | stack[sp] = stack[sp + 1 + i]; | ||
949 | } | ||
950 | |||
951 | void PSStack::pop() { | ||
952 | if (!checkUnderflow()) { | ||
953 | return; | ||
954 | } | ||
955 | ++sp; | ||
956 | } | ||
957 | |||
958 | PostScriptFunction::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 | |||
1007 | PostScriptFunction::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 | |||
1013 | PostScriptFunction::~PostScriptFunction() { | ||
1014 | gfree(code); | ||
1015 | } | ||
1016 | |||
1017 | void 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 | |||
1041 | GBool 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 | |||
1161 | GString *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 | |||
1193 | void PostScriptFunction::resizeCode(int newSize) { | ||
1194 | if (newSize >= codeSize) { | ||
1195 | codeSize += 64; | ||
1196 | code = (PSObject *)grealloc(code, codeSize * sizeof(PSObject)); | ||
1197 | } | ||
1198 | } | ||
1199 | |||
1200 | void 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 | |||
19 | class Dict; | ||
20 | class Stream; | ||
21 | struct PSObject; | ||
22 | class PSStack; | ||
23 | |||
24 | //------------------------------------------------------------------------ | ||
25 | // Function | ||
26 | //------------------------------------------------------------------------ | ||
27 | |||
28 | #define funcMaxInputs 8 | ||
29 | #define funcMaxOutputs 8 | ||
30 | |||
31 | class Function { | ||
32 | public: | ||
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 | |||
55 | protected: | ||
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 | |||
69 | class IdentityFunction: public Function { | ||
70 | public: | ||
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 | |||
78 | private: | ||
79 | }; | ||
80 | |||
81 | //------------------------------------------------------------------------ | ||
82 | // SampledFunction | ||
83 | //------------------------------------------------------------------------ | ||
84 | |||
85 | class SampledFunction: public Function { | ||
86 | public: | ||
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 | |||
94 | private: | ||
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 | |||
112 | class ExponentialFunction: public Function { | ||
113 | public: | ||
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 | |||
121 | private: | ||
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 | |||
135 | class StitchingFunction: public Function { | ||
136 | public: | ||
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 | |||
144 | private: | ||
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 | |||
159 | class PostScriptFunction: public Function { | ||
160 | public: | ||
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 | |||
168 | private: | ||
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 | |||
47 | Operator 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 | |||
208 | GfxResources::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 | |||
247 | GfxResources::~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 | |||
258 | GfxFont *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 | |||
272 | GBool 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 | |||
286 | GBool 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 | |||
300 | void 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 | |||
314 | GfxPattern *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 | |||
333 | GfxShading *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 | |||
352 | GBool 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 | |||
371 | Gfx::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 | |||
408 | Gfx::~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 | |||
425 | void 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 | |||
449 | void 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 | |||
527 | void 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 | |||
566 | Operator *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 | |||
587 | GBool 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 | |||
602 | int Gfx::getPos() { | ||
603 | return parser ? parser->getPos() : -1; | ||
604 | } | ||
605 | |||
606 | //------------------------------------------------------------------------ | ||
607 | // graphics state operators | ||
608 | //------------------------------------------------------------------------ | ||
609 | |||
610 | void Gfx::opSave(Object args[], int numArgs) { | ||
611 | out->saveState(state); | ||
612 | state = state->save(); | ||
613 | } | ||
614 | |||
615 | void Gfx::opRestore(Object args[], int numArgs) { | ||
616 | state = state->restore(); | ||
617 | out->restoreState(state); | ||
618 | } | ||
619 | |||
620 | void 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 | |||
630 | void 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 | |||
652 | void Gfx::opSetFlat(Object args[], int numArgs) { | ||
653 | state->setFlatness((int)args[0].getNum()); | ||
654 | out->updateFlatness(state); | ||
655 | } | ||
656 | |||
657 | void Gfx::opSetLineJoin(Object args[], int numArgs) { | ||
658 | state->setLineJoin(args[0].getInt()); | ||
659 | out->updateLineJoin(state); | ||
660 | } | ||
661 | |||
662 | void Gfx::opSetLineCap(Object args[], int numArgs) { | ||
663 | state->setLineCap(args[0].getInt()); | ||
664 | out->updateLineCap(state); | ||
665 | } | ||
666 | |||
667 | void Gfx::opSetMiterLimit(Object args[], int numArgs) { | ||
668 | state->setMiterLimit(args[0].getNum()); | ||
669 | out->updateMiterLimit(state); | ||
670 | } | ||
671 | |||
672 | void Gfx::opSetLineWidth(Object args[], int numArgs) { | ||
673 | state->setLineWidth(args[0].getNum()); | ||
674 | out->updateLineWidth(state); | ||
675 | } | ||
676 | |||
677 | void 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 | |||
701 | void Gfx::opSetRenderingIntent(Object args[], int numArgs) { | ||
702 | } | ||
703 | |||
704 | //------------------------------------------------------------------------ | ||
705 | // color operators | ||
706 | //------------------------------------------------------------------------ | ||
707 | |||
708 | void 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 | |||
718 | void 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 | |||
728 | void 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 | |||
741 | void 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 | |||
754 | void 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 | |||
767 | void 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 | |||
780 | void 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 | |||
806 | void 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 | |||
832 | void 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 | |||
844 | void 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 | |||
856 | void 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 | |||
888 | void 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 | |||
924 | void Gfx::opMoveTo(Object args[], int numArgs) { | ||
925 | state->moveTo(args[0].getNum(), args[1].getNum()); | ||
926 | } | ||
927 | |||
928 | void 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 | |||
936 | void 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 | |||
952 | void 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 | |||
968 | void 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 | |||
984 | void 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 | |||
998 | void 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 | |||
1010 | void Gfx::opEndPath(Object args[], int numArgs) { | ||
1011 | doEndPath(); | ||
1012 | } | ||
1013 | |||
1014 | void 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 | |||
1024 | void 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 | |||
1036 | void 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 | |||
1051 | void 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 | |||
1066 | void 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 | |||
1082 | void 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 | |||
1099 | void 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 | |||
1115 | void 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 | |||
1132 | void 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 | |||
1301 | void 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 | |||
1343 | void 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 | |||
1622 | void 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 | |||
1639 | void Gfx::opClip(Object args[], int numArgs) { | ||
1640 | clip = clipNormal; | ||
1641 | } | ||
1642 | |||
1643 | void Gfx::opEOClip(Object args[], int numArgs) { | ||
1644 | clip = clipEO; | ||
1645 | } | ||
1646 | |||
1647 | //------------------------------------------------------------------------ | ||
1648 | // text object operators | ||
1649 | //------------------------------------------------------------------------ | ||
1650 | |||
1651 | void 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 | |||
1659 | void Gfx::opEndText(Object args[], int numArgs) { | ||
1660 | } | ||
1661 | |||
1662 | //------------------------------------------------------------------------ | ||
1663 | // text state operators | ||
1664 | //------------------------------------------------------------------------ | ||
1665 | |||
1666 | void Gfx::opSetCharSpacing(Object args[], int numArgs) { | ||
1667 | state->setCharSpace(args[0].getNum()); | ||
1668 | out->updateCharSpace(state); | ||
1669 | } | ||
1670 | |||
1671 | void 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 | |||
1688 | void Gfx::opSetTextLeading(Object args[], int numArgs) { | ||
1689 | state->setLeading(args[0].getNum()); | ||
1690 | } | ||
1691 | |||
1692 | void Gfx::opSetTextRender(Object args[], int numArgs) { | ||
1693 | state->setRender(args[0].getInt()); | ||
1694 | out->updateRender(state); | ||
1695 | } | ||
1696 | |||
1697 | void Gfx::opSetTextRise(Object args[], int numArgs) { | ||
1698 | state->setRise(args[0].getNum()); | ||
1699 | out->updateRise(state); | ||
1700 | } | ||
1701 | |||
1702 | void Gfx::opSetWordSpacing(Object args[], int numArgs) { | ||
1703 | state->setWordSpace(args[0].getNum()); | ||
1704 | out->updateWordSpace(state); | ||
1705 | } | ||
1706 | |||
1707 | void 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 | |||
1717 | void 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 | |||
1726 | void 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 | |||
1737 | void 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 | |||
1747 | void 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 | |||
1760 | void 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 | |||
1768 | void 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 | |||
1782 | void 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 | |||
1800 | void 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 | |||
1824 | void 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 | |||
1969 | void 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 | |||
2011 | void 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 | |||
2159 | void 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 | |||
2218 | void 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 | |||
2281 | void 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 | |||
2346 | void 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 | |||
2368 | Stream *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 | |||
2403 | void Gfx::opImageData(Object args[], int numArgs) { | ||
2404 | error(getPos(), "Internal: got 'ID' operator"); | ||
2405 | } | ||
2406 | |||
2407 | void Gfx::opEndImage(Object args[], int numArgs) { | ||
2408 | error(getPos(), "Internal: got 'EI' operator"); | ||
2409 | } | ||
2410 | |||
2411 | //------------------------------------------------------------------------ | ||
2412 | // type 3 font operators | ||
2413 | //------------------------------------------------------------------------ | ||
2414 | |||
2415 | void Gfx::opSetCharWidth(Object args[], int numArgs) { | ||
2416 | error(getPos(), "Encountered 'd0' operator in content stream"); | ||
2417 | } | ||
2418 | |||
2419 | void Gfx::opSetCacheDevice(Object args[], int numArgs) { | ||
2420 | error(getPos(), "Encountered 'd1' operator in content stream"); | ||
2421 | } | ||
2422 | |||
2423 | //------------------------------------------------------------------------ | ||
2424 | // compatibility operators | ||
2425 | //------------------------------------------------------------------------ | ||
2426 | |||
2427 | void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) { | ||
2428 | ++ignoreUndef; | ||
2429 | } | ||
2430 | |||
2431 | void Gfx::opEndIgnoreUndef(Object args[], int numArgs) { | ||
2432 | if (ignoreUndef > 0) | ||
2433 | --ignoreUndef; | ||
2434 | } | ||
2435 | |||
2436 | //------------------------------------------------------------------------ | ||
2437 | // marked content operators | ||
2438 | //------------------------------------------------------------------------ | ||
2439 | |||
2440 | void 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 | |||
2450 | void Gfx::opEndMarkedContent(Object args[], int numArgs) { | ||
2451 | } | ||
2452 | |||
2453 | void 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 | |||
18 | class GString; | ||
19 | class XRef; | ||
20 | class Array; | ||
21 | class Stream; | ||
22 | class Parser; | ||
23 | class Dict; | ||
24 | class OutputDev; | ||
25 | class GfxFontDict; | ||
26 | class GfxFont; | ||
27 | class GfxPattern; | ||
28 | class GfxShading; | ||
29 | class GfxAxialShading; | ||
30 | class GfxState; | ||
31 | class Gfx; | ||
32 | struct PDFRectangle; | ||
33 | |||
34 | //------------------------------------------------------------------------ | ||
35 | // Gfx | ||
36 | //------------------------------------------------------------------------ | ||
37 | |||
38 | enum GfxClipType { | ||
39 | clipNone, | ||
40 | clipNormal, | ||
41 | clipEO | ||
42 | }; | ||
43 | |||
44 | enum 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 | |||
58 | struct Operator { | ||
59 | char name[4]; | ||
60 | int numArgs; | ||
61 | TchkType tchk[maxArgs]; | ||
62 | void (Gfx::*func)(Object args[], int numArgs); | ||
63 | }; | ||
64 | |||
65 | class GfxResources { | ||
66 | public: | ||
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 | |||
81 | private: | ||
82 | |||
83 | GfxFontDict *fonts; | ||
84 | Object xObjDict; | ||
85 | Object colorSpaceDict; | ||
86 | Object patternDict; | ||
87 | Object shadingDict; | ||
88 | Object gStateDict; | ||
89 | GfxResources *next; | ||
90 | }; | ||
91 | |||
92 | class Gfx { | ||
93 | public: | ||
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 | |||
109 | private: | ||
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 | |||
32 | struct StdFontMapEntry { | ||
33 | char *altName; | ||
34 | char *properName; | ||
35 | }; | ||
36 | |||
37 | static 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 | |||
89 | GfxFont *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 | |||
125 | GfxFont::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 | |||
134 | GfxFont::~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 | |||
147 | void 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 | |||
276 | CharCodeToUnicode *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 | |||
298 | void 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 | |||
308 | char *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 | |||
327 | char *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 | |||
368 | Gfx8BitFont::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 | |||
743 | Gfx8BitFont::~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 | |||
757 | int 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 | |||
769 | CharCodeToUnicode *Gfx8BitFont::getToUnicode() { | ||
770 | ctu->incRefCnt(); | ||
771 | return ctu; | ||
772 | } | ||
773 | |||
774 | Object *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 | |||
787 | static int cmpWidthExcep(const void *w1, const void *w2) { | ||
788 | return ((GfxFontCIDWidthExcep *)w1)->first - | ||
789 | ((GfxFontCIDWidthExcep *)w2)->first; | ||
790 | } | ||
791 | |||
792 | static int cmpWidthExcepV(const void *w1, const void *w2) { | ||
793 | return ((GfxFontCIDWidthExcepV *)w1)->first - | ||
794 | ((GfxFontCIDWidthExcepV *)w2)->first; | ||
795 | } | ||
796 | |||
797 | GfxCIDFont::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 | |||
1099 | GfxCIDFont::~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 | |||
1113 | int 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 | |||
1189 | CharCodeToUnicode *GfxCIDFont::getToUnicode() { | ||
1190 | ctu->incRefCnt(); | ||
1191 | return ctu; | ||
1192 | } | ||
1193 | |||
1194 | GString *GfxCIDFont::getCollection() { | ||
1195 | return cMap ? cMap->getCollection() : (GString *)NULL; | ||
1196 | } | ||
1197 | |||
1198 | //------------------------------------------------------------------------ | ||
1199 | // GfxFontDict | ||
1200 | //------------------------------------------------------------------------ | ||
1201 | |||
1202 | GfxFontDict::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 | |||
1227 | GfxFontDict::~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 | |||
1238 | GfxFont *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 | |||
21 | class Dict; | ||
22 | class CMap; | ||
23 | class CharCodeToUnicode; | ||
24 | struct GfxFontCIDWidths; | ||
25 | |||
26 | //------------------------------------------------------------------------ | ||
27 | // GfxFontType | ||
28 | //------------------------------------------------------------------------ | ||
29 | |||
30 | enum 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 | |||
47 | struct GfxFontCIDWidthExcep { | ||
48 | CID first; // this record applies to | ||
49 | CID last; // CIDs <first>..<last> | ||
50 | fouble width; // char width | ||
51 | }; | ||
52 | |||
53 | struct 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 | |||
60 | struct 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 | |||
81 | class GfxFont { | ||
82 | public: | ||
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 | |||
154 | protected: | ||
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 | |||
180 | class Gfx8BitFont: public GfxFont { | ||
181 | public: | ||
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 | |||
210 | private: | ||
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 | |||
225 | class GfxCIDFont: public GfxFont { | ||
226 | public: | ||
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 | |||
250 | private: | ||
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 | |||
264 | class GfxFontDict { | ||
265 | public: | ||
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 | |||
280 | private: | ||
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 | |||
26 | static inline fouble clip01(fouble x) { | ||
27 | return (x < 0) ? fouble(0) : ((x > 1) ? fouble(1) : x); | ||
28 | } | ||
29 | |||
30 | //------------------------------------------------------------------------ | ||
31 | // GfxColorSpace | ||
32 | //------------------------------------------------------------------------ | ||
33 | |||
34 | GfxColorSpace::GfxColorSpace() { | ||
35 | } | ||
36 | |||
37 | GfxColorSpace::~GfxColorSpace() { | ||
38 | } | ||
39 | |||
40 | GfxColorSpace *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 | |||
91 | void 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 | |||
105 | GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() { | ||
106 | } | ||
107 | |||
108 | GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { | ||
109 | } | ||
110 | |||
111 | GfxColorSpace *GfxDeviceGrayColorSpace::copy() { | ||
112 | return new GfxDeviceGrayColorSpace(); | ||
113 | } | ||
114 | |||
115 | void GfxDeviceGrayColorSpace::getGray(GfxColor *color, fouble *gray) { | ||
116 | *gray = clip01(color->c[0]); | ||
117 | } | ||
118 | |||
119 | void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | ||
120 | rgb->r = rgb->g = rgb->b = clip01(color->c[0]); | ||
121 | } | ||
122 | |||
123 | void 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 | |||
132 | GfxCalGrayColorSpace::GfxCalGrayColorSpace() { | ||
133 | whiteX = whiteY = whiteZ = 1; | ||
134 | blackX = blackY = blackZ = 0; | ||
135 | gamma = 1; | ||
136 | } | ||
137 | |||
138 | GfxCalGrayColorSpace::~GfxCalGrayColorSpace() { | ||
139 | } | ||
140 | |||
141 | GfxColorSpace *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 | |||
155 | GfxColorSpace *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 | |||
200 | void GfxCalGrayColorSpace::getGray(GfxColor *color, fouble *gray) { | ||
201 | *gray = clip01(color->c[0]); | ||
202 | } | ||
203 | |||
204 | void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | ||
205 | rgb->r = rgb->g = rgb->b = clip01(color->c[0]); | ||
206 | } | ||
207 | |||
208 | void 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 | |||
217 | GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() { | ||
218 | } | ||
219 | |||
220 | GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { | ||
221 | } | ||
222 | |||
223 | GfxColorSpace *GfxDeviceRGBColorSpace::copy() { | ||
224 | return new GfxDeviceRGBColorSpace(); | ||
225 | } | ||
226 | |||
227 | void 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 | |||
233 | void 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 | |||
239 | void 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 | |||
262 | GfxCalRGBColorSpace::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 | |||
271 | GfxCalRGBColorSpace::~GfxCalRGBColorSpace() { | ||
272 | } | ||
273 | |||
274 | GfxColorSpace *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 | |||
294 | GfxColorSpace *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 | |||
358 | void 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 | |||
364 | void 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 | |||
370 | void 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 | |||
393 | GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() { | ||
394 | } | ||
395 | |||
396 | GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { | ||
397 | } | ||
398 | |||
399 | GfxColorSpace *GfxDeviceCMYKColorSpace::copy() { | ||
400 | return new GfxDeviceCMYKColorSpace(); | ||
401 | } | ||
402 | |||
403 | void 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 | |||
410 | void 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 | |||
416 | void 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. | ||
429 | static 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 | |||
435 | GfxLabColorSpace::GfxLabColorSpace() { | ||
436 | whiteX = whiteY = whiteZ = 1; | ||
437 | blackX = blackY = blackZ = 0; | ||
438 | aMin = bMin = -100; | ||
439 | aMax = bMax = 100; | ||
440 | } | ||
441 | |||
442 | GfxLabColorSpace::~GfxLabColorSpace() { | ||
443 | } | ||
444 | |||
445 | GfxColorSpace *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 | |||
465 | GfxColorSpace *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 | |||
533 | void 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 | |||
542 | void 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 | |||
579 | void 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 | |||
600 | void 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 | |||
614 | GfxICCBasedColorSpace::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 | |||
623 | GfxICCBasedColorSpace::~GfxICCBasedColorSpace() { | ||
624 | delete alt; | ||
625 | } | ||
626 | |||
627 | GfxColorSpace *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 | |||
639 | GfxColorSpace *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 | |||
708 | void GfxICCBasedColorSpace::getGray(GfxColor *color, fouble *gray) { | ||
709 | alt->getGray(color, gray); | ||
710 | } | ||
711 | |||
712 | void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | ||
713 | alt->getRGB(color, rgb); | ||
714 | } | ||
715 | |||
716 | void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { | ||
717 | alt->getCMYK(color, cmyk); | ||
718 | } | ||
719 | |||
720 | void 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 | |||
735 | GfxIndexedColorSpace::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 | |||
743 | GfxIndexedColorSpace::~GfxIndexedColorSpace() { | ||
744 | delete base; | ||
745 | gfree(lookup); | ||
746 | } | ||
747 | |||
748 | GfxColorSpace *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 | |||
757 | GfxColorSpace *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 | |||
823 | void 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 | |||
836 | void 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 | |||
849 | void 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 | |||
862 | void 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 | |||
873 | GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA, | ||
874 | GfxColorSpace *altA, | ||
875 | Function *funcA) { | ||
876 | name = nameA; | ||
877 | alt = altA; | ||
878 | func = funcA; | ||
879 | } | ||
880 | |||
881 | GfxSeparationColorSpace::~GfxSeparationColorSpace() { | ||
882 | delete name; | ||
883 | delete alt; | ||
884 | delete func; | ||
885 | } | ||
886 | |||
887 | GfxColorSpace *GfxSeparationColorSpace::copy() { | ||
888 | return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy()); | ||
889 | } | ||
890 | |||
891 | //~ handle the 'All' and 'None' colorants | ||
892 | GfxColorSpace *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 | |||
933 | void GfxSeparationColorSpace::getGray(GfxColor *color, fouble *gray) { | ||
934 | GfxColor color2; | ||
935 | |||
936 | func->transform(color->c, color2.c); | ||
937 | alt->getGray(&color2, gray); | ||
938 | } | ||
939 | |||
940 | void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | ||
941 | GfxColor color2; | ||
942 | |||
943 | func->transform(color->c, color2.c); | ||
944 | alt->getRGB(&color2, rgb); | ||
945 | } | ||
946 | |||
947 | void 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 | |||
958 | GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, | ||
959 | GfxColorSpace *altA, | ||
960 | Function *funcA) { | ||
961 | nComps = nCompsA; | ||
962 | alt = altA; | ||
963 | func = funcA; | ||
964 | } | ||
965 | |||
966 | GfxDeviceNColorSpace::~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 | |||
976 | GfxColorSpace *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 | ||
988 | GfxColorSpace *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 | |||
1045 | void GfxDeviceNColorSpace::getGray(GfxColor *color, fouble *gray) { | ||
1046 | GfxColor color2; | ||
1047 | |||
1048 | func->transform(color->c, color2.c); | ||
1049 | alt->getGray(&color2, gray); | ||
1050 | } | ||
1051 | |||
1052 | void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | ||
1053 | GfxColor color2; | ||
1054 | |||
1055 | func->transform(color->c, color2.c); | ||
1056 | alt->getRGB(&color2, rgb); | ||
1057 | } | ||
1058 | |||
1059 | void 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 | |||
1070 | GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) { | ||
1071 | under = underA; | ||
1072 | } | ||
1073 | |||
1074 | GfxPatternColorSpace::~GfxPatternColorSpace() { | ||
1075 | if (under) { | ||
1076 | delete under; | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | GfxColorSpace *GfxPatternColorSpace::copy() { | ||
1081 | return new GfxPatternColorSpace(under ? under->copy() : | ||
1082 | (GfxColorSpace *)NULL); | ||
1083 | } | ||
1084 | |||
1085 | GfxColorSpace *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 | |||
1108 | void GfxPatternColorSpace::getGray(GfxColor *color, fouble *gray) { | ||
1109 | *gray = 0; | ||
1110 | } | ||
1111 | |||
1112 | void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | ||
1113 | rgb->r = rgb->g = rgb->b = 0; | ||
1114 | } | ||
1115 | |||
1116 | void 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 | |||
1125 | GfxPattern::GfxPattern(int typeA) { | ||
1126 | type = typeA; | ||
1127 | } | ||
1128 | |||
1129 | GfxPattern::~GfxPattern() { | ||
1130 | } | ||
1131 | |||
1132 | GfxPattern *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 | |||
1153 | GfxTilingPattern::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 | |||
1222 | GfxTilingPattern::~GfxTilingPattern() { | ||
1223 | resDict.free(); | ||
1224 | contentStream.free(); | ||
1225 | } | ||
1226 | |||
1227 | GfxPattern *GfxTilingPattern::copy() { | ||
1228 | return new GfxTilingPattern(this); | ||
1229 | } | ||
1230 | |||
1231 | GfxTilingPattern::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 | |||
1243 | GfxShading::GfxShading() { | ||
1244 | } | ||
1245 | |||
1246 | GfxShading::~GfxShading() { | ||
1247 | delete colorSpace; | ||
1248 | } | ||
1249 | |||
1250 | GfxShading *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 | |||
1347 | GfxAxialShading::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 | |||
1368 | GfxAxialShading::~GfxAxialShading() { | ||
1369 | int i; | ||
1370 | |||
1371 | for (i = 0; i < nFuncs; ++i) { | ||
1372 | delete funcs[i]; | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | GfxAxialShading *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 | |||
1451 | void 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 | |||
1463 | GfxImageColorMap::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 | |||
1565 | GfxImageColorMap::~GfxImageColorMap() { | ||
1566 | delete colorSpace; | ||
1567 | gfree(lookup); | ||
1568 | } | ||
1569 | |||
1570 | void 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 | |||
1589 | void 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 | |||
1608 | void 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 | |||
1631 | GfxSubpath::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 | |||
1643 | GfxSubpath::~GfxSubpath() { | ||
1644 | gfree(x); | ||
1645 | gfree(y); | ||
1646 | gfree(curve); | ||
1647 | } | ||
1648 | |||
1649 | // Used for copy(). | ||
1650 | GfxSubpath::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 | |||
1662 | void 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 | |||
1675 | void 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 | |||
1694 | void 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 | |||
1701 | GfxPath::GfxPath() { | ||
1702 | justMoved = gFalse; | ||
1703 | size = 16; | ||
1704 | n = 0; | ||
1705 | firstX = firstY = 0; | ||
1706 | subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *)); | ||
1707 | } | ||
1708 | |||
1709 | GfxPath::~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(). | ||
1718 | GfxPath::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 | |||
1732 | void GfxPath::moveTo(fouble x, fouble y) { | ||
1733 | justMoved = gTrue; | ||
1734 | firstX = x; | ||
1735 | firstY = y; | ||
1736 | } | ||
1737 | |||
1738 | void 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 | |||
1752 | void 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 | |||
1767 | void 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 | |||
1787 | GfxState::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 | |||
1876 | GfxState::~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(); | ||
1900 | GfxState::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 | |||
1921 | fouble 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 | |||
1929 | fouble 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 | |||
1939 | void 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 | |||
1947 | void 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 | |||
1957 | void 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 | |||
1972 | void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { | ||
1973 | if (fillColorSpace) { | ||
1974 | delete fillColorSpace; | ||
1975 | } | ||
1976 | fillColorSpace = colorSpace; | ||
1977 | } | ||
1978 | |||
1979 | void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) { | ||
1980 | if (strokeColorSpace) { | ||
1981 | delete strokeColorSpace; | ||
1982 | } | ||
1983 | strokeColorSpace = colorSpace; | ||
1984 | } | ||
1985 | |||
1986 | void GfxState::setFillPattern(GfxPattern *pattern) { | ||
1987 | if (fillPattern) { | ||
1988 | delete fillPattern; | ||
1989 | } | ||
1990 | fillPattern = pattern; | ||
1991 | } | ||
1992 | |||
1993 | void GfxState::setStrokePattern(GfxPattern *pattern) { | ||
1994 | if (strokePattern) { | ||
1995 | delete strokePattern; | ||
1996 | } | ||
1997 | strokePattern = pattern; | ||
1998 | } | ||
1999 | |||
2000 | void 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 | |||
2008 | void GfxState::clearPath() { | ||
2009 | delete path; | ||
2010 | path = new GfxPath(); | ||
2011 | } | ||
2012 | |||
2013 | void 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 | |||
2054 | void GfxState::textShift(fouble tx) { | ||
2055 | fouble dx, dy; | ||
2056 | |||
2057 | textTransformDelta(tx, 0, &dx, &dy); | ||
2058 | curX += dx; | ||
2059 | curY += dy; | ||
2060 | } | ||
2061 | |||
2062 | void GfxState::shift(fouble dx, fouble dy) { | ||
2063 | curX += dx; | ||
2064 | curY += dy; | ||
2065 | } | ||
2066 | |||
2067 | GfxState *GfxState::save() { | ||
2068 | GfxState *newState; | ||
2069 | |||
2070 | newState = copy(); | ||
2071 | newState->saved = this; | ||
2072 | return newState; | ||
2073 | } | ||
2074 | |||
2075 | GfxState *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 | |||
20 | class Array; | ||
21 | class GfxFont; | ||
22 | struct PDFRectangle; | ||
23 | |||
24 | //------------------------------------------------------------------------ | ||
25 | // GfxColor | ||
26 | //------------------------------------------------------------------------ | ||
27 | |||
28 | #define gfxColorMaxComps funcMaxOutputs | ||
29 | |||
30 | struct GfxColor { | ||
31 | fouble c[gfxColorMaxComps]; | ||
32 | }; | ||
33 | |||
34 | //------------------------------------------------------------------------ | ||
35 | // GfxRGB | ||
36 | //------------------------------------------------------------------------ | ||
37 | |||
38 | struct GfxRGB { | ||
39 | fouble r, g, b; | ||
40 | }; | ||
41 | |||
42 | //------------------------------------------------------------------------ | ||
43 | // GfxCMYK | ||
44 | //------------------------------------------------------------------------ | ||
45 | |||
46 | struct GfxCMYK { | ||
47 | fouble c, m, y, k; | ||
48 | }; | ||
49 | |||
50 | //------------------------------------------------------------------------ | ||
51 | // GfxColorSpace | ||
52 | //------------------------------------------------------------------------ | ||
53 | |||
54 | enum 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 | |||
68 | class GfxColorSpace { | ||
69 | public: | ||
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 | |||
92 | private: | ||
93 | }; | ||
94 | |||
95 | //------------------------------------------------------------------------ | ||
96 | // GfxDeviceGrayColorSpace | ||
97 | //------------------------------------------------------------------------ | ||
98 | |||
99 | class GfxDeviceGrayColorSpace: public GfxColorSpace { | ||
100 | public: | ||
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 | |||
113 | private: | ||
114 | }; | ||
115 | |||
116 | //------------------------------------------------------------------------ | ||
117 | // GfxCalGrayColorSpace | ||
118 | //------------------------------------------------------------------------ | ||
119 | |||
120 | class GfxCalGrayColorSpace: public GfxColorSpace { | ||
121 | public: | ||
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 | |||
146 | private: | ||
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 | |||
157 | class GfxDeviceRGBColorSpace: public GfxColorSpace { | ||
158 | public: | ||
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 | |||
171 | private: | ||
172 | }; | ||
173 | |||
174 | //------------------------------------------------------------------------ | ||
175 | // GfxCalRGBColorSpace | ||
176 | //------------------------------------------------------------------------ | ||
177 | |||
178 | class GfxCalRGBColorSpace: public GfxColorSpace { | ||
179 | public: | ||
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 | |||
207 | private: | ||
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 | |||
219 | class GfxDeviceCMYKColorSpace: public GfxColorSpace { | ||
220 | public: | ||
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 | |||
233 | private: | ||
234 | }; | ||
235 | |||
236 | //------------------------------------------------------------------------ | ||
237 | // GfxLabColorSpace | ||
238 | //------------------------------------------------------------------------ | ||
239 | |||
240 | class GfxLabColorSpace: public GfxColorSpace { | ||
241 | public: | ||
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 | |||
272 | private: | ||
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 | |||
284 | class GfxICCBasedColorSpace: public GfxColorSpace { | ||
285 | public: | ||
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 | |||
308 | private: | ||
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 | |||
321 | class GfxIndexedColorSpace: public GfxColorSpace { | ||
322 | public: | ||
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 | |||
346 | private: | ||
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 | |||
357 | class GfxSeparationColorSpace: public GfxColorSpace { | ||
358 | public: | ||
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 | |||
380 | private: | ||
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 | |||
391 | class GfxDeviceNColorSpace: public GfxColorSpace { | ||
392 | public: | ||
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 | |||
411 | private: | ||
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 | |||
425 | class GfxPatternColorSpace: public GfxColorSpace { | ||
426 | public: | ||
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 | |||
445 | private: | ||
446 | |||
447 | GfxColorSpace *under; // underlying color space (for uncolored | ||
448 | // patterns) | ||
449 | }; | ||
450 | |||
451 | //------------------------------------------------------------------------ | ||
452 | // GfxPattern | ||
453 | //------------------------------------------------------------------------ | ||
454 | |||
455 | class GfxPattern { | ||
456 | public: | ||
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 | |||
467 | private: | ||
468 | |||
469 | int type; | ||
470 | }; | ||
471 | |||
472 | //------------------------------------------------------------------------ | ||
473 | // GfxTilingPattern | ||
474 | //------------------------------------------------------------------------ | ||
475 | |||
476 | class GfxTilingPattern: public GfxPattern { | ||
477 | public: | ||
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 | |||
494 | private: | ||
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 | |||
511 | class GfxShading { | ||
512 | public: | ||
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 | |||
527 | private: | ||
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 | |||
541 | class GfxAxialShading: public GfxShading { | ||
542 | public: | ||
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 | |||
561 | private: | ||
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 | |||
574 | class GfxImageColorMap { | ||
575 | public: | ||
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 | |||
602 | private: | ||
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 | |||
621 | class GfxSubpath { | ||
622 | public: | ||
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 | |||
654 | private: | ||
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 | |||
666 | class GfxPath { | ||
667 | public: | ||
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 | |||
706 | private: | ||
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 | |||
722 | class GfxState { | ||
723 | public: | ||
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 | |||
876 | private: | ||
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 | |||
40 | GlobalParams *globalParams = NULL; | ||
41 | |||
42 | //------------------------------------------------------------------------ | ||
43 | // DisplayFontParam | ||
44 | //------------------------------------------------------------------------ | ||
45 | |||
46 | DisplayFontParam::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 | |||
64 | DisplayFontParam::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 | |||
71 | DisplayFontParam::~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 | |||
99 | PSFontParam::PSFontParam(GString *pdfFontNameA, GString *psFontNameA) { | ||
100 | pdfFontName = pdfFontNameA; | ||
101 | psFontName = psFontNameA; | ||
102 | } | ||
103 | |||
104 | PSFontParam::~PSFontParam() { | ||
105 | delete pdfFontName; | ||
106 | delete psFontName; | ||
107 | } | ||
108 | |||
109 | //------------------------------------------------------------------------ | ||
110 | // parsing | ||
111 | //------------------------------------------------------------------------ | ||
112 | |||
113 | GlobalParams::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 | |||
332 | void 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 | |||
367 | void 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 | |||
384 | void 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 | |||
401 | void 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 | |||
419 | void 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 | |||
429 | void 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 | |||
481 | void 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 | |||
502 | void 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 | |||
525 | void 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 | |||
537 | void 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 | |||
550 | void 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 | |||
561 | void 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 | |||
582 | void 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 | |||
591 | void 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 | |||
604 | void 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 | |||
621 | void 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 | |||
641 | GlobalParams::~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 | |||
682 | CharCode GlobalParams::getMacRomanCharCode(char *charName) { | ||
683 | return macRomanReverseMap->lookup(charName); | ||
684 | } | ||
685 | |||
686 | Unicode GlobalParams::mapNameToUnicode(char *charName) { | ||
687 | return nameToUnicode->lookup(charName); | ||
688 | } | ||
689 | |||
690 | FILE *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 | |||
699 | UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) { | ||
700 | return (UnicodeMap *)residentUnicodeMaps->lookup(encodingName); | ||
701 | } | ||
702 | |||
703 | FILE *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 | |||
712 | FILE *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 | |||
734 | FILE *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 | |||
751 | DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) { | ||
752 | return (DisplayFontParam *)displayFonts->lookup(fontName); | ||
753 | } | ||
754 | |||
755 | DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *collection) { | ||
756 | return (DisplayFontParam *)displayCIDFonts->lookup(collection); | ||
757 | } | ||
758 | |||
759 | PSFontParam *GlobalParams::getPSFont(GString *fontName) { | ||
760 | return (PSFontParam *)psFonts->lookup(fontName); | ||
761 | } | ||
762 | |||
763 | GString *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 | |||
793 | CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) { | ||
794 | return cidToUnicodeCache->getCIDToUnicode(collection); | ||
795 | } | ||
796 | |||
797 | UnicodeMap *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 | |||
807 | CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) { | ||
808 | return cMapCache->getCMap(collection, cMapName); | ||
809 | } | ||
810 | |||
811 | UnicodeMap *GlobalParams::getTextEncoding() { | ||
812 | return getUnicodeMap(textEncoding); | ||
813 | } | ||
814 | |||
815 | //------------------------------------------------------------------------ | ||
816 | // functions to set parameters | ||
817 | //------------------------------------------------------------------------ | ||
818 | |||
819 | void GlobalParams::setPSFile(char *file) { | ||
820 | if (psFile) { | ||
821 | delete psFile; | ||
822 | } | ||
823 | psFile = new GString(file); | ||
824 | } | ||
825 | |||
826 | GBool 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 | |||
845 | void GlobalParams::setPSPaperWidth(int width) { | ||
846 | psPaperWidth = width; | ||
847 | } | ||
848 | |||
849 | void GlobalParams::setPSPaperHeight(int height) { | ||
850 | psPaperHeight = height; | ||
851 | } | ||
852 | |||
853 | void GlobalParams::setPSDuplex(GBool duplex) { | ||
854 | psDuplex = duplex; | ||
855 | } | ||
856 | |||
857 | void GlobalParams::setPSLevel(PSLevel level) { | ||
858 | psLevel = level; | ||
859 | } | ||
860 | |||
861 | void GlobalParams::setPSEmbedType1(GBool embed) { | ||
862 | psEmbedType1 = embed; | ||
863 | } | ||
864 | |||
865 | void GlobalParams::setPSEmbedTrueType(GBool embed) { | ||
866 | psEmbedTrueType = embed; | ||
867 | } | ||
868 | |||
869 | void GlobalParams::setPSOPI(GBool opi) { | ||
870 | psOPI = opi; | ||
871 | } | ||
872 | |||
873 | void GlobalParams::setTextEncoding(char *encodingName) { | ||
874 | delete textEncoding; | ||
875 | textEncoding = new GString(encodingName); | ||
876 | } | ||
877 | |||
878 | GBool 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 | |||
891 | GBool GlobalParams::setT1libControl(char *s) { | ||
892 | return setFontRastControl(&t1libControl, s); | ||
893 | } | ||
894 | |||
895 | GBool GlobalParams::setFreeTypeControl(char *s) { | ||
896 | return setFontRastControl(&freetypeControl, s); | ||
897 | } | ||
898 | |||
899 | GBool 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 | |||
914 | void 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 | |||
20 | class GString; | ||
21 | class GList; | ||
22 | class GHash; | ||
23 | class NameToCharCode; | ||
24 | class CharCodeToUnicode; | ||
25 | class CIDToUnicodeCache; | ||
26 | class UnicodeMap; | ||
27 | class UnicodeMapCache; | ||
28 | class CMap; | ||
29 | class CMapCache; | ||
30 | class GlobalParams; | ||
31 | |||
32 | //------------------------------------------------------------------------ | ||
33 | |||
34 | // The global parameters object. | ||
35 | extern GlobalParams *globalParams; | ||
36 | |||
37 | //------------------------------------------------------------------------ | ||
38 | |||
39 | enum DisplayFontParamKind { | ||
40 | displayFontX, | ||
41 | displayFontT1, | ||
42 | displayFontTT | ||
43 | }; | ||
44 | |||
45 | class DisplayFontParam { | ||
46 | public: | ||
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. | ||
70 | enum 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 | |||
79 | class PSFontParam { | ||
80 | public: | ||
81 | |||
82 | GString *pdfFontName; | ||
83 | GString *psFontName; | ||
84 | |||
85 | PSFontParam(GString *pdfFontNameA, GString *psFontNameA); | ||
86 | ~PSFontParam(); | ||
87 | }; | ||
88 | |||
89 | //------------------------------------------------------------------------ | ||
90 | |||
91 | enum PSLevel { | ||
92 | psLevel1, | ||
93 | psLevel1Sep, | ||
94 | psLevel2, | ||
95 | psLevel2Sep | ||
96 | }; | ||
97 | |||
98 | //------------------------------------------------------------------------ | ||
99 | |||
100 | enum EndOfLineKind { | ||
101 | eolUnix, // LF | ||
102 | eolDOS, // CR+LF | ||
103 | eolMac // CR | ||
104 | }; | ||
105 | |||
106 | //------------------------------------------------------------------------ | ||
107 | |||
108 | class GlobalParams { | ||
109 | public: | ||
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 | |||
169 | private: | ||
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. | ||
25 | static 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 | |||
48 | Lexer::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 | |||
59 | Lexer::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 | |||
77 | Lexer::~Lexer() { | ||
78 | if (!curStr.isNone()) { | ||
79 | curStr.streamClose(); | ||
80 | curStr.free(); | ||
81 | } | ||
82 | if (freeArray) { | ||
83 | delete streams; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | int 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 | |||
103 | int Lexer::lookChar() { | ||
104 | if (curStr.isNone()) { | ||
105 | return EOF; | ||
106 | } | ||
107 | return curStr.streamLookChar(); | ||
108 | } | ||
109 | |||
110 | Object *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 | |||
458 | void 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 | |||
19 | class XRef; | ||
20 | |||
21 | #define tokBufSize 128 // size of token buffer | ||
22 | |||
23 | //------------------------------------------------------------------------ | ||
24 | // Lexer | ||
25 | //------------------------------------------------------------------------ | ||
26 | |||
27 | class Lexer { | ||
28 | public: | ||
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 | |||
62 | private: | ||
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 | |||
26 | static GString *getFileSpecName(Object *fileSpecObj); | ||
27 | |||
28 | //------------------------------------------------------------------------ | ||
29 | // LinkDest | ||
30 | //------------------------------------------------------------------------ | ||
31 | |||
32 | LinkDest::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 | |||
190 | LinkDest::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 | |||
212 | LinkGoTo::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 | |||
236 | LinkGoTo::~LinkGoTo() { | ||
237 | if (dest) | ||
238 | delete dest; | ||
239 | if (namedDest) | ||
240 | delete namedDest; | ||
241 | } | ||
242 | |||
243 | //------------------------------------------------------------------------ | ||
244 | // LinkGoToR | ||
245 | //------------------------------------------------------------------------ | ||
246 | |||
247 | LinkGoToR::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 | |||
274 | LinkGoToR::~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 | |||
288 | LinkLaunch::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 | |||
316 | LinkLaunch::~LinkLaunch() { | ||
317 | if (fileName) | ||
318 | delete fileName; | ||
319 | if (params) | ||
320 | delete params; | ||
321 | } | ||
322 | |||
323 | //------------------------------------------------------------------------ | ||
324 | // LinkURI | ||
325 | //------------------------------------------------------------------------ | ||
326 | |||
327 | LinkURI::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 | |||
362 | LinkURI::~LinkURI() { | ||
363 | if (uri) | ||
364 | delete uri; | ||
365 | } | ||
366 | |||
367 | //------------------------------------------------------------------------ | ||
368 | // LinkNamed | ||
369 | //------------------------------------------------------------------------ | ||
370 | |||
371 | LinkNamed::LinkNamed(Object *nameObj) { | ||
372 | name = NULL; | ||
373 | if (nameObj->isName()) { | ||
374 | name = new GString(nameObj->getName()); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | LinkNamed::~LinkNamed() { | ||
379 | if (name) { | ||
380 | delete name; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | //------------------------------------------------------------------------ | ||
385 | // LinkUnknown | ||
386 | //------------------------------------------------------------------------ | ||
387 | |||
388 | LinkUnknown::LinkUnknown(char *actionA) { | ||
389 | action = new GString(actionA); | ||
390 | } | ||
391 | |||
392 | LinkUnknown::~LinkUnknown() { | ||
393 | delete action; | ||
394 | } | ||
395 | |||
396 | //------------------------------------------------------------------------ | ||
397 | // Link | ||
398 | //------------------------------------------------------------------------ | ||
399 | |||
400 | Link::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 | |||
533 | Link::~Link() { | ||
534 | if (action) | ||
535 | delete action; | ||
536 | } | ||
537 | |||
538 | //------------------------------------------------------------------------ | ||
539 | // Links | ||
540 | //------------------------------------------------------------------------ | ||
541 | |||
542 | Links::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 | |||
574 | Links::~Links() { | ||
575 | int i; | ||
576 | |||
577 | for (i = 0; i < numLinks; ++i) | ||
578 | delete links[i]; | ||
579 | gfree(links); | ||
580 | } | ||
581 | |||
582 | LinkAction *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 | |||
593 | GBool 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). | ||
606 | static 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 | |||
18 | class GString; | ||
19 | class Array; | ||
20 | class Dict; | ||
21 | |||
22 | //------------------------------------------------------------------------ | ||
23 | // LinkAction | ||
24 | //------------------------------------------------------------------------ | ||
25 | |||
26 | enum 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 | |||
35 | class LinkAction { | ||
36 | public: | ||
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 | |||
52 | enum LinkDestKind { | ||
53 | destXYZ, | ||
54 | destFit, | ||
55 | destFitH, | ||
56 | destFitV, | ||
57 | destFitR, | ||
58 | destFitB, | ||
59 | destFitBH, | ||
60 | destFitBV | ||
61 | }; | ||
62 | |||
63 | class LinkDest { | ||
64 | public: | ||
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 | |||
91 | private: | ||
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 | |||
113 | class LinkGoTo: public LinkAction { | ||
114 | public: | ||
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 | |||
130 | private: | ||
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 | |||
142 | class LinkGoToR: public LinkAction { | ||
143 | public: | ||
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 | |||
161 | private: | ||
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 | |||
174 | class LinkLaunch: public LinkAction { | ||
175 | public: | ||
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 | |||
191 | private: | ||
192 | |||
193 | GString *fileName; // file name | ||
194 | GString *params; // parameters | ||
195 | }; | ||
196 | |||
197 | //------------------------------------------------------------------------ | ||
198 | // LinkURI | ||
199 | //------------------------------------------------------------------------ | ||
200 | |||
201 | class LinkURI: public LinkAction { | ||
202 | public: | ||
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 | |||
217 | private: | ||
218 | |||
219 | GString *uri; // the URI | ||
220 | }; | ||
221 | |||
222 | //------------------------------------------------------------------------ | ||
223 | // LinkNamed | ||
224 | //------------------------------------------------------------------------ | ||
225 | |||
226 | class LinkNamed: public LinkAction { | ||
227 | public: | ||
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 | |||
239 | private: | ||
240 | |||
241 | GString *name; | ||
242 | }; | ||
243 | |||
244 | //------------------------------------------------------------------------ | ||
245 | // LinkUnknown | ||
246 | //------------------------------------------------------------------------ | ||
247 | |||
248 | class LinkUnknown: public LinkAction { | ||
249 | public: | ||
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 | |||
264 | private: | ||
265 | |||
266 | GString *action; // action subtype | ||
267 | }; | ||
268 | |||
269 | //------------------------------------------------------------------------ | ||
270 | // Link | ||
271 | //------------------------------------------------------------------------ | ||
272 | |||
273 | class Link { | ||
274 | public: | ||
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 | |||
297 | private: | ||
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 | |||
310 | class Links { | ||
311 | public: | ||
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 | |||
330 | private: | ||
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 | |||
20 | struct NameToCharCodeEntry { | ||
21 | char *name; | ||
22 | CharCode c; | ||
23 | }; | ||
24 | |||
25 | //------------------------------------------------------------------------ | ||
26 | |||
27 | NameToCharCode::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 | |||
38 | NameToCharCode::~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 | |||
49 | void 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 | |||
91 | CharCode 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 | |||
106 | int 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 | |||
18 | struct NameToCharCodeEntry; | ||
19 | |||
20 | //------------------------------------------------------------------------ | ||
21 | |||
22 | class NameToCharCode { | ||
23 | public: | ||
24 | |||
25 | NameToCharCode(); | ||
26 | ~NameToCharCode(); | ||
27 | |||
28 | void add(char *name, CharCode c); | ||
29 | CharCode lookup(char *name); | ||
30 | |||
31 | private: | ||
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 | |||
9 | static 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 | |||
26 | char *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 | ||
44 | int Object::numAlloc[numObjTypes] = | ||
45 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
46 | #endif | ||
47 | |||
48 | Object *Object::initArray(XRef *xref) { | ||
49 | initObj(objArray); | ||
50 | array = new Array(xref); | ||
51 | return this; | ||
52 | } | ||
53 | |||
54 | Object *Object::initDict(XRef *xref) { | ||
55 | initObj(objDict); | ||
56 | dict = new Dict(xref); | ||
57 | return this; | ||
58 | } | ||
59 | |||
60 | Object *Object::initStream(Stream *streamA) { | ||
61 | initObj(objStream); | ||
62 | stream = streamA; | ||
63 | return this; | ||
64 | } | ||
65 | |||
66 | Object *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 | |||
96 | Object *Object::fetch(XRef *xref, Object *obj) { | ||
97 | return (type == objRef && xref) ? | ||
98 | xref->fetch(ref.num, ref.gen, obj) : copy(obj); | ||
99 | } | ||
100 | |||
101 | void 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 | |||
136 | char *Object::getTypeName() { | ||
137 | return objTypeNames[type]; | ||
138 | } | ||
139 | |||
140 | void 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 | |||
207 | void 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 | |||
22 | class XRef; | ||
23 | class Array; | ||
24 | class Dict; | ||
25 | class Stream; | ||
26 | |||
27 | //------------------------------------------------------------------------ | ||
28 | // Ref | ||
29 | //------------------------------------------------------------------------ | ||
30 | |||
31 | struct Ref { | ||
32 | int num; // object number | ||
33 | int gen; // generation number | ||
34 | }; | ||
35 | |||
36 | //------------------------------------------------------------------------ | ||
37 | // object types | ||
38 | //------------------------------------------------------------------------ | ||
39 | |||
40 | enum 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 | |||
74 | class Object { | ||
75 | public: | ||
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 | |||
190 | private: | ||
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 | |||
218 | inline int Object::arrayGetLength() | ||
219 | { return array->getLength(); } | ||
220 | |||
221 | inline void Object::arrayAdd(Object *elem) | ||
222 | { array->add(elem); } | ||
223 | |||
224 | inline Object *Object::arrayGet(int i, Object *obj) | ||
225 | { return array->get(i, obj); } | ||
226 | |||
227 | inline 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 | |||
236 | inline int Object::dictGetLength() | ||
237 | { return dict->getLength(); } | ||
238 | |||
239 | inline void Object::dictAdd(char *key, Object *val) | ||
240 | { dict->add(key, val); } | ||
241 | |||
242 | inline GBool Object::dictIs(char *dictType) | ||
243 | { return dict->is(dictType); } | ||
244 | |||
245 | inline GBool Object::isDict(char *dictType) | ||
246 | { return type == objDict && dictIs(dictType); } | ||
247 | |||
248 | inline Object *Object::dictLookup(char *key, Object *obj) | ||
249 | { return dict->lookup(key, obj); } | ||
250 | |||
251 | inline Object *Object::dictLookupNF(char *key, Object *obj) | ||
252 | { return dict->lookupNF(key, obj); } | ||
253 | |||
254 | inline char *Object::dictGetKey(int i) | ||
255 | { return dict->getKey(i); } | ||
256 | |||
257 | inline Object *Object::dictGetVal(int i, Object *obj) | ||
258 | { return dict->getVal(i, obj); } | ||
259 | |||
260 | inline 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 | |||
269 | inline GBool Object::streamIs(char *dictType) | ||
270 | { return stream->getDict()->is(dictType); } | ||
271 | |||
272 | inline GBool Object::isStream(char *dictType) | ||
273 | { return type == objStream && streamIs(dictType); } | ||
274 | |||
275 | inline void Object::streamReset() | ||
276 | { stream->reset(); } | ||
277 | |||
278 | inline void Object::streamClose() | ||
279 | { stream->close(); } | ||
280 | |||
281 | inline int Object::streamGetChar() | ||
282 | { return stream->getChar(); } | ||
283 | |||
284 | inline int Object::streamLookChar() | ||
285 | { return stream->lookChar(); } | ||
286 | |||
287 | inline char *Object::streamGetLine(char *buf, int size) | ||
288 | { return stream->getLine(buf, size); } | ||
289 | |||
290 | inline int Object::streamGetPos() | ||
291 | { return stream->getPos(); } | ||
292 | |||
293 | inline void Object::streamSetPos(int pos) | ||
294 | { stream->setPos(pos); } | ||
295 | |||
296 | inline 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 | |||
24 | void 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 | |||
40 | void 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 | |||
45 | void 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 | |||
50 | void 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 | |||
62 | void 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 | |||
76 | void 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 | ||
92 | void OutputDev::opiBegin(GfxState *state, Dict *opiDict) { | ||
93 | } | ||
94 | |||
95 | void 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 | |||
19 | class GString; | ||
20 | class GfxState; | ||
21 | class GfxColorSpace; | ||
22 | class GfxImageColorMap; | ||
23 | class Stream; | ||
24 | class Link; | ||
25 | class Catalog; | ||
26 | |||
27 | //------------------------------------------------------------------------ | ||
28 | // OutputDev | ||
29 | //------------------------------------------------------------------------ | ||
30 | |||
31 | class OutputDev { | ||
32 | public: | ||
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 | |||
137 | private: | ||
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 | |||
40 | PDFDoc::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 | |||
85 | PDFDoc::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 | |||
98 | GBool 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 | |||
120 | PDFDoc::~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. | ||
143 | void 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 | |||
172 | void 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 | |||
191 | void 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 | |||
200 | GBool 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 | |||
229 | GBool 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 | |||
246 | void 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 | |||
22 | class GString; | ||
23 | class BaseStream; | ||
24 | class OutputDev; | ||
25 | class Links; | ||
26 | class LinkAction; | ||
27 | class LinkDest; | ||
28 | |||
29 | //------------------------------------------------------------------------ | ||
30 | // PDFDoc | ||
31 | //------------------------------------------------------------------------ | ||
32 | |||
33 | class PDFDoc { | ||
34 | public: | ||
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 | |||
124 | private: | ||
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 | |||
32 | PageAttrs::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 | |||
105 | PageAttrs::~PageAttrs() { | ||
106 | resources.free(); | ||
107 | } | ||
108 | |||
109 | GBool 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 | |||
159 | Page::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 | |||
198 | Page::~Page() { | ||
199 | delete attrs; | ||
200 | annots.free(); | ||
201 | contents.free(); | ||
202 | } | ||
203 | |||
204 | void 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 | |||
18 | class Dict; | ||
19 | class XRef; | ||
20 | class OutputDev; | ||
21 | class Links; | ||
22 | class Catalog; | ||
23 | |||
24 | //------------------------------------------------------------------------ | ||
25 | |||
26 | struct PDFRectangle { | ||
27 | fouble x1, y1, x2, y2; | ||
28 | }; | ||
29 | |||
30 | //------------------------------------------------------------------------ | ||
31 | // PageAttrs | ||
32 | //------------------------------------------------------------------------ | ||
33 | |||
34 | class PageAttrs { | ||
35 | public: | ||
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 | |||
57 | private: | ||
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 | |||
76 | class Page { | ||
77 | public: | ||
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 | |||
114 | private: | ||
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 | |||
25 | Parser::Parser(XRef *xrefA, Lexer *lexerA) { | ||
26 | xref = xrefA; | ||
27 | lexer = lexerA; | ||
28 | inlineImg = 0; | ||
29 | lexer->getObj(&buf1); | ||
30 | lexer->getObj(&buf2); | ||
31 | } | ||
32 | |||
33 | Parser::~Parser() { | ||
34 | buf1.free(); | ||
35 | buf2.free(); | ||
36 | delete lexer; | ||
37 | } | ||
38 | |||
39 | #ifndef NO_DECRYPTION | ||
40 | Object *Parser::getObj(Object *obj, | ||
41 | Guchar *fileKey, int keyLength, | ||
42 | int objNum, int objGen) { | ||
43 | #else | ||
44 | Object *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 | |||
155 | Stream *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 | |||
200 | void 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 | |||
22 | class Parser { | ||
23 | public: | ||
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 | |||
46 | private: | ||
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 | |||
11 | struct 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 | ||
33 | static 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) | ||
106 | static 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 | ||
129 | static 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) | ||
298 | static 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) | ||
360 | static 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 | ||
440 | static 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__ | ||
34 | static GBool setDJSYSFLAGS = gFalse; | ||
35 | #endif | ||
36 | |||
37 | #ifdef VMS | ||
38 | #if (__VMS_VER < 70000000) | ||
39 | extern "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 | |||
56 | Stream::Stream() { | ||
57 | ref = 1; | ||
58 | } | ||
59 | |||
60 | Stream::~Stream() { | ||
61 | } | ||
62 | |||
63 | void Stream::close() { | ||
64 | } | ||
65 | |||
66 | int Stream::getRawChar() { | ||
67 | error(-1, "Internal: called getRawChar() on non-predictor stream"); | ||
68 | return EOF; | ||
69 | } | ||
70 | |||
71 | char *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 | |||
92 | GString *Stream::getPSFilter(char *indent) { | ||
93 | return new GString(); | ||
94 | } | ||
95 | |||
96 | Stream *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", ¶ms); | ||
109 | if (params.isNull()) { | ||
110 | params.free(); | ||
111 | dict->dictLookup("DP", ¶ms); | ||
112 | } | ||
113 | if (obj.isName()) { | ||
114 | str = makeFilter(obj.getName(), str, ¶ms); | ||
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, ¶ms2); | ||
120 | else | ||
121 | params2.initNull(); | ||
122 | if (obj2.isName()) { | ||
123 | str = makeFilter(obj2.getName(), str, ¶ms2); | ||
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 | |||
140 | Stream *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 | |||
269 | BaseStream::BaseStream(Object *dictA) { | ||
270 | dict = *dictA; | ||
271 | #ifndef NO_DECRYPTION | ||
272 | decrypt = NULL; | ||
273 | #endif | ||
274 | } | ||
275 | |||
276 | BaseStream::~BaseStream() { | ||
277 | dict.free(); | ||
278 | #ifndef NO_DECRYPTION | ||
279 | if (decrypt) | ||
280 | delete decrypt; | ||
281 | #endif | ||
282 | } | ||
283 | |||
284 | #ifndef NO_DECRYPTION | ||
285 | void 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 | |||
295 | FilterStream::FilterStream(Stream *strA) { | ||
296 | str = strA; | ||
297 | } | ||
298 | |||
299 | FilterStream::~FilterStream() { | ||
300 | } | ||
301 | |||
302 | void FilterStream::close() { | ||
303 | str->close(); | ||
304 | } | ||
305 | |||
306 | void FilterStream::setPos(int pos) { | ||
307 | error(-1, "Internal: called setPos() on FilterStream"); | ||
308 | } | ||
309 | |||
310 | //------------------------------------------------------------------------ | ||
311 | // ImageStream | ||
312 | //------------------------------------------------------------------------ | ||
313 | |||
314 | ImageStream::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 | |||
332 | ImageStream::~ImageStream() { | ||
333 | gfree(imgLine); | ||
334 | } | ||
335 | |||
336 | void ImageStream::reset() { | ||
337 | str->reset(); | ||
338 | } | ||
339 | |||
340 | GBool 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 | |||
388 | void 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 | |||
401 | StreamPredictor::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 | |||
417 | StreamPredictor::~StreamPredictor() { | ||
418 | gfree(predLine); | ||
419 | } | ||
420 | |||
421 | int StreamPredictor::lookChar() { | ||
422 | if (predIdx >= rowBytes) { | ||
423 | if (!getNextLine()) { | ||
424 | return EOF; | ||
425 | } | ||
426 | } | ||
427 | return predLine[predIdx]; | ||
428 | } | ||
429 | |||
430 | int StreamPredictor::getChar() { | ||
431 | if (predIdx >= rowBytes) { | ||
432 | if (!getNextLine()) { | ||
433 | return EOF; | ||
434 | } | ||
435 | } | ||
436 | return predLine[predIdx++]; | ||
437 | } | ||
438 | |||
439 | GBool 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 | |||
557 | FileStream::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 | |||
567 | FileStream::~FileStream() { | ||
568 | close(); | ||
569 | } | ||
570 | |||
571 | Stream *FileStream::makeSubStream(int startA, int lengthA, Object *dictA) { | ||
572 | return new FileStream(f, startA, lengthA, dictA); | ||
573 | } | ||
574 | |||
575 | void 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 | |||
586 | void FileStream::close() { | ||
587 | if (savePos >= 0) { | ||
588 | fseek(f, savePos, SEEK_SET); | ||
589 | savePos = -1; | ||
590 | } | ||
591 | } | ||
592 | |||
593 | GBool 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 | |||
624 | void 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 | |||
645 | void FileStream::moveStart(int delta) { | ||
646 | start += delta; | ||
647 | bufPtr = bufEnd = buf; | ||
648 | bufPos = start; | ||
649 | } | ||
650 | |||
651 | //------------------------------------------------------------------------ | ||
652 | // EmbedStream | ||
653 | //------------------------------------------------------------------------ | ||
654 | |||
655 | EmbedStream::EmbedStream(Stream *strA, Object *dictA): | ||
656 | BaseStream(dictA) { | ||
657 | str = strA; | ||
658 | } | ||
659 | |||
660 | EmbedStream::~EmbedStream() { | ||
661 | } | ||
662 | |||
663 | Stream *EmbedStream::makeSubStream(int start, int length, Object *dictA) { | ||
664 | error(-1, "Internal: called makeSubStream() on EmbedStream"); | ||
665 | return NULL; | ||
666 | } | ||
667 | |||
668 | void EmbedStream::setPos(int pos) { | ||
669 | error(-1, "Internal: called setPos() on EmbedStream"); | ||
670 | } | ||
671 | |||
672 | int EmbedStream::getStart() { | ||
673 | error(-1, "Internal: called getStart() on EmbedStream"); | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | void EmbedStream::moveStart(int start) { | ||
678 | error(-1, "Internal: called moveStart() on EmbedStream"); | ||
679 | } | ||
680 | |||
681 | //------------------------------------------------------------------------ | ||
682 | // ASCIIHexStream | ||
683 | //------------------------------------------------------------------------ | ||
684 | |||
685 | ASCIIHexStream::ASCIIHexStream(Stream *strA): | ||
686 | FilterStream(strA) { | ||
687 | buf = EOF; | ||
688 | eof = gFalse; | ||
689 | } | ||
690 | |||
691 | ASCIIHexStream::~ASCIIHexStream() { | ||
692 | delete str; | ||
693 | } | ||
694 | |||
695 | void ASCIIHexStream::reset() { | ||
696 | str->reset(); | ||
697 | buf = EOF; | ||
698 | eof = gFalse; | ||
699 | } | ||
700 | |||
701 | int 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 | |||
754 | GString *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 | |||
764 | GBool ASCIIHexStream::isBinary(GBool last) { | ||
765 | return str->isBinary(gFalse); | ||
766 | } | ||
767 | |||
768 | //------------------------------------------------------------------------ | ||
769 | // ASCII85Stream | ||
770 | //------------------------------------------------------------------------ | ||
771 | |||
772 | ASCII85Stream::ASCII85Stream(Stream *strA): | ||
773 | FilterStream(strA) { | ||
774 | index = n = 0; | ||
775 | eof = gFalse; | ||
776 | } | ||
777 | |||
778 | ASCII85Stream::~ASCII85Stream() { | ||
779 | delete str; | ||
780 | } | ||
781 | |||
782 | void ASCII85Stream::reset() { | ||
783 | str->reset(); | ||
784 | index = n = 0; | ||
785 | eof = gFalse; | ||
786 | } | ||
787 | |||
788 | int 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 | |||
832 | GString *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 | |||
842 | GBool ASCII85Stream::isBinary(GBool last) { | ||
843 | return str->isBinary(gFalse); | ||
844 | } | ||
845 | |||
846 | //------------------------------------------------------------------------ | ||
847 | // LZWStream | ||
848 | //------------------------------------------------------------------------ | ||
849 | |||
850 | LZWStream::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 | |||
863 | LZWStream::~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 | |||
880 | int LZWStream::getChar() { | ||
881 | if (pred) { | ||
882 | return pred->getChar(); | ||
883 | } | ||
884 | return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); | ||
885 | } | ||
886 | |||
887 | int LZWStream::lookChar() { | ||
888 | if (pred) { | ||
889 | return pred->lookChar(); | ||
890 | } | ||
891 | return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); | ||
892 | } | ||
893 | |||
894 | int LZWStream::getRawChar() { | ||
895 | return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); | ||
896 | } | ||
897 | |||
898 | void 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 | |||
988 | void 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 | |||
1111 | int 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 | |||
1126 | GBool 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 | |||
1146 | GString *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 | |||
1159 | GBool LZWStream::isBinary(GBool last) { | ||
1160 | return str->isBinary(gTrue); | ||
1161 | } | ||
1162 | |||
1163 | //------------------------------------------------------------------------ | ||
1164 | // RunLengthStream | ||
1165 | //------------------------------------------------------------------------ | ||
1166 | |||
1167 | RunLengthStream::RunLengthStream(Stream *strA): | ||
1168 | FilterStream(strA) { | ||
1169 | bufPtr = bufEnd = buf; | ||
1170 | eof = gFalse; | ||
1171 | } | ||
1172 | |||
1173 | RunLengthStream::~RunLengthStream() { | ||
1174 | delete str; | ||
1175 | } | ||
1176 | |||
1177 | void RunLengthStream::reset() { | ||
1178 | str->reset(); | ||
1179 | bufPtr = bufEnd = buf; | ||
1180 | eof = gFalse; | ||
1181 | } | ||
1182 | |||
1183 | GString *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 | |||
1193 | GBool RunLengthStream::isBinary(GBool last) { | ||
1194 | return str->isBinary(gTrue); | ||
1195 | } | ||
1196 | |||
1197 | GBool 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 | |||
1227 | CCITTFaxStream::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 | |||
1252 | CCITTFaxStream::~CCITTFaxStream() { | ||
1253 | delete str; | ||
1254 | gfree(refLine); | ||
1255 | gfree(codingLine); | ||
1256 | } | ||
1257 | |||
1258 | void 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 | |||
1288 | int 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 | |||
1572 | short 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 | |||
1602 | short 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 | |||
1650 | short 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 | |||
1713 | short 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 | |||
1733 | GString *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 | |||
1767 | GBool 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 | ||
1807 | static Guchar dctClip[768]; | ||
1808 | static int dctClipInit = 0; | ||
1809 | |||
1810 | // zig zag decode map | ||
1811 | static 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 | |||
1829 | DCTStream::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 | |||
1853 | DCTStream::~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 | |||
1862 | void DCTStream::reset() { | ||
1863 | str->reset(); | ||
1864 | if (!readHeader()) { | ||
1865 | y = height; | ||
1866 | return; | ||
1867 | } | ||
1868 | restartMarker = 0xd0; | ||
1869 | restart(); | ||
1870 | } | ||
1871 | |||
1872 | int 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 | |||
1891 | int 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 | |||
1906 | void 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 | |||
1915 | GBool 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 | ||
2040 | GBool 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 | ||
2198 | GBool 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 | |||
2355 | int 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 | |||
2380 | int 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 | |||
2395 | int 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 | |||
2419 | GBool 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 | |||
2527 | GBool 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 | |||
2556 | GBool 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 | |||
2589 | GBool 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 | |||
2610 | GBool 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 | |||
2655 | GBool 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 | |||
2667 | GBool 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 | |||
2691 | GBool 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 | |||
2702 | int 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 | |||
2716 | int 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 | |||
2726 | GString *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 | |||
2736 | GBool DCTStream::isBinary(GBool last) { | ||
2737 | return str->isBinary(gTrue); | ||
2738 | } | ||
2739 | |||
2740 | //------------------------------------------------------------------------ | ||
2741 | // FlateStream | ||
2742 | //------------------------------------------------------------------------ | ||
2743 | |||
2744 | int 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 | |||
2748 | FlateDecode 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 | |||
2780 | FlateDecode 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 | |||
2813 | FlateStream::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 | |||
2823 | FlateStream::~FlateStream() { | ||
2824 | if (pred) { | ||
2825 | delete pred; | ||
2826 | } | ||
2827 | delete str; | ||
2828 | } | ||
2829 | |||
2830 | void 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 | |||
2866 | int 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 | |||
2883 | int 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 | |||
2898 | int 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 | |||
2912 | GString *FlateStream::getPSFilter(char *indent) { | ||
2913 | return NULL; | ||
2914 | } | ||
2915 | |||
2916 | GBool FlateStream::isBinary(GBool last) { | ||
2917 | return str->isBinary(gTrue); | ||
2918 | } | ||
2919 | |||
2920 | void 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 | |||
2979 | err: | ||
2980 | error(getPos(), "Unexpected end of file in flate stream"); | ||
2981 | endOfBlock = eof = gTrue; | ||
2982 | remain = 0; | ||
2983 | } | ||
2984 | |||
2985 | GBool 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 | |||
3035 | err: | ||
3036 | error(getPos(), "Bad block header in flate stream"); | ||
3037 | endOfBlock = eof = gTrue; | ||
3038 | return gFalse; | ||
3039 | } | ||
3040 | |||
3041 | void 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 | |||
3073 | GBool 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 | |||
3144 | err: | ||
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. | ||
3154 | void 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 | |||
3192 | int 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 | |||
3226 | int 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 | |||
3245 | EOFStream::EOFStream(Stream *strA): | ||
3246 | FilterStream(strA) { | ||
3247 | } | ||
3248 | |||
3249 | EOFStream::~EOFStream() { | ||
3250 | delete str; | ||
3251 | } | ||
3252 | |||
3253 | //------------------------------------------------------------------------ | ||
3254 | // FixedLengthEncoder | ||
3255 | //------------------------------------------------------------------------ | ||
3256 | |||
3257 | FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA): | ||
3258 | FilterStream(strA) { | ||
3259 | length = lengthA; | ||
3260 | count = 0; | ||
3261 | } | ||
3262 | |||
3263 | FixedLengthEncoder::~FixedLengthEncoder() { | ||
3264 | if (str->isEncoder()) | ||
3265 | delete str; | ||
3266 | } | ||
3267 | |||
3268 | void FixedLengthEncoder::reset() { | ||
3269 | str->reset(); | ||
3270 | count = 0; | ||
3271 | } | ||
3272 | |||
3273 | void FixedLengthEncoder::close() { | ||
3274 | } | ||
3275 | |||
3276 | int FixedLengthEncoder::getChar() { | ||
3277 | if (length >= 0 && count >= length) | ||
3278 | return EOF; | ||
3279 | ++count; | ||
3280 | return str->getChar(); | ||
3281 | } | ||
3282 | |||
3283 | int FixedLengthEncoder::lookChar() { | ||
3284 | if (length >= 0 && count >= length) | ||
3285 | return EOF; | ||
3286 | return str->getChar(); | ||
3287 | } | ||
3288 | |||
3289 | //------------------------------------------------------------------------ | ||
3290 | // ASCII85Encoder | ||
3291 | //------------------------------------------------------------------------ | ||
3292 | |||
3293 | ASCII85Encoder::ASCII85Encoder(Stream *strA): | ||
3294 | FilterStream(strA) { | ||
3295 | bufPtr = bufEnd = buf; | ||
3296 | lineLen = 0; | ||
3297 | eof = gFalse; | ||
3298 | } | ||
3299 | |||
3300 | ASCII85Encoder::~ASCII85Encoder() { | ||
3301 | if (str->isEncoder()) | ||
3302 | delete str; | ||
3303 | } | ||
3304 | |||
3305 | void ASCII85Encoder::reset() { | ||
3306 | str->reset(); | ||
3307 | bufPtr = bufEnd = buf; | ||
3308 | lineLen = 0; | ||
3309 | eof = gFalse; | ||
3310 | } | ||
3311 | |||
3312 | void ASCII85Encoder::close() { | ||
3313 | } | ||
3314 | |||
3315 | GBool 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 | |||
3365 | RunLengthEncoder::RunLengthEncoder(Stream *strA): | ||
3366 | FilterStream(strA) { | ||
3367 | bufPtr = bufEnd = nextEnd = buf; | ||
3368 | eof = gFalse; | ||
3369 | } | ||
3370 | |||
3371 | RunLengthEncoder::~RunLengthEncoder() { | ||
3372 | if (str->isEncoder()) | ||
3373 | delete str; | ||
3374 | } | ||
3375 | |||
3376 | void RunLengthEncoder::reset() { | ||
3377 | str->reset(); | ||
3378 | bufPtr = bufEnd = nextEnd = buf; | ||
3379 | eof = gFalse; | ||
3380 | } | ||
3381 | |||
3382 | void 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 | // | ||
3393 | GBool 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 | ||
21 | class Decrypt; | ||
22 | #endif | ||
23 | class BaseStream; | ||
24 | |||
25 | //------------------------------------------------------------------------ | ||
26 | |||
27 | enum 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 | |||
43 | class Stream { | ||
44 | public: | ||
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 | |||
103 | private: | ||
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 | |||
116 | class BaseStream: public Stream { | ||
117 | public: | ||
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 | ||
136 | protected: | ||
137 | |||
138 | Decrypt *decrypt; | ||
139 | #endif | ||
140 | |||
141 | private: | ||
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 | |||
152 | class FilterStream: public Stream { | ||
153 | public: | ||
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 | |||
163 | protected: | ||
164 | |||
165 | Stream *str; | ||
166 | }; | ||
167 | |||
168 | //------------------------------------------------------------------------ | ||
169 | // ImageStream | ||
170 | //------------------------------------------------------------------------ | ||
171 | |||
172 | class ImageStream { | ||
173 | public: | ||
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 | |||
192 | private: | ||
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 | |||
207 | class StreamPredictor { | ||
208 | public: | ||
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 | |||
220 | private: | ||
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 | |||
242 | class FileStream: public BaseStream { | ||
243 | public: | ||
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 | |||
261 | private: | ||
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 | |||
285 | class EmbedStream: public BaseStream { | ||
286 | public: | ||
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 | |||
301 | private: | ||
302 | |||
303 | Stream *str; | ||
304 | }; | ||
305 | |||
306 | //------------------------------------------------------------------------ | ||
307 | // ASCIIHexStream | ||
308 | //------------------------------------------------------------------------ | ||
309 | |||
310 | class ASCIIHexStream: public FilterStream { | ||
311 | public: | ||
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 | |||
323 | private: | ||
324 | |||
325 | int buf; | ||
326 | GBool eof; | ||
327 | }; | ||
328 | |||
329 | //------------------------------------------------------------------------ | ||
330 | // ASCII85Stream | ||
331 | //------------------------------------------------------------------------ | ||
332 | |||
333 | class ASCII85Stream: public FilterStream { | ||
334 | public: | ||
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 | |||
346 | private: | ||
347 | |||
348 | int c[5]; | ||
349 | int b[4]; | ||
350 | int index, n; | ||
351 | GBool eof; | ||
352 | }; | ||
353 | |||
354 | //------------------------------------------------------------------------ | ||
355 | // LZWStream | ||
356 | //------------------------------------------------------------------------ | ||
357 | |||
358 | class LZWStream: public FilterStream { | ||
359 | public: | ||
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 | |||
372 | private: | ||
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 | |||
394 | class RunLengthStream: public FilterStream { | ||
395 | public: | ||
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 | |||
408 | private: | ||
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 | |||
422 | struct CCITTCodeTable; | ||
423 | |||
424 | class CCITTFaxStream: public FilterStream { | ||
425 | public: | ||
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 | |||
439 | private: | ||
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 | ||
472 | struct 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 | ||
482 | struct 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 | |||
489 | class DCTStream: public FilterStream { | ||
490 | public: | ||
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 | |||
502 | private: | ||
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 | ||
555 | struct 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 | ||
562 | struct 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 | ||
568 | struct FlateDecode { | ||
569 | int bits; // # extra bits | ||
570 | int first; // first length/distance | ||
571 | }; | ||
572 | |||
573 | class FlateStream: public FilterStream { | ||
574 | public: | ||
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 | |||
587 | private: | ||
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 | |||
624 | class EOFStream: public FilterStream { | ||
625 | public: | ||
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 | |||
641 | class FixedLengthEncoder: public FilterStream { | ||
642 | public: | ||
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 | |||
655 | private: | ||
656 | |||
657 | int length; | ||
658 | int count; | ||
659 | }; | ||
660 | |||
661 | //------------------------------------------------------------------------ | ||
662 | // ASCII85Encoder | ||
663 | //------------------------------------------------------------------------ | ||
664 | |||
665 | class ASCII85Encoder: public FilterStream { | ||
666 | public: | ||
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 | |||
681 | private: | ||
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 | |||
696 | class RunLengthEncoder: public FilterStream { | ||
697 | public: | ||
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 | |||
712 | private: | ||
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 | |||
37 | TextString::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 | |||
59 | TextString::~TextString() { | ||
60 | gfree(text); | ||
61 | gfree(xRight); | ||
62 | } | ||
63 | |||
64 | void 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 | |||
83 | TextPage::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 | |||
93 | TextPage::~TextPage() { | ||
94 | clear(); | ||
95 | } | ||
96 | |||
97 | void 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 | |||
129 | void 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 | |||
140 | void 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 | |||
164 | void 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 | |||
216 | void 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 | |||
276 | GBool 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 | |||
354 | GString *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 | |||
432 | void 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 | |||
594 | void 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 | |||
614 | TextOutputDev::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 | |||
639 | TextOutputDev::~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 | |||
651 | void TextOutputDev::startPage(int pageNum, GfxState *state) { | ||
652 | text->clear(); | ||
653 | } | ||
654 | |||
655 | void TextOutputDev::endPage() { | ||
656 | text->coalesce(); | ||
657 | if (f) { | ||
658 | text->dump(f); | ||
659 | } | ||
660 | } | ||
661 | |||
662 | void TextOutputDev::updateFont(GfxState *state) { | ||
663 | text->updateFont(state); | ||
664 | } | ||
665 | |||
666 | void TextOutputDev::beginString(GfxState *state, GString *s) { | ||
667 | text->beginString(state); | ||
668 | } | ||
669 | |||
670 | void TextOutputDev::endString(GfxState *state) { | ||
671 | text->endString(); | ||
672 | } | ||
673 | |||
674 | void 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 | |||
681 | GBool 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 | |||
21 | class GfxState; | ||
22 | class GString; | ||
23 | |||
24 | //------------------------------------------------------------------------ | ||
25 | // TextString | ||
26 | //------------------------------------------------------------------------ | ||
27 | |||
28 | class TextString { | ||
29 | public: | ||
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 | |||
41 | private: | ||
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 | |||
60 | class TextPage { | ||
61 | public: | ||
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 | |||
105 | private: | ||
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 | |||
123 | class TextOutputDev: public OutputDev { | ||
124 | public: | ||
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 | |||
180 | private: | ||
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 | |||
28 | struct UnicodeMapExt { | ||
29 | Unicode u; // Unicode char | ||
30 | char code[maxExtCode]; | ||
31 | Guint nBytes; | ||
32 | }; | ||
33 | |||
34 | //------------------------------------------------------------------------ | ||
35 | |||
36 | UnicodeMap *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 | |||
107 | UnicodeMap::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 | |||
117 | UnicodeMap::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 | |||
128 | UnicodeMap::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 | |||
137 | UnicodeMap::~UnicodeMap() { | ||
138 | delete encodingName; | ||
139 | if (kind == unicodeMapUser && ranges) { | ||
140 | gfree(ranges); | ||
141 | } | ||
142 | if (eMaps) { | ||
143 | gfree(eMaps); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | void UnicodeMap::incRefCnt() { | ||
148 | ++refCnt; | ||
149 | } | ||
150 | |||
151 | void UnicodeMap::decRefCnt() { | ||
152 | if (--refCnt == 0) { | ||
153 | delete this; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | GBool UnicodeMap::match(GString *encodingNameA) { | ||
158 | return !encodingName->cmp(encodingNameA); | ||
159 | } | ||
160 | |||
161 | int 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 | |||
211 | UnicodeMapCache::UnicodeMapCache() { | ||
212 | int i; | ||
213 | |||
214 | for (i = 0; i < unicodeMapCacheSize; ++i) { | ||
215 | cache[i] = NULL; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | UnicodeMapCache::~UnicodeMapCache() { | ||
220 | int i; | ||
221 | |||
222 | for (i = 0; i < unicodeMapCacheSize; ++i) { | ||
223 | if (cache[i]) { | ||
224 | cache[i]->decRefCnt(); | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
229 | UnicodeMap *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 | |||
21 | class GString; | ||
22 | |||
23 | //------------------------------------------------------------------------ | ||
24 | |||
25 | enum UnicodeMapKind { | ||
26 | unicodeMapUser, // read from a file | ||
27 | unicodeMapResident, // static list of ranges | ||
28 | unicodeMapFunc // function pointer | ||
29 | }; | ||
30 | |||
31 | typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize); | ||
32 | |||
33 | struct UnicodeMapRange { | ||
34 | Unicode start, end; // range of Unicode chars | ||
35 | Guint code, nBytes; // first output code | ||
36 | }; | ||
37 | |||
38 | struct UnicodeMapExt; | ||
39 | |||
40 | //------------------------------------------------------------------------ | ||
41 | |||
42 | class UnicodeMap { | ||
43 | public: | ||
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 | |||
74 | private: | ||
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 | |||
94 | class UnicodeMapCache { | ||
95 | public: | ||
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 | |||
105 | private: | ||
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 | |||
9 | static 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 | |||
52 | static 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 | |||
146 | static 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 | |||
271 | static 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 | |||
51 | XRef::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 | |||
108 | XRef::~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. | ||
118 | int 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. | ||
207 | GBool 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. | ||
336 | GBool 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 | ||
438 | GBool 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 | ||
521 | GBool 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 | |||
535 | GBool 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 | |||
544 | GBool 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 | |||
553 | GBool 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 | |||
562 | GBool 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 | |||
571 | Object *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 | |||
612 | Object *XRef::getDocInfo(Object *obj) { | ||
613 | return trailerDict.dictLookup("Info", obj); | ||
614 | } | ||
615 | |||
616 | // Added for the pdftex project. | ||
617 | Object *XRef::getDocInfoNF(Object *obj) { | ||
618 | return trailerDict.dictLookupNF("Info", obj); | ||
619 | } | ||
620 | |||
621 | int 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 | |||
19 | class Dict; | ||
20 | class Stream; | ||
21 | |||
22 | //------------------------------------------------------------------------ | ||
23 | // XRef | ||
24 | //------------------------------------------------------------------------ | ||
25 | |||
26 | struct XRefEntry { | ||
27 | int offset; | ||
28 | int gen; | ||
29 | GBool used; | ||
30 | }; | ||
31 | |||
32 | class XRef { | ||
33 | public: | ||
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 | |||
81 | private: | ||
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 | ||
diff --git a/pics/qpdf_icon.png b/pics/qpdf_icon.png new file mode 100644 index 0000000..af9c22f --- a/dev/null +++ b/pics/qpdf_icon.png | |||
Binary files differ | |||