Coverage Report

Created: 2022-04-12 06:19

/src/xpdf-4.03/xpdf/JBIG2Stream.cc
Line
Count
Source (jump to first uncovered line)
1
//========================================================================
2
//
3
// JBIG2Stream.cc
4
//
5
// Copyright 2002-2003 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#ifdef USE_GCC_PRAGMAS
12
#pragma implementation
13
#endif
14
15
#include <stdlib.h>
16
#include <limits.h>
17
#include "gmempp.h"
18
#include "GList.h"
19
#include "Error.h"
20
#include "JArithmeticDecoder.h"
21
#include "JBIG2Stream.h"
22
23
//~ share these tables
24
#include "Stream-CCITT.h"
25
26
//------------------------------------------------------------------------
27
28
static int contextSize[4] = { 16, 13, 10, 10 };
29
static int refContextSize[2] = { 13, 10 };
30
31
//------------------------------------------------------------------------
32
// JBIG2HuffmanTable
33
//------------------------------------------------------------------------
34
35
4.62M
#define jbig2HuffmanLOW 0xfffffffd
36
4.62M
#define jbig2HuffmanOOB 0xfffffffe
37
101M
#define jbig2HuffmanEOT 0xffffffff
38
39
struct JBIG2HuffmanTable {
40
  int val;
41
  Guint prefixLen;
42
  Guint rangeLen;   // can also be LOW, OOB, or EOT
43
  Guint prefix;
44
};
45
46
JBIG2HuffmanTable huffTableA[] = {
47
  {     0, 1,  4,              0x000 },
48
  {    16, 2,  8,              0x002 },
49
  {   272, 3, 16,              0x006 },
50
  { 65808, 3, 32,              0x007 },
51
  {     0, 0, jbig2HuffmanEOT, 0     }
52
};
53
54
JBIG2HuffmanTable huffTableB[] = {
55
  {     0, 1,  0,              0x000 },
56
  {     1, 2,  0,              0x002 },
57
  {     2, 3,  0,              0x006 },
58
  {     3, 4,  3,              0x00e },
59
  {    11, 5,  6,              0x01e },
60
  {    75, 6, 32,              0x03e },
61
  {     0, 6, jbig2HuffmanOOB, 0x03f },
62
  {     0, 0, jbig2HuffmanEOT, 0     }
63
};
64
65
JBIG2HuffmanTable huffTableC[] = {
66
  {     0, 1,  0,              0x000 },
67
  {     1, 2,  0,              0x002 },
68
  {     2, 3,  0,              0x006 },
69
  {     3, 4,  3,              0x00e },
70
  {    11, 5,  6,              0x01e },
71
  {     0, 6, jbig2HuffmanOOB, 0x03e },
72
  {    75, 7, 32,              0x0fe },
73
  {  -256, 8,  8,              0x0fe },
74
  {  -257, 8, jbig2HuffmanLOW, 0x0ff },
75
  {     0, 0, jbig2HuffmanEOT, 0     }
76
};
77
78
JBIG2HuffmanTable huffTableD[] = {
79
  {     1, 1,  0,              0x000 },
80
  {     2, 2,  0,              0x002 },
81
  {     3, 3,  0,              0x006 },
82
  {     4, 4,  3,              0x00e },
83
  {    12, 5,  6,              0x01e },
84
  {    76, 5, 32,              0x01f },
85
  {     0, 0, jbig2HuffmanEOT, 0     }
86
};
87
88
JBIG2HuffmanTable huffTableE[] = {
89
  {     1, 1,  0,              0x000 },
90
  {     2, 2,  0,              0x002 },
91
  {     3, 3,  0,              0x006 },
92
  {     4, 4,  3,              0x00e },
93
  {    12, 5,  6,              0x01e },
94
  {    76, 6, 32,              0x03e },
95
  {  -255, 7,  8,              0x07e },
96
  {  -256, 7, jbig2HuffmanLOW, 0x07f },
97
  {     0, 0, jbig2HuffmanEOT, 0     }
98
};
99
100
JBIG2HuffmanTable huffTableF[] = {
101
  {     0, 2,  7,              0x000 },
102
  {   128, 3,  7,              0x002 },
103
  {   256, 3,  8,              0x003 },
104
  { -1024, 4,  9,              0x008 },
105
  {  -512, 4,  8,              0x009 },
106
  {  -256, 4,  7,              0x00a },
107
  {   -32, 4,  5,              0x00b },
108
  {   512, 4,  9,              0x00c },
109
  {  1024, 4, 10,              0x00d },
110
  { -2048, 5, 10,              0x01c },
111
  {  -128, 5,  6,              0x01d },
112
  {   -64, 5,  5,              0x01e },
113
  { -2049, 6, jbig2HuffmanLOW, 0x03e },
114
  {  2048, 6, 32,              0x03f },
115
  {     0, 0, jbig2HuffmanEOT, 0     }
116
};
117
118
JBIG2HuffmanTable huffTableG[] = {
119
  {  -512, 3,  8,              0x000 },
120
  {   256, 3,  8,              0x001 },
121
  {   512, 3,  9,              0x002 },
122
  {  1024, 3, 10,              0x003 },
123
  { -1024, 4,  9,              0x008 },
124
  {  -256, 4,  7,              0x009 },
125
  {   -32, 4,  5,              0x00a },
126
  {     0, 4,  5,              0x00b },
127
  {   128, 4,  7,              0x00c },
128
  {  -128, 5,  6,              0x01a },
129
  {   -64, 5,  5,              0x01b },
130
  {    32, 5,  5,              0x01c },
131
  {    64, 5,  6,              0x01d },
132
  { -1025, 5, jbig2HuffmanLOW, 0x01e },
133
  {  2048, 5, 32,              0x01f },
134
  {     0, 0, jbig2HuffmanEOT, 0     }
135
};
136
137
JBIG2HuffmanTable huffTableH[] = {
138
  {     0, 2,  1,              0x000 },
139
  {     0, 2, jbig2HuffmanOOB, 0x001 },
140
  {     4, 3,  4,              0x004 },
141
  {    -1, 4,  0,              0x00a },
142
  {    22, 4,  4,              0x00b },
143
  {    38, 4,  5,              0x00c },
144
  {     2, 5,  0,              0x01a },
145
  {    70, 5,  6,              0x01b },
146
  {   134, 5,  7,              0x01c },
147
  {     3, 6,  0,              0x03a },
148
  {    20, 6,  1,              0x03b },
149
  {   262, 6,  7,              0x03c },
150
  {   646, 6, 10,              0x03d },
151
  {    -2, 7,  0,              0x07c },
152
  {   390, 7,  8,              0x07d },
153
  {   -15, 8,  3,              0x0fc },
154
  {    -5, 8,  1,              0x0fd },
155
  {    -7, 9,  1,              0x1fc },
156
  {    -3, 9,  0,              0x1fd },
157
  {   -16, 9, jbig2HuffmanLOW, 0x1fe },
158
  {  1670, 9, 32,              0x1ff },
159
  {     0, 0, jbig2HuffmanEOT, 0     }
160
};
161
162
JBIG2HuffmanTable huffTableI[] = {
163
  {     0, 2, jbig2HuffmanOOB, 0x000 },
164
  {    -1, 3,  1,              0x002 },
165
  {     1, 3,  1,              0x003 },
166
  {     7, 3,  5,              0x004 },
167
  {    -3, 4,  1,              0x00a },
168
  {    43, 4,  5,              0x00b },
169
  {    75, 4,  6,              0x00c },
170
  {     3, 5,  1,              0x01a },
171
  {   139, 5,  7,              0x01b },
172
  {   267, 5,  8,              0x01c },
173
  {     5, 6,  1,              0x03a },
174
  {    39, 6,  2,              0x03b },
175
  {   523, 6,  8,              0x03c },
176
  {  1291, 6, 11,              0x03d },
177
  {    -5, 7,  1,              0x07c },
178
  {   779, 7,  9,              0x07d },
179
  {   -31, 8,  4,              0x0fc },
180
  {   -11, 8,  2,              0x0fd },
181
  {   -15, 9,  2,              0x1fc },
182
  {    -7, 9,  1,              0x1fd },
183
  {   -32, 9, jbig2HuffmanLOW, 0x1fe },
184
  {  3339, 9, 32,              0x1ff },
185
  {     0, 0, jbig2HuffmanEOT, 0     }
186
};
187
188
JBIG2HuffmanTable huffTableJ[] = {
189
  {    -2, 2,  2,              0x000 },
190
  {     6, 2,  6,              0x001 },
191
  {     0, 2, jbig2HuffmanOOB, 0x002 },
192
  {    -3, 5,  0,              0x018 },
193
  {     2, 5,  0,              0x019 },
194
  {    70, 5,  5,              0x01a },
195
  {     3, 6,  0,              0x036 },
196
  {   102, 6,  5,              0x037 },
197
  {   134, 6,  6,              0x038 },
198
  {   198, 6,  7,              0x039 },
199
  {   326, 6,  8,              0x03a },
200
  {   582, 6,  9,              0x03b },
201
  {  1094, 6, 10,              0x03c },
202
  {   -21, 7,  4,              0x07a },
203
  {    -4, 7,  0,              0x07b },
204
  {     4, 7,  0,              0x07c },
205
  {  2118, 7, 11,              0x07d },
206
  {    -5, 8,  0,              0x0fc },
207
  {     5, 8,  0,              0x0fd },
208
  {   -22, 8, jbig2HuffmanLOW, 0x0fe },
209
  {  4166, 8, 32,              0x0ff },
210
  {     0, 0, jbig2HuffmanEOT, 0     }
211
};
212
213
JBIG2HuffmanTable huffTableK[] = {
214
  {     1, 1,  0,              0x000 },
215
  {     2, 2,  1,              0x002 },
216
  {     4, 4,  0,              0x00c },
217
  {     5, 4,  1,              0x00d },
218
  {     7, 5,  1,              0x01c },
219
  {     9, 5,  2,              0x01d },
220
  {    13, 6,  2,              0x03c },
221
  {    17, 7,  2,              0x07a },
222
  {    21, 7,  3,              0x07b },
223
  {    29, 7,  4,              0x07c },
224
  {    45, 7,  5,              0x07d },
225
  {    77, 7,  6,              0x07e },
226
  {   141, 7, 32,              0x07f },
227
  {     0, 0, jbig2HuffmanEOT, 0     }
228
};
229
230
JBIG2HuffmanTable huffTableL[] = {
231
  {     1, 1,  0,              0x000 },
232
  {     2, 2,  0,              0x002 },
233
  {     3, 3,  1,              0x006 },
234
  {     5, 5,  0,              0x01c },
235
  {     6, 5,  1,              0x01d },
236
  {     8, 6,  1,              0x03c },
237
  {    10, 7,  0,              0x07a },
238
  {    11, 7,  1,              0x07b },
239
  {    13, 7,  2,              0x07c },
240
  {    17, 7,  3,              0x07d },
241
  {    25, 7,  4,              0x07e },
242
  {    41, 8,  5,              0x0fe },
243
  {    73, 8, 32,              0x0ff },
244
  {     0, 0, jbig2HuffmanEOT, 0     }
245
};
246
247
JBIG2HuffmanTable huffTableM[] = {
248
  {     1, 1,  0,              0x000 },
249
  {     2, 3,  0,              0x004 },
250
  {     7, 3,  3,              0x005 },
251
  {     3, 4,  0,              0x00c },
252
  {     5, 4,  1,              0x00d },
253
  {     4, 5,  0,              0x01c },
254
  {    15, 6,  1,              0x03a },
255
  {    17, 6,  2,              0x03b },
256
  {    21, 6,  3,              0x03c },
257
  {    29, 6,  4,              0x03d },
258
  {    45, 6,  5,              0x03e },
259
  {    77, 7,  6,              0x07e },
260
  {   141, 7, 32,              0x07f },
261
  {     0, 0, jbig2HuffmanEOT, 0     }
262
};
263
264
JBIG2HuffmanTable huffTableN[] = {
265
  {     0, 1,  0,              0x000 },
266
  {    -2, 3,  0,              0x004 },
267
  {    -1, 3,  0,              0x005 },
268
  {     1, 3,  0,              0x006 },
269
  {     2, 3,  0,              0x007 },
270
  {     0, 0, jbig2HuffmanEOT, 0     }
271
};
272
273
JBIG2HuffmanTable huffTableO[] = {
274
  {     0, 1,  0,              0x000 },
275
  {    -1, 3,  0,              0x004 },
276
  {     1, 3,  0,              0x005 },
277
  {    -2, 4,  0,              0x00c },
278
  {     2, 4,  0,              0x00d },
279
  {    -4, 5,  1,              0x01c },
280
  {     3, 5,  1,              0x01d },
281
  {    -8, 6,  2,              0x03c },
282
  {     5, 6,  2,              0x03d },
283
  {   -24, 7,  4,              0x07c },
284
  {     9, 7,  4,              0x07d },
285
  {   -25, 7, jbig2HuffmanLOW, 0x07e },
286
  {    25, 7, 32,              0x07f },
287
  {     0, 0, jbig2HuffmanEOT, 0     }
288
};
289
290
//------------------------------------------------------------------------
291
// JBIG2HuffmanDecoder
292
//------------------------------------------------------------------------
293
294
class JBIG2HuffmanDecoder {
295
public:
296
297
  JBIG2HuffmanDecoder();
298
  ~JBIG2HuffmanDecoder();
299
2.16k
  void setStream(Stream *strA) { str = strA; }
300
301
  void reset();
302
303
  // Returns false for OOB, otherwise sets *<x> and returns true.
304
  GBool decodeInt(int *x, JBIG2HuffmanTable *table);
305
306
  Guint readBits(Guint n);
307
  Guint readBit();
308
309
  // Sort the table by prefix length and assign prefix values.
310
  void buildTable(JBIG2HuffmanTable *table, Guint len);
311
312
3.24k
  void resetByteCounter() { byteCounter = 0; }
313
2.14k
  Guint getByteCounter() { return byteCounter; }
314
315
private:
316
317
  Stream *str;
318
  Guint buf;
319
  Guint bufLen;
320
  Guint byteCounter;
321
};
322
323
251k
JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
324
251k
  str = NULL;
325
251k
  byteCounter = 0;
326
251k
  reset();
327
251k
}
328
329
250k
JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
330
250k
}
331
332
251k
void JBIG2HuffmanDecoder::reset() {
333
251k
  buf = 0;
334
251k
  bufLen = 0;
335
251k
}
336
337
//~ optimize this
338
9.25M
GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
339
9.25M
  Guint i, len, prefix;
340
341
9.25M
  i = 0;
342
9.25M
  len = 0;
343
9.25M
  prefix = 0;
344
101M
  while (table[i].rangeLen != jbig2HuffmanEOT) {
345
138M
    while (len < table[i].prefixLen) {
346
41.6M
      prefix = (prefix << 1) | readBit();
347
41.6M
      ++len;
348
41.6M
    }
349
97.1M
    if (prefix == table[i].prefix) {
350
4.62M
      if (table[i].rangeLen == jbig2HuffmanOOB) {
351
30
  return gFalse;
352
30
      }
353
4.62M
      if (table[i].rangeLen == jbig2HuffmanLOW) {
354
0
  *x = table[i].val - readBits(32);
355
4.62M
      } else if (table[i].rangeLen > 0) {
356
4.62M
  *x = table[i].val + readBits(table[i].rangeLen);
357
4.62M
      } else {
358
26
  *x = table[i].val;
359
26
      }
360
4.62M
      return gTrue;
361
4.62M
    }
362
92.5M
    ++i;
363
92.5M
  }
364
4.62M
  return gFalse;
365
9.25M
}
366
367
4.85M
Guint JBIG2HuffmanDecoder::readBits(Guint n) {
368
4.85M
  Guint x, mask, nLeft;
369
370
4.85M
  mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
371
4.85M
  if (bufLen >= n) {
372
159k
    x = (buf >> (bufLen - n)) & mask;
373
159k
    bufLen -= n;
374
4.70M
  } else {
375
4.70M
    x = buf & ((1 << bufLen) - 1);
376
4.70M
    nLeft = n - bufLen;
377
4.70M
    bufLen = 0;
378
19.1M
    while (nLeft >= 8) {
379
14.4M
      x = (x << 8) | (str->getChar() & 0xff);
380
14.4M
      ++byteCounter;
381
14.4M
      nLeft -= 8;
382
14.4M
    }
383
4.70M
    if (nLeft > 0) {
384
4.12M
      buf = str->getChar();
385
4.12M
      ++byteCounter;
386
4.12M
      bufLen = 8 - nLeft;
387
4.12M
      x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
388
4.12M
    }
389
4.70M
  }
390
4.85M
  return x;
391
4.85M
}
392
393
41.6M
Guint JBIG2HuffmanDecoder::readBit() {
394
41.6M
  if (bufLen == 0) {
395
5.20M
    buf = str->getChar();
396
5.20M
    ++byteCounter;
397
5.20M
    bufLen = 8;
398
5.20M
  }
399
41.6M
  --bufLen;
400
41.6M
  return (buf >> bufLen) & 1;
401
41.6M
}
402
403
21
void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
404
21
  Guint i, j, k, prefix;
405
21
  JBIG2HuffmanTable tab;
406
407
  // stable selection sort:
408
  // - entries with prefixLen > 0, in ascending prefixLen order
409
  // - entry with prefixLen = 0, rangeLen = EOT
410
  // - all other entries with prefixLen = 0
411
  // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
412
115k
  for (i = 0; i < len; ++i) {
413
5.16M
    for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
414
115k
    if (j == len) {
415
17
      break;
416
17
    }
417
413M
    for (k = j + 1; k < len; ++k) {
418
413M
      if (table[k].prefixLen > 0 &&
419
413M
    table[k].prefixLen < table[j].prefixLen) {
420
54
  j = k;
421
54
      }
422
413M
    }
423
115k
    if (j != i) {
424
115k
      tab = table[j];
425
5.16M
      for (k = j; k > i; --k) {
426
5.05M
  table[k] = table[k - 1];
427
5.05M
      }
428
115k
      table[i] = tab;
429
115k
    }
430
115k
  }
431
21
  table[i] = table[len];
432
433
  // assign prefixes
434
21
  if (table[0].rangeLen != jbig2HuffmanEOT) {
435
20
    i = 0;
436
20
    prefix = 0;
437
20
    table[i++].prefix = prefix++;
438
115k
    for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
439
115k
      prefix <<= table[i].prefixLen - table[i-1].prefixLen;
440
115k
      table[i].prefix = prefix++;
441
115k
    }
442
20
  }
443
21
}
444
445
//------------------------------------------------------------------------
446
// JBIG2MMRDecoder
447
//------------------------------------------------------------------------
448
449
class JBIG2MMRDecoder {
450
public:
451
452
  JBIG2MMRDecoder();
453
  ~JBIG2MMRDecoder();
454
2.16k
  void setStream(Stream *strA) { str = strA; }
455
  void reset();
456
  int get2DCode();
457
  int getBlackCode();
458
  int getWhiteCode();
459
  Guint get24Bits();
460
3.24k
  void resetByteCounter() { byteCounter = 0; }
461
2.14k
  Guint getByteCounter() { return byteCounter; }
462
  void skipTo(Guint length);
463
464
private:
465
466
  Stream *str;
467
  Guint buf;
468
  Guint bufLen;
469
  Guint nBytesRead;
470
  Guint byteCounter;
471
};
472
473
251k
JBIG2MMRDecoder::JBIG2MMRDecoder() {
474
251k
  str = NULL;
475
251k
  byteCounter = 0;
476
251k
  reset();
477
251k
}
478
479
250k
JBIG2MMRDecoder::~JBIG2MMRDecoder() {
480
250k
}
481
482
251k
void JBIG2MMRDecoder::reset() {
483
251k
  buf = 0;
484
251k
  bufLen = 0;
485
251k
  nBytesRead = 0;
486
251k
}
487
488
0
int JBIG2MMRDecoder::get2DCode() {
489
0
  CCITTCode *p;
490
491
0
  if (bufLen == 0) {
492
0
    buf = str->getChar() & 0xff;
493
0
    bufLen = 8;
494
0
    ++nBytesRead;
495
0
    ++byteCounter;
496
0
    p = &twoDimTab1[(buf >> 1) & 0x7f];
497
0
  } else if (bufLen >= 7) {
498
0
    p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
499
0
  } else {
500
0
    p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
501
0
    if (p->bits < 0 || p->bits > (int)bufLen) {
502
0
      buf = (buf << 8) | (str->getChar() & 0xff);
503
0
      bufLen += 8;
504
0
      ++nBytesRead;
505
0
      ++byteCounter;
506
0
      p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
507
0
    }
508
0
  }
509
0
  if (p->bits < 0) {
510
0
    error(errSyntaxError, str->getPos(),
511
0
    "Bad two dim code in JBIG2 MMR stream");
512
0
    return EOF;
513
0
  }
514
0
  bufLen -= p->bits;
515
0
  return p->n;
516
0
}
517
518
0
int JBIG2MMRDecoder::getWhiteCode() {
519
0
  CCITTCode *p;
520
0
  Guint code;
521
522
0
  if (bufLen == 0) {
523
0
    buf = str->getChar() & 0xff;
524
0
    bufLen = 8;
525
0
    ++nBytesRead;
526
0
    ++byteCounter;
527
0
  }
528
0
  while (1) {
529
0
    if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
530
0
      if (bufLen <= 12) {
531
0
  code = buf << (12 - bufLen);
532
0
      } else {
533
0
  code = buf >> (bufLen - 12);
534
0
      }
535
0
      p = &whiteTab1[code & 0x1f];
536
0
    } else {
537
0
      if (bufLen <= 9) {
538
0
  code = buf << (9 - bufLen);
539
0
      } else {
540
0
  code = buf >> (bufLen - 9);
541
0
      }
542
0
      p = &whiteTab2[code & 0x1ff];
543
0
    }
544
0
    if (p->bits > 0 && p->bits <= (int)bufLen) {
545
0
      bufLen -= p->bits;
546
0
      return p->n;
547
0
    }
548
0
    if (bufLen >= 12) {
549
0
      break;
550
0
    }
551
0
    buf = (buf << 8) | (str->getChar() & 0xff);
552
0
    bufLen += 8;
553
0
    ++nBytesRead;
554
0
    ++byteCounter;
555
0
  }
556
0
  error(errSyntaxError, str->getPos(), "Bad white code in JBIG2 MMR stream");
557
  // eat a bit and return a positive number so that the caller doesn't
558
  // go into an infinite loop
559
0
  --bufLen;
560
0
  return 1;
561
0
}
562
563
0
int JBIG2MMRDecoder::getBlackCode() {
564
0
  CCITTCode *p;
565
0
  Guint code;
566
567
0
  if (bufLen == 0) {
568
0
    buf = str->getChar() & 0xff;
569
0
    bufLen = 8;
570
0
    ++nBytesRead;
571
0
    ++byteCounter;
572
0
  }
573
0
  while (1) {
574
0
    if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
575
0
      if (bufLen <= 13) {
576
0
  code = buf << (13 - bufLen);
577
0
      } else {
578
0
  code = buf >> (bufLen - 13);
579
0
      }
580
0
      p = &blackTab1[code & 0x7f];
581
0
    } else if (bufLen >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 &&
582
0
         ((buf >> (bufLen - 6)) & 0x03) != 0) {
583
0
      if (bufLen <= 12) {
584
0
  code = buf << (12 - bufLen);
585
0
      } else {
586
0
  code = buf >> (bufLen - 12);
587
0
      }
588
0
      p = &blackTab2[(code & 0xff) - 64];
589
0
    } else {
590
0
      if (bufLen <= 6) {
591
0
  code = buf << (6 - bufLen);
592
0
      } else {
593
0
  code = buf >> (bufLen - 6);
594
0
      }
595
0
      p = &blackTab3[code & 0x3f];
596
0
    }
597
0
    if (p->bits > 0 && p->bits <= (int)bufLen) {
598
0
      bufLen -= p->bits;
599
0
      return p->n;
600
0
    }
601
0
    if (bufLen >= 13) {
602
0
      break;
603
0
    }
604
0
    buf = (buf << 8) | (str->getChar() & 0xff);
605
0
    bufLen += 8;
606
0
    ++nBytesRead;
607
0
    ++byteCounter;
608
0
  }
609
0
  error(errSyntaxError, str->getPos(), "Bad black code in JBIG2 MMR stream");
610
  // eat a bit and return a positive number so that the caller doesn't
611
  // go into an infinite loop
612
0
  --bufLen;
613
0
  return 1;
614
0
}
615
616
0
Guint JBIG2MMRDecoder::get24Bits() {
617
0
  while (bufLen < 24) {
618
0
    buf = (buf << 8) | (str->getChar() & 0xff);
619
0
    bufLen += 8;
620
0
    ++nBytesRead;
621
0
    ++byteCounter;
622
0
  }
623
0
  return (buf >> (bufLen - 24)) & 0xffffff;
624
0
}
625
626
0
void JBIG2MMRDecoder::skipTo(Guint length) {
627
0
  int n;
628
629
0
  n = str->discardChars(length - nBytesRead);
630
0
  nBytesRead += n;
631
0
  byteCounter += n;
632
0
}
633
634
//------------------------------------------------------------------------
635
// JBIG2Segment
636
//------------------------------------------------------------------------
637
638
enum JBIG2SegmentType {
639
  jbig2SegBitmap,
640
  jbig2SegSymbolDict,
641
  jbig2SegPatternDict,
642
  jbig2SegCodeTable
643
};
644
645
class JBIG2Segment {
646
public:
647
648
4.57k
  JBIG2Segment(Guint segNumA) { segNum = segNumA; }
649
4.32k
  virtual ~JBIG2Segment() {}
650
0
  void setSegNum(Guint segNumA) { segNum = segNumA; }
651
10
  Guint getSegNum() { return segNum; }
652
  virtual JBIG2SegmentType getType() = 0;
653
654
private:
655
656
  Guint segNum;
657
};
658
659
//------------------------------------------------------------------------
660
// JBIG2Bitmap
661
//------------------------------------------------------------------------
662
663
struct JBIG2BitmapPtr {
664
  Guchar *p;
665
  int shift;
666
  int x;
667
};
668
669
class JBIG2Bitmap: public JBIG2Segment {
670
public:
671
672
  JBIG2Bitmap(Guint segNumA, int wA, int hA);
673
  virtual ~JBIG2Bitmap();
674
0
  virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
675
1
  JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
676
  JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
677
  void expand(int newH, Guint pixel);
678
  void clearToZero();
679
  void clearToOne();
680
477
  int getWidth() { return w; }
681
477
  int getHeight() { return h; }
682
43.0k
  int getLineSize() { return line; }
683
  int getPixel(int x, int y)
684
7.36M
    { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
685
7.36M
             (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
686
  void setPixel(int x, int y)
687
1.92M
    { data[y * line + (x >> 3)] |= (Guchar)(1 << (7 - (x & 7))); }
688
  void clearPixel(int x, int y)
689
0
    { data[y * line + (x >> 3)] &= (Guchar)(0x7f7f >> (x & 7)); }
690
  void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
691
  int nextPixel(JBIG2BitmapPtr *ptr);
692
  void duplicateRow(int yDest, int ySrc);
693
  void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
694
44.0k
  Guchar *getDataPtr() { return data; }
695
1.05k
  int getDataSize() { return h * line; }
696
697
private:
698
699
  JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
700
701
  int w, h, line;
702
  Guchar *data;
703
};
704
705
JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
706
  JBIG2Segment(segNumA)
707
4.54k
{
708
4.54k
  w = wA;
709
4.54k
  h = hA;
710
4.54k
  line = (wA + 7) >> 3;
711
4.54k
  if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
712
    // force a call to gmalloc(-1), which will throw an exception
713
18
    h = -1;
714
18
    line = 2;
715
18
  }
716
  // need to allocate one extra guard byte for use in combine()
717
4.54k
  data = (Guchar *)gmalloc(h * line + 1);
718
4.54k
  data[h * line] = 0;
719
4.54k
}
720
721
JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
722
  JBIG2Segment(segNumA)
723
1
{
724
1
  w = bitmap->w;
725
1
  h = bitmap->h;
726
1
  line = bitmap->line;
727
1
  if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
728
    // force a call to gmalloc(-1), which will throw an exception
729
0
    h = -1;
730
0
    line = 2;
731
0
  }
732
  // need to allocate one extra guard byte for use in combine()
733
1
  data = (Guchar *)gmalloc(h * line + 1);
734
1
  memcpy(data, bitmap->data, h * line);
735
1
  data[h * line] = 0;
736
1
}
737
738
4.29k
JBIG2Bitmap::~JBIG2Bitmap() {
739
4.29k
  gfree(data);
740
4.29k
}
741
742
//~ optimize this
743
56
JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
744
56
  JBIG2Bitmap *slice;
745
56
  Guint xx, yy;
746
747
56
  slice = new JBIG2Bitmap(0, wA, hA);
748
56
  slice->clearToZero();
749
14.2k
  for (yy = 0; yy < hA; ++yy) {
750
3.62M
    for (xx = 0; xx < wA; ++xx) {
751
3.61M
      if (getPixel(x + xx, y + yy)) {
752
1.77M
  slice->setPixel(xx, yy);
753
1.77M
      }
754
3.61M
    }
755
14.2k
  }
756
56
  return slice;
757
56
}
758
759
0
void JBIG2Bitmap::expand(int newH, Guint pixel) {
760
0
  if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) {
761
0
    return;
762
0
  }
763
  // need to allocate one extra guard byte for use in combine()
764
0
  data = (Guchar *)grealloc(data, newH * line + 1);
765
0
  if (pixel) {
766
0
    memset(data + h * line, 0xff, (newH - h) * line);
767
0
  } else {
768
0
    memset(data + h * line, 0x00, (newH - h) * line);
769
0
  }
770
0
  h = newH;
771
0
  data[h * line] = 0;
772
0
}
773
774
4.52k
void JBIG2Bitmap::clearToZero() {
775
4.52k
  memset(data, 0, h * line);
776
4.52k
}
777
778
1
void JBIG2Bitmap::clearToOne() {
779
1
  memset(data, 0xff, h * line);
780
1
}
781
782
14.3k
inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
783
14.3k
  if (y < 0 || y >= h || x >= w) {
784
8.14k
    ptr->p = NULL;
785
8.14k
    ptr->shift = 0; // make gcc happy
786
8.14k
    ptr->x = 0; // make gcc happy
787
8.14k
  } else if (x < 0) {
788
3.14k
    ptr->p = &data[y * line];
789
3.14k
    ptr->shift = 7;
790
3.14k
    ptr->x = x;
791
3.14k
  } else {
792
3.07k
    ptr->p = &data[y * line + (x >> 3)];
793
3.07k
    ptr->shift = 7 - (x & 7);
794
3.07k
    ptr->x = x;
795
3.07k
  }
796
14.3k
}
797
798
1.61M
inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
799
1.61M
  int pix;
800
801
1.61M
  if (!ptr->p) {
802
934k
    pix = 0;
803
934k
  } else if (ptr->x < 0) {
804
14.9k
    ++ptr->x;
805
14.9k
    pix = 0;
806
663k
  } else {
807
663k
    pix = (*ptr->p >> ptr->shift) & 1;
808
663k
    if (++ptr->x == w) {
809
3.17k
      ptr->p = NULL;
810
660k
    } else if (ptr->shift == 0) {
811
78.8k
      ++ptr->p;
812
78.8k
      ptr->shift = 7;
813
581k
    } else {
814
581k
      --ptr->shift;
815
581k
    }
816
663k
  }
817
1.61M
  return pix;
818
1.61M
}
819
820
0
void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
821
0
  memcpy(data + yDest * line, data + ySrc * line, line);
822
0
}
823
824
void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
825
240
        Guint combOp) {
826
240
  int x0, x1, y0, y1, xx, yy;
827
240
  Guchar *srcPtr, *destPtr;
828
240
  Guchar dest, src0, src1, src, m1, m2, m3;
829
240
  Guint s1, s2;
830
240
  GBool oneByte;
831
832
  // check for the pathological case where y = -2^31
833
240
  if (y < -0x7fffffff) {
834
0
    return;
835
0
  }
836
240
  if (y < 0) {
837
201
    y0 = -y;
838
201
  } else {
839
39
    y0 = 0;
840
39
  }
841
240
  if (y > INT_MAX - bitmap->h) {
842
0
    return;
843
0
  }
844
240
  if (y + bitmap->h > h) {
845
39
    y1 = h - y;
846
201
  } else {
847
201
    y1 = bitmap->h;
848
201
  }
849
240
  if (y0 >= y1) {
850
215
    return;
851
215
  }
852
853
25
  if (x >= 0) {
854
16
    x0 = x & ~7;
855
16
  } else {
856
9
    x0 = 0;
857
9
  }
858
25
  x1 = x + bitmap->w;
859
25
  if (x1 > w) {
860
14
    x1 = w;
861
14
  }
862
25
  if (x0 >= x1) {
863
17
    return;
864
17
  }
865
866
8
  s1 = x & 7;
867
8
  s2 = 8 - s1;
868
8
  m1 = (Guchar)(0xff >> (x1 & 7));
869
8
  m2 = (Guchar)(0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7)));
870
8
  m3 = (Guchar)((0xff >> s1) & m2);
871
872
8
  oneByte = x0 == ((x1 - 1) & ~7);
873
874
916
  for (yy = y0; yy < y1; ++yy) {
875
876
    // one byte per line -- need to mask both left and right side
877
908
    if (oneByte) {
878
0
      if (x >= 0) {
879
0
  destPtr = data + (y + yy) * line + (x >> 3);
880
0
  srcPtr = bitmap->data + yy * bitmap->line;
881
0
  dest = *destPtr;
882
0
  src1 = *srcPtr;
883
0
  switch (combOp) {
884
0
  case 0: // or
885
0
    dest |= (Guchar)((src1 >> s1) & m2);
886
0
    break;
887
0
  case 1: // and
888
0
    dest &= (Guchar)(((0xff00 | src1) >> s1) | m1);
889
0
    break;
890
0
  case 2: // xor
891
0
    dest ^= (Guchar)((src1 >> s1) & m2);
892
0
    break;
893
0
  case 3: // xnor
894
0
    dest ^= (Guchar)(((src1 ^ 0xff) >> s1) & m2);
895
0
    break;
896
0
  case 4: // replace
897
0
    dest = (Guchar)((dest & ~m3) | ((src1 >> s1) & m3));
898
0
    break;
899
0
  }
900
0
  *destPtr = dest;
901
0
      } else {
902
0
  destPtr = data + (y + yy) * line;
903
0
  srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
904
0
  dest = *destPtr;
905
0
  src1 = *srcPtr;
906
0
  switch (combOp) {
907
0
  case 0: // or
908
0
    dest |= src1 & m2;
909
0
    break;
910
0
  case 1: // and
911
0
    dest &= src1 | m1;
912
0
    break;
913
0
  case 2: // xor
914
0
    dest ^= src1 & m2;
915
0
    break;
916
0
  case 3: // xnor
917
0
    dest ^= (src1 ^ 0xff) & m2;
918
0
    break;
919
0
  case 4: // replace
920
0
    dest = (src1 & m2) | (dest & m1);
921
0
    break;
922
0
  }
923
0
  *destPtr = dest;
924
0
      }
925
926
    // multiple bytes per line -- need to mask left side of left-most
927
    // byte and right side of right-most byte
928
908
    } else {
929
930
      // left-most byte
931
908
      if (x >= 0) {
932
903
  destPtr = data + (y + yy) * line + (x >> 3);
933
903
  srcPtr = bitmap->data + yy * bitmap->line;
934
903
  src1 = *srcPtr++;
935
903
  dest = *destPtr;
936
903
  switch (combOp) {
937
903
  case 0: // or
938
903
    dest |= (Guchar)(src1 >> s1);
939
903
    break;
940
0
  case 1: // and
941
0
    dest &= (Guchar)((0xff00 | src1) >> s1);
942
0
    break;
943
0
  case 2: // xor
944
0
    dest ^= (Guchar)(src1 >> s1);
945
0
    break;
946
0
  case 3: // xnor
947
0
    dest ^= (Guchar)((src1 ^ 0xff) >> s1);
948
0
    break;
949
0
  case 4: // replace
950
0
    dest = (Guchar)((dest & (0xff << s2)) | (src1 >> s1));
951
0
    break;
952
903
  }
953
903
  *destPtr++ = dest;
954
903
  xx = x0 + 8;
955
903
      } else {
956
5
  destPtr = data + (y + yy) * line;
957
5
  srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
958
5
  src1 = *srcPtr++;
959
5
  xx = x0;
960
5
      }
961
962
      // middle bytes
963
25.3k
      for (; xx < x1 - 8; xx += 8) {
964
24.4k
  dest = *destPtr;
965
24.4k
  src0 = src1;
966
24.4k
  src1 = *srcPtr++;
967
24.4k
  src = (Guchar)(((src0 << 8) | src1) >> s1);
968
24.4k
  switch (combOp) {
969
24.4k
  case 0: // or
970
24.4k
    dest |= src;
971
24.4k
    break;
972
0
  case 1: // and
973
0
    dest &= src;
974
0
    break;
975
0
  case 2: // xor
976
0
    dest ^= src;
977
0
    break;
978
0
  case 3: // xnor
979
0
    dest ^= src ^ 0xff;
980
0
    break;
981
0
  case 4: // replace
982
0
    dest = src;
983
0
    break;
984
24.4k
  }
985
24.4k
  *destPtr++ = dest;
986
24.4k
      }
987
988
      // right-most byte
989
      // note: this last byte (src1) may not actually be used, depending
990
      // on the values of s1, m1, and m2 - and in fact, it may be off
991
      // the edge of the source bitmap, which means we need to allocate
992
      // one extra guard byte at the end of each bitmap
993
908
      dest = *destPtr;
994
908
      src0 = src1;
995
908
      src1 = *srcPtr++;
996
908
      src = (Guchar)(((src0 << 8) | src1) >> s1);
997
908
      switch (combOp) {
998
908
      case 0: // or
999
908
  dest |= src & m2;
1000
908
  break;
1001
0
      case 1: // and
1002
0
  dest &= src | m1;
1003
0
  break;
1004
0
      case 2: // xor
1005
0
  dest ^= src & m2;
1006
0
  break;
1007
0
      case 3: // xnor
1008
0
  dest ^= (src ^ 0xff) & m2;
1009
0
  break;
1010
0
      case 4: // replace
1011
0
  dest = (src & m2) | (dest & m1);
1012
0
  break;
1013
908
      }
1014
908
      *destPtr = dest;
1015
908
    }
1016
908
  }
1017
8
}
1018
1019
//------------------------------------------------------------------------
1020
// JBIG2SymbolDict
1021
//------------------------------------------------------------------------
1022
1023
class JBIG2SymbolDict: public JBIG2Segment {
1024
public:
1025
1026
  JBIG2SymbolDict(Guint segNumA, Guint sizeA);
1027
  virtual ~JBIG2SymbolDict();
1028
8
  virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
1029
8
  Guint getSize() { return size; }
1030
1
  void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1031
0
  JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1032
  void setGenericRegionStats(JArithmeticDecoderStats *stats)
1033
1
    { genericRegionStats = stats; }
1034
  void setRefinementRegionStats(JArithmeticDecoderStats *stats)
1035
0
    { refinementRegionStats = stats; }
1036
  JArithmeticDecoderStats *getGenericRegionStats()
1037
0
    { return genericRegionStats; }
1038
  JArithmeticDecoderStats *getRefinementRegionStats()
1039
0
    { return refinementRegionStats; }
1040
1041
private:
1042
1043
  Guint size;
1044
  JBIG2Bitmap **bitmaps;
1045
  JArithmeticDecoderStats *genericRegionStats;
1046
  JArithmeticDecoderStats *refinementRegionStats;
1047
};
1048
1049
JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1050
  JBIG2Segment(segNumA)
1051
11
{
1052
11
  Guint i;
1053
1054
11
  size = sizeA;
1055
11
  bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1056
487
  for (i = 0; i < size; ++i) {
1057
476
    bitmaps[i] = NULL;
1058
476
  }
1059
11
  genericRegionStats = NULL;
1060
11
  refinementRegionStats = NULL;
1061
11
}
1062
1063
7
JBIG2SymbolDict::~JBIG2SymbolDict() {
1064
7
  Guint i;
1065
1066
483
  for (i = 0; i < size; ++i) {
1067
476
    if (bitmaps[i]) {
1068
1
      delete bitmaps[i];
1069
1
    }
1070
476
  }
1071
7
  gfree(bitmaps);
1072
7
  if (genericRegionStats) {
1073
0
    delete genericRegionStats;
1074
0
  }
1075
7
  if (refinementRegionStats) {
1076
0
    delete refinementRegionStats;
1077
0
  }
1078
7
}
1079
1080
//------------------------------------------------------------------------
1081
// JBIG2PatternDict
1082
//------------------------------------------------------------------------
1083
1084
class JBIG2PatternDict: public JBIG2Segment {
1085
public:
1086
1087
  JBIG2PatternDict(Guint segNumA, Guint sizeA);
1088
  virtual ~JBIG2PatternDict();
1089
0
  virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
1090
0
  Guint getSize() { return size; }
1091
56
  void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1092
0
  JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1093
1094
private:
1095
1096
  Guint size;
1097
  JBIG2Bitmap **bitmaps;
1098
};
1099
1100
JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
1101
  JBIG2Segment(segNumA)
1102
4
{
1103
4
  size = sizeA;
1104
4
  bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1105
4
}
1106
1107
2
JBIG2PatternDict::~JBIG2PatternDict() {
1108
2
  Guint i;
1109
1110
30
  for (i = 0; i < size; ++i) {
1111
28
    delete bitmaps[i];
1112
28
  }
1113
2
  gfree(bitmaps);
1114
2
}
1115
1116
//------------------------------------------------------------------------
1117
// JBIG2CodeTable
1118
//------------------------------------------------------------------------
1119
1120
class JBIG2CodeTable: public JBIG2Segment {
1121
public:
1122
1123
  JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
1124
  virtual ~JBIG2CodeTable();
1125
0
  virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
1126
0
  JBIG2HuffmanTable *getHuffTable() { return table; }
1127
1128
private:
1129
1130
  JBIG2HuffmanTable *table;
1131
};
1132
1133
JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
1134
  JBIG2Segment(segNumA)
1135
19
{
1136
19
  table = tableA;
1137
19
}
1138
1139
5
JBIG2CodeTable::~JBIG2CodeTable() {
1140
5
  gfree(table);
1141
5
}
1142
1143
//------------------------------------------------------------------------
1144
// JBIG2Stream
1145
//------------------------------------------------------------------------
1146
1147
JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
1148
  FilterStream(strA)
1149
251k
{
1150
251k
  pageBitmap = NULL;
1151
1152
251k
  arithDecoder = new JArithmeticDecoder();
1153
251k
  genericRegionStats = new JArithmeticDecoderStats(1 << 1);
1154
251k
  refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
1155
251k
  iadhStats = new JArithmeticDecoderStats(1 << 9);
1156
251k
  iadwStats = new JArithmeticDecoderStats(1 << 9);
1157
251k
  iaexStats = new JArithmeticDecoderStats(1 << 9);
1158
251k
  iaaiStats = new JArithmeticDecoderStats(1 << 9);
1159
251k
  iadtStats = new JArithmeticDecoderStats(1 << 9);
1160
251k
  iaitStats = new JArithmeticDecoderStats(1 << 9);
1161
251k
  iafsStats = new JArithmeticDecoderStats(1 << 9);
1162
251k
  iadsStats = new JArithmeticDecoderStats(1 << 9);
1163
251k
  iardxStats = new JArithmeticDecoderStats(1 << 9);
1164
251k
  iardyStats = new JArithmeticDecoderStats(1 << 9);
1165
251k
  iardwStats = new JArithmeticDecoderStats(1 << 9);
1166
251k
  iardhStats = new JArithmeticDecoderStats(1 << 9);
1167
251k
  iariStats = new JArithmeticDecoderStats(1 << 9);
1168
251k
  iaidStats = new JArithmeticDecoderStats(1 << 1);
1169
251k
  huffDecoder = new JBIG2HuffmanDecoder();
1170
251k
  mmrDecoder = new JBIG2MMRDecoder();
1171
1172
251k
  globalsStreamA->copy(&globalsStream);
1173
251k
  segments = globalSegments = NULL;
1174
251k
  curStr = NULL;
1175
251k
  dataPtr = dataEnd = NULL;
1176
251k
}
1177
1178
250k
JBIG2Stream::~JBIG2Stream() {
1179
250k
  close();
1180
250k
  globalsStream.free();
1181
250k
  delete arithDecoder;
1182
250k
  delete genericRegionStats;
1183
250k
  delete refinementRegionStats;
1184
250k
  delete iadhStats;
1185
250k
  delete iadwStats;
1186
250k
  delete iaexStats;
1187
250k
  delete iaaiStats;
1188
250k
  delete iadtStats;
1189
250k
  delete iaitStats;
1190
250k
  delete iafsStats;
1191
250k
  delete iadsStats;
1192
250k
  delete iardxStats;
1193
250k
  delete iardyStats;
1194
250k
  delete iardwStats;
1195
250k
  delete iardhStats;
1196
250k
  delete iariStats;
1197
250k
  delete iaidStats;
1198
250k
  delete huffDecoder;
1199
250k
  delete mmrDecoder;
1200
250k
  delete str;
1201
250k
}
1202
1203
250k
Stream *JBIG2Stream::copy() {
1204
250k
  return new JBIG2Stream(str->copy(), &globalsStream);
1205
250k
}
1206
1207
1.09k
void JBIG2Stream::reset() {
1208
1.09k
  GList *t;
1209
1210
1.09k
  segments = new GList();
1211
1.09k
  globalSegments = new GList();
1212
1213
  // read the globals stream
1214
1.09k
  if (globalsStream.isStream()) {
1215
1.08k
    curStr = globalsStream.getStream();
1216
1.08k
    curStr->reset();
1217
1.08k
    arithDecoder->setStream(curStr);
1218
1.08k
    huffDecoder->setStream(curStr);
1219
1.08k
    mmrDecoder->setStream(curStr);
1220
1.08k
    readSegments();
1221
1.08k
    curStr->close();
1222
    // swap the newly read segments list into globalSegments
1223
1.08k
    t = segments;
1224
1.08k
    segments = globalSegments;
1225
1.08k
    globalSegments = t;
1226
1.08k
  }
1227
1228
  // read the main stream
1229
1.09k
  curStr = str;
1230
1.09k
  curStr->reset();
1231
1.09k
  arithDecoder->setStream(curStr);
1232
1.09k
  huffDecoder->setStream(curStr);
1233
1.09k
  mmrDecoder->setStream(curStr);
1234
1.09k
  readSegments();
1235
1236
1.09k
  if (pageBitmap) {
1237
1.05k
    dataPtr = pageBitmap->getDataPtr();
1238
1.05k
    dataEnd = dataPtr + pageBitmap->getDataSize();
1239
1.05k
  } else {
1240
49
    dataPtr = dataEnd = NULL;
1241
49
  }
1242
1.09k
}
1243
1244
251k
void JBIG2Stream::close() {
1245
251k
  if (pageBitmap) {
1246
1.00k
    delete pageBitmap;
1247
1.00k
    pageBitmap = NULL;
1248
1.00k
  }
1249
251k
  if (segments) {
1250
1.00k
    deleteGList(segments, JBIG2Segment);
1251
1.00k
    segments = NULL;
1252
1.00k
  }
1253
251k
  if (globalSegments) {
1254
1.00k
    deleteGList(globalSegments, JBIG2Segment);
1255
1.00k
    globalSegments = NULL;
1256
1.00k
  }
1257
251k
  dataPtr = dataEnd = NULL;
1258
251k
  FilterStream::close();
1259
251k
}
1260
1261
8.98k
int JBIG2Stream::getChar() {
1262
8.98k
  if (dataPtr && dataPtr < dataEnd) {
1263
8.98k
    return (*dataPtr++ ^ 0xff) & 0xff;
1264
8.98k
  }
1265
0
  return EOF;
1266
8.98k
}
1267
1268
0
int JBIG2Stream::lookChar() {
1269
0
  if (dataPtr && dataPtr < dataEnd) {
1270
0
    return (*dataPtr ^ 0xff) & 0xff;
1271
0
  }
1272
0
  return EOF;
1273
0
}
1274
1275
1.99k
int JBIG2Stream::getBlock(char *blk, int size) {
1276
1.99k
  int n, i;
1277
1278
1.99k
  if (size <= 0) {
1279
0
    return 0;
1280
0
  }
1281
1.99k
  if (dataEnd - dataPtr < size) {
1282
998
    n = (int)(dataEnd - dataPtr);
1283
998
  } else {
1284
998
    n = size;
1285
998
  }
1286
6.50M
  for (i = 0; i < n; ++i) {
1287
6.50M
    blk[i] = *dataPtr++ ^ 0xff;
1288
6.50M
  }
1289
1.99k
  return n;
1290
1.99k
}
1291
1292
GString *JBIG2Stream::getPSFilter(int psLevel, const char *indent,
1293
0
          GBool okToReadStream) {
1294
0
  return NULL;
1295
0
}
1296
1297
0
GBool JBIG2Stream::isBinary(GBool last) {
1298
0
  return str->isBinary(gTrue);
1299
0
}
1300
1301
2.16k
void JBIG2Stream::readSegments() {
1302
2.16k
  Guint segNum, segFlags, segType, page, segLength;
1303
2.16k
  Guint refFlags, nRefSegs;
1304
2.16k
  Guint *refSegs;
1305
2.16k
  int c1, c2, c3;
1306
2.16k
  Guint i;
1307
1308
2.16k
  done = gFalse;
1309
4.26k
  while (!done && readULong(&segNum)) {
1310
1311
    // segment header flags
1312
4.24k
    if (!readUByte(&segFlags)) {
1313
1
      goto eofError1;
1314
1
    }
1315
4.24k
    segType = segFlags & 0x3f;
1316
1317
    // referred-to segment count and retention flags
1318
4.24k
    if (!readUByte(&refFlags)) {
1319
0
      goto eofError1;
1320
0
    }
1321
4.24k
    nRefSegs = refFlags >> 5;
1322
4.24k
    if (nRefSegs == 7) {
1323
1.00k
      if ((c1 = curStr->getChar()) == EOF ||
1324
1.00k
    (c2 = curStr->getChar()) == EOF ||
1325
1.00k
    (c3 = curStr->getChar()) == EOF) {
1326
0
  goto eofError1;
1327
0
      }
1328
1.00k
      refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
1329
1.00k
      nRefSegs = refFlags & 0x1fffffff;
1330
1.00k
      i = (nRefSegs + 9) >> 3;
1331
1.00k
      if (curStr->discardChars(i) != i) {
1332
1.00k
  goto eofError1;
1333
1.00k
      }
1334
1.00k
    }
1335
1336
    // referred-to segment numbers
1337
3.24k
    refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint));
1338
3.24k
    if (segNum <= 256) {
1339
3.23k
      for (i = 0; i < nRefSegs; ++i) {
1340
1.05k
  if (!readUByte(&refSegs[i])) {
1341
0
    goto eofError2;
1342
0
  }
1343
1.05k
      }
1344
2.17k
    } else if (segNum <= 65536) {
1345
18
      for (i = 0; i < nRefSegs; ++i) {
1346
0
  if (!readUWord(&refSegs[i])) {
1347
0
    goto eofError2;
1348
0
  }
1349
0
      }
1350
1.05k
    } else {
1351
2.17k
      for (i = 0; i < nRefSegs; ++i) {
1352
1.11k
  if (!readULong(&refSegs[i])) {
1353
1
    goto eofError2;
1354
1
  }
1355
1.11k
      }
1356
1.05k
    }
1357
1358
    // segment page association
1359
3.24k
    if (segFlags & 0x40) {
1360
11
      if (!readULong(&page)) {
1361
0
  goto eofError2;
1362
0
      }
1363
3.23k
    } else {
1364
3.23k
      if (!readUByte(&page)) {
1365
0
  goto eofError2;
1366
0
      }
1367
3.23k
    }
1368
1369
    // segment data length
1370
3.24k
    if (!readULong(&segLength)) {
1371
0
      goto eofError2;
1372
0
    }
1373
1374
    // check for missing page information segment
1375
3.24k
    if (!pageBitmap && ((segType >= 4 && segType <= 7) ||
1376
1.17k
      (segType >= 20 && segType <= 43))) {
1377
0
      error(errSyntaxError, getPos(),
1378
0
      "First JBIG2 segment associated with a page must be a page information segment");
1379
0
      goto syntaxError;
1380
0
    }
1381
1382
    // read the segment data
1383
3.24k
    arithDecoder->resetByteCounter();
1384
3.24k
    huffDecoder->resetByteCounter();
1385
3.24k
    mmrDecoder->resetByteCounter();
1386
3.24k
    byteCounter = 0;
1387
3.24k
    switch (segType) {
1388
86
    case 0:
1389
86
      if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
1390
62
  goto syntaxError;
1391
62
      }
1392
24
      break;
1393
24
    case 4:
1394
0
      readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
1395
0
      break;
1396
1.04k
    case 6:
1397
1.04k
      readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
1398
1.04k
      break;
1399
0
    case 7:
1400
0
      readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
1401
0
      break;
1402
4
    case 16:
1403
4
      readPatternDictSeg(segNum, segLength);
1404
4
      break;
1405
0
    case 20:
1406
0
      readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
1407
0
          refSegs, nRefSegs);
1408
0
      break;
1409
0
    case 22:
1410
0
      readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
1411
0
          refSegs, nRefSegs);
1412
0
      break;
1413
3
    case 23:
1414
3
      readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
1415
3
          refSegs, nRefSegs);
1416
3
      break;
1417
2
    case 36:
1418
2
      readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
1419
2
      break;
1420
0
    case 38:
1421
0
      readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
1422
0
      break;
1423
0
    case 39:
1424
0
      readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
1425
0
      break;
1426
0
    case 40:
1427
0
      readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
1428
0
             refSegs, nRefSegs);
1429
0
      break;
1430
0
    case 42:
1431
0
      readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
1432
0
             refSegs, nRefSegs);
1433
0
      break;
1434
0
    case 43:
1435
0
      readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
1436
0
             refSegs, nRefSegs);
1437
0
      break;
1438
1.05k
    case 48:
1439
1.05k
      readPageInfoSeg(segLength);
1440
1.05k
      break;
1441
0
    case 50:
1442
0
      readEndOfStripeSeg(segLength);
1443
0
      break;
1444
0
    case 51:
1445
      // end of file segment
1446
0
      done = gTrue;
1447
0
      break;
1448
0
    case 52:
1449
0
      readProfilesSeg(segLength);
1450
0
      break;
1451
19
    case 53:
1452
19
      readCodeTableSeg(segNum, segLength);
1453
19
      break;
1454
1
    case 62:
1455
1
      readExtensionSeg(segLength);
1456
1
      break;
1457
1.02k
    default:
1458
1.02k
      error(errSyntaxError, getPos(), "Unknown segment type in JBIG2 stream");
1459
1.02k
      if (curStr->discardChars(segLength) != segLength) {
1460
1.02k
  goto eofError2;
1461
1.02k
      }
1462
1
      break;
1463
3.24k
    }
1464
1465
    // skip any unused data at the end of the segment
1466
    // (except for immediate generic region segments which have
1467
    // 0xffffffff = unspecified length)
1468
2.14k
    if (!(segType == 38 && segLength == 0xffffffff)) {
1469
2.14k
      byteCounter += arithDecoder->getByteCounter();
1470
2.14k
      byteCounter += huffDecoder->getByteCounter();
1471
2.14k
      byteCounter += mmrDecoder->getByteCounter();
1472
      // do a sanity check on byteCounter vs segLength -- if there is
1473
      // a problem, abort the decode
1474
2.14k
      if (byteCounter > segLength ||
1475
2.14k
    segLength - byteCounter > 65536) {
1476
39
  error(errSyntaxError, getPos(),
1477
39
        "Invalid segment length in JBIG2 stream");
1478
39
  gfree(refSegs);
1479
39
  break;
1480
39
      }
1481
2.10k
      byteCounter += curStr->discardChars(segLength - byteCounter);
1482
2.10k
    }
1483
1484
2.10k
    gfree(refSegs);
1485
2.10k
  }
1486
1487
60
  return;
1488
1489
62
 syntaxError:
1490
62
  gfree(refSegs);
1491
62
  return;
1492
1493
1.02k
 eofError2:
1494
1.02k
  gfree(refSegs);
1495
2.02k
 eofError1:
1496
2.02k
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
1497
2.02k
}
1498
1499
GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
1500
86
             Guint *refSegs, Guint nRefSegs) {
1501
86
  JBIG2SymbolDict *symbolDict;
1502
86
  JBIG2HuffmanTable *huffDHTable, *huffDWTable;
1503
86
  JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
1504
86
  JBIG2Segment *seg;
1505
86
  GList *codeTables;
1506
86
  JBIG2SymbolDict *inputSymbolDict;
1507
86
  Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
1508
86
  Guint huffDH, huffDW, huffBMSize, huffAggInst;
1509
86
  Guint contextUsed, contextRetained;
1510
86
  int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
1511
86
  Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
1512
86
  JBIG2Bitmap **bitmaps;
1513
86
  JBIG2Bitmap *collBitmap, *refBitmap;
1514
86
  Guint *symWidths;
1515
86
  Guint symHeight, symWidth, totalWidth, x, symID;
1516
86
  int dh, dw, refAggNum, refDX, refDY, bmSize;
1517
86
  GBool ex;
1518
86
  int run, prevRun, cnt;
1519
86
  Guint i, j, k;
1520
1521
86
  symWidths = NULL;
1522
1523
  // symbol dictionary flags
1524
86
  if (!readUWord(&flags)) {
1525
0
    goto eofError;
1526
0
  }
1527
86
  sdTemplate = (flags >> 10) & 3;
1528
86
  sdrTemplate = (flags >> 12) & 1;
1529
86
  huff = flags & 1;
1530
86
  refAgg = (flags >> 1) & 1;
1531
86
  huffDH = (flags >> 2) & 3;
1532
86
  huffDW = (flags >> 4) & 3;
1533
86
  huffBMSize = (flags >> 6) & 1;
1534
86
  huffAggInst = (flags >> 7) & 1;
1535
86
  contextUsed = (flags >> 8) & 1;
1536
86
  contextRetained = (flags >> 9) & 1;
1537
1538
  // symbol dictionary AT flags
1539
86
  if (!huff) {
1540
82
    if (sdTemplate == 0) {
1541
32
      if (!readByte(&sdATX[0]) ||
1542
32
    !readByte(&sdATY[0]) ||
1543
32
    !readByte(&sdATX[1]) ||
1544
32
    !readByte(&sdATY[1]) ||
1545
32
    !readByte(&sdATX[2]) ||
1546
32
    !readByte(&sdATY[2]) ||
1547
32
    !readByte(&sdATX[3]) ||
1548
32
    !readByte(&sdATY[3])) {
1549
0
  goto eofError;
1550
0
      }
1551
50
    } else {
1552
50
      if (!readByte(&sdATX[0]) ||
1553
50
    !readByte(&sdATY[0])) {
1554
0
  goto eofError;
1555
0
      }
1556
50
    }
1557
82
  }
1558
1559
  // symbol dictionary refinement AT flags
1560
86
  if (refAgg && !sdrTemplate) {
1561
4
    if (!readByte(&sdrATX[0]) ||
1562
4
  !readByte(&sdrATY[0]) ||
1563
4
  !readByte(&sdrATX[1]) ||
1564
4
  !readByte(&sdrATY[1])) {
1565
0
      goto eofError;
1566
0
    }
1567
4
  }
1568
1569
  // SDNUMEXSYMS and SDNUMNEWSYMS
1570
86
  if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
1571
0
    goto eofError;
1572
0
  }
1573
1574
  // get referenced segments: input symbol dictionaries and code tables
1575
86
  codeTables = new GList();
1576
86
  numInputSyms = 0;
1577
90
  for (i = 0; i < nRefSegs; ++i) {
1578
4
    if ((seg = findSegment(refSegs[i]))) {
1579
0
      if (seg->getType() == jbig2SegSymbolDict) {
1580
0
  j = ((JBIG2SymbolDict *)seg)->getSize();
1581
0
  if (j > INT_MAX || numInputSyms > INT_MAX - j) {
1582
0
    error(errSyntaxError, getPos(),
1583
0
    "Too many input symbols in JBIG2 symbol dictionary");
1584
0
    delete codeTables;
1585
0
    goto eofError;
1586
0
  }
1587
0
  numInputSyms += j;
1588
0
      } else if (seg->getType() == jbig2SegCodeTable) {
1589
0
  codeTables->append(seg);
1590
0
      }
1591
0
    }
1592
4
  }
1593
86
  if (numNewSyms > INT_MAX || numInputSyms > INT_MAX - numNewSyms) {
1594
7
    error(errSyntaxError, getPos(),
1595
7
    "Too many input symbols in JBIG2 symbol dictionary");
1596
7
    delete codeTables;
1597
7
    goto eofError;
1598
7
  }
1599
1600
  // compute symbol code length
1601
79
  i = numInputSyms + numNewSyms;
1602
79
  if (i <= 1) {
1603
9
    symCodeLen = huff ? 1 : 0;
1604
70
  } else {
1605
70
    --i;
1606
70
    symCodeLen = 0;
1607
    // i = floor((numSyms-1) / 2^symCodeLen)
1608
765
    while (i > 0) {
1609
695
      ++symCodeLen;
1610
695
      i >>= 1;
1611
695
    }
1612
70
  }
1613
1614
  // get the input symbol bitmaps
1615
79
  bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms,
1616
79
             sizeof(JBIG2Bitmap *));
1617
1.04M
  for (i = 0; i < numInputSyms + numNewSyms; ++i) {
1618
1.04M
    bitmaps[i] = NULL;
1619
1.04M
  }
1620
79
  k = 0;
1621
79
  inputSymbolDict = NULL;
1622
79
  for (i = 0; i < nRefSegs; ++i) {
1623
0
    if ((seg = findSegment(refSegs[i]))) {
1624
0
      if (seg->getType() == jbig2SegSymbolDict) {
1625
0
  inputSymbolDict = (JBIG2SymbolDict *)seg;
1626
0
  for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1627
0
    bitmaps[k++] = inputSymbolDict->getBitmap(j);
1628
0
  }
1629
0
      }
1630
0
    }
1631
0
  }
1632
1633
  // get the Huffman tables
1634
79
  huffDHTable = huffDWTable = NULL; // make gcc happy
1635
79
  huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
1636
79
  i = 0;
1637
79
  if (huff) {
1638
2
    if (huffDH == 0) {
1639
2
      huffDHTable = huffTableD;
1640
2
    } else if (huffDH == 1) {
1641
0
      huffDHTable = huffTableE;
1642
0
    } else {
1643
0
      if (i >= (Guint)codeTables->getLength()) {
1644
0
  goto codeTableError;
1645
0
      }
1646
0
      huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1647
0
    }
1648
2
    if (huffDW == 0) {
1649
0
      huffDWTable = huffTableB;
1650
2
    } else if (huffDW == 1) {
1651
2
      huffDWTable = huffTableC;
1652
2
    } else {
1653
0
      if (i >= (Guint)codeTables->getLength()) {
1654
0
  goto codeTableError;
1655
0
      }
1656
0
      huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1657
0
    }
1658
2
    if (huffBMSize == 0) {
1659
2
      huffBMSizeTable = huffTableA;
1660
2
    } else {
1661
0
      if (i >= (Guint)codeTables->getLength()) {
1662
0
  goto codeTableError;
1663
0
      }
1664
0
      huffBMSizeTable =
1665
0
    ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1666
0
    }
1667
2
    if (huffAggInst == 0) {
1668
2
      huffAggInstTable = huffTableA;
1669
2
    } else {
1670
0
      if (i >= (Guint)codeTables->getLength()) {
1671
0
  goto codeTableError;
1672
0
      }
1673
0
      huffAggInstTable =
1674
0
    ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1675
0
    }
1676
2
  }
1677
79
  delete codeTables;
1678
1679
  // set up the Huffman decoder
1680
79
  if (huff) {
1681
2
    huffDecoder->reset();
1682
1683
  // set up the arithmetic decoder
1684
77
  } else {
1685
77
    if (contextUsed && inputSymbolDict) {
1686
0
      resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
1687
77
    } else {
1688
77
      resetGenericStats(sdTemplate, NULL);
1689
77
    }
1690
77
    resetIntStats(symCodeLen);
1691
77
    arithDecoder->start();
1692
77
  }
1693
1694
  // set up the arithmetic decoder for refinement/aggregation
1695
79
  if (refAgg) {
1696
47
    if (contextUsed && inputSymbolDict) {
1697
0
      resetRefinementStats(sdrTemplate,
1698
0
         inputSymbolDict->getRefinementRegionStats());
1699
47
    } else {
1700
47
      resetRefinementStats(sdrTemplate, NULL);
1701
47
    }
1702
47
  }
1703
1704
  // allocate symbol widths storage
1705
79
  if (huff && !refAgg) {
1706
0
    symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
1707
0
  }
1708
1709
79
  symHeight = 0;
1710
79
  i = 0;
1711
33.5k
  while (i < numNewSyms) {
1712
1713
    // read the height class delta height
1714
33.5k
    if (huff) {
1715
0
      huffDecoder->decodeInt(&dh, huffDHTable);
1716
33.5k
    } else {
1717
33.5k
      arithDecoder->decodeInt(&dh, iadhStats);
1718
33.5k
    }
1719
33.5k
    if ((dh <= 0 && (Guint)-dh >= symHeight) ||
1720
33.5k
  (dh > 0 && (Guint)dh > UINT_MAX - symHeight)) {
1721
2
      error(errSyntaxError, getPos(),
1722
2
      "Bad delta-height value in JBIG2 symbol dictionary");
1723
2
      goto syntaxError;
1724
2
    }
1725
33.5k
    symHeight += dh;
1726
33.5k
    symWidth = 0;
1727
33.5k
    totalWidth = 0;
1728
33.5k
    j = i;
1729
1730
    // sanity check to avoid extremely long run-times with damaged streams
1731
33.5k
    if (symHeight > 100000) {
1732
3
      error(errSyntaxError, getPos(),
1733
3
      "Bogus symbol height value in JBIG2 symbol dictionary");
1734
3
      goto syntaxError;
1735
3
    }
1736
1737
    // read the symbols in this height class
1738
36.7k
    while (1) {
1739
1740
      // read the delta width
1741
36.7k
      if (huff) {
1742
0
  if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
1743
0
    break;
1744
0
  }
1745
36.7k
      } else {
1746
36.7k
  if (!arithDecoder->decodeInt(&dw, iadwStats)) {
1747
131
    break;
1748
131
  }
1749
36.7k
      }
1750
36.5k
      if ((dw <= 0 && (Guint)-dw >= symWidth) ||
1751
36.5k
    (dw > 0 && (Guint)dw > UINT_MAX - symWidth)) {
1752
24
  error(errSyntaxError, getPos(),
1753
24
        "Bad delta-height value in JBIG2 symbol dictionary");
1754
24
  goto syntaxError;
1755
24
      }
1756
36.5k
      symWidth += dw;
1757
36.5k
      if (i >= numNewSyms) {
1758
5
  error(errSyntaxError, getPos(),
1759
5
        "Too many symbols in JBIG2 symbol dictionary");
1760
5
  goto syntaxError;
1761
5
      }
1762
1763
      // sanity check to avoid extremely long run-times with damaged streams
1764
36.5k
      if (symWidth > 100000) {
1765
6
  error(errSyntaxError, getPos(),
1766
6
        "Bogus symbol width value in JBIG2 symbol dictionary");
1767
6
  goto syntaxError;
1768
6
      }
1769
1770
      // using a collective bitmap, so don't read a bitmap here
1771
36.5k
      if (huff && !refAgg) {
1772
0
  symWidths[i] = symWidth;
1773
0
  totalWidth += symWidth;
1774
1775
      // refinement/aggregate coding
1776
36.5k
      } else if (refAgg) {
1777
36.3k
  if (huff) {
1778
0
    if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
1779
0
      break;
1780
0
    }
1781
36.3k
  } else {
1782
36.3k
    if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
1783
33.3k
      break;
1784
33.3k
    }
1785
36.3k
  }
1786
#if 0 //~ This special case was added about a year before the final draft
1787
      //~ of the JBIG2 spec was released.  I have encountered some old
1788
      //~ JBIG2 images that predate it.
1789
  if (0) {
1790
#else
1791
2.97k
  if (refAggNum == 1) {
1792
11
#endif
1793
11
    if (huff) {
1794
0
      symID = huffDecoder->readBits(symCodeLen);
1795
0
      huffDecoder->decodeInt(&refDX, huffTableO);
1796
0
      huffDecoder->decodeInt(&refDY, huffTableO);
1797
0
      huffDecoder->decodeInt(&bmSize, huffTableA);
1798
0
      huffDecoder->reset();
1799
0
      arithDecoder->start();
1800
11
    } else {
1801
11
      symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
1802
11
      arithDecoder->decodeInt(&refDX, iardxStats);
1803
11
      arithDecoder->decodeInt(&refDY, iardyStats);
1804
11
    }
1805
11
    if (symID >= numInputSyms + i) {
1806
11
      error(errSyntaxError, getPos(),
1807
11
      "Invalid symbol ID in JBIG2 symbol dictionary");
1808
11
      goto syntaxError;
1809
11
    }
1810
0
    refBitmap = bitmaps[symID];
1811
0
    bitmaps[numInputSyms + i] =
1812
0
        readGenericRefinementRegion(symWidth, symHeight,
1813
0
            sdrTemplate, gFalse,
1814
0
            refBitmap, refDX, refDY,
1815
0
            sdrATX, sdrATY);
1816
    //~ do we need to use the bmSize value here (in Huffman mode)?
1817
2.96k
  } else {
1818
2.96k
    bitmaps[numInputSyms + i] =
1819
2.96k
        readTextRegion(huff, gTrue, symWidth, symHeight,
1820
2.96k
           refAggNum, 0, numInputSyms + i, NULL,
1821
2.96k
           symCodeLen, bitmaps, 0, 0, 0, 1, 0,
1822
2.96k
           huffTableF, huffTableH, huffTableK, huffTableO,
1823
2.96k
           huffTableO, huffTableO, huffTableO, huffTableA,
1824
2.96k
           sdrTemplate, sdrATX, sdrATY);
1825
2.96k
  }
1826
1827
      // non-ref/agg coding
1828
2.97k
      } else {
1829
222
  bitmaps[numInputSyms + i] =
1830
222
      readGenericBitmap(gFalse, symWidth, symHeight,
1831
222
            sdTemplate, gFalse, gFalse, NULL,
1832
222
            sdATX, sdATY, 0);
1833
222
      }
1834
1835
3.18k
      ++i;
1836
3.18k
    }
1837
1838
    // read the collective bitmap
1839
33.4k
    if (huff && !refAgg) {
1840
0
      if (totalWidth == 0) {
1841
0
  error(errSyntaxError, getPos(),
1842
0
        "Invalid height class width in JBIG2 symbol dictionary");
1843
0
  goto syntaxError;
1844
0
      }
1845
0
      huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
1846
0
      huffDecoder->reset();
1847
0
      if (bmSize == 0) {
1848
0
  collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1849
0
  bmSize = symHeight * ((totalWidth + 7) >> 3);
1850
0
  byteCounter += curStr->getBlock((char *)collBitmap->getDataPtr(),
1851
0
          bmSize);
1852
0
      } else {
1853
0
  collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
1854
0
               0, gFalse, gFalse, NULL, NULL, NULL,
1855
0
               bmSize);
1856
0
      }
1857
0
      x = 0;
1858
0
      for (; j < i; ++j) {
1859
0
  bitmaps[numInputSyms + j] =
1860
0
      collBitmap->getSlice(x, 0, symWidths[j], symHeight);
1861
0
  x += symWidths[j];
1862
0
      }
1863
0
      delete collBitmap;
1864
0
    }
1865
33.4k
  }
1866
1867
  // create the symbol dict object
1868
28
  symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1869
1870
  // exported symbol list
1871
28
  i = j = 0;
1872
28
  ex = gFalse;
1873
28
  prevRun = 1;
1874
31
  while (i < numInputSyms + numNewSyms) {
1875
5
    if (huff) {
1876
0
      huffDecoder->decodeInt(&run, huffTableA);
1877
5
    } else {
1878
5
      arithDecoder->decodeInt(&run, iaexStats);
1879
5
    }
1880
5
    if (run == 0 && prevRun == 0) {
1881
      // this avoids infinite loops with damaged files (consecutive
1882
      // zero runs are never useful)
1883
1
      error(errSyntaxError, getPos(),
1884
1
      "Invalid exported symbol list in JBIG2 symbol dictionary");
1885
1
      delete symbolDict;
1886
1
      goto syntaxError;
1887
1
    }
1888
4
    if (i + run > numInputSyms + numNewSyms ||
1889
4
  (ex && j + run > numExSyms)) {
1890
1
      error(errSyntaxError, getPos(),
1891
1
      "Too many exported symbols in JBIG2 symbol dictionary");
1892
1
      delete symbolDict;
1893
1
      goto syntaxError;
1894
1
    }
1895
3
    if (ex) {
1896
2
      for (cnt = 0; cnt < run; ++cnt) {
1897
1
  symbolDict->setBitmap(j++, bitmaps[i++]->copy());
1898
1
      }
1899
2
    } else {
1900
2
      i += run;
1901
2
    }
1902
3
    ex = !ex;
1903
3
    prevRun = run;
1904
3
  }
1905
26
  if (j != numExSyms) {
1906
2
    error(errSyntaxError, getPos(), "Too few symbols in JBIG2 symbol dictionary");
1907
2
    delete symbolDict;
1908
2
    goto syntaxError;
1909
2
  }
1910
1911
24
  for (i = 0; i < numNewSyms; ++i) {
1912
0
    delete bitmaps[numInputSyms + i];
1913
0
  }
1914
24
  gfree(bitmaps);
1915
24
  if (symWidths) {
1916
0
    gfree(symWidths);
1917
0
  }
1918
1919
  // save the arithmetic decoder stats
1920
24
  if (!huff && contextRetained) {
1921
1
    symbolDict->setGenericRegionStats(genericRegionStats->copy());
1922
1
    if (refAgg) {
1923
0
      symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1924
0
    }
1925
1
  }
1926
1927
  // store the new symbol dict
1928
24
  segments->append(symbolDict);
1929
1930
24
  return gTrue;
1931
1932
0
 codeTableError:
1933
0
  error(errSyntaxError, getPos(), "Missing code table in JBIG2 symbol dictionary");
1934
0
  delete codeTables;
1935
1936
55
 syntaxError:
1937
986k
  for (i = 0; i < numNewSyms; ++i) {
1938
986k
    if (bitmaps[numInputSyms + i]) {
1939
3.03k
      delete bitmaps[numInputSyms + i];
1940
3.03k
    }
1941
986k
  }
1942
55
  gfree(bitmaps);
1943
55
  if (symWidths) {
1944
0
    gfree(symWidths);
1945
0
  }
1946
55
  return gFalse;
1947
1948
7
 eofError:
1949
7
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
1950
7
  return gFalse;
1951
0
}
1952
1953
void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
1954
            GBool lossless, Guint length,
1955
1.04k
            Guint *refSegs, Guint nRefSegs) {
1956
1.04k
  JBIG2Bitmap *bitmap;
1957
1.04k
  JBIG2HuffmanTable runLengthTab[36];
1958
1.04k
  JBIG2HuffmanTable *symCodeTab;
1959
1.04k
  JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
1960
1.04k
  JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
1961
1.04k
  JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
1962
1.04k
  JBIG2Segment *seg;
1963
1.04k
  GList *codeTables;
1964
1.04k
  JBIG2SymbolDict *symbolDict;
1965
1.04k
  JBIG2Bitmap **syms;
1966
1.04k
  Guint w, h, x, y, segInfoFlags, extCombOp;
1967
1.04k
  Guint flags, huff, refine, logStrips, refCorner, transposed;
1968
1.04k
  Guint combOp, defPixel, templ;
1969
1.04k
  int sOffset;
1970
1.04k
  Guint huffFlags, huffFS, huffDS, huffDT;
1971
1.04k
  Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
1972
1.04k
  Guint numInstances, numSyms, symCodeLen;
1973
1.04k
  int atx[2], aty[2];
1974
1.04k
  Guint i, k, kk;
1975
1.04k
  int j;
1976
1977
  // region segment info field
1978
1.04k
  if (!readULong(&w) || !readULong(&h) ||
1979
1.04k
      !readULong(&x) || !readULong(&y) ||
1980
1.04k
      !readUByte(&segInfoFlags)) {
1981
1
    goto eofError;
1982
1
  }
1983
1.04k
  if (w == 0 || h == 0) {
1984
0
    error(errSyntaxError, getPos(), "Bad size in JBIG2 text region segment");
1985
0
    return;
1986
0
  }
1987
  // sanity check: if the w/h/x/y values are way out of range, it likely
1988
  // indicates a damaged JBIG2 stream
1989
1.04k
  if (w / 10 > pageW || h / 10 > pageH ||
1990
1.04k
      x / 10 > pageW || y / 10 > pageH) {
1991
5
    error(errSyntaxError, getPos(),
1992
5
    "Bad size or position in JBIG2 text region segment");
1993
5
    done = gTrue;
1994
5
    return;
1995
5
  }
1996
1.04k
  extCombOp = segInfoFlags & 7;
1997
1998
  // rest of the text region header
1999
1.04k
  if (!readUWord(&flags)) {
2000
0
    goto eofError;
2001
0
  }
2002
1.04k
  huff = flags & 1;
2003
1.04k
  refine = (flags >> 1) & 1;
2004
1.04k
  logStrips = (flags >> 2) & 3;
2005
1.04k
  refCorner = (flags >> 4) & 3;
2006
1.04k
  transposed = (flags >> 6) & 1;
2007
1.04k
  combOp = (flags >> 7) & 3;
2008
1.04k
  defPixel = (flags >> 9) & 1;
2009
1.04k
  sOffset = (flags >> 10) & 0x1f;
2010
1.04k
  if (sOffset & 0x10) {
2011
1
    sOffset |= -1 - 0x0f;
2012
1
  }
2013
1.04k
  templ = (flags >> 15) & 1;
2014
1.04k
  huffFS = huffDS = huffDT = 0; // make gcc happy
2015
1.04k
  huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
2016
1.04k
  if (huff) {
2017
2
    if (!readUWord(&huffFlags)) {
2018
0
      goto eofError;
2019
0
    }
2020
2
    huffFS = huffFlags & 3;
2021
2
    huffDS = (huffFlags >> 2) & 3;
2022
2
    huffDT = (huffFlags >> 4) & 3;
2023
2
    huffRDW = (huffFlags >> 6) & 3;
2024
2
    huffRDH = (huffFlags >> 8) & 3;
2025
2
    huffRDX = (huffFlags >> 10) & 3;
2026
2
    huffRDY = (huffFlags >> 12) & 3;
2027
2
    huffRSize = (huffFlags >> 14) & 1;
2028
2
  }
2029
1.04k
  if (refine && templ == 0) {
2030
0
    if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
2031
0
  !readByte(&atx[1]) || !readByte(&aty[1])) {
2032
0
      goto eofError;
2033
0
    }
2034
0
  }
2035
1.04k
  if (!readULong(&numInstances)) {
2036
0
    goto eofError;
2037
0
  }
2038
2039
  // get symbol dictionaries and tables
2040
1.04k
  codeTables = new GList();
2041
1.04k
  numSyms = 0;
2042
1.04k
  for (i = 0; i < nRefSegs; ++i) {
2043
1.04k
    if ((seg = findSegment(refSegs[i]))) {
2044
4
      if (seg->getType() == jbig2SegSymbolDict) {
2045
4
  numSyms += ((JBIG2SymbolDict *)seg)->getSize();
2046
4
      } else if (seg->getType() == jbig2SegCodeTable) {
2047
0
  codeTables->append(seg);
2048
0
      }
2049
1.03k
    } else {
2050
1.03k
      error(errSyntaxError, getPos(),
2051
1.03k
      "Invalid segment reference in JBIG2 text region");
2052
1.03k
      delete codeTables;
2053
1.03k
      return;
2054
1.03k
    }
2055
1.04k
  }
2056
4
  i = numSyms;
2057
4
  if (i <= 1) {
2058
4
    symCodeLen = huff ? 1 : 0;
2059
4
  } else {
2060
0
    --i;
2061
0
    symCodeLen = 0;
2062
    // i = floor((numSyms-1) / 2^symCodeLen)
2063
0
    while (i > 0) {
2064
0
      ++symCodeLen;
2065
0
      i >>= 1;
2066
0
    }
2067
0
  }
2068
2069
  // get the symbol bitmaps
2070
4
  syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
2071
4
  kk = 0;
2072
8
  for (i = 0; i < nRefSegs; ++i) {
2073
4
    if ((seg = findSegment(refSegs[i]))) {
2074
4
      if (seg->getType() == jbig2SegSymbolDict) {
2075
4
  symbolDict = (JBIG2SymbolDict *)seg;
2076
4
  for (k = 0; k < symbolDict->getSize(); ++k) {
2077
0
    syms[kk++] = symbolDict->getBitmap(k);
2078
0
  }
2079
4
      }
2080
4
    }
2081
4
  }
2082
2083
  // get the Huffman tables
2084
4
  huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
2085
4
  huffRDWTable = huffRDHTable = NULL; // make gcc happy
2086
4
  huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
2087
4
  i = 0;
2088
4
  if (huff) {
2089
1
    if (huffFS == 0) {
2090
1
      huffFSTable = huffTableF;
2091
1
    } else if (huffFS == 1) {
2092
0
      huffFSTable = huffTableG;
2093
0
    } else {
2094
0
      if (i >= (Guint)codeTables->getLength()) {
2095
0
  goto codeTableError;
2096
0
      }
2097
0
      huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2098
0
    }
2099
1
    if (huffDS == 0) {
2100
1
      huffDSTable = huffTableH;
2101
1
    } else if (huffDS == 1) {
2102
0
      huffDSTable = huffTableI;
2103
0
    } else if (huffDS == 2) {
2104
0
      huffDSTable = huffTableJ;
2105
0
    } else {
2106
0
      if (i >= (Guint)codeTables->getLength()) {
2107
0
  goto codeTableError;
2108
0
      }
2109
0
      huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2110
0
    }
2111
1
    if (huffDT == 0) {
2112
1
      huffDTTable = huffTableK;
2113
1
    } else if (huffDT == 1) {
2114
0
      huffDTTable = huffTableL;
2115
0
    } else if (huffDT == 2) {
2116
0
      huffDTTable = huffTableM;
2117
0
    } else {
2118
0
      if (i >= (Guint)codeTables->getLength()) {
2119
0
  goto codeTableError;
2120
0
      }
2121
0
      huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2122
0
    }
2123
1
    if (huffRDW == 0) {
2124
1
      huffRDWTable = huffTableN;
2125
1
    } else if (huffRDW == 1) {
2126
0
      huffRDWTable = huffTableO;
2127
0
    } else {
2128
0
      if (i >= (Guint)codeTables->getLength()) {
2129
0
  goto codeTableError;
2130
0
      }
2131
0
      huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2132
0
    }
2133
1
    if (huffRDH == 0) {
2134
1
      huffRDHTable = huffTableN;
2135
1
    } else if (huffRDH == 1) {
2136
0
      huffRDHTable = huffTableO;
2137
0
    } else {
2138
0
      if (i >= (Guint)codeTables->getLength()) {
2139
0
  goto codeTableError;
2140
0
      }
2141
0
      huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2142
0
    }
2143
1
    if (huffRDX == 0) {
2144
1
      huffRDXTable = huffTableN;
2145
1
    } else if (huffRDX == 1) {
2146
0
      huffRDXTable = huffTableO;
2147
0
    } else {
2148
0
      if (i >= (Guint)codeTables->getLength()) {
2149
0
  goto codeTableError;
2150
0
      }
2151
0
      huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2152
0
    }
2153
1
    if (huffRDY == 0) {
2154
1
      huffRDYTable = huffTableN;
2155
1
    } else if (huffRDY == 1) {
2156
0
      huffRDYTable = huffTableO;
2157
0
    } else {
2158
0
      if (i >= (Guint)codeTables->getLength()) {
2159
0
  goto codeTableError;
2160
0
      }
2161
0
      huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2162
0
    }
2163
1
    if (huffRSize == 0) {
2164
1
      huffRSizeTable = huffTableA;
2165
1
    } else {
2166
0
      if (i >= (Guint)codeTables->getLength()) {
2167
0
  goto codeTableError;
2168
0
      }
2169
0
      huffRSizeTable =
2170
0
    ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2171
0
    }
2172
1
  }
2173
4
  delete codeTables;
2174
2175
  // symbol ID Huffman decoding table
2176
4
  if (huff) {
2177
1
    huffDecoder->reset();
2178
33
    for (i = 0; i < 32; ++i) {
2179
32
      runLengthTab[i].val = i;
2180
32
      runLengthTab[i].prefixLen = huffDecoder->readBits(4);
2181
32
      runLengthTab[i].rangeLen = 0;
2182
32
      runLengthTab[i].prefix = 0;
2183
32
    }
2184
1
    runLengthTab[32].val = 0x103;
2185
1
    runLengthTab[32].prefixLen = huffDecoder->readBits(4);
2186
1
    runLengthTab[32].rangeLen = 2;
2187
1
    runLengthTab[32].prefix = 0;
2188
1
    runLengthTab[33].val = 0x203;
2189
1
    runLengthTab[33].prefixLen = huffDecoder->readBits(4);
2190
1
    runLengthTab[33].rangeLen = 3;
2191
1
    runLengthTab[33].prefix = 0;
2192
1
    runLengthTab[34].val = 0x20b;
2193
1
    runLengthTab[34].prefixLen = huffDecoder->readBits(4);
2194
1
    runLengthTab[34].rangeLen = 7;
2195
1
    runLengthTab[34].prefix = 0;
2196
1
    runLengthTab[35].prefixLen = 0;
2197
1
    runLengthTab[35].rangeLen = jbig2HuffmanEOT;
2198
1
    runLengthTab[35].prefix = 0;
2199
1
    huffDecoder->buildTable(runLengthTab, 35);
2200
1
    symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1,
2201
1
                 sizeof(JBIG2HuffmanTable));
2202
1
    for (i = 0; i < numSyms; ++i) {
2203
0
      symCodeTab[i].val = i;
2204
0
      symCodeTab[i].rangeLen = 0;
2205
0
    }
2206
1
    i = 0;
2207
1
    while (i < numSyms) {
2208
0
      huffDecoder->decodeInt(&j, runLengthTab);
2209
0
      if (j > 0x200) {
2210
0
  for (j -= 0x200; j && i < numSyms; --j) {
2211
0
    symCodeTab[i++].prefixLen = 0;
2212
0
  }
2213
0
      } else if (j > 0x100) {
2214
0
  if (i == 0) {
2215
0
    error(errSyntaxError, getPos(), "Invalid code in JBIG2 text region");
2216
0
    gfree(syms);
2217
0
    gfree(symCodeTab);
2218
0
    return;
2219
0
  }
2220
0
  for (j -= 0x100; j && i < numSyms; --j) {
2221
0
    symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
2222
0
    ++i;
2223
0
  }
2224
0
      } else {
2225
0
  symCodeTab[i++].prefixLen = j;
2226
0
      }
2227
0
    }
2228
1
    symCodeTab[numSyms].prefixLen = 0;
2229
1
    symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
2230
1
    huffDecoder->buildTable(symCodeTab, numSyms);
2231
1
    huffDecoder->reset();
2232
2233
  // set up the arithmetic decoder
2234
3
  } else {
2235
3
    symCodeTab = NULL;
2236
3
    resetIntStats(symCodeLen);
2237
3
    arithDecoder->start();
2238
3
  }
2239
4
  if (refine) {
2240
0
    resetRefinementStats(templ, NULL);
2241
0
  }
2242
2243
4
  bitmap = readTextRegion(huff, refine, w, h, numInstances,
2244
4
        logStrips, numSyms, symCodeTab, symCodeLen, syms,
2245
4
        defPixel, combOp, transposed, refCorner, sOffset,
2246
4
        huffFSTable, huffDSTable, huffDTTable,
2247
4
        huffRDWTable, huffRDHTable,
2248
4
        huffRDXTable, huffRDYTable, huffRSizeTable,
2249
4
        templ, atx, aty);
2250
2251
4
  gfree(syms);
2252
2253
  // combine the region bitmap into the page bitmap
2254
4
  if (imm) {
2255
4
    if (pageH == 0xffffffff && y + h > curPageH) {
2256
0
      pageBitmap->expand(y + h, pageDefPixel);
2257
0
    }
2258
4
    pageBitmap->combine(bitmap, x, y, extCombOp);
2259
4
    delete bitmap;
2260
2261
  // store the region bitmap
2262
4
  } else {
2263
0
    bitmap->setSegNum(segNum);
2264
0
    segments->append(bitmap);
2265
0
  }
2266
2267
  // clean up the Huffman decoder
2268
4
  if (huff) {
2269
1
    gfree(symCodeTab);
2270
1
  }
2271
2272
4
  return;
2273
2274
0
 codeTableError:
2275
0
  error(errSyntaxError, getPos(), "Missing code table in JBIG2 text region");
2276
0
  delete codeTables;
2277
0
  gfree(syms);
2278
0
  return;
2279
2280
1
 eofError:
2281
1
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2282
1
  return;
2283
4
}
2284
2285
JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
2286
           int w, int h,
2287
           Guint numInstances,
2288
           Guint logStrips,
2289
           int numSyms,
2290
           JBIG2HuffmanTable *symCodeTab,
2291
           Guint symCodeLen,
2292
           JBIG2Bitmap **syms,
2293
           Guint defPixel, Guint combOp,
2294
           Guint transposed, Guint refCorner,
2295
           int sOffset,
2296
           JBIG2HuffmanTable *huffFSTable,
2297
           JBIG2HuffmanTable *huffDSTable,
2298
           JBIG2HuffmanTable *huffDTTable,
2299
           JBIG2HuffmanTable *huffRDWTable,
2300
           JBIG2HuffmanTable *huffRDHTable,
2301
           JBIG2HuffmanTable *huffRDXTable,
2302
           JBIG2HuffmanTable *huffRDYTable,
2303
           JBIG2HuffmanTable *huffRSizeTable,
2304
           Guint templ,
2305
2.96k
           int *atx, int *aty) {
2306
2.96k
  JBIG2Bitmap *bitmap;
2307
2.96k
  JBIG2Bitmap *symbolBitmap;
2308
2.96k
  Guint strips;
2309
2.96k
  int t, dt, tt, s, ds, sFirst, j;
2310
2.96k
  int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
2311
2.96k
  Guint symID, inst, bw, bh;
2312
2313
2.96k
  strips = 1 << logStrips;
2314
2315
  // allocate the bitmap
2316
2.96k
  bitmap = new JBIG2Bitmap(0, w, h);
2317
2.96k
  if (defPixel) {
2318
0
    bitmap->clearToOne();
2319
2.96k
  } else {
2320
2.96k
    bitmap->clearToZero();
2321
2.96k
  }
2322
2323
  // decode initial T value
2324
2.96k
  if (huff) {
2325
1
    huffDecoder->decodeInt(&t, huffDTTable);
2326
2.96k
  } else {
2327
2.96k
    arithDecoder->decodeInt(&t, iadtStats);
2328
2.96k
  }
2329
2.96k
  t *= -(int)strips;
2330
2331
2.96k
  inst = 0;
2332
2.96k
  sFirst = 0;
2333
9.26k
  while (inst < numInstances) {
2334
2335
    // decode delta-T
2336
6.51k
    if (huff) {
2337
31
      if (!huffDecoder->decodeInt(&dt, huffDTTable)) {
2338
0
  break;
2339
0
      }
2340
6.48k
    } else {
2341
6.48k
      if (!arithDecoder->decodeInt(&dt, iadtStats)) {
2342
79
  break;
2343
79
      }
2344
6.48k
    }
2345
6.43k
    t += dt * strips;
2346
2347
    // first S value
2348
6.43k
    if (huff) {
2349
31
      if (!huffDecoder->decodeInt(&ds, huffFSTable)) {
2350
0
  break;
2351
0
      }
2352
6.40k
    } else {
2353
6.40k
      if (!arithDecoder->decodeInt(&ds, iafsStats)) {
2354
126
  break;
2355
126
      }
2356
6.40k
    }
2357
6.31k
    sFirst += ds;
2358
6.31k
    s = sFirst;
2359
2360
    // read the instances
2361
    // (this loop test is here to avoid an infinite loop with damaged
2362
    // JBIG2 streams where the normal loop exit doesn't get triggered)
2363
5.50M
    while (inst < numInstances) {
2364
2365
      // T value
2366
5.50M
      if (strips == 1) {
2367
5.50M
  dt = 0;
2368
5.50M
      } else if (huff) {
2369
0
  dt = huffDecoder->readBits(logStrips);
2370
0
      } else {
2371
0
  arithDecoder->decodeInt(&dt, iaitStats);
2372
0
      }
2373
5.50M
      tt = t + dt;
2374
2375
      // symbol ID
2376
5.50M
      if (huff) {
2377
4.62M
  if (symCodeTab) {
2378
4.62M
    huffDecoder->decodeInt(&j, symCodeTab);
2379
4.62M
    symID = (Guint)j;
2380
4.62M
  } else {
2381
0
    symID = huffDecoder->readBits(symCodeLen);
2382
0
  }
2383
4.62M
      } else {
2384
873k
  symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
2385
873k
      }
2386
2387
5.50M
      if (symID >= (Guint)numSyms) {
2388
5.50M
  error(errSyntaxError, getPos(),
2389
5.50M
        "Invalid symbol number in JBIG2 text region");
2390
5.50M
      } else {
2391
2392
  // get the symbol bitmap
2393
252
  symbolBitmap = NULL;
2394
252
  if (refine) {
2395
252
    if (huff) {
2396
0
      ri = (int)huffDecoder->readBit();
2397
252
    } else {
2398
252
      arithDecoder->decodeInt(&ri, iariStats);
2399
252
    }
2400
252
  } else {
2401
0
    ri = 0;
2402
0
  }
2403
252
  if (ri) {
2404
241
    if (huff) {
2405
0
      huffDecoder->decodeInt(&rdw, huffRDWTable);
2406
0
      huffDecoder->decodeInt(&rdh, huffRDHTable);
2407
0
      huffDecoder->decodeInt(&rdx, huffRDXTable);
2408
0
      huffDecoder->decodeInt(&rdy, huffRDYTable);
2409
0
      huffDecoder->decodeInt(&bmSize, huffRSizeTable);
2410
0
      huffDecoder->reset();
2411
0
      arithDecoder->start();
2412
241
    } else {
2413
241
      arithDecoder->decodeInt(&rdw, iardwStats);
2414
241
      arithDecoder->decodeInt(&rdh, iardhStats);
2415
241
      arithDecoder->decodeInt(&rdx, iardxStats);
2416
241
      arithDecoder->decodeInt(&rdy, iardyStats);
2417
241
    }
2418
241
    refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
2419
241
    refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
2420
2421
241
    symbolBitmap =
2422
241
      readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
2423
241
          rdh + syms[symID]->getHeight(),
2424
241
          templ, gFalse, syms[symID],
2425
241
          refDX, refDY, atx, aty);
2426
    //~ do we need to use the bmSize value here (in Huffman mode)?
2427
241
  } else {
2428
11
    symbolBitmap = syms[symID];
2429
11
  }
2430
2431
  // combine the symbol bitmap into the region bitmap
2432
  //~ something is wrong here - refCorner shouldn't degenerate into
2433
  //~   two cases
2434
252
  bw = symbolBitmap->getWidth() - 1;
2435
252
  bh = symbolBitmap->getHeight() - 1;
2436
252
  if (transposed) {
2437
0
    switch (refCorner) {
2438
0
    case 0: // bottom left
2439
0
      bitmap->combine(symbolBitmap, tt, s, combOp);
2440
0
      break;
2441
0
    case 1: // top left
2442
0
      bitmap->combine(symbolBitmap, tt, s, combOp);
2443
0
      break;
2444
0
    case 2: // bottom right
2445
0
      bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2446
0
      break;
2447
0
    case 3: // top right
2448
0
      bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2449
0
      break;
2450
0
    }
2451
0
    s += bh;
2452
252
  } else {
2453
252
    switch (refCorner) {
2454
0
    case 0: // bottom left
2455
0
      bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2456
0
      break;
2457
236
    case 1: // top left
2458
236
      bitmap->combine(symbolBitmap, s, tt, combOp);
2459
236
      break;
2460
0
    case 2: // bottom right
2461
0
      bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2462
0
      break;
2463
0
    case 3: // top right
2464
0
      bitmap->combine(symbolBitmap, s, tt, combOp);
2465
0
      break;
2466
252
    }
2467
236
    s += bw;
2468
236
  }
2469
236
  if (ri) {
2470
225
    delete symbolBitmap;
2471
225
  }
2472
236
      }
2473
2474
      // next instance
2475
5.50M
      ++inst;
2476
2477
      // next S value
2478
5.50M
      if (huff) {
2479
4.62M
  if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
2480
30
    break;
2481
30
  }
2482
4.62M
      } else {
2483
873k
  if (!arithDecoder->decodeInt(&ds, iadsStats)) {
2484
3.57k
    break;
2485
3.57k
  }
2486
873k
      }
2487
5.49M
      s += sOffset + ds;
2488
5.49M
    }
2489
6.31k
  }
2490
2491
2.95k
  return bitmap;
2492
2.96k
}
2493
2494
4
void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
2495
4
  JBIG2PatternDict *patternDict;
2496
4
  JBIG2Bitmap *bitmap;
2497
4
  Guint flags, patternW, patternH, grayMax, templ, mmr;
2498
4
  int atx[4], aty[4];
2499
4
  Guint i, x;
2500
2501
  // halftone dictionary flags, pattern width and height, max gray value
2502
4
  if (!readUByte(&flags) ||
2503
4
      !readUByte(&patternW) ||
2504
4
      !readUByte(&patternH) ||
2505
4
      !readULong(&grayMax)) {
2506
0
    goto eofError;
2507
0
  }
2508
4
  if (patternW == 0 || patternH == 0) {
2509
0
    error(errSyntaxError, getPos(),
2510
0
    "Bad size in JBIG2 pattern dictionary segment");
2511
0
    return;
2512
0
  }
2513
4
  templ = (flags >> 1) & 3;
2514
4
  mmr = flags & 1;
2515
2516
  // set up the arithmetic decoder
2517
4
  if (!mmr) {
2518
4
    resetGenericStats(templ, NULL);
2519
4
    arithDecoder->start();
2520
4
  }
2521
2522
  // read the bitmap
2523
4
  atx[0] = -(int)patternW; aty[0] =  0;
2524
4
  atx[1] = -3;             aty[1] = -1;
2525
4
  atx[2] =  2;             aty[2] = -2;
2526
4
  atx[3] = -2;             aty[3] = -2;
2527
4
  bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
2528
4
           templ, gFalse, gFalse, NULL,
2529
4
           atx, aty, length - 7);
2530
2531
  // create the pattern dict object
2532
4
  patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
2533
2534
  // split up the bitmap
2535
4
  x = 0;
2536
60
  for (i = 0; i <= grayMax; ++i) {
2537
56
    patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
2538
56
    x += patternW;
2539
56
  }
2540
2541
  // free memory
2542
4
  delete bitmap;
2543
2544
  // store the new pattern dict
2545
4
  segments->append(patternDict);
2546
2547
4
  return;
2548
2549
0
 eofError:
2550
0
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2551
0
}
2552
2553
void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
2554
          GBool lossless, Guint length,
2555
3
          Guint *refSegs, Guint nRefSegs) {
2556
3
  JBIG2Bitmap *bitmap;
2557
3
  JBIG2Segment *seg;
2558
3
  JBIG2PatternDict *patternDict;
2559
3
  JBIG2Bitmap *skipBitmap;
2560
3
  Guint *grayImg;
2561
3
  JBIG2Bitmap *grayBitmap;
2562
3
  JBIG2Bitmap *patternBitmap;
2563
3
  Guint w, h, x, y, segInfoFlags, extCombOp;
2564
3
  Guint flags, mmr, templ, enableSkip, combOp;
2565
3
  Guint gridW, gridH, stepX, stepY, patW, patH;
2566
3
  int atx[4], aty[4];
2567
3
  int gridX, gridY, xx, yy, bit, j;
2568
3
  Guint bpp, m, n, i;
2569
2570
  // region segment info field
2571
3
  if (!readULong(&w) || !readULong(&h) ||
2572
3
      !readULong(&x) || !readULong(&y) ||
2573
3
      !readUByte(&segInfoFlags)) {
2574
0
    goto eofError;
2575
0
  }
2576
  // sanity check: if the w/h/x/y values are way out of range, it likely
2577
  // indicates a damaged JBIG2 stream
2578
3
  if (w / 10 > pageW || h / 10 > pageH ||
2579
3
      x / 10 > pageW || y / 10 > pageH) {
2580
3
    error(errSyntaxError, getPos(),
2581
3
    "Bad size or position in JBIG2 halftone region segment");
2582
3
    done = gTrue;
2583
3
    return;
2584
3
  }
2585
0
  extCombOp = segInfoFlags & 7;
2586
2587
  // rest of the halftone region header
2588
0
  if (!readUByte(&flags)) {
2589
0
    goto eofError;
2590
0
  }
2591
0
  mmr = flags & 1;
2592
0
  templ = (flags >> 1) & 3;
2593
0
  enableSkip = (flags >> 3) & 1;
2594
0
  combOp = (flags >> 4) & 7;
2595
0
  if (!readULong(&gridW) || !readULong(&gridH) ||
2596
0
      !readLong(&gridX) || !readLong(&gridY) ||
2597
0
      !readUWord(&stepX) || !readUWord(&stepY)) {
2598
0
    goto eofError;
2599
0
  }
2600
0
  if (w == 0 || h == 0 || w >= INT_MAX / h) {
2601
0
    error(errSyntaxError, getPos(),
2602
0
    "Bad bitmap size in JBIG2 halftone segment");
2603
0
    return;
2604
0
  }
2605
0
  if (gridW == 0 || gridH == 0 || gridW >= INT_MAX / gridH) {
2606
0
    error(errSyntaxError, getPos(), "Bad grid size in JBIG2 halftone segment");
2607
0
    return;
2608
0
  }
2609
2610
  // get pattern dictionary
2611
0
  if (nRefSegs != 1) {
2612
0
    error(errSyntaxError, getPos(),
2613
0
    "Bad symbol dictionary reference in JBIG2 halftone segment");
2614
0
    return;
2615
0
  }
2616
0
  if (!(seg = findSegment(refSegs[0])) ||
2617
0
      seg->getType() != jbig2SegPatternDict) {
2618
0
    error(errSyntaxError, getPos(),
2619
0
    "Bad symbol dictionary reference in JBIG2 halftone segment");
2620
0
    return;
2621
0
  }
2622
0
  patternDict = (JBIG2PatternDict *)seg;
2623
0
  i = patternDict->getSize();
2624
0
  if (i <= 1) {
2625
0
    bpp = 0;
2626
0
  } else {
2627
0
    --i;
2628
0
    bpp = 0;
2629
    // i = floor((size-1) / 2^bpp)
2630
0
    while (i > 0) {
2631
0
      ++bpp;
2632
0
      i >>= 1;
2633
0
    }
2634
0
  }
2635
0
  patW = patternDict->getBitmap(0)->getWidth();
2636
0
  patH = patternDict->getBitmap(0)->getHeight();
2637
2638
  // set up the arithmetic decoder
2639
0
  if (!mmr) {
2640
0
    resetGenericStats(templ, NULL);
2641
0
    arithDecoder->start();
2642
0
  }
2643
2644
  // allocate the bitmap
2645
0
  bitmap = new JBIG2Bitmap(segNum, w, h);
2646
0
  if (flags & 0x80) { // HDEFPIXEL
2647
0
    bitmap->clearToOne();
2648
0
  } else {
2649
0
    bitmap->clearToZero();
2650
0
  }
2651
2652
  // compute the skip bitmap
2653
0
  skipBitmap = NULL;
2654
0
  if (enableSkip) {
2655
0
    skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
2656
0
    skipBitmap->clearToZero();
2657
0
    for (m = 0; m < gridH; ++m) {
2658
0
      for (n = 0; n < gridW; ++n) {
2659
0
  xx = gridX + m * stepY + n * stepX;
2660
0
  yy = gridY + m * stepX - n * stepY;
2661
0
  if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
2662
0
      ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
2663
0
    skipBitmap->setPixel(n, m);
2664
0
  }
2665
0
      }
2666
0
    }
2667
0
  }
2668
2669
  // read the gray-scale image
2670
0
  grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint));
2671
0
  memset(grayImg, 0, gridW * gridH * sizeof(Guint));
2672
0
  atx[0] = templ <= 1 ? 3 : 2;  aty[0] = -1;
2673
0
  atx[1] = -3;                  aty[1] = -1;
2674
0
  atx[2] =  2;                  aty[2] = -2;
2675
0
  atx[3] = -2;                  aty[3] = -2;
2676
0
  for (j = bpp - 1; j >= 0; --j) {
2677
0
    grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
2678
0
           enableSkip, skipBitmap, atx, aty, -1);
2679
0
    i = 0;
2680
0
    for (m = 0; m < gridH; ++m) {
2681
0
      for (n = 0; n < gridW; ++n) {
2682
0
  bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
2683
0
  grayImg[i] = (grayImg[i] << 1) | bit;
2684
0
  ++i;
2685
0
      }
2686
0
    }
2687
0
    delete grayBitmap;
2688
0
  }
2689
2690
  // decode the image
2691
0
  i = 0;
2692
0
  for (m = 0; m < gridH; ++m) {
2693
0
    xx = gridX + m * stepY;
2694
0
    yy = gridY + m * stepX;
2695
0
    for (n = 0; n < gridW; ++n) {
2696
0
      if (!(enableSkip && skipBitmap->getPixel(n, m))) {
2697
0
  patternBitmap = patternDict->getBitmap(grayImg[i]);
2698
0
  bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
2699
0
      }
2700
0
      xx += stepX;
2701
0
      yy -= stepY;
2702
0
      ++i;
2703
0
    }
2704
0
  }
2705
2706
0
  gfree(grayImg);
2707
0
  if (skipBitmap) {
2708
0
    delete skipBitmap;
2709
0
  }
2710
2711
  // combine the region bitmap into the page bitmap
2712
0
  if (imm) {
2713
0
    if (pageH == 0xffffffff && y + h > curPageH) {
2714
0
      pageBitmap->expand(y + h, pageDefPixel);
2715
0
    }
2716
0
    pageBitmap->combine(bitmap, x, y, extCombOp);
2717
0
    delete bitmap;
2718
2719
  // store the region bitmap
2720
0
  } else {
2721
0
    segments->append(bitmap);
2722
0
  }
2723
2724
0
  return;
2725
2726
0
 eofError:
2727
0
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2728
0
}
2729
2730
void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
2731
2
               GBool lossless, Guint length) {
2732
2
  JBIG2Bitmap *bitmap;
2733
2
  Guint w, h, x, y, segInfoFlags, extCombOp, rowCount;
2734
2
  Guint flags, mmr, templ, tpgdOn;
2735
2
  int atx[4], aty[4];
2736
2737
  // region segment info field
2738
2
  if (!readULong(&w) || !readULong(&h) ||
2739
2
      !readULong(&x) || !readULong(&y) ||
2740
2
      !readUByte(&segInfoFlags)) {
2741
0
    goto eofError;
2742
0
  }
2743
2
  if (w == 0 || h == 0) {
2744
0
    error(errSyntaxError, getPos(),
2745
0
    "Bad bitmap size in JBIG2 generic region segment");
2746
0
    return;
2747
0
  }
2748
  // sanity check: if the w/h/x/y values are way out of range, it likely
2749
  // indicates a damaged JBIG2 stream
2750
2
  if (w / 10 > pageW || h / 10 > pageH ||
2751
2
      x / 10 > pageW || y / 10 > pageH) {
2752
2
    error(errSyntaxError, getPos(),
2753
2
    "Bad size or position in JBIG2 generic region segment");
2754
2
    done = gTrue;
2755
2
    return;
2756
2
  }
2757
0
  extCombOp = segInfoFlags & 7;
2758
2759
  // rest of the generic region segment header
2760
0
  if (!readUByte(&flags)) {
2761
0
    goto eofError;
2762
0
  }
2763
0
  mmr = flags & 1;
2764
0
  templ = (flags >> 1) & 3;
2765
0
  tpgdOn = (flags >> 3) & 1;
2766
2767
  // AT flags
2768
0
  if (!mmr) {
2769
0
    if (templ == 0) {
2770
0
      if (!readByte(&atx[0]) ||
2771
0
    !readByte(&aty[0]) ||
2772
0
    !readByte(&atx[1]) ||
2773
0
    !readByte(&aty[1]) ||
2774
0
    !readByte(&atx[2]) ||
2775
0
    !readByte(&aty[2]) ||
2776
0
    !readByte(&atx[3]) ||
2777
0
    !readByte(&aty[3])) {
2778
0
  goto eofError;
2779
0
      }
2780
0
    } else {
2781
0
      if (!readByte(&atx[0]) ||
2782
0
    !readByte(&aty[0])) {
2783
0
  goto eofError;
2784
0
      }
2785
0
    }
2786
0
  }
2787
2788
  // set up the arithmetic decoder
2789
0
  if (!mmr) {
2790
0
    resetGenericStats(templ, NULL);
2791
0
    arithDecoder->start();
2792
0
  }
2793
2794
  // read the bitmap
2795
0
  bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
2796
0
           NULL, atx, aty, mmr ? length - 18 : 0);
2797
2798
  // combine the region bitmap into the page bitmap
2799
0
  if (imm) {
2800
0
    if (pageH == 0xffffffff && y + h > curPageH) {
2801
0
      pageBitmap->expand(y + h, pageDefPixel);
2802
0
    }
2803
0
    pageBitmap->combine(bitmap, x, y, extCombOp);
2804
0
    delete bitmap;
2805
2806
  // store the region bitmap
2807
0
  } else {
2808
0
    bitmap->setSegNum(segNum);
2809
0
    segments->append(bitmap);
2810
0
  }
2811
2812
  // immediate generic segments can have an unspecified length, in
2813
  // which case, a row count is stored at the end of the segment
2814
0
  if (imm && length == 0xffffffff) {
2815
0
    readULong(&rowCount);
2816
0
  }
2817
2818
0
  return;
2819
2820
0
 eofError:
2821
0
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2822
0
}
2823
2824
inline void JBIG2Stream::mmrAddPixels(int a1, int blackPixels,
2825
0
              int *codingLine, int *a0i, int w) {
2826
0
  if (a1 > codingLine[*a0i]) {
2827
0
    if (a1 > w) {
2828
0
      error(errSyntaxError, getPos(),
2829
0
            "JBIG2 MMR row is wrong length ({0:d})", a1);
2830
0
      a1 = w;
2831
0
    }
2832
0
    if ((*a0i & 1) ^ blackPixels) {
2833
0
      ++*a0i;
2834
0
    }
2835
0
    codingLine[*a0i] = a1;
2836
0
  }
2837
0
}
2838
2839
inline void JBIG2Stream::mmrAddPixelsNeg(int a1, int blackPixels,
2840
0
           int *codingLine, int *a0i, int w) {
2841
0
  if (a1 > codingLine[*a0i]) {
2842
0
    if (a1 > w) {
2843
0
      error(errSyntaxError, getPos(),
2844
0
            "JBIG2 MMR row is wrong length ({0:d})", a1);
2845
0
      a1 = w;
2846
0
    }
2847
0
    if ((*a0i & 1) ^ blackPixels) {
2848
0
      ++*a0i;
2849
0
    }
2850
0
    codingLine[*a0i] = a1;
2851
0
  } else if (a1 < codingLine[*a0i]) {
2852
0
    if (a1 < 0) {
2853
0
      error(errSyntaxError, getPos(), "Invalid JBIG2 MMR code");
2854
0
      a1 = 0;
2855
0
    }
2856
0
    while (*a0i > 0 && a1 <= codingLine[*a0i - 1]) {
2857
0
      --*a0i;
2858
0
    }
2859
0
    codingLine[*a0i] = a1;
2860
0
  }
2861
0
}
2862
2863
JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
2864
              int templ, GBool tpgdOn,
2865
              GBool useSkip, JBIG2Bitmap *skip,
2866
              int *atx, int *aty,
2867
226
              int mmrDataLength) {
2868
226
  JBIG2Bitmap *bitmap;
2869
226
  GBool ltp;
2870
226
  Guint ltpCX, cx, cx0, cx1, cx2;
2871
226
  int *refLine, *codingLine;
2872
226
  int code1, code2, code3;
2873
226
  Guchar *p0, *p1, *p2, *pp;
2874
226
  Guchar *atP0, *atP1, *atP2, *atP3;
2875
226
  Guint buf0, buf1, buf2;
2876
226
  Guint atBuf0, atBuf1, atBuf2, atBuf3;
2877
226
  int atShift0, atShift1, atShift2, atShift3;
2878
226
  Guchar mask;
2879
226
  int x, y, x0, x1, a0i, b1i, blackPixels, pix, i;
2880
2881
226
  bitmap = new JBIG2Bitmap(0, w, h);
2882
226
  bitmap->clearToZero();
2883
2884
  //----- MMR decode
2885
2886
226
  if (mmr) {
2887
2888
0
    mmrDecoder->reset();
2889
0
    if (w > INT_MAX - 3) {
2890
0
      error(errSyntaxError, getPos(), "Bad width in JBIG2 generic bitmap");
2891
      // force a call to gmalloc(-1), which will throw an exception
2892
0
      w = -4;
2893
0
    }
2894
    // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w
2895
    // ---> max codingLine size = w + 1
2896
    // refLine has two extra guard entries at the end
2897
    // ---> max refLine size = w + 3
2898
0
    codingLine = (int *)gmallocn(w + 1, sizeof(int));
2899
0
    refLine = (int *)gmallocn(w + 3, sizeof(int));
2900
0
    codingLine[0] = w;
2901
2902
0
    for (y = 0; y < h; ++y) {
2903
2904
      // copy coding line to ref line
2905
0
      for (i = 0; codingLine[i] < w; ++i) {
2906
0
  refLine[i] = codingLine[i];
2907
0
      }
2908
0
      refLine[i++] = w;
2909
0
      refLine[i++] = w;
2910
0
      refLine[i] = w;
2911
2912
      // decode a line
2913
0
      codingLine[0] = 0;
2914
0
      a0i = 0;
2915
0
      b1i = 0;
2916
0
      blackPixels = 0;
2917
      // invariant:
2918
      // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] <= w
2919
      // exception at left edge:
2920
      //   codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
2921
      // exception at right edge:
2922
      //   refLine[b1i] = refLine[b1i+1] = w is possible
2923
0
      while (codingLine[a0i] < w) {
2924
0
  code1 = mmrDecoder->get2DCode();
2925
0
  switch (code1) {
2926
0
  case twoDimPass:
2927
0
          mmrAddPixels(refLine[b1i + 1], blackPixels, codingLine, &a0i, w);
2928
0
          if (refLine[b1i + 1] < w) {
2929
0
            b1i += 2;
2930
0
          }
2931
0
          break;
2932
0
  case twoDimHoriz:
2933
0
          code1 = code2 = 0;
2934
0
          if (blackPixels) {
2935
0
            do {
2936
0
              code1 += code3 = mmrDecoder->getBlackCode();
2937
0
            } while (code3 >= 64);
2938
0
            do {
2939
0
              code2 += code3 = mmrDecoder->getWhiteCode();
2940
0
            } while (code3 >= 64);
2941
0
          } else {
2942
0
            do {
2943
0
              code1 += code3 = mmrDecoder->getWhiteCode();
2944
0
            } while (code3 >= 64);
2945
0
            do {
2946
0
              code2 += code3 = mmrDecoder->getBlackCode();
2947
0
            } while (code3 >= 64);
2948
0
          }
2949
0
          mmrAddPixels(codingLine[a0i] + code1, blackPixels,
2950
0
           codingLine, &a0i, w);
2951
0
          if (codingLine[a0i] < w) {
2952
0
            mmrAddPixels(codingLine[a0i] + code2, blackPixels ^ 1,
2953
0
       codingLine, &a0i, w);
2954
0
          }
2955
0
          while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2956
0
            b1i += 2;
2957
0
          }
2958
0
          break;
2959
0
  case twoDimVertR3:
2960
0
          mmrAddPixels(refLine[b1i] + 3, blackPixels, codingLine, &a0i, w);
2961
0
          blackPixels ^= 1;
2962
0
          if (codingLine[a0i] < w) {
2963
0
            ++b1i;
2964
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2965
0
              b1i += 2;
2966
0
            }
2967
0
          }
2968
0
          break;
2969
0
  case twoDimVertR2:
2970
0
          mmrAddPixels(refLine[b1i] + 2, blackPixels, codingLine, &a0i, w);
2971
0
          blackPixels ^= 1;
2972
0
          if (codingLine[a0i] < w) {
2973
0
            ++b1i;
2974
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2975
0
              b1i += 2;
2976
0
            }
2977
0
          }
2978
0
          break;
2979
0
  case twoDimVertR1:
2980
0
          mmrAddPixels(refLine[b1i] + 1, blackPixels, codingLine, &a0i, w);
2981
0
          blackPixels ^= 1;
2982
0
          if (codingLine[a0i] < w) {
2983
0
            ++b1i;
2984
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2985
0
              b1i += 2;
2986
0
            }
2987
0
          }
2988
0
          break;
2989
0
  case twoDimVert0:
2990
0
          mmrAddPixels(refLine[b1i], blackPixels, codingLine, &a0i, w);
2991
0
          blackPixels ^= 1;
2992
0
          if (codingLine[a0i] < w) {
2993
0
            ++b1i;
2994
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2995
0
              b1i += 2;
2996
0
            }
2997
0
          }
2998
0
          break;
2999
0
  case twoDimVertL3:
3000
0
          mmrAddPixelsNeg(refLine[b1i] - 3, blackPixels, codingLine, &a0i, w);
3001
0
          blackPixels ^= 1;
3002
0
          if (codingLine[a0i] < w) {
3003
0
            if (b1i > 0) {
3004
0
              --b1i;
3005
0
            } else {
3006
0
              ++b1i;
3007
0
            }
3008
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3009
0
              b1i += 2;
3010
0
            }
3011
0
          }
3012
0
          break;
3013
0
  case twoDimVertL2:
3014
0
          mmrAddPixelsNeg(refLine[b1i] - 2, blackPixels, codingLine, &a0i, w);
3015
0
          blackPixels ^= 1;
3016
0
          if (codingLine[a0i] < w) {
3017
0
            if (b1i > 0) {
3018
0
              --b1i;
3019
0
            } else {
3020
0
              ++b1i;
3021
0
            }
3022
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3023
0
              b1i += 2;
3024
0
            }
3025
0
          }
3026
0
          break;
3027
0
  case twoDimVertL1:
3028
0
          mmrAddPixelsNeg(refLine[b1i] - 1, blackPixels, codingLine, &a0i, w);
3029
0
          blackPixels ^= 1;
3030
0
          if (codingLine[a0i] < w) {
3031
0
            if (b1i > 0) {
3032
0
              --b1i;
3033
0
            } else {
3034
0
              ++b1i;
3035
0
            }
3036
0
            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3037
0
              b1i += 2;
3038
0
            }
3039
0
          }
3040
0
          break;
3041
0
  case EOF:
3042
0
          mmrAddPixels(w, 0, codingLine, &a0i, w);
3043
0
          break;
3044
0
  default:
3045
0
    error(errSyntaxError, getPos(),
3046
0
    "Illegal code in JBIG2 MMR bitmap data");
3047
0
          mmrAddPixels(w, 0, codingLine, &a0i, w);
3048
0
    break;
3049
0
  }
3050
0
      }
3051
3052
      // convert the run lengths to a bitmap line
3053
0
      i = 0;
3054
0
      while (1) {
3055
0
  if (codingLine[i] >= w) {
3056
0
    break;
3057
0
  }
3058
0
  for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
3059
0
    bitmap->setPixel(x, y);
3060
0
  }
3061
0
  if (codingLine[i+1] >= w) {
3062
0
    break;
3063
0
  }
3064
0
  i += 2;
3065
0
      }
3066
0
    }
3067
3068
0
    if (mmrDataLength >= 0) {
3069
0
      mmrDecoder->skipTo(mmrDataLength);
3070
0
    } else {
3071
0
      if (mmrDecoder->get24Bits() != 0x001001) {
3072
0
  error(errSyntaxError, getPos(),
3073
0
        "Missing EOFB in JBIG2 MMR bitmap data");
3074
0
      }
3075
0
    }
3076
3077
0
    gfree(refLine);
3078
0
    gfree(codingLine);
3079
3080
  //----- arithmetic decode
3081
3082
226
  } else {
3083
    // set up the typical row context
3084
226
    ltpCX = 0; // make gcc happy
3085
226
    if (tpgdOn) {
3086
0
      switch (templ) {
3087
0
      case 0:
3088
0
  ltpCX = 0x3953; // 001 11001 0101 0011
3089
0
  break;
3090
0
      case 1:
3091
0
  ltpCX = 0x079a; // 0011 11001 101 0
3092
0
  break;
3093
0
      case 2:
3094
0
  ltpCX = 0x0e3; // 001 1100 01 1
3095
0
  break;
3096
0
      case 3:
3097
0
  ltpCX = 0x18b; // 01100 0101 1
3098
0
  break;
3099
0
      }
3100
0
    }
3101
3102
226
    ltp = 0;
3103
226
    cx = cx0 = cx1 = cx2 = 0; // make gcc happy
3104
7.58k
    for (y = 0; y < h; ++y) {
3105
3106
      // check for a "typical" (duplicate) row
3107
7.36k
      if (tpgdOn) {
3108
0
  if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
3109
0
    ltp = !ltp;
3110
0
  }
3111
0
  if (ltp) {
3112
0
    if (y > 0) {
3113
0
      bitmap->duplicateRow(y, y-1);
3114
0
    }
3115
0
    continue;
3116
0
  }
3117
0
      }
3118
3119
7.36k
      switch (templ) {
3120
6.34k
      case 0:
3121
3122
  // set up the context
3123
6.34k
  p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3124
6.34k
  buf2 = *p2++ << 8;
3125
6.34k
  if (y >= 1) {
3126
6.12k
    p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3127
6.12k
    buf1 = *p1++ << 8;
3128
6.12k
    if (y >= 2) {
3129
5.94k
      p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3130
5.94k
      buf0 = *p0++ << 8;
3131
5.94k
    } else {
3132
178
      p0 = NULL;
3133
178
      buf0 = 0;
3134
178
    }
3135
6.12k
  } else {
3136
222
    p1 = p0 = NULL;
3137
222
    buf1 = buf0 = 0;
3138
222
  }
3139
3140
6.34k
  if (atx[0] >= -8 && atx[0] <= 8 &&
3141
6.34k
      atx[1] >= -8 && atx[1] <= 8 &&
3142
6.34k
      atx[2] >= -8 && atx[2] <= 8 &&
3143
6.34k
      atx[3] >= -8 && atx[3] <= 8) {
3144
    // set up the adaptive context
3145
5.94k
    if (aty[0] <= 0 && y + aty[0] >= 0) {
3146
5.73k
      atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3147
5.73k
      atBuf0 = *atP0++ << 8;
3148
5.73k
    } else {
3149
211
      atP0 = NULL;
3150
211
      atBuf0 = 0;
3151
211
    }
3152
5.94k
    atShift0 = 15 - atx[0];
3153
5.94k
    if (aty[1] <= 0 && y + aty[1] >= 0) {
3154
5.70k
      atP1 = bitmap->getDataPtr() + (y + aty[1]) * bitmap->getLineSize();
3155
5.70k
      atBuf1 = *atP1++ << 8;
3156
5.70k
    } else {
3157
237
      atP1 = NULL;
3158
237
      atBuf1 = 0;
3159
237
    }
3160
5.94k
    atShift1 = 15 - atx[1];
3161
5.94k
    if (aty[2] <= 0 && y + aty[2] >= 0) {
3162
5.56k
      atP2 = bitmap->getDataPtr() + (y + aty[2]) * bitmap->getLineSize();
3163
5.56k
      atBuf2 = *atP2++ << 8;
3164
5.56k
    } else {
3165
374
      atP2 = NULL;
3166
374
      atBuf2 = 0;
3167
374
    }
3168
5.94k
    atShift2 = 15 - atx[2];
3169
5.94k
    if (aty[3] <= 0 && y + aty[3] >= 0) {
3170
5.56k
      atP3 = bitmap->getDataPtr() + (y + aty[3]) * bitmap->getLineSize();
3171
5.56k
      atBuf3 = *atP3++ << 8;
3172
5.56k
    } else {
3173
374
      atP3 = NULL;
3174
374
      atBuf3 = 0;
3175
374
    }
3176
5.94k
    atShift3 = 15 - atx[3];
3177
3178
    // decode the row
3179
59.4k
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3180
53.5k
      if (x0 + 8 < w) {
3181
47.5k
        if (p0) {
3182
45.9k
    buf0 |= *p0++;
3183
45.9k
        }
3184
47.5k
        if (p1) {
3185
46.7k
    buf1 |= *p1++;
3186
46.7k
        }
3187
47.5k
        buf2 |= *p2++;
3188
47.5k
        if (atP0) {
3189
46.7k
    atBuf0 |= *atP0++;
3190
46.7k
        }
3191
47.5k
        if (atP1) {
3192
46.6k
    atBuf1 |= *atP1++;
3193
46.6k
        }
3194
47.5k
        if (atP2) {
3195
45.9k
    atBuf2 |= *atP2++;
3196
45.9k
        }
3197
47.5k
        if (atP3) {
3198
45.9k
    atBuf3 |= *atP3++;
3199
45.9k
        }
3200
47.5k
      }
3201
53.5k
      for (x1 = 0, mask = 0x80;
3202
459k
     x1 < 8 && x < w;
3203
406k
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3204
3205
        // build the context
3206
406k
        cx0 = (buf0 >> 14) & 0x07;
3207
406k
        cx1 = (buf1 >> 13) & 0x1f;
3208
406k
        cx2 = (buf2 >> 16) & 0x0f;
3209
406k
        cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
3210
406k
       (((atBuf0 >> atShift0) & 1) << 3) |
3211
406k
       (((atBuf1 >> atShift1) & 1) << 2) |
3212
406k
       (((atBuf2 >> atShift2) & 1) << 1) |
3213
406k
       ((atBuf3 >> atShift3) & 1);
3214
3215
        // check for a skipped pixel
3216
406k
        if (!(useSkip && skip->getPixel(x, y))) {
3217
3218
    // decode the pixel
3219
406k
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3220
140k
      *pp |= mask;
3221
140k
      buf2 |= 0x8000;
3222
140k
      if (aty[0] == 0) {
3223
0
        atBuf0 |= 0x8000;
3224
0
      }
3225
140k
      if (aty[1] == 0) {
3226
2.10k
        atBuf1 |= 0x8000;
3227
2.10k
      }
3228
140k
      if (aty[2] == 0) {
3229
6
        atBuf2 |= 0x8000;
3230
6
      }
3231
140k
      if (aty[3] == 0) {
3232
6
        atBuf3 |= 0x8000;
3233
6
      }
3234
140k
    }
3235
406k
        }
3236
3237
        // update the context
3238
406k
        buf0 <<= 1;
3239
406k
        buf1 <<= 1;
3240
406k
        buf2 <<= 1;
3241
406k
        atBuf0 <<= 1;
3242
406k
        atBuf1 <<= 1;
3243
406k
        atBuf2 <<= 1;
3244
406k
        atBuf3 <<= 1;
3245
406k
      }
3246
53.5k
    }
3247
3248
5.94k
  } else {
3249
    // decode the row
3250
5.06k
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3251
4.66k
      if (x0 + 8 < w) {
3252
4.26k
        if (p0) {
3253
4.08k
    buf0 |= *p0++;
3254
4.08k
        }
3255
4.26k
        if (p1) {
3256
4.17k
    buf1 |= *p1++;
3257
4.17k
        }
3258
4.26k
        buf2 |= *p2++;
3259
4.26k
      }
3260
4.66k
      for (x1 = 0, mask = 0x80;
3261
40.3k
     x1 < 8 && x < w;
3262
35.6k
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3263
3264
        // build the context
3265
35.6k
        cx0 = (buf0 >> 14) & 0x07;
3266
35.6k
        cx1 = (buf1 >> 13) & 0x1f;
3267
35.6k
        cx2 = (buf2 >> 16) & 0x0f;
3268
35.6k
        cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
3269
35.6k
       (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) |
3270
35.6k
       (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) |
3271
35.6k
       (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) |
3272
35.6k
       bitmap->getPixel(x + atx[3], y + aty[3]);
3273
3274
        // check for a skipped pixel
3275
35.6k
        if (!(useSkip && skip->getPixel(x, y))) {
3276
3277
    // decode the pixel
3278
35.6k
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3279
5.18k
      *pp |= mask;
3280
5.18k
      buf2 |= 0x8000;
3281
5.18k
    }
3282
35.6k
        }
3283
3284
        // update the context
3285
35.6k
        buf0 <<= 1;
3286
35.6k
        buf1 <<= 1;
3287
35.6k
        buf2 <<= 1;
3288
35.6k
      }
3289
4.66k
    }
3290
401
  }
3291
6.34k
  break;
3292
3293
0
      case 1:
3294
3295
  // set up the context
3296
0
  p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3297
0
  buf2 = *p2++ << 8;
3298
0
  if (y >= 1) {
3299
0
    p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3300
0
    buf1 = *p1++ << 8;
3301
0
    if (y >= 2) {
3302
0
      p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3303
0
      buf0 = *p0++ << 8;
3304
0
    } else {
3305
0
      p0 = NULL;
3306
0
      buf0 = 0;
3307
0
    }
3308
0
  } else {
3309
0
    p1 = p0 = NULL;
3310
0
    buf1 = buf0 = 0;
3311
0
  }
3312
3313
0
  if (atx[0] >= -8 && atx[0] <= 8) {
3314
    // set up the adaptive context
3315
0
    if (aty[0] <= 0 && y + aty[0] >= 0) {
3316
0
      atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3317
0
      atBuf0 = *atP0++ << 8;
3318
0
    } else {
3319
0
      atP0 = NULL;
3320
0
      atBuf0 = 0;
3321
0
    }
3322
0
    atShift0 = 15 - atx[0];
3323
3324
    // decode the row
3325
0
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3326
0
      if (x0 + 8 < w) {
3327
0
        if (p0) {
3328
0
    buf0 |= *p0++;
3329
0
        }
3330
0
        if (p1) {
3331
0
    buf1 |= *p1++;
3332
0
        }
3333
0
        buf2 |= *p2++;
3334
0
        if (atP0) {
3335
0
    atBuf0 |= *atP0++;
3336
0
        }
3337
0
      }
3338
0
      for (x1 = 0, mask = 0x80;
3339
0
     x1 < 8 && x < w;
3340
0
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3341
3342
        // build the context
3343
0
        cx0 = (buf0 >> 13) & 0x0f;
3344
0
        cx1 = (buf1 >> 13) & 0x1f;
3345
0
        cx2 = (buf2 >> 16) & 0x07;
3346
0
        cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
3347
0
       ((atBuf0 >> atShift0) & 1);
3348
3349
        // check for a skipped pixel
3350
0
        if (!(useSkip && skip->getPixel(x, y))) {
3351
3352
    // decode the pixel
3353
0
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3354
0
      *pp |= mask;
3355
0
      buf2 |= 0x8000;
3356
0
      if (aty[0] == 0) {
3357
0
        atBuf0 |= 0x8000;
3358
0
      }
3359
0
    }
3360
0
        }
3361
3362
        // update the context
3363
0
        buf0 <<= 1;
3364
0
        buf1 <<= 1;
3365
0
        buf2 <<= 1;
3366
0
        atBuf0 <<= 1;
3367
0
      }
3368
0
    }
3369
3370
0
  } else {
3371
    // decode the row
3372
0
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3373
0
      if (x0 + 8 < w) {
3374
0
        if (p0) {
3375
0
    buf0 |= *p0++;
3376
0
        }
3377
0
        if (p1) {
3378
0
    buf1 |= *p1++;
3379
0
        }
3380
0
        buf2 |= *p2++;
3381
0
      }
3382
0
      for (x1 = 0, mask = 0x80;
3383
0
     x1 < 8 && x < w;
3384
0
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3385
3386
        // build the context
3387
0
        cx0 = (buf0 >> 13) & 0x0f;
3388
0
        cx1 = (buf1 >> 13) & 0x1f;
3389
0
        cx2 = (buf2 >> 16) & 0x07;
3390
0
        cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
3391
0
       bitmap->getPixel(x + atx[0], y + aty[0]);
3392
3393
        // check for a skipped pixel
3394
0
        if (!(useSkip && skip->getPixel(x, y))) {
3395
3396
    // decode the pixel
3397
0
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3398
0
      *pp |= mask;
3399
0
      buf2 |= 0x8000;
3400
0
    }
3401
0
        }
3402
3403
        // update the context
3404
0
        buf0 <<= 1;
3405
0
        buf1 <<= 1;
3406
0
        buf2 <<= 1;
3407
0
      }
3408
0
    }
3409
0
  }
3410
0
  break;
3411
3412
0
      case 2:
3413
3414
  // set up the context
3415
0
  p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3416
0
  buf2 = *p2++ << 8;
3417
0
  if (y >= 1) {
3418
0
    p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3419
0
    buf1 = *p1++ << 8;
3420
0
    if (y >= 2) {
3421
0
      p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3422
0
      buf0 = *p0++ << 8;
3423
0
    } else {
3424
0
      p0 = NULL;
3425
0
      buf0 = 0;
3426
0
    }
3427
0
  } else {
3428
0
    p1 = p0 = NULL;
3429
0
    buf1 = buf0 = 0;
3430
0
  }
3431
3432
0
  if (atx[0] >= -8 && atx[0] <= 8) {
3433
    // set up the adaptive context
3434
0
    if (aty[0] <= 0 && y + aty[0] >= 0) {
3435
0
      atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3436
0
      atBuf0 = *atP0++ << 8;
3437
0
    } else {
3438
0
      atP0 = NULL;
3439
0
      atBuf0 = 0;
3440
0
    }
3441
0
    atShift0 = 15 - atx[0];
3442
3443
    // decode the row
3444
0
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3445
0
      if (x0 + 8 < w) {
3446
0
        if (p0) {
3447
0
    buf0 |= *p0++;
3448
0
        }
3449
0
        if (p1) {
3450
0
    buf1 |= *p1++;
3451
0
        }
3452
0
        buf2 |= *p2++;
3453
0
        if (atP0) {
3454
0
    atBuf0 |= *atP0++;
3455
0
        }
3456
0
      }
3457
0
      for (x1 = 0, mask = 0x80;
3458
0
     x1 < 8 && x < w;
3459
0
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3460
3461
        // build the context
3462
0
        cx0 = (buf0 >> 14) & 0x07;
3463
0
        cx1 = (buf1 >> 14) & 0x0f;
3464
0
        cx2 = (buf2 >> 16) & 0x03;
3465
0
        cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
3466
0
       ((atBuf0 >> atShift0) & 1);
3467
3468
        // check for a skipped pixel
3469
0
        if (!(useSkip && skip->getPixel(x, y))) {
3470
3471
    // decode the pixel
3472
0
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3473
0
      *pp |= mask;
3474
0
      buf2 |= 0x8000;
3475
0
      if (aty[0] == 0) {
3476
0
        atBuf0 |= 0x8000;
3477
0
      }
3478
0
    }
3479
0
        }
3480
3481
        // update the context
3482
0
        buf0 <<= 1;
3483
0
        buf1 <<= 1;
3484
0
        buf2 <<= 1;
3485
0
        atBuf0 <<= 1;
3486
0
      }
3487
0
    }
3488
3489
0
  } else {
3490
    // decode the row
3491
0
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3492
0
      if (x0 + 8 < w) {
3493
0
        if (p0) {
3494
0
    buf0 |= *p0++;
3495
0
        }
3496
0
        if (p1) {
3497
0
    buf1 |= *p1++;
3498
0
        }
3499
0
        buf2 |= *p2++;
3500
0
      }
3501
0
      for (x1 = 0, mask = 0x80;
3502
0
     x1 < 8 && x < w;
3503
0
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3504
3505
        // build the context
3506
0
        cx0 = (buf0 >> 14) & 0x07;
3507
0
        cx1 = (buf1 >> 14) & 0x0f;
3508
0
        cx2 = (buf2 >> 16) & 0x03;
3509
0
        cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
3510
0
       bitmap->getPixel(x + atx[0], y + aty[0]);
3511
3512
        // check for a skipped pixel
3513
0
        if (!(useSkip && skip->getPixel(x, y))) {
3514
3515
    // decode the pixel
3516
0
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3517
0
      *pp |= mask;
3518
0
      buf2 |= 0x8000;
3519
0
    }
3520
0
        }
3521
3522
        // update the context
3523
0
        buf0 <<= 1;
3524
0
        buf1 <<= 1;
3525
0
        buf2 <<= 1;
3526
0
      }
3527
0
    }
3528
0
  }
3529
0
  break;
3530
3531
1.01k
      case 3:
3532
3533
  // set up the context
3534
1.01k
  p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3535
1.01k
  buf2 = *p2++ << 8;
3536
1.01k
  if (y >= 1) {
3537
1.01k
    p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3538
1.01k
    buf1 = *p1++ << 8;
3539
1.01k
  } else {
3540
4
    p1 = NULL;
3541
4
    buf1 = 0;
3542
4
  }
3543
3544
1.01k
  if (atx[0] >= -8 && atx[0] <= 8) {
3545
    // set up the adaptive context
3546
0
    if (aty[0] <= 0 && y + aty[0] >= 0) {
3547
0
      atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3548
0
      atBuf0 = *atP0++ << 8;
3549
0
    } else {
3550
0
      atP0 = NULL;
3551
0
      atBuf0 = 0;
3552
0
    }
3553
0
    atShift0 = 15 - atx[0];
3554
3555
    // decode the row
3556
0
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3557
0
      if (x0 + 8 < w) {
3558
0
        if (p1) {
3559
0
    buf1 |= *p1++;
3560
0
        }
3561
0
        buf2 |= *p2++;
3562
0
        if (atP0) {
3563
0
    atBuf0 |= *atP0++;
3564
0
        }
3565
0
      }
3566
0
      for (x1 = 0, mask = 0x80;
3567
0
     x1 < 8 && x < w;
3568
0
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3569
3570
        // build the context
3571
0
        cx1 = (buf1 >> 14) & 0x1f;
3572
0
        cx2 = (buf2 >> 16) & 0x0f;
3573
0
        cx = (cx1 << 5) | (cx2 << 1) |
3574
0
       ((atBuf0 >> atShift0) & 1);
3575
3576
        // check for a skipped pixel
3577
0
        if (!(useSkip && skip->getPixel(x, y))) {
3578
3579
    // decode the pixel
3580
0
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3581
0
      *pp |= mask;
3582
0
      buf2 |= 0x8000;
3583
0
      if (aty[0] == 0) {
3584
0
        atBuf0 |= 0x8000;
3585
0
      }
3586
0
    }
3587
0
        }
3588
3589
        // update the context
3590
0
        buf1 <<= 1;
3591
0
        buf2 <<= 1;
3592
0
        atBuf0 <<= 1;
3593
0
      }
3594
0
    }
3595
3596
1.01k
  } else {
3597
    // decode the row
3598
453k
    for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3599
452k
      if (x0 + 8 < w) {
3600
451k
        if (p1) {
3601
449k
    buf1 |= *p1++;
3602
449k
        }
3603
451k
        buf2 |= *p2++;
3604
451k
      }
3605
452k
      for (x1 = 0, mask = 0x80;
3606
4.06M
     x1 < 8 && x < w;
3607
3.61M
     ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3608
3609
        // build the context
3610
3.61M
        cx1 = (buf1 >> 14) & 0x1f;
3611
3.61M
        cx2 = (buf2 >> 16) & 0x0f;
3612
3.61M
        cx = (cx1 << 5) | (cx2 << 1) |
3613
3.61M
       bitmap->getPixel(x + atx[0], y + aty[0]);
3614
3615
        // check for a skipped pixel
3616
3.61M
        if (!(useSkip && skip->getPixel(x, y))) {
3617
3618
    // decode the pixel
3619
3.61M
    if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3620
1.77M
      *pp |= mask;
3621
1.77M
      buf2 |= 0x8000;
3622
1.77M
    }
3623
3.61M
        }
3624
3625
        // update the context
3626
3.61M
        buf1 <<= 1;
3627
3.61M
        buf2 <<= 1;
3628
3.61M
      }
3629
452k
    }
3630
1.01k
  }
3631
1.01k
  break;
3632
7.36k
      }
3633
7.36k
    }
3634
226
  }
3635
3636
226
  return bitmap;
3637
226
}
3638
3639
void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
3640
             GBool lossless, Guint length,
3641
             Guint *refSegs,
3642
0
             Guint nRefSegs) {
3643
0
  JBIG2Bitmap *bitmap, *refBitmap;
3644
0
  Guint w, h, x, y, segInfoFlags, extCombOp;
3645
0
  Guint flags, templ, tpgrOn;
3646
0
  int atx[2], aty[2];
3647
0
  JBIG2Segment *seg;
3648
3649
  // region segment info field
3650
0
  if (!readULong(&w) || !readULong(&h) ||
3651
0
      !readULong(&x) || !readULong(&y) ||
3652
0
      !readUByte(&segInfoFlags)) {
3653
0
    goto eofError;
3654
0
  }
3655
0
  if (w == 0 || h == 0) {
3656
0
    error(errSyntaxError, getPos(),
3657
0
    "Bad size in JBIG2 generic refinement region segment");
3658
0
    return;
3659
0
  }
3660
  // sanity check: if the w/h/x/y values are way out of range, it likely
3661
  // indicates a damaged JBIG2 stream
3662
0
  if (w / 10 > pageW || h / 10 > pageH ||
3663
0
      x / 10 > pageW || y / 10 > pageH) {
3664
0
    error(errSyntaxError, getPos(),
3665
0
    "Bad size or position in JBIG2 generic refinement region segment");
3666
0
    done = gTrue;
3667
0
    return;
3668
0
  }
3669
0
  extCombOp = segInfoFlags & 7;
3670
3671
  // rest of the generic refinement region segment header
3672
0
  if (!readUByte(&flags)) {
3673
0
    goto eofError;
3674
0
  }
3675
0
  templ = flags & 1;
3676
0
  tpgrOn = (flags >> 1) & 1;
3677
3678
  // AT flags
3679
0
  if (!templ) {
3680
0
    if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
3681
0
  !readByte(&atx[1]) || !readByte(&aty[1])) {
3682
0
      goto eofError;
3683
0
    }
3684
0
  }
3685
3686
  // resize the page bitmap if needed
3687
0
  if (nRefSegs == 0 || imm) {
3688
0
    if (pageH == 0xffffffff && y + h > curPageH) {
3689
0
      pageBitmap->expand(y + h, pageDefPixel);
3690
0
    }
3691
0
  }
3692
3693
  // get referenced bitmap
3694
0
  if (nRefSegs > 1) {
3695
0
    error(errSyntaxError, getPos(),
3696
0
    "Bad reference in JBIG2 generic refinement segment");
3697
0
    return;
3698
0
  }
3699
0
  if (nRefSegs == 1) {
3700
0
    if (!(seg = findSegment(refSegs[0])) ||
3701
0
  seg->getType() != jbig2SegBitmap) {
3702
0
      error(errSyntaxError, getPos(),
3703
0
      "Bad bitmap reference in JBIG2 generic refinement segment");
3704
0
      return;
3705
0
    }
3706
0
    refBitmap = (JBIG2Bitmap *)seg;
3707
0
  } else {
3708
0
    refBitmap = pageBitmap->getSlice(x, y, w, h);
3709
0
  }
3710
3711
  // set up the arithmetic decoder
3712
0
  resetRefinementStats(templ, NULL);
3713
0
  arithDecoder->start();
3714
3715
  // read
3716
0
  bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
3717
0
               refBitmap, 0, 0, atx, aty);
3718
3719
  // combine the region bitmap into the page bitmap
3720
0
  if (imm) {
3721
0
    pageBitmap->combine(bitmap, x, y, extCombOp);
3722
0
    delete bitmap;
3723
3724
  // store the region bitmap
3725
0
  } else {
3726
0
    bitmap->setSegNum(segNum);
3727
0
    segments->append(bitmap);
3728
0
  }
3729
3730
  // delete the referenced bitmap
3731
0
  if (nRefSegs == 1) {
3732
0
    discardSegment(refSegs[0]);
3733
0
  } else {
3734
0
    delete refBitmap;
3735
0
  }
3736
3737
0
  return;
3738
3739
0
 eofError:
3740
0
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
3741
0
}
3742
3743
JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
3744
                  int templ, GBool tpgrOn,
3745
                  JBIG2Bitmap *refBitmap,
3746
                  int refDX, int refDY,
3747
241
                  int *atx, int *aty) {
3748
241
  JBIG2Bitmap *bitmap;
3749
241
  GBool ltp;
3750
241
  Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
3751
241
  JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
3752
241
  JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
3753
241
  int x, y, pix;
3754
3755
241
  bitmap = new JBIG2Bitmap(0, w, h);
3756
241
  bitmap->clearToZero();
3757
3758
  // set up the typical row context
3759
241
  if (templ) {
3760
225
    ltpCX = 0x008;
3761
225
  } else {
3762
16
    ltpCX = 0x0010;
3763
16
  }
3764
3765
241
  ltp = 0;
3766
3.11k
  for (y = 0; y < h; ++y) {
3767
3768
2.87k
    if (templ) {
3769
3770
      // set up the context
3771
2.87k
      bitmap->getPixelPtr(0, y-1, &cxPtr0);
3772
2.87k
      cx0 = bitmap->nextPixel(&cxPtr0);
3773
2.87k
      bitmap->getPixelPtr(-1, y, &cxPtr1);
3774
2.87k
      refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
3775
2.87k
      refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
3776
2.87k
      cx3 = refBitmap->nextPixel(&cxPtr3);
3777
2.87k
      cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3778
2.87k
      refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
3779
2.87k
      cx4 = refBitmap->nextPixel(&cxPtr4);
3780
3781
      // set up the typical prediction context
3782
2.87k
      tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3783
2.87k
      if (tpgrOn) {
3784
0
  refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3785
0
  tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3786
0
  tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3787
0
  tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3788
0
  refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3789
0
  tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3790
0
  tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3791
0
  tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3792
0
  refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3793
0
  tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3794
0
  tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3795
0
  tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3796
2.87k
      } else {
3797
2.87k
  tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy
3798
2.87k
  tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
3799
2.87k
  tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
3800
2.87k
      }
3801
3802
323k
      for (x = 0; x < w; ++x) {
3803
3804
  // update the context
3805
320k
  cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
3806
320k
  cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3807
320k
  cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
3808
3809
320k
  if (tpgrOn) {
3810
    // update the typical predictor context
3811
0
    tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3812
0
    tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3813
0
    tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3814
3815
    // check for a "typical" pixel
3816
0
    if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3817
0
      ltp = !ltp;
3818
0
    }
3819
0
    if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3820
0
      bitmap->clearPixel(x, y);
3821
0
      continue;
3822
0
    } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3823
0
      bitmap->setPixel(x, y);
3824
0
      continue;
3825
0
    }
3826
0
  }
3827
3828
  // build the context
3829
320k
  cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
3830
320k
       (refBitmap->nextPixel(&cxPtr2) << 5) |
3831
320k
       (cx3 << 2) | cx4;
3832
3833
  // decode the pixel
3834
320k
  if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3835
147k
    bitmap->setPixel(x, y);
3836
147k
  }
3837
320k
      }
3838
3839
2.87k
    } else {
3840
3841
      // set up the context
3842
0
      bitmap->getPixelPtr(0, y-1, &cxPtr0);
3843
0
      cx0 = bitmap->nextPixel(&cxPtr0);
3844
0
      bitmap->getPixelPtr(-1, y, &cxPtr1);
3845
0
      refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
3846
0
      cx2 = refBitmap->nextPixel(&cxPtr2);
3847
0
      refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
3848
0
      cx3 = refBitmap->nextPixel(&cxPtr3);
3849
0
      cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3850
0
      refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
3851
0
      cx4 = refBitmap->nextPixel(&cxPtr4);
3852
0
      cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
3853
0
      bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
3854
0
      refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
3855
3856
      // set up the typical prediction context
3857
0
      tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3858
0
      if (tpgrOn) {
3859
0
  refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3860
0
  tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3861
0
  tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3862
0
  tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3863
0
  refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3864
0
  tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3865
0
  tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3866
0
  tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3867
0
  refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3868
0
  tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3869
0
  tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3870
0
  tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3871
0
      } else {
3872
0
  tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy
3873
0
  tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
3874
0
  tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
3875
0
      }
3876
3877
0
      for (x = 0; x < w; ++x) {
3878
3879
  // update the context
3880
0
  cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
3881
0
  cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
3882
0
  cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3883
0
  cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
3884
3885
0
  if (tpgrOn) {
3886
    // update the typical predictor context
3887
0
    tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3888
0
    tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3889
0
    tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3890
3891
    // check for a "typical" pixel
3892
0
    if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3893
0
      ltp = !ltp;
3894
0
    }
3895
0
    if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3896
0
      bitmap->clearPixel(x, y);
3897
0
      continue;
3898
0
    } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3899
0
      bitmap->setPixel(x, y);
3900
0
      continue;
3901
0
    }
3902
0
  }
3903
3904
  // build the context
3905
0
  cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
3906
0
       (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
3907
0
       (bitmap->nextPixel(&cxPtr5) << 1) |
3908
0
       refBitmap->nextPixel(&cxPtr6);
3909
3910
  // decode the pixel
3911
0
  if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3912
0
    bitmap->setPixel(x, y);
3913
0
  }
3914
0
      }
3915
0
    }
3916
2.87k
  }
3917
3918
241
  return bitmap;
3919
241
}
3920
3921
1.05k
void JBIG2Stream::readPageInfoSeg(Guint length) {
3922
1.05k
  Guint xRes, yRes, flags, striping;
3923
3924
1.05k
  if (!readULong(&pageW) || !readULong(&pageH) ||
3925
1.05k
      !readULong(&xRes) || !readULong(&yRes) ||
3926
1.05k
      !readUByte(&flags) || !readUWord(&striping)) {
3927
0
    goto eofError;
3928
0
  }
3929
1.05k
  if (pageW == 0 || pageH == 0 || pageW > INT_MAX / pageW) {
3930
5
    error(errSyntaxError, getPos(), "Bad page size in JBIG2 stream");
3931
5
    return;
3932
5
  }
3933
1.05k
  pageDefPixel = (flags >> 2) & 1;
3934
1.05k
  defCombOp = (flags >> 3) & 3;
3935
3936
  // allocate the page bitmap
3937
1.05k
  if (pageH == 0xffffffff) {
3938
0
    curPageH = striping & 0x7fff;
3939
1.05k
  } else {
3940
1.05k
    curPageH = pageH;
3941
1.05k
  }
3942
1.05k
  pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
3943
3944
  // default pixel value
3945
1.05k
  if (pageDefPixel) {
3946
1
    pageBitmap->clearToOne();
3947
1.05k
  } else {
3948
1.05k
    pageBitmap->clearToZero();
3949
1.05k
  }
3950
3951
1.05k
  return;
3952
3953
0
 eofError:
3954
0
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
3955
0
}
3956
3957
0
void JBIG2Stream::readEndOfStripeSeg(Guint length) {
3958
  // skip the segment
3959
0
  byteCounter += curStr->discardChars(length);
3960
0
}
3961
3962
0
void JBIG2Stream::readProfilesSeg(Guint length) {
3963
  // skip the segment
3964
0
  byteCounter += curStr->discardChars(length);
3965
0
}
3966
3967
19
void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
3968
19
  JBIG2HuffmanTable *huffTab;
3969
19
  Guint flags, oob, prefixBits, rangeBits;
3970
19
  int lowVal, highVal, val;
3971
19
  Guint huffTabSize, i;
3972
3973
19
  if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
3974
0
    goto eofError;
3975
0
  }
3976
19
  oob = flags & 1;
3977
19
  prefixBits = ((flags >> 1) & 7) + 1;
3978
19
  rangeBits = ((flags >> 4) & 7) + 1;
3979
3980
19
  huffDecoder->reset();
3981
19
  huffTabSize = 8;
3982
19
  huffTab = (JBIG2HuffmanTable *)
3983
19
                gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable));
3984
19
  i = 0;
3985
19
  val = lowVal;
3986
115k
  while (val < highVal) {
3987
115k
    if (i == huffTabSize) {
3988
160
      huffTabSize *= 2;
3989
160
      huffTab = (JBIG2HuffmanTable *)
3990
160
              greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
3991
160
    }
3992
115k
    huffTab[i].val = val;
3993
115k
    huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3994
115k
    huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
3995
115k
    val += 1 << huffTab[i].rangeLen;
3996
115k
    ++i;
3997
115k
  }
3998
19
  if (i + oob + 3 > huffTabSize) {
3999
0
    huffTabSize = i + oob + 3;
4000
0
    huffTab = (JBIG2HuffmanTable *)
4001
0
                  greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
4002
0
  }
4003
19
  huffTab[i].val = lowVal - 1;
4004
19
  huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4005
19
  huffTab[i].rangeLen = jbig2HuffmanLOW;
4006
19
  ++i;
4007
19
  huffTab[i].val = highVal;
4008
19
  huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4009
19
  huffTab[i].rangeLen = 32;
4010
19
  ++i;
4011
19
  if (oob) {
4012
3
    huffTab[i].val = 0;
4013
3
    huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4014
3
    huffTab[i].rangeLen = jbig2HuffmanOOB;
4015
3
    ++i;
4016
3
  }
4017
19
  huffTab[i].val = 0;
4018
19
  huffTab[i].prefixLen = 0;
4019
19
  huffTab[i].rangeLen = jbig2HuffmanEOT;
4020
19
  huffDecoder->buildTable(huffTab, i);
4021
4022
  // create and store the new table segment
4023
19
  segments->append(new JBIG2CodeTable(segNum, huffTab));
4024
4025
19
  return;
4026
4027
0
 eofError:
4028
0
  error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
4029
0
}
4030
4031
1
void JBIG2Stream::readExtensionSeg(Guint length) {
4032
  // skip the segment
4033
1
  byteCounter += curStr->discardChars(length);
4034
1
}
4035
4036
1.05k
JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
4037
1.05k
  JBIG2Segment *seg;
4038
1.05k
  int i;
4039
4040
1.05k
  for (i = 0; i < globalSegments->getLength(); ++i) {
4041
10
    seg = (JBIG2Segment *)globalSegments->get(i);
4042
10
    if (seg->getSegNum() == segNum) {
4043
8
      return seg;
4044
8
    }
4045
10
  }
4046
1.04k
  for (i = 0; i < segments->getLength(); ++i) {
4047
0
    seg = (JBIG2Segment *)segments->get(i);
4048
0
    if (seg->getSegNum() == segNum) {
4049
0
      return seg;
4050
0
    }
4051
0
  }
4052
1.04k
  return NULL;
4053
1.04k
}
4054
4055
0
void JBIG2Stream::discardSegment(Guint segNum) {
4056
0
  JBIG2Segment *seg;
4057
0
  int i;
4058
4059
0
  for (i = 0; i < globalSegments->getLength(); ++i) {
4060
0
    seg = (JBIG2Segment *)globalSegments->get(i);
4061
0
    if (seg->getSegNum() == segNum) {
4062
0
      globalSegments->del(i);
4063
0
      return;
4064
0
    }
4065
0
  }
4066
0
  for (i = 0; i < segments->getLength(); ++i) {
4067
0
    seg = (JBIG2Segment *)segments->get(i);
4068
0
    if (seg->getSegNum() == segNum) {
4069
0
      segments->del(i);
4070
0
      return;
4071
0
    }
4072
0
  }
4073
0
}
4074
4075
void JBIG2Stream::resetGenericStats(Guint templ,
4076
80
            JArithmeticDecoderStats *prevStats) {
4077
80
  int size;
4078
4079
80
  size = contextSize[templ];
4080
80
  if (prevStats && prevStats->getContextSize() == size) {
4081
0
    if (genericRegionStats->getContextSize() == size) {
4082
0
      genericRegionStats->copyFrom(prevStats);
4083
0
    } else {
4084
0
      delete genericRegionStats;
4085
0
      genericRegionStats = prevStats->copy();
4086
0
    }
4087
80
  } else {
4088
80
    if (genericRegionStats->getContextSize() == size) {
4089
0
      genericRegionStats->reset();
4090
80
    } else {
4091
80
      delete genericRegionStats;
4092
80
      genericRegionStats = new JArithmeticDecoderStats(1 << size);
4093
80
    }
4094
80
  }
4095
80
}
4096
4097
void JBIG2Stream::resetRefinementStats(Guint templ,
4098
47
               JArithmeticDecoderStats *prevStats) {
4099
47
  int size;
4100
4101
47
  size = refContextSize[templ];
4102
47
  if (prevStats && prevStats->getContextSize() == size) {
4103
0
    if (refinementRegionStats->getContextSize() == size) {
4104
0
      refinementRegionStats->copyFrom(prevStats);
4105
0
    } else {
4106
0
      delete refinementRegionStats;
4107
0
      refinementRegionStats = prevStats->copy();
4108
0
    }
4109
47
  } else {
4110
47
    if (refinementRegionStats->getContextSize() == size) {
4111
0
      refinementRegionStats->reset();
4112
47
    } else {
4113
47
      delete refinementRegionStats;
4114
47
      refinementRegionStats = new JArithmeticDecoderStats(1 << size);
4115
47
    }
4116
47
  }
4117
47
}
4118
4119
79
void JBIG2Stream::resetIntStats(int symCodeLen) {
4120
79
  iadhStats->reset();
4121
79
  iadwStats->reset();
4122
79
  iaexStats->reset();
4123
79
  iaaiStats->reset();
4124
79
  iadtStats->reset();
4125
79
  iaitStats->reset();
4126
79
  iafsStats->reset();
4127
79
  iadsStats->reset();
4128
79
  iardxStats->reset();
4129
79
  iardyStats->reset();
4130
79
  iardwStats->reset();
4131
79
  iardhStats->reset();
4132
79
  iariStats->reset();
4133
79
  if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
4134
10
    iaidStats->reset();
4135
69
  } else {
4136
69
    delete iaidStats;
4137
69
    iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
4138
69
  }
4139
79
}
4140
4141
14.9k
GBool JBIG2Stream::readUByte(Guint *x) {
4142
14.9k
  int c0;
4143
4144
14.9k
  if ((c0 = curStr->getChar()) == EOF) {
4145
1
    return gFalse;
4146
1
  }
4147
14.9k
  ++byteCounter;
4148
14.9k
  *x = (Guint)c0;
4149
14.9k
  return gTrue;
4150
14.9k
}
4151
4152
372
GBool JBIG2Stream::readByte(int *x) {
4153
372
 int c0;
4154
4155
372
  if ((c0 = curStr->getChar()) == EOF) {
4156
0
    return gFalse;
4157
0
  }
4158
372
  ++byteCounter;
4159
372
  *x = c0;
4160
372
  if (c0 & 0x80) {
4161
202
    *x |= -1 - 0xff;
4162
202
  }
4163
372
  return gTrue;
4164
372
}
4165
4166
2.18k
GBool JBIG2Stream::readUWord(Guint *x) {
4167
2.18k
  int c0, c1;
4168
4169
2.18k
  if ((c0 = curStr->getChar()) == EOF ||
4170
2.18k
      (c1 = curStr->getChar()) == EOF) {
4171
0
    return gFalse;
4172
0
  }
4173
2.18k
  byteCounter += 2;
4174
2.18k
  *x = (Guint)((c0 << 8) | c1);
4175
2.18k
  return gTrue;
4176
2.18k
}
4177
4178
18.3k
GBool JBIG2Stream::readULong(Guint *x) {
4179
18.3k
  int c0, c1, c2, c3;
4180
4181
18.3k
  if ((c0 = curStr->getChar()) == EOF ||
4182
18.3k
      (c1 = curStr->getChar()) == EOF ||
4183
18.3k
      (c2 = curStr->getChar()) == EOF ||
4184
18.3k
      (c3 = curStr->getChar()) == EOF) {
4185
20
    return gFalse;
4186
20
  }
4187
18.2k
  byteCounter += 4;
4188
18.2k
  *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4189
18.2k
  return gTrue;
4190
18.3k
}
4191
4192
38
GBool JBIG2Stream::readLong(int *x) {
4193
38
  int c0, c1, c2, c3;
4194
4195
38
  if ((c0 = curStr->getChar()) == EOF ||
4196
38
      (c1 = curStr->getChar()) == EOF ||
4197
38
      (c2 = curStr->getChar()) == EOF ||
4198
38
      (c3 = curStr->getChar()) == EOF) {
4199
0
    return gFalse;
4200
0
  }
4201
38
  byteCounter += 4;
4202
38
  *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4203
38
  if (c0 & 0x80) {
4204
4
    *x |= -1 - (int)0xffffffff;
4205
4
  }
4206
38
  return gTrue;
4207
38
}