lib/pdf: make startPage() upstream compatible
[swftools.git] / lib / pdf / xpdf-changes.patch
1 --- xpdf/Catalog.cc.orig        2010-05-18 11:22:18.000000000 -0700
2 +++ xpdf/Catalog.cc     2010-05-18 11:22:18.000000000 -0700
3 @@ -193,7 +193,7 @@
4    if (!kids.isArray()) {
5      error(-1, "Kids object (page %d) is wrong type (%s)",
6           start+1, kids.getTypeName());
7 -    goto err1;
8 +    return start;
9    }
10    for (i = 0; i < kids.arrayGetLength(); ++i) {
11      kids.arrayGetNF(i, &kidRef);
12 --- xpdf/CharCodeToUnicode.cc.orig      2010-05-18 11:22:18.000000000 -0700
13 +++ xpdf/CharCodeToUnicode.cc   2010-05-18 11:22:18.000000000 -0700
14 @@ -208,13 +208,13 @@
15                                    int nBits) {
16    PSTokenizer *pst;
17    char tok1[256], tok2[256], tok3[256];
18 -  int nDigits, n1, n2, n3;
19 +  int maxCode, n1, n2, n3;
20    CharCode i;
21    CharCode code1, code2;
22    GString *name;
23    FILE *f;
24  
25 -  nDigits = nBits / 4;
26 +  maxCode = (nBits == 8) ? 0xff : (nBits == 16) ? 0xffff : 0xffffffff;
27    pst = new PSTokenizer(getCharFunc, data);
28    pst->getToken(tok1, sizeof(tok1), &n1);
29    while (pst->getToken(tok2, sizeof(tok2), &n2)) {
30 @@ -241,9 +241,9 @@
31           error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
32           break;
33         }
34 -       if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
35 +       if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
36               tok2[0] == '<' && tok2[n2 - 1] == '>')) {
37 -         error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
38 +         error(-1, "Illegal entry in bfchar block in ToUnicode CMap.");
39           continue;
40         }
41         tok1[n1 - 1] = tok2[n2 - 1] = '\0';
42 @@ -251,6 +251,9 @@
43           error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
44           continue;
45         }
46 +        if (code1 > maxCode) {
47 +          error(-1, "Invalid entry in bfchar block in ToUnicode CMap");
48 +        }
49         addMapping(code1, tok2 + 1, n2 - 2, 0);
50        }
51        pst->getToken(tok1, sizeof(tok1), &n1);
52 @@ -266,8 +269,8 @@
53           error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
54           break;
55         }
56 -       if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
57 -             n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
58 +       if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
59 +             tok2[0] == '<' && tok2[n2 - 1] == '>')) {
60           error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
61           continue;
62         }
63 @@ -277,6 +280,10 @@
64           error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
65           continue;
66         }
67 +        if (code1 > maxCode || code2 > maxCode) {
68 +           error(-1, "Invalid entry in bfrange block in ToUnicode CMap");
69 +       }
70 +
71         if (!strcmp(tok3, "[")) {
72           i = 0;
73           while (pst->getToken(tok1, sizeof(tok1), &n1) &&
74 @@ -320,7 +327,13 @@
75    if (code >= mapLen) {
76      oldLen = mapLen;
77      mapLen = (code + 256) & ~255;
78 +    Unicode *oldmap;
79      map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode));
80 +    if(!map) {
81 +       /* we sometimes get overflows for files trying to use 0xffffffff as charcode */
82 +       map = oldmap;
83 +       return;
84 +    }
85      for (i = oldLen; i < mapLen; ++i) {
86        map[i] = 0;
87      }
88 --- xpdf/Decrypt.cc.orig        2010-05-18 11:22:18.000000000 -0700
89 +++ xpdf/Decrypt.cc     2010-05-18 11:22:18.000000000 -0700
90 @@ -596,6 +596,7 @@
91    s->bufIdx = 0;
92    if (last) {
93      n = s->buf[15];
94 +    if(!n || n>16) n=16;
95      for (i = 15; i >= n; --i) {
96        s->buf[i] = s->buf[i-n];
97      }
98 --- xpdf/Gfx.cc.orig    2010-05-18 11:22:18.000000000 -0700
99 +++ xpdf/Gfx.cc 2010-05-18 11:22:18.000000000 -0700
100 @@ -465,6 +469,7 @@
101    abortCheckCbkData = abortCheckCbkDataA;
102  
103    // set crop box
104 +#ifdef XPDFEXE
105    if (cropBox) {
106      state->moveTo(cropBox->x1, cropBox->y1);
107      state->lineTo(cropBox->x2, cropBox->y1);
108 @@ -475,6 +480,7 @@
109      out->clip(state);
110      state->clearPath();
111    }
112 +#endif
113  }
114  
115  Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
116 @@ -3182,8 +3188,11 @@
117                             u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
118                             &dx, &dy, &originX, &originY);
119        dx = dx * state->getFontSize() + state->getCharSpace();
120 -      if (n == 1 && *p == ' ') {
121 -       dx += state->getWordSpace();
122 +      if (n == 1 && (*p == ' ' || *p == 0)) {
123 +        double w=state->getWordSpace();
124 +        if (w==0 && dx==0)
125 +          w=state->getFontSize()/3; // workaround for zero word space
126 +        dx += w;
127        }
128        dx *= state->getHorizScaling();
129        dy *= state->getFontSize();
130 @@ -3476,11 +3485,13 @@
131        }
132      }
133      if (!obj1.isNull()) {
134 -      colorSpace = GfxColorSpace::parse(&obj1);
135 +      colorSpace = GfxColorSpace::parse(&obj1, csMode);
136      } else if (csMode == streamCSDeviceGray) {
137        colorSpace = new GfxDeviceGrayColorSpace();
138      } else if (csMode == streamCSDeviceRGB) {
139        colorSpace = new GfxDeviceRGBColorSpace();
140 +    } else if (csMode == streamCSDeviceRGBX) {
141 +      colorSpace = new GfxDeviceRGBXColorSpace();
142      } else if (csMode == streamCSDeviceCMYK) {
143        colorSpace = new GfxDeviceCMYKColorSpace();
144      } else {
145 @@ -3824,6 +3835,7 @@
146      out->beginTransparencyGroup(state, bbox, blendingColorSpace,
147                                 isolated, knockout, softMask);
148    }
149 +  GfxState*old_state = state;
150  
151    // set new base matrix
152    for (i = 0; i < 6; ++i) {
153 @@ -3835,6 +3847,9 @@
154    display(str, gFalse);
155  
156    if (softMask || transpGroup) {
157 +    // restore graphics state
158 +    while(state != old_state)
159 +       restoreState();
160      out->endTransparencyGroup(state);
161    }
162  
163 --- xpdf/GfxFont.cc.orig        2010-05-18 11:22:18.000000000 -0700
164 +++ xpdf/GfxFont.cc     2010-05-18 11:22:18.000000000 -0700
165 @@ -919,6 +919,10 @@
166    return 1;
167  }
168  
169 +CharCodeToUnicode* Gfx8BitFont::getCTU() {
170 +    return ctu;
171 +}
172 +
173  CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
174    ctu->incRefCnt();
175    return ctu;
176 @@ -1411,6 +1415,10 @@
177    }
178  }
179  
180 +CharCodeToUnicode* GfxCIDFont::getCTU() {
181 +    return ctu;
182 +}
183 +
184  int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
185                             Unicode *u, int uSize, int *uLen,
186                             double *dx, double *dy, double *ox, double *oy) {
187 --- xpdf/GfxFont.h.orig 2010-05-18 11:22:18.000000000 -0700
188 +++ xpdf/GfxFont.h      2010-05-18 11:22:18.000000000 -0700
189 @@ -164,6 +164,7 @@
190    virtual int getNextChar(char *s, int len, CharCode *code,
191                           Unicode *u, int uSize, int *uLen,
192                           double *dx, double *dy, double *ox, double *oy) = 0;
193 +  virtual CharCodeToUnicode* getCTU() = 0;
194  
195  protected:
196  
197 @@ -204,6 +205,7 @@
198    virtual int getNextChar(char *s, int len, CharCode *code,
199                           Unicode *u, int uSize, int *uLen,
200                           double *dx, double *dy, double *ox, double *oy);
201 +  virtual CharCodeToUnicode* getCTU();
202  
203    // Return the encoding.
204    char **getEncoding() { return enc; }
205 @@ -212,7 +214,7 @@
206    CharCodeToUnicode *getToUnicode();
207  
208    // Return the character name associated with <code>.
209 -  char *getCharName(int code) { return enc[code]; }
210 +  char *getCharName(int code) { return code>=256?0:enc[code]; }
211  
212    // Returns true if the PDF font specified an encoding.
213    GBool getHasEncoding() { return hasEncoding; }
214 @@ -266,6 +268,7 @@
215    virtual int getNextChar(char *s, int len, CharCode *code,
216                           Unicode *u, int uSize, int *uLen,
217                           double *dx, double *dy, double *ox, double *oy);
218 +  virtual CharCodeToUnicode* getCTU();
219  
220    // Return the writing mode (0=horizontal, 1=vertical).
221    virtual int getWMode();
222 --- xpdf/GfxState.cc.orig       2010-05-18 11:22:18.000000000 -0700
223 +++ xpdf/GfxState.cc    2010-05-18 11:22:18.000000000 -0700
224 @@ -21,6 +21,7 @@
225  #include "Array.h"
226  #include "Page.h"
227  #include "GfxState.h"
228 +#include "cmyk.h"
229  
230  //------------------------------------------------------------------------
231  
232 @@ -92,7 +93,7 @@
233  GfxColorSpace::~GfxColorSpace() {
234  }
235  
236 -GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
237 +GfxColorSpace *GfxColorSpace::parse(Object *csObj, StreamColorSpaceMode csMode) {
238    GfxColorSpace *cs;
239    Object obj1;
240  
241 @@ -101,7 +102,10 @@
242      if (csObj->isName("DeviceGray") || csObj->isName("G")) {
243        cs = new GfxDeviceGrayColorSpace();
244      } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
245 -      cs = new GfxDeviceRGBColorSpace();
246 +      if(csMode == streamCSDeviceRGBX)
247 +       cs = new GfxDeviceRGBXColorSpace();
248 +      else
249 +       cs = new GfxDeviceRGBColorSpace();
250      } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
251        cs = new GfxDeviceCMYKColorSpace();
252      } else if (csObj->isName("Pattern")) {
253 @@ -114,7 +118,10 @@
254      if (obj1.isName("DeviceGray") || obj1.isName("G")) {
255        cs = new GfxDeviceGrayColorSpace();
256      } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
257 -      cs = new GfxDeviceRGBColorSpace();
258 +      if(csMode == streamCSDeviceRGBX)
259 +        cs = new GfxDeviceRGBColorSpace();
260 +      else
261 +       cs = new GfxDeviceRGBColorSpace();
262      } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
263        cs = new GfxDeviceCMYKColorSpace();
264      } else if (obj1.isName("CalGray")) {
265 @@ -333,6 +340,17 @@
266  }
267  
268  //------------------------------------------------------------------------
269 +// GfxDeviceRGBXColorSpace
270 +//------------------------------------------------------------------------
271 +
272 +GfxDeviceRGBXColorSpace::GfxDeviceRGBXColorSpace() {
273 +}
274 +
275 +GfxColorSpace *GfxDeviceRGBXColorSpace::copy() {
276 +  return new GfxDeviceRGBXColorSpace();
277 +}
278 +
279 +//------------------------------------------------------------------------
280  // GfxCalRGBColorSpace
281  //------------------------------------------------------------------------
282  
283 @@ -490,6 +508,18 @@
284                                 - 0.11 * color->c[2] + 0.5));
285  }
286  
287 +/*void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
288 +    unsigned char r,g,b;
289 +    float c = color->c[0];
290 +    float m = color->c[1];
291 +    float y = color->c[2];
292 +    float k = color->c[3];
293 +    convert_cmyk2rgb(c,m,y,k, &r,&g,&b);
294 +    rgb->r = r/255.0;
295 +    rgb->g = g/255.0;
296 +    rgb->b = b/255.0;
297 +}*/
298 +
299  void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
300    double c, m, y, k, c1, m1, y1, k1, r, g, b, x;
301  
302 @@ -3187,6 +3217,7 @@
303    GfxIndexedColorSpace *indexedCS;
304    GfxSeparationColorSpace *sepCS;
305    int maxPixel, indexHigh;
306 +  int maxPixelForAlloc;
307    Guchar *lookup2;
308    Function *sepFunc;
309    Object obj;
310 @@ -3199,6 +3230,7 @@
311    // bits per component and color space
312    bits = bitsA;
313    maxPixel = (1 << bits) - 1;
314 +  maxPixelForAlloc = (1 << (bits>8?bits:8));
315    colorSpace = colorSpaceA;
316  
317    // initialize
318 @@ -3253,7 +3285,7 @@
319      lookup2 = indexedCS->getLookup();
320      colorSpace2->getDefaultRanges(x, y, indexHigh);
321      for (k = 0; k < nComps2; ++k) {
322 -      lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
323 +      lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1,
324                                            sizeof(GfxColorComp));
325        for (i = 0; i <= maxPixel; ++i) {
326         j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
327 @@ -3272,7 +3304,7 @@
328      nComps2 = colorSpace2->getNComps();
329      sepFunc = sepCS->getFunc();
330      for (k = 0; k < nComps2; ++k) {
331 -      lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
332 +      lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1,
333                                            sizeof(GfxColorComp));
334        for (i = 0; i <= maxPixel; ++i) {
335         x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
336 @@ -3282,7 +3314,7 @@
337      }
338    } else {
339      for (k = 0; k < nComps; ++k) {
340 -      lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
341 +      lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1,
342                                            sizeof(GfxColorComp));
343        for (i = 0; i <= maxPixel; ++i) {
344         lookup[k][i] = dblToCol(decodeLow[k] +
345 @@ -3754,7 +3786,10 @@
346  }
347  
348  void GfxState::setPath(GfxPath *pathA) {
349 +  if(pathA) {
350 +      if(path)
351    delete path;
352 +  }
353    path = pathA;
354  }
355  
356 --- xpdf/GfxState.h.orig        2010-05-18 11:22:18.000000000 -0700
357 +++ xpdf/GfxState.h     2010-05-18 11:22:18.000000000 -0700
358 @@ -138,7 +138,7 @@
359    virtual GfxColorSpaceMode getMode() = 0;
360  
361    // Construct a color space.  Returns NULL if unsuccessful.
362 -  static GfxColorSpace *parse(Object *csObj);
363 +  static GfxColorSpace *parse(Object *csObj, StreamColorSpaceMode csMode = streamCSNone);
364  
365    // Convert to gray, RGB, or CMYK.
366    virtual void getGray(GfxColor *color, GfxGray *gray) = 0;
367 @@ -252,6 +252,19 @@
368  };
369  
370  //------------------------------------------------------------------------
371 +// GfxDeviceRGBXColorSpace
372 +//------------------------------------------------------------------------
373 +
374 +class GfxDeviceRGBXColorSpace: public GfxDeviceRGBColorSpace {
375 +public:
376 +
377 +  GfxDeviceRGBXColorSpace();
378 +  virtual GfxColorSpace *copy();
379 +  virtual int getNComps() { return 4; }
380 +private:
381 +};
382 +
383 +//------------------------------------------------------------------------
384  // GfxCalRGBColorSpace
385  //------------------------------------------------------------------------
386  
387 --- xpdf/GlobalParams.cc.orig   2010-05-18 11:22:18.000000000 -0700
388 +++ xpdf/GlobalParams.cc        2010-05-18 11:22:18.000000000 -0700
389 @@ -914,6 +914,29 @@
390    int line;
391    char buf[512];
392  
393 +  /* extract path */
394 +  if(fileName) {
395 +    char* cfgFileName = fileName->getCString();
396 +    char* pos1 = strrchr(cfgFileName, '/');
397 +    char* pos2 = strrchr(cfgFileName, '\\');
398 +    char* p = pos1>pos2?pos1:pos2;
399 +    int pos = p ? p-cfgFileName : -1;
400 +    GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos));
401 +    if(pos1>=0)
402 +       path->append('/');
403 +    else if(pos2>=0)
404 +       path->append('\\');
405 +    else
406 +#ifdef WIN32
407 +       path->append('\\');
408 +#else
409 +       path->append('/');
410 +#endif
411 +    this->path = path;
412 +  } else {
413 +    this->path = new GString();
414 +  }
415 +  
416    line = 1;
417    while (getLine(buf, sizeof(buf) - 1, f)) {
418      parseLine(buf, fileName, line);
419 @@ -1114,6 +1137,42 @@
420    deleteGList(tokens, GString);
421  }
422  
423 +static char is_absolute(char*filename)
424 +{
425 +    int l = strlen(filename);
426 +    if(filename[0] == '/' || filename[0] == '\\') 
427 +       return 1;
428 +    if(l>2 && filename[1]==':' && (filename[2]=='\\' || filename[2]=='/'))
429 +       return 1;
430 +    return 0;
431 +}
432 +
433 +static GString* qualify_filename(GString*path, GString*filename)
434 +{
435 +  GString*fullpath = 0;
436 +  char*prefix = "/usr/local/share/xpdf/";
437 +
438 +  if (!is_absolute(filename->getCString())) {
439 +    /* relative path */
440 +    fullpath = path->copy();
441 +    fullpath->append(filename);
442 +  } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) {
443 +    /* xpdf default path */
444 +    char*s = strchr(filename->getCString()+strlen(prefix), '/');
445 +    if(s) {
446 +       fullpath = path->copy();
447 +       fullpath->append(s+1);
448 +    } else {
449 +       fullpath = filename->copy();
450 +    }
451 +  } else {
452 +    /* absolute path */
453 +    fullpath = filename->copy();
454 +  }
455 +  //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString());
456 +  return fullpath;
457 +}
458 +
459  void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
460                                          int line) {
461    GString *name;
462 @@ -1128,10 +1187,10 @@
463           fileName->getCString(), line);
464      return;
465    }
466 -  name = (GString *)tokens->get(1);
467 +  name = qualify_filename(this->path, (GString *)tokens->get(1));
468    if (!(f = fopen(name->getCString(), "r"))) {
469 -    error(-1, "Couldn't open 'nameToUnicode' file '%s'",
470 -         name->getCString());
471 +    error(-1, "Couldn't open 'nameToUnicode' file '%s' using path '%s'",
472 +         name->getCString(), path->getCString());
473      return;
474    }
475    line2 = 1;
476 @@ -1160,10 +1219,12 @@
477    }
478    collection = (GString *)tokens->get(1);
479    name = (GString *)tokens->get(2);
480 +
481    if ((old = (GString *)cidToUnicodes->remove(collection))) {
482      delete old;
483    }
484 -  cidToUnicodes->add(collection->copy(), name->copy());
485 +
486 +  cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name));
487  }
488  
489  void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
490 @@ -1180,7 +1241,8 @@
491    if ((old = (GString *)unicodeToUnicodes->remove(font))) {
492      delete old;
493    }
494 -  unicodeToUnicodes->add(font->copy(), file->copy());
495 +
496 +  unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file));
497  }
498  
499  void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
500 @@ -1197,7 +1259,8 @@
501    if ((old = (GString *)unicodeMaps->remove(encodingName))) {
502      delete old;
503    }
504 -  unicodeMaps->add(encodingName->copy(), name->copy());
505 +
506 +  unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name));
507  }
508  
509  void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
510 @@ -1215,23 +1278,30 @@
511      list = new GList();
512      cMapDirs->add(collection->copy(), list);
513    }
514 -  list->append(dir->copy());
515 +
516 +  list->append(qualify_filename(this->path, dir));
517  }
518  
519  void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
520                                      int line) {
521 +  GString *dir;
522 +
523    if (tokens->getLength() != 2) {
524      error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
525           fileName->getCString(), line);
526      return;
527    }
528 -  toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
529 +
530 +  dir = (GString *)tokens->get(1);
531 +
532 +  toUnicodeDirs->append(qualify_filename(this->path, dir));
533  }
534  
535  void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
536                                     DisplayFontParamKind kind,
537                                     GString *fileName, int line) {
538    DisplayFontParam *param, *old;
539 +  GString *file;
540  
541    if (tokens->getLength() < 2) {
542      goto err1;
543 @@ -1243,13 +1313,15 @@
544      if (tokens->getLength() != 3) {
545        goto err2;
546      }
547 -    param->t1.fileName = ((GString *)tokens->get(2))->copy();
548 +    file = (GString *)tokens->get(2);
549 +    param->t1.fileName = qualify_filename(this->path, file);
550      break;
551    case displayFontTT:
552      if (tokens->getLength() != 3) {
553        goto err2;
554      }
555 -    param->tt.fileName = ((GString *)tokens->get(2))->copy();
556 +    file = (GString *)tokens->get(2);
557 +    param->tt.fileName = qualify_filename(this->path, file);
558      break;
559    }
560  
561 --- xpdf/GlobalParams.h.orig    2010-05-18 11:22:18.000000000 -0700
562 +++ xpdf/GlobalParams.h 2010-05-18 11:22:18.000000000 -0700
563 @@ -196,7 +196,7 @@
564    // file.
565    GlobalParams(char *cfgFileName);
566  
567 -  ~GlobalParams();
568 +  virtual ~GlobalParams();
569  
570    void setBaseDir(char *dir);
571    void setupBaseFonts(char *dir);
572 @@ -213,8 +213,8 @@
573    FILE *getUnicodeMapFile(GString *encodingName);
574    FILE *findCMapFile(GString *collection, GString *cMapName);
575    FILE *findToUnicodeFile(GString *name);
576 -  DisplayFontParam *getDisplayFont(GString *fontName);
577 -  DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
578 +  virtual DisplayFontParam *getDisplayFont(GString *fontName);
579 +  virtual DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
580    GString *getPSFile();
581    int getPSPaperWidth();
582    int getPSPaperHeight();
583 @@ -316,7 +316,7 @@
584  private:
585  
586    void createDefaultKeyBindings();
587 -  void parseFile(GString *fileName, FILE *f);
588 +public: void parseFile(GString *fileName, FILE *f); private:
589    void parseNameToUnicode(GList *tokens, GString *fileName, int line);
590    void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
591    void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line);
592 @@ -358,6 +358,10 @@
593    GBool loadPlugin(char *type, char *name);
594  #endif
595  
596 +  //----- config file base path
597 +
598 +  GString*path;
599 +
600    //----- static tables
601  
602    NameToCharCode *             // mapping from char name to
603 --- xpdf/JBIG2Stream.cc.orig    2010-05-18 11:22:18.000000000 -0700
604 +++ xpdf/JBIG2Stream.cc 2010-05-18 11:22:18.000000000 -0700
605 @@ -1514,11 +1514,14 @@
606    }
607  
608    // compute symbol code length
609 -  symCodeLen = 1;
610 -  i = (numInputSyms + numNewSyms) >> 1;
611 -  while (i) {
612 -    ++symCodeLen;
613 -    i >>= 1;
614 +  symCodeLen = 0;
615 +  i = 1;
616 +  while (i < numInputSyms + numNewSyms) {
617 +   ++symCodeLen;
618 +   i <<= 1;
619 +  }
620 +  if (huff && symCodeLen == 0) {
621 +   symCodeLen = 1;
622    }
623  
624    // get the input symbol bitmaps
625 @@ -1921,6 +1924,9 @@
626      ++symCodeLen;
627      i <<= 1;
628    }
629 +  if (huff && symCodeLen == 0) {
630 +    symCodeLen = 1;
631 +  }
632  
633    // get the symbol bitmaps
634    syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
635 --- xpdf/JPXStream.cc.orig      2010-05-18 11:22:18.000000000 -0700
636 +++ xpdf/JPXStream.cc   2010-05-18 11:22:18.000000000 -0700
637 @@ -241,6 +242,12 @@
638    haveCompMap = gFalse;
639    haveChannelDefn = gFalse;
640  
641 +  img.xSize = 0;
642 +  img.ySize = 0;
643 +  img.xOffset = 0;
644 +  img.yOffset = 0;
645 +  curX = 0;
646 +  curY = 0;
647    img.tiles = NULL;
648    bitBuf = 0;
649    bitBufLen = 0;
650 @@ -450,6 +450,7 @@
651    GBool haveBPC, haveCSMode;
652  
653    csPrec = 0; // make gcc happy
654 +  Guint num_components = 0;
655    haveBPC = haveCSMode = gFalse;
656    str->reset();
657    if (str->lookChar() == 0xff) {
658 @@ -463,7 +464,7 @@
659         cover(1);
660         if (readULong(&dummy) &&
661             readULong(&dummy) &&
662 -           readUWord(&dummy) &&
663 +           readUWord(&num_components) &&
664             readUByte(&bpc1) &&
665             readUByte(&dummy) &&
666             readUByte(&dummy) &&
667 @@ -519,6 +520,9 @@
668        }
669      }
670    }
671 +  if(*csMode == streamCSDeviceRGB && num_components == 4) {
672 +    *csMode = streamCSDeviceRGBX;
673 +  }
674    str->close();
675  }
676  
677 --- xpdf/Lexer.cc.orig  2010-05-18 11:22:18.000000000 -0700
678 +++ xpdf/Lexer.cc       2010-05-18 11:22:18.000000000 -0700
679 @@ -74,6 +74,7 @@
680      curStr.streamReset();
681    }
682  }
683 +static int illegalChars = 0;
684  
685  Lexer::~Lexer() {
686    if (!curStr.isNone()) {
687 @@ -83,6 +84,9 @@
688    if (freeArray) {
689      delete streams;
690    }
691 +  if(illegalChars)
692 +      error(0, "Illegal characters in hex string (%d)", illegalChars);
693 +  illegalChars = 0;
694  }
695  
696  int Lexer::getChar() {
697 @@ -330,7 +334,8 @@
698         } else if (c2 >= 'a' && c2 <= 'f') {
699           c += c2 - 'a' + 10;
700         } else {
701 -         error(getPos(), "Illegal digit in hex char in name");
702 +         illegalChars++;
703 +         //error(getPos(), "Illegal digit in hex char in name");
704         }
705        }
706       notEscChar:
707 @@ -384,8 +389,10 @@
708             c2 += c - 'A' + 10;
709           else if (c >= 'a' && c <= 'f')
710             c2 += c - 'a' + 10;
711 -         else
712 -           error(getPos(), "Illegal character <%02x> in hex string", c);
713 +         else {
714 +           illegalChars++;
715 +           //error(getPos(), "Illegal character <%02x> in hex string", c);
716 +         }
717           if (++m == 2) {
718             if (n == tokBufSize) {
719               if (!s)
720 @@ -421,7 +428,8 @@
721        tokBuf[2] = '\0';
722        obj->initCmd(tokBuf);
723      } else {
724 -      error(getPos(), "Illegal character '>'");
725 +      illegalChars++;
726 +      //error(getPos(), "Illegal character '>'");
727        obj->initError();
728      }
729      break;
730 @@ -430,7 +438,8 @@
731    case ')':
732    case '{':
733    case '}':
734 -    error(getPos(), "Illegal character '%c'", c);
735 +    //error(getPos(), "Illegal character '%c'", c);
736 +    illegalChars++;
737      obj->initError();
738      break;
739  
740 @@ -459,7 +468,6 @@
741      }
742      break;
743    }
744 -
745    return obj;
746  }
747  
748 --- xpdf/Link.cc.orig   2010-05-18 11:22:18.000000000 -0700
749 +++ xpdf/Link.cc        2010-05-18 11:22:18.000000000 -0700
750 @@ -430,10 +430,9 @@
751        delete dest;
752        dest = NULL;
753      }
754 -
755    // error
756    } else {
757 -    error(-1, "Illegal annotation destination");
758 +    error(-1, "Illegal annotation destination %d", destObj->getType());
759    }
760  }
761  
762 @@ -468,10 +467,9 @@
763        delete dest;
764        dest = NULL;
765      }
766 -
767    // error
768    } else {
769 -    error(-1, "Illegal annotation destination");
770 +    error(-1, "Illegal annotation destination %d", destObj->getType());
771    }
772  }
773  
774 --- xpdf/OutputDev.h.orig       2010-05-18 11:22:18.000000000 -0700
775 +++ xpdf/OutputDev.h    2010-05-18 11:22:18.000000000 -0700
776 @@ -17,6 +17,7 @@
777  
778  #include "gtypes.h"
779  #include "CharTypes.h"
780 +#include "Object.h"
781  
782  class GString;
783  class GfxState;
784 --- xpdf/SplashFTFont.cc.orig   2010-05-18 11:22:18.000000000 -0700
785 +++ xpdf/SplashFTFont.cc        2010-05-18 11:22:18.000000000 -0700
786 @@ -46,6 +46,7 @@
787    int x, y;
788  
789    face = fontFileA->face;
790 +  
791    if (FT_New_Size(face, &sizeObj)) {
792      return;
793    }
794 @@ -54,6 +55,10 @@
795    if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
796      return;
797    }
798
799 +  this->ascender = face->ascender;
800 +  this->descender = face->descender;
801 +
802    // if the textMat values are too small, FreeType's fixed point
803    // arithmetic doesn't work so well
804    textScale = splashSqrt(textMat[2]*textMat[2] + textMat[3]*textMat[3]) / size;
805 @@ -228,6 +233,12 @@
806    GBool needClose;
807  };
808  
809 +int SplashFTFont::getNumChars()
810 +{
811 +  SplashFTFontFile* ff = (SplashFTFontFile *)fontFile;
812 +  return ff->face->num_glyphs;
813 +}
814 +
815  SplashPath *SplashFTFont::getGlyphPath(int c) {
816    static FT_Outline_Funcs outlineFuncs = {
817  #if FREETYPE_MINOR <= 1
818 @@ -249,6 +260,8 @@
819    FT_UInt gid;
820    FT_Glyph glyph;
821  
822 +  this->last_advance = -1;
823 +
824    ff = (SplashFTFontFile *)fontFile;
825    ff->face->size = sizeObj;
826    FT_Set_Transform(ff->face, &textMatrix, NULL);
827 @@ -262,17 +275,24 @@
828      // skip the TrueType notdef glyph
829      return NULL;
830    }
831 -  if (FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP)) {
832 +  int error = 0;
833 +  if ((error=FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING))) {
834 +      fprintf(stderr, "Truetype wasn't able to load glyph %d, error %d\n", gid, error);
835      return NULL;
836    }
837    if (FT_Get_Glyph(slot, &glyph)) {
838      return NULL;
839    }
840 +  this->last_advance = glyph->advance.x/65536.0;
841 +
842    path.path = new SplashPath();
843    path.textScale = textScale;
844    path.needClose = gFalse;
845 -  FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
846 +  error = FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
847                        &outlineFuncs, &path);
848 +  if(error) {
849 +      fprintf(stderr, "Truetype wasn't able to read glyph %d, error %d\n", gid, error);
850 +  }
851    if (path.needClose) {
852      path.path->close();
853    }
854 --- xpdf/SplashFTFont.h.orig    2010-05-18 11:22:18.000000000 -0700
855 +++ xpdf/SplashFTFont.h 2010-05-18 11:22:18.000000000 -0700
856 @@ -42,6 +42,9 @@
857    virtual GBool makeGlyph(int c, int xFrac, int yFrac,
858                           SplashGlyphBitmap *bitmap);
859  
860 +  // return the number of characters in this font
861 +  virtual int getNumChars();
862 +
863    // Return the path for a glyph.
864    virtual SplashPath *getGlyphPath(int c);
865  
866 --- xpdf/SplashFTFontEngine.cc.orig     2010-05-18 11:22:18.000000000 -0700
867 +++ xpdf/SplashFTFontEngine.cc  2010-05-18 11:22:18.000000000 -0700
868 @@ -13,9 +13,7 @@
869  #endif
870  
871  #include <stdio.h>
872 -#ifndef WIN32
873  #  include <unistd.h>
874 -#endif
875  #include "gmem.h"
876  #include "GString.h"
877  #include "gfile.h"
878 --- xpdf/SplashFont.cc.orig     2010-05-18 11:22:18.000000000 -0700
879 +++ xpdf/SplashFont.cc  2010-05-18 11:22:18.000000000 -0700
880 @@ -48,6 +48,10 @@
881    cacheTags = NULL;
882  
883    xMin = yMin = xMax = yMax = 0;
884 +
885 +  last_advance = -1;
886 +  ascender = -1;
887 +  descender = -1;
888  }
889  
890  void SplashFont::initCache() {
891 --- xpdf/SplashFont.h.orig      2010-05-18 11:22:18.000000000 -0700
892 +++ xpdf/SplashFont.h   2010-05-18 11:22:18.000000000 -0700
893 @@ -73,6 +73,9 @@
894    virtual GBool makeGlyph(int c, int xFrac, int yFrac,
895                           SplashGlyphBitmap *bitmap) = 0;
896  
897 +  // return the number of characters in this font
898 +  virtual int getNumChars() = 0;
899 +
900    // Return the path for a glyph.
901    virtual SplashPath *getGlyphPath(int c) = 0;
902  
903 @@ -83,6 +86,9 @@
904    void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA)
905      { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
906  
907 +  double ascender;
908 +  double descender;
909 +  double last_advance; //set after getGlyphPath()
910  protected:
911  
912    SplashFontFile *fontFile;
913 --- xpdf/SplashFontFile.cc.orig 2010-05-18 11:22:18.000000000 -0700
914 +++ xpdf/SplashFontFile.cc      2010-05-18 11:22:18.000000000 -0700
915 @@ -11,9 +11,7 @@
916  #endif
917  
918  #include <stdio.h>
919 -#ifndef WIN32
920 -#  include <unistd.h>
921 -#endif
922 +#include <unistd.h>
923  #include "GString.h"
924  #include "SplashFontFile.h"
925  #include "SplashFontFileID.h"
926 --- xpdf/SplashOutputDev.cc.orig        2010-05-18 11:22:18.000000000 -0700
927 +++ xpdf/SplashOutputDev.cc     2010-05-18 11:22:18.000000000 -0700
928 @@ -13,6 +13,7 @@
929  #endif
930  
931  #include <string.h>
932 +#include <unistd.h>
933  #include <math.h>
934  #include "gfile.h"
935  #include "GlobalParams.h"
936 @@ -2646,9 +2647,9 @@
937  
938    softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
939                               1, splashModeMono8, gFalse);
940 -  memset(softMask->getDataPtr(), 0,
941 -        softMask->getRowSize() * softMask->getHeight());
942 +  memset(softMask->getDataPtr(), 0x00, softMask->getRowSize()*softMask->getHeight());
943    p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
944 +  if (tx<softMask->getWidth() && ty<softMask->getHeight())
945    for (y = 0; y < tBitmap->getHeight(); ++y) {
946      for (x = 0; x < tBitmap->getWidth(); ++x) {
947        tBitmap->getPixel(x, y, color);
948 --- xpdf/SplashOutputDev.h.orig 2010-05-18 11:22:18.000000000 -0700
949 +++ xpdf/SplashOutputDev.h      2010-05-18 11:22:18.000000000 -0700
950 @@ -196,6 +196,9 @@
951    virtual void setVectorAntialias(GBool vaa);
952  #endif
953  
954 +  void doUpdateFont(GfxState *state);
955 +  
956 +  SplashPath *convertPath(GfxState *state, GfxPath *path);
957  private:
958  
959    void setupScreenParams(double hDPI, double vDPI);
960 @@ -204,8 +207,6 @@
961  #else
962    SplashPattern *getColor(GfxGray gray, GfxRGB *rgb);
963  #endif
964 -  SplashPath *convertPath(GfxState *state, GfxPath *path);
965 -  void doUpdateFont(GfxState *state);
966    void drawType3Glyph(T3FontCache *t3Font,
967                       T3FontCacheTag *tag, Guchar *data);
968    static GBool imageMaskSrc(void *data, SplashColorPtr line);
969 --- xpdf/SplashScreen.cc.orig   2010-05-18 11:22:18.000000000 -0700
970 +++ xpdf/SplashScreen.cc        2010-05-18 11:22:18.000000000 -0700
971 @@ -363,6 +363,8 @@
972  int SplashScreen::test(int x, int y, Guchar value) {
973    int xx, yy;
974  
975 +  return 1;
976 +
977    if (value < minVal) {
978      return 0;
979    }
980 --- xpdf/SplashXPathScanner.cc.orig     2010-05-18 11:22:18.000000000 -0700
981 +++ xpdf/SplashXPathScanner.cc  2010-05-18 11:22:18.000000000 -0700
982 @@ -394,10 +394,10 @@
983           *p++ &= mask;
984           xx = (xx & ~7) + 8;
985         }
986 -       for (; xx + 7 <= xx0; xx += 8) {
987 +       for (; xx + 7 < xx0; xx += 8) {
988           *p++ = 0x00;
989         }
990 -       if (xx <= xx0) {
991 +       if (xx < xx0) {
992           *p &= 0xff >> (xx0 & 7);
993         }
994        }
995 @@ -417,10 +417,10 @@
996         *p++ &= mask;
997         xx = (xx & ~7) + 8;
998        }
999 -      for (; xx + 7 <= xx0; xx += 8) {
1000 +      for (; xx + 7 < xx0; xx += 8) {
1001         *p++ = 0x00;
1002        }
1003 -      if (xx <= xx0) {
1004 +      if (xx < xx0) {
1005         *p &= 0xff >> (xx0 & 7);
1006        }
1007      }
1008 --- xpdf/Stream.cc.orig 2010-05-18 11:22:18.000000000 -0700
1009 +++ xpdf/Stream.cc      2010-05-18 11:22:18.000000000 -0700
1010 @@ -18,6 +18,8 @@
1011  #include <limits.h>
1012  #ifndef WIN32
1013  #include <unistd.h>
1014 +#else
1015 +extern "C" int unlink(char *filename);
1016  #endif
1017  #include <string.h>
1018  #include <ctype.h>
1019 @@ -2456,6 +2460,9 @@
1020    // check for an EOB run
1021    if (eobRun > 0) {
1022      while (i <= scanInfo.lastCoeff) {
1023 +      if(i>=64) {
1024 +         return gFalse;
1025 +      }
1026        j = dctZigZag[i++];
1027        if (data[j] != 0) {
1028         if ((bit = readBit()) == EOF) {
1029 @@ -2480,6 +2487,9 @@
1030      if (c == 0xf0) {
1031        k = 0;
1032        while (k < 16) {
1033 +        if(i>=64) {
1034 +         return gFalse;
1035 +       }
1036         j = dctZigZag[i++];
1037         if (data[j] == 0) {
1038           ++k;
1039 @@ -2505,6 +2515,9 @@
1040        }
1041        eobRun += 1 << j;
1042        while (i <= scanInfo.lastCoeff) {
1043 +       if(i>=64) {
1044 +         return gFalse;
1045 +       }
1046         j = dctZigZag[i++];
1047         if (data[j] != 0) {
1048           if ((bit = readBit()) == EOF) {
1049 @@ -2527,6 +2540,9 @@
1050        }
1051        k = 0;
1052        do {
1053 +       if(i>=64) {
1054 +         return gFalse;
1055 +       }
1056         j = dctZigZag[i++];
1057         while (data[j] != 0) {
1058           if ((bit = readBit()) == EOF) {
1059 @@ -2535,6 +2551,9 @@
1060           if (bit) {
1061             data[j] += 1 << scanInfo.al;
1062           }
1063 +         if(i>=64) {
1064 +           return gFalse;
1065 +         }
1066           j = dctZigZag[i++];
1067         }
1068         ++k;
1069 --- xpdf/Stream.h.orig  2010-05-18 11:22:18.000000000 -0700
1070 +++ xpdf/Stream.h       2010-05-18 11:22:18.000000000 -0700
1071 @@ -41,7 +41,8 @@
1072    streamCSNone,
1073    streamCSDeviceGray,
1074    streamCSDeviceRGB,
1075 -  streamCSDeviceCMYK
1076 +  streamCSDeviceCMYK,
1077 +  streamCSDeviceRGBX
1078  };
1079  
1080  //------------------------------------------------------------------------
1081 --- xpdf/TextOutputDev.h.orig   2010-05-18 11:22:18.000000000 -0700
1082 +++ xpdf/TextOutputDev.h        2010-05-18 11:22:18.000000000 -0700
1083 @@ -170,6 +170,7 @@
1084    friend class TextFlow;
1085    friend class TextWordList;
1086    friend class TextPage;
1087 +  friend class XMLOutputDev;
1088  };
1089  
1090  //------------------------------------------------------------------------
1091 --- xpdf/gfile.cc.orig  2010-05-18 11:22:18.000000000 -0700
1092 +++ xpdf/gfile.cc       2010-05-18 11:22:18.000000000 -0700
1093 @@ -439,6 +439,52 @@
1094  #endif
1095  }
1096  
1097 +static char* getTempDir()
1098 +{
1099 +#ifdef WIN32
1100 +    char*dir = getenv("TMP");
1101 +    if(!dir) dir = getenv("TEMP");
1102 +    if(!dir) dir = getenv("tmp");
1103 +    if(!dir) dir = getenv("temp");
1104 +    if(!dir) dir = "C:\\";
1105 +#else
1106 +    char* dir = "/tmp/";
1107 +#endif
1108 +    return dir;
1109 +}
1110 +
1111 +char* mktmpname(char*ptr) {
1112 +    static char tmpbuf[128];
1113 +    char*dir = getTempDir();
1114 +    int l = strlen(dir);
1115 +    char*sep = "";
1116 +    if(!ptr)
1117 +       ptr = tmpbuf;
1118 +    if(l && dir[l-1]!='/' && dir[l-1]!='\\') {
1119 +#ifdef WIN32
1120 +       sep = "\\";
1121 +#else
1122 +       sep = "/";
1123 +#endif
1124 +    }
1125 +
1126 + //   used to be mktemp. This does remove the warnings, but
1127 + //   It's not exactly an improvement.
1128 +#ifdef HAVE_LRAND48
1129 +    sprintf(ptr, "%s%s%08x%08x",dir,sep,(unsigned int)lrand48(),(unsigned int)lrand48());
1130 +#else
1131 +#   ifdef HAVE_RAND
1132 +       sprintf(ptr, "%s%s%08x%08x",dir,sep,rand(),rand());
1133 +#   else
1134 +       static int count = 1;
1135 +       sprintf(ptr, "%s%s%08x%04x%04x",dir,sep,time(0),(unsigned int)tmpbuf^((unsigned int)tmpbuf)>>16,count);
1136 +       count ++;
1137 +#   endif
1138 +#endif
1139 +     return ptr;
1140 +}
1141 +
1142 +
1143  GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
1144  #if defined(WIN32)
1145    //---------- Win32 ----------
1146 @@ -460,7 +506,7 @@
1147    s->append("x");
1148    t = (int)time(NULL);
1149    for (i = 0; i < 1000; ++i) {
1150 -    sprintf(buf, "%d", t + i);
1151 +    sprintf(buf, "%08x-%08x", t + i, GetCurrentThreadId());
1152      s2 = s->copy()->append(buf);
1153      if (ext) {
1154        s2->append(ext);
1155 @@ -468,8 +514,7 @@
1156      if (!(f2 = fopen(s2->getCString(), "r"))) {
1157        if (!(f2 = fopen(s2->getCString(), mode))) {
1158         delete s2;
1159 -       delete s;
1160 -       return gFalse;
1161 +        continue;
1162        }
1163        *name = s2;
1164        *f = f2;
1165 @@ -479,6 +524,7 @@
1166      fclose(f2);
1167      delete s2;
1168    }
1169 +  fprintf(stderr, "Couldn't create temporary file\n");
1170    delete s;
1171    return gFalse;
1172  #elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS)
1173 @@ -489,7 +535,7 @@
1174    // with this file name after the tmpnam call and before the fopen
1175    // call.  I will happily accept fixes to this function for non-Unix
1176    // OSs.
1177 -  if (!(s = tmpnam(NULL))) {
1178 +  if (!(s = mktmpname(NULL))) {
1179      return gFalse;
1180    }
1181    *name = new GString(s);
1182 @@ -516,7 +562,7 @@
1183      (*name)->append("/XXXXXX")->append(ext);
1184      fd = mkstemps((*name)->getCString(), strlen(ext));
1185  #else
1186 -    if (!(s = tmpnam(NULL))) {
1187 +    if (!(s = mktmpname(NULL))) {
1188        return gFalse;
1189      }
1190      *name = new GString(s);
1191 @@ -533,7 +579,7 @@
1192      (*name)->append("/XXXXXX");
1193      fd = mkstemp((*name)->getCString());
1194  #else // HAVE_MKSTEMP
1195 -    if (!(s = tmpnam(NULL))) {
1196 +    if (!(s = mktmpname(NULL))) {
1197        return gFalse;
1198      }
1199      *name = new GString(s);
1200 --- xpdf/gfile.h.orig   2010-05-18 11:22:18.000000000 -0700
1201 +++ xpdf/gfile.h        2010-05-18 11:22:18.000000000 -0700
1202 @@ -58,6 +58,9 @@
1203  // Get current directory.
1204  extern GString *getCurrentDir();
1205  
1206 +/* create a temporary filename */
1207 +char* mktmpname(char*ptr);
1208 +
1209  // Append a file name to a path string.  <path> may be an empty
1210  // string, denoting the current directory).  Returns <path>.
1211  extern GString *appendToPath(GString *path, char *fileName);
1212 --- xpdf/JBIG2Stream.cc.orig    2010-05-18 11:33:21.000000000 -0700
1213 +++ xpdf/JBIG2Stream.cc 2010-06-03 16:55:03.000000000 -0700
1214 @@ -6,7 +6,24 @@
1215  //
1216  //========================================================================
1217  
1218 -#include <aconf.h>
1219 +//========================================================================
1220 +//
1221 +// Modified under the Poppler project - http://poppler.freedesktop.org
1222 +//
1223 +// All changes made under the Poppler project to this file are licensed
1224 +// under GPL version 2 or later
1225 +//
1226 +// Copyright (C) 2006 Raj Kumar <rkumar@archive.org>
1227 +// Copyright (C) 2006 Paul Walmsley <paul@booyaka.com>
1228 +// Copyright (C) 2006-2009 Albert Astals Cid <aacid@kde.org>
1229 +// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
1230 +//
1231 +// To see a description of the changes please see the Changelog file that
1232 +// came with your tarball or type make ChangeLog if you are building from git
1233 +//
1234 +//========================================================================
1235 +
1236 +#include <config.h>
1237  
1238  #ifdef USE_GCC_PRAGMAS
1239  #pragma implementation
1240 @@ -24,8 +41,8 @@
1241  
1242  //------------------------------------------------------------------------
1243  
1244 -static int contextSize[4] = { 16, 13, 10, 10 };
1245 -static int refContextSize[2] = { 13, 10 };
1246 +static const int contextSize[4] = { 16, 13, 10, 10 };
1247 +static const int refContextSize[2] = { 13, 10 };
1248  
1249  //------------------------------------------------------------------------
1250  // JBIG2HuffmanTable
1251 @@ -42,7 +59,7 @@
1252    Guint prefix;
1253  };
1254  
1255 -JBIG2HuffmanTable huffTableA[] = {
1256 +static JBIG2HuffmanTable huffTableA[] = {
1257    {     0, 1,  4,              0x000 },
1258    {    16, 2,  8,              0x002 },
1259    {   272, 3, 16,              0x006 },
1260 @@ -50,7 +67,7 @@
1261    {     0, 0, jbig2HuffmanEOT, 0     }
1262  };
1263  
1264 -JBIG2HuffmanTable huffTableB[] = {
1265 +static JBIG2HuffmanTable huffTableB[] = {
1266    {     0, 1,  0,              0x000 },
1267    {     1, 2,  0,              0x002 },
1268    {     2, 3,  0,              0x006 },
1269 @@ -61,7 +78,7 @@
1270    {     0, 0, jbig2HuffmanEOT, 0     }
1271  };
1272  
1273 -JBIG2HuffmanTable huffTableC[] = {
1274 +static JBIG2HuffmanTable huffTableC[] = {
1275    {     0, 1,  0,              0x000 },
1276    {     1, 2,  0,              0x002 },
1277    {     2, 3,  0,              0x006 },
1278 @@ -74,7 +91,7 @@
1279    {     0, 0, jbig2HuffmanEOT, 0     }
1280  };
1281  
1282 -JBIG2HuffmanTable huffTableD[] = {
1283 +static JBIG2HuffmanTable huffTableD[] = {
1284    {     1, 1,  0,              0x000 },
1285    {     2, 2,  0,              0x002 },
1286    {     3, 3,  0,              0x006 },
1287 @@ -84,7 +101,7 @@
1288    {     0, 0, jbig2HuffmanEOT, 0     }
1289  };
1290  
1291 -JBIG2HuffmanTable huffTableE[] = {
1292 +static JBIG2HuffmanTable huffTableE[] = {
1293    {     1, 1,  0,              0x000 },
1294    {     2, 2,  0,              0x002 },
1295    {     3, 3,  0,              0x006 },
1296 @@ -96,7 +113,7 @@
1297    {     0, 0, jbig2HuffmanEOT, 0     }
1298  };
1299  
1300 -JBIG2HuffmanTable huffTableF[] = {
1301 +static JBIG2HuffmanTable huffTableF[] = {
1302    {     0, 2,  7,              0x000 },
1303    {   128, 3,  7,              0x002 },
1304    {   256, 3,  8,              0x003 },
1305 @@ -114,7 +131,7 @@
1306    {     0, 0, jbig2HuffmanEOT, 0     }
1307  };
1308  
1309 -JBIG2HuffmanTable huffTableG[] = {
1310 +static JBIG2HuffmanTable huffTableG[] = {
1311    {  -512, 3,  8,              0x000 },
1312    {   256, 3,  8,              0x001 },
1313    {   512, 3,  9,              0x002 },
1314 @@ -133,7 +150,7 @@
1315    {     0, 0, jbig2HuffmanEOT, 0     }
1316  };
1317  
1318 -JBIG2HuffmanTable huffTableH[] = {
1319 +static JBIG2HuffmanTable huffTableH[] = {
1320    {     0, 2,  1,              0x000 },
1321    {     0, 2, jbig2HuffmanOOB, 0x001 },
1322    {     4, 3,  4,              0x004 },
1323 @@ -158,7 +175,7 @@
1324    {     0, 0, jbig2HuffmanEOT, 0     }
1325  };
1326  
1327 -JBIG2HuffmanTable huffTableI[] = {
1328 +static JBIG2HuffmanTable huffTableI[] = {
1329    {     0, 2, jbig2HuffmanOOB, 0x000 },
1330    {    -1, 3,  1,              0x002 },
1331    {     1, 3,  1,              0x003 },
1332 @@ -184,7 +201,7 @@
1333    {     0, 0, jbig2HuffmanEOT, 0     }
1334  };
1335  
1336 -JBIG2HuffmanTable huffTableJ[] = {
1337 +static JBIG2HuffmanTable huffTableJ[] = {
1338    {    -2, 2,  2,              0x000 },
1339    {     6, 2,  6,              0x001 },
1340    {     0, 2, jbig2HuffmanOOB, 0x002 },
1341 @@ -209,7 +226,7 @@
1342    {     0, 0, jbig2HuffmanEOT, 0     }
1343  };
1344  
1345 -JBIG2HuffmanTable huffTableK[] = {
1346 +static JBIG2HuffmanTable huffTableK[] = {
1347    {     1, 1,  0,              0x000 },
1348    {     2, 2,  1,              0x002 },
1349    {     4, 4,  0,              0x00c },
1350 @@ -226,7 +243,7 @@
1351    {     0, 0, jbig2HuffmanEOT, 0     }
1352  };
1353  
1354 -JBIG2HuffmanTable huffTableL[] = {
1355 +static JBIG2HuffmanTable huffTableL[] = {
1356    {     1, 1,  0,              0x000 },
1357    {     2, 2,  0,              0x002 },
1358    {     3, 3,  1,              0x006 },
1359 @@ -243,7 +260,7 @@
1360    {     0, 0, jbig2HuffmanEOT, 0     }
1361  };
1362  
1363 -JBIG2HuffmanTable huffTableM[] = {
1364 +static JBIG2HuffmanTable huffTableM[] = {
1365    {     1, 1,  0,              0x000 },
1366    {     2, 3,  0,              0x004 },
1367    {     7, 3,  3,              0x005 },
1368 @@ -260,7 +277,7 @@
1369    {     0, 0, jbig2HuffmanEOT, 0     }
1370  };
1371  
1372 -JBIG2HuffmanTable huffTableN[] = {
1373 +static JBIG2HuffmanTable huffTableN[] = {
1374    {     0, 1,  0,              0x000 },
1375    {    -2, 3,  0,              0x004 },
1376    {    -1, 3,  0,              0x005 },
1377 @@ -269,7 +286,7 @@
1378    {     0, 0, jbig2HuffmanEOT, 0     }
1379  };
1380  
1381 -JBIG2HuffmanTable huffTableO[] = {
1382 +static JBIG2HuffmanTable huffTableO[] = {
1383    {     0, 1,  0,              0x000 },
1384    {    -1, 3,  0,              0x004 },
1385    {     1, 3,  0,              0x005 },
1386 @@ -473,7 +490,7 @@
1387  }
1388  
1389  int JBIG2MMRDecoder::get2DCode() {
1390 -  CCITTCode *p;
1391 +  const CCITTCode *p;
1392  
1393    if (bufLen == 0) {
1394      buf = str->getChar() & 0xff;
1395 @@ -500,7 +517,7 @@
1396  }
1397  
1398  int JBIG2MMRDecoder::getWhiteCode() {
1399 -  CCITTCode *p;
1400 +  const CCITTCode *p;
1401    Guint code;
1402  
1403    if (bufLen == 0) {
1404 @@ -543,7 +560,7 @@
1405  }
1406  
1407  int JBIG2MMRDecoder::getBlackCode() {
1408 -  CCITTCode *p;
1409 +  const CCITTCode *p;
1410    Guint code;
1411  
1412    if (bufLen == 0) {
1413 @@ -670,6 +687,7 @@
1414    void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
1415    Guchar *getDataPtr() { return data; }
1416    int getDataSize() { return h * line; }
1417 +  GBool isOk() { return data != NULL; }
1418  
1419  private:
1420  
1421 @@ -685,10 +703,11 @@
1422    w = wA;
1423    h = hA;
1424    line = (wA + 7) >> 3;
1425 +
1426    if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
1427 -    // force a call to gmalloc(-1), which will throw an exception
1428 -    h = -1;
1429 -    line = 2;
1430 +    error(-1, "invalid width/height");
1431 +    data = NULL;
1432 +    return;
1433    }
1434    // need to allocate one extra guard byte for use in combine()
1435    data = (Guchar *)gmalloc(h * line + 1);
1436 @@ -701,10 +720,11 @@
1437    w = bitmap->w;
1438    h = bitmap->h;
1439    line = bitmap->line;
1440 +
1441    if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
1442 -    // force a call to gmalloc(-1), which will throw an exception
1443 -    h = -1;
1444 -    line = 2;
1445 +    error(-1, "invalid width/height");
1446 +    data = NULL;
1447 +    return;
1448    }
1449    // need to allocate one extra guard byte for use in combine()
1450    data = (Guchar *)gmalloc(h * line + 1);
1451 @@ -735,6 +755,9 @@
1452  
1453  void JBIG2Bitmap::expand(int newH, Guint pixel) {
1454    if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) {
1455 +    error(-1, "invalid width/height");
1456 +    gfree(data);
1457 +    data = NULL;
1458      return;
1459    }
1460    // need to allocate one extra guard byte for use in combine()
1461 @@ -1002,6 +1025,7 @@
1462    Guint getSize() { return size; }
1463    void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1464    JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1465 +  GBool isOk() { return bitmaps != NULL; }
1466    void setGenericRegionStats(JArithmeticDecoderStats *stats)
1467      { genericRegionStats = stats; }
1468    void setRefinementRegionStats(JArithmeticDecoderStats *stats)
1469 @@ -1022,13 +1046,9 @@
1470  JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1471    JBIG2Segment(segNumA)
1472  {
1473 -  Guint i;
1474 -
1475    size = sizeA;
1476    bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1477 -  for (i = 0; i < size; ++i) {
1478 -    bitmaps[i] = NULL;
1479 -  }
1480 +  if (!bitmaps) size = 0;
1481    genericRegionStats = NULL;
1482    refinementRegionStats = NULL;
1483  }
1484 @@ -1037,9 +1057,7 @@
1485    Guint i;
1486  
1487    for (i = 0; i < size; ++i) {
1488 -    if (bitmaps[i]) {
1489 -      delete bitmaps[i];
1490 -    }
1491 +    delete bitmaps[i];
1492    }
1493    gfree(bitmaps);
1494    if (genericRegionStats) {
1495 @@ -1247,6 +1265,7 @@
1496    Guint segNum, segFlags, segType, page, segLength;
1497    Guint refFlags, nRefSegs;
1498    Guint *refSegs;
1499 +  int segDataPos;
1500    int c1, c2, c3;
1501    Guint i;
1502  
1503 @@ -1314,6 +1333,9 @@
1504        goto eofError2;
1505      }
1506  
1507 +    // keep track of the start of the segment data 
1508 +    segDataPos = getPos();
1509 +
1510      // check for missing page information segment
1511      if (!pageBitmap && ((segType >= 4 && segType <= 7) ||
1512                         (segType >= 20 && segType <= 43))) {
1513 @@ -1398,6 +1420,45 @@
1514        break;
1515      }
1516  
1517 +    // Make sure the segment handler read all of the bytes in the 
1518 +    // segment data, unless this segment is marked as having an
1519 +    // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft)
1520 +
1521 +    if (segLength != 0xffffffff) {
1522 +
1523 +      int segExtraBytes = segDataPos + segLength - getPos();
1524 +      if (segExtraBytes > 0) {
1525 +
1526 +       // If we didn't read all of the bytes in the segment data,
1527 +       // indicate an error, and throw away the rest of the data.
1528 +       
1529 +       // v.3.1.01.13 of the LuraTech PDF Compressor Server will
1530 +       // sometimes generate an extraneous NULL byte at the end of
1531 +       // arithmetic-coded symbol dictionary segments when numNewSyms
1532 +       // == 0.  Segments like this often occur for blank pages.
1533 +       
1534 +       error(getPos(), "%d extraneous byte%s after segment",
1535 +             segExtraBytes, (segExtraBytes > 1) ? "s" : "");
1536 +       
1537 +       // Burn through the remaining bytes -- inefficient, but
1538 +       // hopefully we're not doing this much
1539 +       
1540 +       int trash;
1541 +       for (int i = segExtraBytes; i > 0; i--) {
1542 +         readByte(&trash);
1543 +       }
1544 +       
1545 +      } else if (segExtraBytes < 0) {
1546 +       
1547 +       // If we read more bytes than we should have, according to the 
1548 +       // segment length field, note an error.
1549 +       
1550 +       error(getPos(), "Previous segment handler read too many bytes");
1551 +       
1552 +      }
1553 +
1554 +    }
1555 +    
1556      gfree(refSegs);
1557    }
1558  
1559 @@ -1493,6 +1554,9 @@
1560    codeTables = new GList();
1561    numInputSyms = 0;
1562    for (i = 0; i < nRefSegs; ++i) {
1563 +    // This is need by bug 12014, returning gFalse makes it not crash
1564 +    // but we end up with a empty page while acroread is able to render
1565 +    // part of it
1566      if ((seg = findSegment(refSegs[i]))) {
1567        if (seg->getType() == jbig2SegSymbolDict) {
1568         j = ((JBIG2SymbolDict *)seg)->getSize();
1569 @@ -1503,8 +1567,11 @@
1570         }
1571         numInputSyms += j;
1572        } else if (seg->getType() == jbig2SegCodeTable) {
1573 -       codeTables->append(seg);
1574 +        codeTables->append(seg);
1575        }
1576 +    } else {
1577 +      delete codeTables;
1578 +      return gFalse;
1579      }
1580    }
1581    if (numInputSyms > UINT_MAX - numNewSyms) {
1582 @@ -1530,12 +1600,11 @@
1583    k = 0;
1584    inputSymbolDict = NULL;
1585    for (i = 0; i < nRefSegs; ++i) {
1586 -    if ((seg = findSegment(refSegs[i]))) {
1587 -      if (seg->getType() == jbig2SegSymbolDict) {
1588 -       inputSymbolDict = (JBIG2SymbolDict *)seg;
1589 -       for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1590 -         bitmaps[k++] = inputSymbolDict->getBitmap(j);
1591 -       }
1592 +    seg = findSegment(refSegs[i]);
1593 +    if (seg != NULL && seg->getType() == jbig2SegSymbolDict) {
1594 +      inputSymbolDict = (JBIG2SymbolDict *)seg;
1595 +      for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1596 +       bitmaps[k++] = inputSymbolDict->getBitmap(j);
1597        }
1598      }
1599    }
1600 @@ -1753,6 +1822,10 @@
1601  
1602    // create the symbol dict object
1603    symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1604 +  if (!symbolDict->isOk()) {
1605 +    delete symbolDict;
1606 +    goto syntaxError;
1607 +  }
1608  
1609    // exported symbol list
1610    i = j = 0;
1611 @@ -1766,6 +1839,7 @@
1612      if (i + run > numInputSyms + numNewSyms ||
1613         (ex && j + run > numExSyms)) {
1614        error(getPos(), "Too many exported symbols in JBIG2 symbol dictionary");
1615 +      for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL);
1616        delete symbolDict;
1617        goto syntaxError;
1618      }
1619 @@ -1780,6 +1854,7 @@
1620    }
1621    if (j != numExSyms) {
1622      error(getPos(), "Too few symbols in JBIG2 symbol dictionary");
1623 +    for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL);
1624      delete symbolDict;
1625      goto syntaxError;
1626    }
1627 @@ -2095,18 +2170,20 @@
1628  
1629    gfree(syms);
1630  
1631 -  // combine the region bitmap into the page bitmap
1632 -  if (imm) {
1633 -    if (pageH == 0xffffffff && y + h > curPageH) {
1634 -      pageBitmap->expand(y + h, pageDefPixel);
1635 -    }
1636 -    pageBitmap->combine(bitmap, x, y, extCombOp);
1637 -    delete bitmap;
1638 +  if (bitmap) {
1639 +    // combine the region bitmap into the page bitmap
1640 +    if (imm) {
1641 +      if (pageH == 0xffffffff && y + h > curPageH) {
1642 +        pageBitmap->expand(y + h, pageDefPixel);
1643 +      }
1644 +      pageBitmap->combine(bitmap, x, y, extCombOp);
1645 +      delete bitmap;
1646  
1647 -  // store the region bitmap
1648 -  } else {
1649 -    bitmap->setSegNum(segNum);
1650 -    segments->append(bitmap);
1651 +    // store the region bitmap
1652 +    } else {
1653 +      bitmap->setSegNum(segNum);
1654 +      segments->append(bitmap);
1655 +    }
1656    }
1657  
1658    // clean up the Huffman decoder
1659 @@ -2159,6 +2236,10 @@
1660  
1661    // allocate the bitmap
1662    bitmap = new JBIG2Bitmap(0, w, h);
1663 +  if (!bitmap->isOk()) {
1664 +    delete bitmap;
1665 +    return NULL;
1666 +  }
1667    if (defPixel) {
1668      bitmap->clearToOne();
1669    } else {
1670 @@ -2235,73 +2316,84 @@
1671           ri = 0;
1672         }
1673         if (ri) {
1674 +         GBool decodeSuccess;
1675           if (huff) {
1676 -           huffDecoder->decodeInt(&rdw, huffRDWTable);
1677 -           huffDecoder->decodeInt(&rdh, huffRDHTable);
1678 -           huffDecoder->decodeInt(&rdx, huffRDXTable);
1679 -           huffDecoder->decodeInt(&rdy, huffRDYTable);
1680 -           huffDecoder->decodeInt(&bmSize, huffRSizeTable);
1681 +           decodeSuccess = huffDecoder->decodeInt(&rdw, huffRDWTable);
1682 +           decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdh, huffRDHTable);
1683 +           decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdx, huffRDXTable);
1684 +           decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdy, huffRDYTable);
1685 +           decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&bmSize, huffRSizeTable);
1686             huffDecoder->reset();
1687             arithDecoder->start();
1688           } else {
1689 -           arithDecoder->decodeInt(&rdw, iardwStats);
1690 -           arithDecoder->decodeInt(&rdh, iardhStats);
1691 -           arithDecoder->decodeInt(&rdx, iardxStats);
1692 -           arithDecoder->decodeInt(&rdy, iardyStats);
1693 +           decodeSuccess = arithDecoder->decodeInt(&rdw, iardwStats);
1694 +           decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdh, iardhStats);
1695 +           decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdx, iardxStats);
1696 +           decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdy, iardyStats);
1697 +         }
1698 +         
1699 +         if (decodeSuccess && syms[symID])
1700 +         {
1701 +           refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
1702 +           refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
1703 +
1704 +           symbolBitmap =
1705 +             readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
1706 +                                         rdh + syms[symID]->getHeight(),
1707 +                                         templ, gFalse, syms[symID],
1708 +                                         refDX, refDY, atx, aty);
1709           }
1710 -         refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
1711 -         refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
1712 -
1713 -         symbolBitmap =
1714 -           readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
1715 -                                       rdh + syms[symID]->getHeight(),
1716 -                                       templ, gFalse, syms[symID],
1717 -                                       refDX, refDY, atx, aty);
1718           //~ do we need to use the bmSize value here (in Huffman mode)?
1719         } else {
1720           symbolBitmap = syms[symID];
1721         }
1722  
1723 -       // combine the symbol bitmap into the region bitmap
1724 -       //~ something is wrong here - refCorner shouldn't degenerate into
1725 -       //~   two cases
1726 -       bw = symbolBitmap->getWidth() - 1;
1727 -       bh = symbolBitmap->getHeight() - 1;
1728 -       if (transposed) {
1729 -         switch (refCorner) {
1730 -         case 0: // bottom left
1731 -           bitmap->combine(symbolBitmap, tt, s, combOp);
1732 -           break;
1733 -         case 1: // top left
1734 -           bitmap->combine(symbolBitmap, tt, s, combOp);
1735 -           break;
1736 -         case 2: // bottom right
1737 -           bitmap->combine(symbolBitmap, tt - bw, s, combOp);
1738 -           break;
1739 -         case 3: // top right
1740 -           bitmap->combine(symbolBitmap, tt - bw, s, combOp);
1741 -           break;
1742 +       if (symbolBitmap) {
1743 +         // combine the symbol bitmap into the region bitmap
1744 +         //~ something is wrong here - refCorner shouldn't degenerate into
1745 +         //~   two cases
1746 +         bw = symbolBitmap->getWidth() - 1;
1747 +         bh = symbolBitmap->getHeight() - 1;
1748 +         if (transposed) {
1749 +           switch (refCorner) {
1750 +           case 0: // bottom left
1751 +             bitmap->combine(symbolBitmap, tt, s, combOp);
1752 +             break;
1753 +           case 1: // top left
1754 +             bitmap->combine(symbolBitmap, tt, s, combOp);
1755 +             break;
1756 +           case 2: // bottom right
1757 +             bitmap->combine(symbolBitmap, tt - bw, s, combOp);
1758 +             break;
1759 +           case 3: // top right
1760 +             bitmap->combine(symbolBitmap, tt - bw, s, combOp);
1761 +             break;
1762 +           }
1763 +           s += bh;
1764 +         } else {
1765 +           switch (refCorner) {
1766 +           case 0: // bottom left
1767 +             bitmap->combine(symbolBitmap, s, tt - bh, combOp);
1768 +             break;
1769 +           case 1: // top left
1770 +             bitmap->combine(symbolBitmap, s, tt, combOp);
1771 +             break;
1772 +           case 2: // bottom right
1773 +             bitmap->combine(symbolBitmap, s, tt - bh, combOp);
1774 +             break;
1775 +           case 3: // top right
1776 +             bitmap->combine(symbolBitmap, s, tt, combOp);
1777 +             break;
1778 +           }
1779 +           s += bw;
1780           }
1781 -         s += bh;
1782 -       } else {
1783 -         switch (refCorner) {
1784 -         case 0: // bottom left
1785 -           bitmap->combine(symbolBitmap, s, tt - bh, combOp);
1786 -           break;
1787 -         case 1: // top left
1788 -           bitmap->combine(symbolBitmap, s, tt, combOp);
1789 -           break;
1790 -         case 2: // bottom right
1791 -           bitmap->combine(symbolBitmap, s, tt - bh, combOp);
1792 -           break;
1793 -         case 3: // top right
1794 -           bitmap->combine(symbolBitmap, s, tt, combOp);
1795 -           break;
1796 +         if (ri) {
1797 +           delete symbolBitmap;
1798           }
1799 -         s += bw;
1800 -       }
1801 -       if (ri) {
1802 -         delete symbolBitmap;
1803 +       } else {
1804 +         // NULL symbolBitmap only happens on error
1805 +         delete bitmap;
1806 +         return NULL;
1807         }
1808        }
1809  
1810 @@ -2431,11 +2523,12 @@
1811      error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
1812      return;
1813    }
1814 -  if (!(seg = findSegment(refSegs[0])) ||
1815 -      seg->getType() != jbig2SegPatternDict) {
1816 +  seg = findSegment(refSegs[0]);
1817 +  if (seg == NULL || seg->getType() != jbig2SegPatternDict) {
1818      error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
1819      return;
1820    }
1821 +
1822    patternDict = (JBIG2PatternDict *)seg;
1823    bpp = 0;
1824    i = 1;
1825 @@ -2591,6 +2684,8 @@
1826    // read the bitmap
1827    bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
1828                              NULL, atx, aty, mmr ? length - 18 : 0);
1829 +  if (!bitmap)
1830 +    return;
1831  
1832    // combine the region bitmap into the page bitmap
1833    if (imm) {
1834 @@ -2616,7 +2711,7 @@
1835                                       int *codingLine, int *a0i, int w) {
1836    if (a1 > codingLine[*a0i]) {
1837      if (a1 > w) {
1838 -      error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1);
1839 +      error(getPos(), "JBIG2 MMR row is wrong length (%d)", a1);
1840        a1 = w;
1841      }
1842      if ((*a0i & 1) ^ blackPixels) {
1843 @@ -2630,7 +2725,7 @@
1844                                          int *codingLine, int *a0i, int w) {
1845    if (a1 > codingLine[*a0i]) {
1846      if (a1 > w) {
1847 -      error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1);
1848 +      error(getPos(), "JBIG2 MMR row is wrong length (%d)", a1);
1849        a1 = w;
1850      }
1851      if ((*a0i & 1) ^ blackPixels) {
1852 @@ -2657,13 +2752,17 @@
1853    JBIG2Bitmap *bitmap;
1854    GBool ltp;
1855    Guint ltpCX, cx, cx0, cx1, cx2;
1856 -  JBIG2BitmapPtr cxPtr0, cxPtr1;
1857 -  JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
1858 +  JBIG2BitmapPtr cxPtr0 = {0}, cxPtr1 = {0};
1859 +  JBIG2BitmapPtr atPtr0 = {0}, atPtr1 = {0}, atPtr2 = {0}, atPtr3 = {0};
1860    int *refLine, *codingLine;
1861    int code1, code2, code3;
1862    int x, y, a0i, b1i, blackPixels, pix, i;
1863  
1864    bitmap = new JBIG2Bitmap(0, w, h);
1865 +  if (!bitmap->isOk()) {
1866 +    delete bitmap;
1867 +    return NULL;
1868 +  }
1869    bitmap->clearToZero();
1870  
1871    //----- MMR decode
1872 @@ -2682,7 +2781,7 @@
1873      // ---> max refLine size = w + 2
1874      codingLine = (int *)gmallocn(w + 1, sizeof(int));
1875      refLine = (int *)gmallocn(w + 2, sizeof(int));
1876 -    codingLine[0] = w;
1877 +    for (i = 0; i < w + 1; ++i) codingLine[i] = w;
1878  
1879      for (y = 0; y < h; ++y) {
1880  
1881 @@ -3093,8 +3192,8 @@
1882      return;
1883    }
1884    if (nRefSegs == 1) {
1885 -    if (!(seg = findSegment(refSegs[0])) ||
1886 -       seg->getType() != jbig2SegBitmap) {
1887 +    seg = findSegment(refSegs[0]);
1888 +    if (seg == NULL || seg->getType() != jbig2SegBitmap) {
1889        error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
1890        return;
1891      }
1892 @@ -3143,11 +3242,24 @@
1893    JBIG2Bitmap *bitmap;
1894    GBool ltp;
1895    Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
1896 -  JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
1897 -  JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
1898 +  JBIG2BitmapPtr cxPtr0 = {0};
1899 +  JBIG2BitmapPtr cxPtr1 = {0};
1900 +  JBIG2BitmapPtr cxPtr2 = {0};
1901 +  JBIG2BitmapPtr cxPtr3 = {0};
1902 +  JBIG2BitmapPtr cxPtr4 = {0};
1903 +  JBIG2BitmapPtr cxPtr5 = {0};
1904 +  JBIG2BitmapPtr cxPtr6 = {0};
1905 +  JBIG2BitmapPtr tpgrCXPtr0 = {0};
1906 +  JBIG2BitmapPtr tpgrCXPtr1 = {0};
1907 +  JBIG2BitmapPtr tpgrCXPtr2 = {0};
1908    int x, y, pix;
1909  
1910    bitmap = new JBIG2Bitmap(0, w, h);
1911 +  if (!bitmap->isOk())
1912 +  {
1913 +    delete bitmap;
1914 +    return NULL;
1915 +  }
1916    bitmap->clearToZero();
1917  
1918    // set up the typical row context
1919 @@ -3332,6 +3444,12 @@
1920    }
1921    pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
1922  
1923 +  if (!pageBitmap->isOk()) {
1924 +    delete pageBitmap;
1925 +    pageBitmap = NULL;
1926 +    return;
1927 +  }
1928 +  
1929    // default pixel value
1930    if (pageDefPixel) {
1931      pageBitmap->clearToOne();