clang-format all pdfium code.
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_Context.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <map>
8 #include <list>
9 #include "JBig2_Context.h"
10
11 // Implement a very small least recently used (LRU) cache. It is very
12 // common for a JBIG2 dictionary to span multiple pages in a PDF file,
13 // and we do not want to decode the same dictionary over and over
14 // again. We key off of the memory location of the dictionary. The
15 // list keeps track of the freshness of entries, with freshest ones
16 // at the front. Even a tiny cache size like 2 makes a dramatic
17 // difference for typical JBIG2 documents.
18 const int kSymbolDictCacheMaxSize = 2;
19
20 void OutputBitmap(CJBig2_Image* pImage) {
21   if (!pImage) {
22     return;
23   }
24 }
25 CJBig2_Context* CJBig2_Context::CreateContext(
26     CJBig2_Module* pModule,
27     uint8_t* pGlobalData,
28     FX_DWORD dwGlobalLength,
29     uint8_t* pData,
30     FX_DWORD dwLength,
31     int32_t nStreamType,
32     std::list<CJBig2_CachePair>* pSymbolDictCache,
33     IFX_Pause* pPause) {
34   return new (pModule)
35       CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLength, nStreamType,
36                      pSymbolDictCache, pPause);
37 }
38 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) {
39   delete pContext;
40 }
41 CJBig2_Context::CJBig2_Context(uint8_t* pGlobalData,
42                                FX_DWORD dwGlobalLength,
43                                uint8_t* pData,
44                                FX_DWORD dwLength,
45                                int32_t nStreamType,
46                                std::list<CJBig2_CachePair>* pSymbolDictCache,
47                                IFX_Pause* pPause) {
48   if (pGlobalData && (dwGlobalLength > 0)) {
49     JBIG2_ALLOC(m_pGlobalContext,
50                 CJBig2_Context(NULL, 0, pGlobalData, dwGlobalLength,
51                                JBIG2_EMBED_STREAM, pSymbolDictCache, pPause));
52   } else {
53     m_pGlobalContext = NULL;
54   }
55   JBIG2_ALLOC(m_pStream, CJBig2_BitStream(pData, dwLength));
56   m_nStreamType = nStreamType;
57   m_nState = JBIG2_OUT_OF_PAGE;
58   JBIG2_ALLOC(m_pSegmentList, CJBig2_List<CJBig2_Segment>);
59   JBIG2_ALLOC(m_pPageInfoList, CJBig2_List<JBig2PageInfo>(1));
60   m_pPage = NULL;
61   m_bBufSpecified = FALSE;
62   m_pPause = pPause;
63   m_nSegmentDecoded = 0;
64   m_PauseStep = 10;
65   m_pArithDecoder = NULL;
66   m_pGRD = NULL;
67   m_gbContext = NULL;
68   m_pSegment = NULL;
69   m_dwOffset = 0;
70   m_ProcessiveStatus = FXCODEC_STATUS_FRAME_READY;
71   m_pSymbolDictCache = pSymbolDictCache;
72 }
73 CJBig2_Context::~CJBig2_Context() {
74   delete m_pArithDecoder;
75   m_pArithDecoder = NULL;
76   delete m_pGRD;
77   m_pGRD = NULL;
78   if (m_gbContext) {
79     m_pModule->JBig2_Free(m_gbContext);
80   }
81   m_gbContext = NULL;
82   delete m_pGlobalContext;
83   m_pGlobalContext = NULL;
84   delete m_pPageInfoList;
85   m_pPageInfoList = NULL;
86   if (m_bBufSpecified) {
87     delete m_pPage;
88   }
89   m_pPage = NULL;
90   delete m_pStream;
91   m_pStream = NULL;
92   delete m_pSegmentList;
93   m_pSegmentList = NULL;
94 }
95 int32_t CJBig2_Context::decodeFile(IFX_Pause* pPause) {
96   uint8_t cFlags;
97   FX_DWORD dwTemp;
98   const uint8_t fileID[] = {0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A};
99   int32_t nRet;
100   if (m_pStream->getByteLeft() < 8) {
101     m_pModule->JBig2_Error("file header too short.");
102     nRet = JBIG2_ERROR_TOO_SHORT;
103     goto failed;
104   }
105   if (JBIG2_memcmp(m_pStream->getPointer(), fileID, 8) != 0) {
106     m_pModule->JBig2_Error("not jbig2 file");
107     nRet = JBIG2_ERROR_FILE_FORMAT;
108     goto failed;
109   }
110   m_pStream->offset(8);
111   if (m_pStream->read1Byte(&cFlags) != 0) {
112     m_pModule->JBig2_Error("file header too short.");
113     nRet = JBIG2_ERROR_TOO_SHORT;
114     goto failed;
115   }
116   if (!(cFlags & 0x02)) {
117     if (m_pStream->readInteger(&dwTemp) != 0) {
118       m_pModule->JBig2_Error("file header too short.");
119       nRet = JBIG2_ERROR_TOO_SHORT;
120       goto failed;
121     }
122     if (dwTemp > 0) {
123       delete m_pPageInfoList;
124       JBIG2_ALLOC(m_pPageInfoList, CJBig2_List<JBig2PageInfo>(dwTemp));
125     }
126   }
127   if (cFlags & 0x01) {
128     m_nStreamType = JBIG2_SQUENTIAL_STREAM;
129     return decode_SquentialOrgnazation(pPause);
130   } else {
131     m_nStreamType = JBIG2_RANDOM_STREAM;
132     return decode_RandomOrgnazation_FirstPage(pPause);
133   }
134 failed:
135   return nRet;
136 }
137 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
138   int32_t nRet;
139   if (m_pStream->getByteLeft() > 0) {
140     while (m_pStream->getByteLeft() >= JBIG2_MIN_SEGMENT_SIZE) {
141       if (m_pSegment == NULL) {
142         JBIG2_ALLOC(m_pSegment, CJBig2_Segment());
143         nRet = parseSegmentHeader(m_pSegment);
144         if (nRet != JBIG2_SUCCESS) {
145           delete m_pSegment;
146           m_pSegment = NULL;
147           return nRet;
148         }
149         m_dwOffset = m_pStream->getOffset();
150       }
151       nRet = parseSegmentData(m_pSegment, pPause);
152       if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
153         m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
154         m_PauseStep = 2;
155         return JBIG2_SUCCESS;
156       }
157       if ((nRet == JBIG2_END_OF_PAGE) || (nRet == JBIG2_END_OF_FILE)) {
158         delete m_pSegment;
159         m_pSegment = NULL;
160         break;
161       } else if (nRet != JBIG2_SUCCESS) {
162         delete m_pSegment;
163         m_pSegment = NULL;
164         return nRet;
165       }
166       m_pSegmentList->addItem(m_pSegment);
167       if (m_pSegment->m_dwData_length != 0xffffffff) {
168         m_dwOffset = m_dwOffset + m_pSegment->m_dwData_length;
169         m_pStream->setOffset(m_dwOffset);
170       } else {
171         m_pStream->offset(4);
172       }
173       OutputBitmap(m_pPage);
174       m_pSegment = NULL;
175       if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
176           pPause->NeedToPauseNow()) {
177         m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
178         m_PauseStep = 2;
179         return JBIG2_SUCCESS;
180       }
181     }
182   } else {
183     return JBIG2_END_OF_FILE;
184   }
185   return JBIG2_SUCCESS;
186 }
187 int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) {
188   return decode_SquentialOrgnazation(pPause);
189 }
190 int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) {
191   CJBig2_Segment* pSegment;
192   int32_t nRet;
193   while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) {
194     JBIG2_ALLOC(pSegment, CJBig2_Segment());
195     nRet = parseSegmentHeader(pSegment);
196     if (nRet != JBIG2_SUCCESS) {
197       delete pSegment;
198       return nRet;
199     } else if (pSegment->m_cFlags.s.type == 51) {
200       delete pSegment;
201       break;
202     }
203     m_pSegmentList->addItem(pSegment);
204     if (pPause && m_pPause && pPause->NeedToPauseNow()) {
205       m_PauseStep = 3;
206       m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
207       return JBIG2_SUCCESS;
208     }
209   }
210   m_nSegmentDecoded = 0;
211   return decode_RandomOrgnazation(pPause);
212 }
213 int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) {
214   int32_t nRet;
215   for (; m_nSegmentDecoded < m_pSegmentList->getLength(); m_nSegmentDecoded++) {
216     nRet = parseSegmentData(m_pSegmentList->getAt(m_nSegmentDecoded), pPause);
217     if ((nRet == JBIG2_END_OF_PAGE) || (nRet == JBIG2_END_OF_FILE)) {
218       break;
219     } else if (nRet != JBIG2_SUCCESS) {
220       return nRet;
221     }
222     if (m_pPage && pPause && pPause->NeedToPauseNow()) {
223       m_PauseStep = 4;
224       m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
225       return JBIG2_SUCCESS;
226     }
227   }
228   return JBIG2_SUCCESS;
229 }
230 int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf,
231                                      int32_t width,
232                                      int32_t height,
233                                      int32_t stride,
234                                      IFX_Pause* pPause) {
235   int32_t nRet = 0;
236   if (m_pGlobalContext) {
237     nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
238     if (nRet != JBIG2_SUCCESS) {
239       m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
240       return nRet;
241     }
242   }
243   m_bFirstPage = TRUE;
244   m_PauseStep = 0;
245   delete m_pPage;
246   JBIG2_ALLOC(m_pPage, CJBig2_Image(width, height, stride, pBuf));
247   m_bBufSpecified = TRUE;
248   if (m_pPage && pPause && pPause->NeedToPauseNow()) {
249     m_PauseStep = 1;
250     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
251     return nRet;
252   }
253   int ret = Continue(pPause);
254   return ret;
255 }
256 int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
257   m_ProcessiveStatus = FXCODEC_STATUS_DECODE_READY;
258   int32_t nRet;
259   if (m_PauseStep <= 1) {
260     switch (m_nStreamType) {
261       case JBIG2_FILE_STREAM:
262         nRet = decodeFile(pPause);
263         break;
264       case JBIG2_SQUENTIAL_STREAM:
265         nRet = decode_SquentialOrgnazation(pPause);
266         break;
267       case JBIG2_RANDOM_STREAM:
268         if (m_bFirstPage) {
269           nRet = decode_RandomOrgnazation_FirstPage(pPause);
270         } else {
271           nRet = decode_RandomOrgnazation(pPause);
272         }
273         break;
274       case JBIG2_EMBED_STREAM:
275         nRet = decode_EmbedOrgnazation(pPause);
276         break;
277       default:
278         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
279         return JBIG2_ERROR_STREAM_TYPE;
280     }
281   } else if (m_PauseStep == 2) {
282     nRet = decode_SquentialOrgnazation(pPause);
283   } else if (m_PauseStep == 3) {
284     nRet = decode_RandomOrgnazation_FirstPage(pPause);
285   } else if (m_PauseStep == 4) {
286     nRet = decode_RandomOrgnazation(pPause);
287   } else if (m_PauseStep == 5) {
288     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
289     return JBIG2_SUCCESS;
290   }
291   if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
292     return nRet;
293   }
294   m_PauseStep = 5;
295   if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) {
296     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
297     return JBIG2_SUCCESS;
298   }
299   if (nRet == JBIG2_SUCCESS) {
300     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
301   } else {
302     m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
303   }
304   return nRet;
305 }
306 int32_t CJBig2_Context::getNextPage(uint8_t* pBuf,
307                                     int32_t width,
308                                     int32_t height,
309                                     int32_t stride,
310                                     IFX_Pause* pPause) {
311   int32_t nRet = JBIG2_ERROR_STREAM_TYPE;
312   m_bFirstPage = FALSE;
313   m_PauseStep = 0;
314   delete m_pPage;
315   JBIG2_ALLOC(m_pPage, CJBig2_Image(width, height, stride, pBuf));
316   m_bBufSpecified = TRUE;
317   if (m_pPage && pPause && pPause->NeedToPauseNow()) {
318     m_PauseStep = 1;
319     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
320     return nRet;
321   }
322   return Continue(pPause);
323   switch (m_nStreamType) {
324     case JBIG2_FILE_STREAM:
325       nRet = decodeFile(pPause);
326       break;
327     case JBIG2_SQUENTIAL_STREAM:
328       nRet = decode_SquentialOrgnazation(pPause);
329       break;
330     case JBIG2_RANDOM_STREAM:
331       nRet = decode_RandomOrgnazation(pPause);
332       break;
333     case JBIG2_EMBED_STREAM:
334       nRet = decode_EmbedOrgnazation(pPause);
335       break;
336     default:
337       return JBIG2_ERROR_STREAM_TYPE;
338   }
339   return nRet;
340 }
341 int32_t CJBig2_Context::getFirstPage(CJBig2_Image** image, IFX_Pause* pPause) {
342   int32_t nRet;
343   m_bFirstPage = TRUE;
344   m_PauseStep = 0;
345   if (m_pGlobalContext) {
346     nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
347     if (nRet != JBIG2_SUCCESS) {
348       return nRet;
349     }
350   }
351   m_bBufSpecified = FALSE;
352   return Continue(pPause);
353 }
354 int32_t CJBig2_Context::getNextPage(CJBig2_Image** image, IFX_Pause* pPause) {
355   int32_t nRet;
356   m_bBufSpecified = FALSE;
357   m_bFirstPage = FALSE;
358   m_PauseStep = 0;
359   switch (m_nStreamType) {
360     case JBIG2_FILE_STREAM:
361       nRet = decodeFile(pPause);
362       break;
363     case JBIG2_SQUENTIAL_STREAM:
364       nRet = decode_SquentialOrgnazation(pPause);
365       break;
366     case JBIG2_RANDOM_STREAM:
367       nRet = decode_RandomOrgnazation(pPause);
368       break;
369     case JBIG2_EMBED_STREAM:
370       nRet = decode_EmbedOrgnazation(pPause);
371       break;
372     default:
373       return JBIG2_ERROR_STREAM_TYPE;
374   }
375   if (nRet == JBIG2_SUCCESS) {
376     *image = m_pPage;
377     m_pPage = NULL;
378     return JBIG2_SUCCESS;
379   }
380   return nRet;
381 }
382 CJBig2_Segment* CJBig2_Context::findSegmentByNumber(FX_DWORD dwNumber) {
383   CJBig2_Segment* pSeg;
384   int32_t i;
385   if (m_pGlobalContext) {
386     pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber);
387     if (pSeg) {
388       return pSeg;
389     }
390   }
391   for (i = 0; i < m_pSegmentList->getLength(); i++) {
392     pSeg = m_pSegmentList->getAt(i);
393     if (pSeg->m_dwNumber == dwNumber) {
394       return pSeg;
395     }
396   }
397   return NULL;
398 }
399 CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex(
400     CJBig2_Segment* pSegment,
401     uint8_t cType,
402     int32_t nIndex) {
403   CJBig2_Segment* pSeg;
404   int32_t i, count;
405   count = 0;
406   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
407     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
408     if (pSeg && pSeg->m_cFlags.s.type == cType) {
409       if (count == nIndex) {
410         return pSeg;
411       } else {
412         count++;
413       }
414     }
415   }
416   return NULL;
417 }
418 int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
419   uint8_t cSSize, cPSize;
420   uint8_t cTemp;
421   FX_WORD wTemp;
422   FX_DWORD dwTemp;
423   if ((m_pStream->readInteger(&pSegment->m_dwNumber) != 0) ||
424       (m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0)) {
425     goto failed;
426   }
427   cTemp = m_pStream->getCurByte();
428   if ((cTemp >> 5) == 7) {
429     if (m_pStream->readInteger(
430             (FX_DWORD*)&pSegment->m_nReferred_to_segment_count) != 0) {
431       goto failed;
432     }
433     pSegment->m_nReferred_to_segment_count &= 0x1fffffff;
434     if (pSegment->m_nReferred_to_segment_count >
435         JBIG2_MAX_REFERRED_SEGMENT_COUNT) {
436       m_pModule->JBig2_Error("Too many referred segments.");
437       return JBIG2_ERROR_LIMIT;
438     }
439     dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8;
440   } else {
441     if (m_pStream->read1Byte(&cTemp) != 0) {
442       goto failed;
443     }
444     pSegment->m_nReferred_to_segment_count = cTemp >> 5;
445     dwTemp = 5 + 1;
446   }
447   cSSize =
448       pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1;
449   cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
450   if (pSegment->m_nReferred_to_segment_count) {
451     pSegment->m_pReferred_to_segment_numbers =
452         (FX_DWORD*)m_pModule->JBig2_Malloc2(
453             sizeof(FX_DWORD), pSegment->m_nReferred_to_segment_count);
454     for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
455       switch (cSSize) {
456         case 1:
457           if (m_pStream->read1Byte(&cTemp) != 0) {
458             goto failed;
459           }
460           pSegment->m_pReferred_to_segment_numbers[i] = cTemp;
461           break;
462         case 2:
463           if (m_pStream->readShortInteger(&wTemp) != 0) {
464             goto failed;
465           }
466           pSegment->m_pReferred_to_segment_numbers[i] = wTemp;
467           break;
468         case 4:
469           if (m_pStream->readInteger(&dwTemp) != 0) {
470             goto failed;
471           }
472           pSegment->m_pReferred_to_segment_numbers[i] = dwTemp;
473           break;
474       }
475       if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber) {
476         m_pModule->JBig2_Error(
477             "The referred segment number is greater than this segment number.");
478         goto failed;
479       }
480     }
481   }
482   if (cPSize == 1) {
483     if (m_pStream->read1Byte(&cTemp) != 0) {
484       goto failed;
485     }
486     pSegment->m_dwPage_association = cTemp;
487   } else {
488     if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
489       goto failed;
490     }
491   }
492   if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) {
493     goto failed;
494   }
495   pSegment->m_pData = m_pStream->getPointer();
496   pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
497   return JBIG2_SUCCESS;
498 failed:
499   m_pModule->JBig2_Error("header too short.");
500   return JBIG2_ERROR_TOO_SHORT;
501 }
502 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
503                                          IFX_Pause* pPause) {
504   int32_t ret = ProcessiveParseSegmentData(pSegment, pPause);
505   while (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
506          m_pStream->getByteLeft() > 0) {
507     ret = ProcessiveParseSegmentData(pSegment, pPause);
508   }
509   return ret;
510 }
511 int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
512                                                    IFX_Pause* pPause) {
513   switch (pSegment->m_cFlags.s.type) {
514     case 0:
515       return parseSymbolDict(pSegment, pPause);
516     case 4:
517     case 6:
518     case 7:
519       if (m_nState == JBIG2_OUT_OF_PAGE) {
520         goto failed2;
521       } else {
522         return parseTextRegion(pSegment);
523       }
524     case 16:
525       return parsePatternDict(pSegment, pPause);
526     case 20:
527     case 22:
528     case 23:
529       if (m_nState == JBIG2_OUT_OF_PAGE) {
530         goto failed2;
531       } else {
532         return parseHalftoneRegion(pSegment, pPause);
533       }
534     case 36:
535     case 38:
536     case 39:
537       if (m_nState == JBIG2_OUT_OF_PAGE) {
538         goto failed2;
539       } else {
540         return parseGenericRegion(pSegment, pPause);
541       }
542     case 40:
543     case 42:
544     case 43:
545       if (m_nState == JBIG2_OUT_OF_PAGE) {
546         goto failed2;
547       } else {
548         return parseGenericRefinementRegion(pSegment);
549       }
550     case 48: {
551       FX_WORD wTemp;
552       JBig2PageInfo* pPageInfo;
553       JBIG2_ALLOC(pPageInfo, JBig2PageInfo);
554       if ((m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0) ||
555           (m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0) ||
556           (m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0) ||
557           (m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0) ||
558           (m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0) ||
559           (m_pStream->readShortInteger(&wTemp) != 0)) {
560         delete pPageInfo;
561         goto failed1;
562       }
563       pPageInfo->m_bIsStriped = ((wTemp >> 15) & 1) ? 1 : 0;
564       pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff;
565       if ((pPageInfo->m_dwHeight == 0xffffffff) &&
566           (pPageInfo->m_bIsStriped != 1)) {
567         m_pModule->JBig2_Warn("page height = 0xffffffff buf stripe field is 0");
568         pPageInfo->m_bIsStriped = 1;
569       }
570       if (!m_bBufSpecified) {
571         delete m_pPage;
572         if (pPageInfo->m_dwHeight == 0xffffffff) {
573           JBIG2_ALLOC(m_pPage, CJBig2_Image(pPageInfo->m_dwWidth,
574                                             pPageInfo->m_wMaxStripeSize));
575         } else {
576           JBIG2_ALLOC(m_pPage, CJBig2_Image(pPageInfo->m_dwWidth,
577                                             pPageInfo->m_dwHeight));
578         }
579       }
580       m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
581       m_pPageInfoList->addItem(pPageInfo);
582       m_nState = JBIG2_IN_PAGE;
583     } break;
584     case 49:
585       m_nState = JBIG2_OUT_OF_PAGE;
586       return JBIG2_END_OF_PAGE;
587       break;
588     case 50:
589       m_pStream->offset(pSegment->m_dwData_length);
590       break;
591     case 51:
592       return JBIG2_END_OF_FILE;
593     case 52:
594       m_pStream->offset(pSegment->m_dwData_length);
595       break;
596     case 53:
597       return parseTable(pSegment);
598     case 62:
599       m_pStream->offset(pSegment->m_dwData_length);
600       break;
601     default:
602       break;
603   }
604   return JBIG2_SUCCESS;
605 failed1:
606   m_pModule->JBig2_Error("segment data too short.");
607   return JBIG2_ERROR_TOO_SHORT;
608 failed2:
609   m_pModule->JBig2_Error("segment syntax error.");
610   return JBIG2_ERROR_FATAL;
611 }
612 int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
613                                         IFX_Pause* pPause) {
614   FX_DWORD dwTemp;
615   FX_WORD wFlags;
616   uint8_t cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST;
617   CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL,
618                       *Table_B4 = NULL, *Table_B5 = NULL;
619   int32_t i, nIndex, nRet;
620   CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL;
621   FX_BOOL bUsed;
622   CJBig2_Image** SDINSYMS = NULL;
623   CJBig2_SDDProc* pSymbolDictDecoder;
624   JBig2ArithCtx *gbContext = NULL, *grContext = NULL;
625   CJBig2_ArithDecoder* pArithDecoder;
626   JBIG2_ALLOC(pSymbolDictDecoder, CJBig2_SDDProc());
627   uint8_t* key = pSegment->m_pData;
628   FX_BOOL cache_hit = false;
629   if (m_pStream->readShortInteger(&wFlags) != 0) {
630     m_pModule->JBig2_Error(
631         "symbol dictionary segment : data header too short.");
632     nRet = JBIG2_ERROR_TOO_SHORT;
633     goto failed;
634   }
635   pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
636   pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
637   pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
638   pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
639   cSDHUFFDH = (wFlags >> 2) & 0x0003;
640   cSDHUFFDW = (wFlags >> 4) & 0x0003;
641   cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
642   cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
643   if (pSymbolDictDecoder->SDHUFF == 0) {
644     if (pSymbolDictDecoder->SDTEMPLATE == 0) {
645       dwTemp = 8;
646     } else {
647       dwTemp = 2;
648     }
649     for (i = 0; i < (int32_t)dwTemp; i++) {
650       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0) {
651         m_pModule->JBig2_Error(
652             "symbol dictionary segment : data header too short.");
653         nRet = JBIG2_ERROR_TOO_SHORT;
654         goto failed;
655       }
656     }
657   }
658   if ((pSymbolDictDecoder->SDREFAGG == 1) &&
659       (pSymbolDictDecoder->SDRTEMPLATE == 0)) {
660     for (i = 0; i < 4; i++) {
661       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0) {
662         m_pModule->JBig2_Error(
663             "symbol dictionary segment : data header too short.");
664         nRet = JBIG2_ERROR_TOO_SHORT;
665         goto failed;
666       }
667     }
668   }
669   if ((m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0) ||
670       (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0)) {
671     m_pModule->JBig2_Error(
672         "symbol dictionary segment : data header too short.");
673     nRet = JBIG2_ERROR_TOO_SHORT;
674     goto failed;
675   }
676   if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
677       pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
678     m_pModule->JBig2_Error(
679         "symbol dictionary segment : too many export/new symbols.");
680     nRet = JBIG2_ERROR_LIMIT;
681     goto failed;
682   }
683   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
684     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) {
685       m_pModule->JBig2_Error(
686           "symbol dictionary segment : can't find refered to segments");
687       nRet = JBIG2_ERROR_FATAL;
688       goto failed;
689     }
690   }
691   pSymbolDictDecoder->SDNUMINSYMS = 0;
692   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
693     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
694     if (pSeg->m_cFlags.s.type == 0) {
695       pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->SDNUMEXSYMS;
696       pLRSeg = pSeg;
697     }
698   }
699   if (pSymbolDictDecoder->SDNUMINSYMS == 0) {
700     SDINSYMS = NULL;
701   } else {
702     SDINSYMS = (CJBig2_Image**)m_pModule->JBig2_Malloc2(
703         sizeof(CJBig2_Image*), pSymbolDictDecoder->SDNUMINSYMS);
704     dwTemp = 0;
705     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
706       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
707       if (pSeg->m_cFlags.s.type == 0) {
708         JBIG2_memcpy(SDINSYMS + dwTemp, pSeg->m_Result.sd->SDEXSYMS,
709                      pSeg->m_Result.sd->SDNUMEXSYMS * sizeof(CJBig2_Image*));
710         dwTemp += pSeg->m_Result.sd->SDNUMEXSYMS;
711       }
712     }
713   }
714   pSymbolDictDecoder->SDINSYMS = SDINSYMS;
715   if (pSymbolDictDecoder->SDHUFF == 1) {
716     if ((cSDHUFFDH == 2) || (cSDHUFFDW == 2)) {
717       m_pModule->JBig2_Error(
718           "symbol dictionary segment : SDHUFFDH=2 or SDHUFFDW=2 is not "
719           "permitted.");
720       nRet = JBIG2_ERROR_FATAL;
721       goto failed;
722     }
723     nIndex = 0;
724     if (cSDHUFFDH == 0) {
725       JBIG2_ALLOC(Table_B4, CJBig2_HuffmanTable(HuffmanTable_B4,
726                                                 sizeof(HuffmanTable_B4) /
727                                                     sizeof(JBig2TableLine),
728                                                 HuffmanTable_HTOOB_B4));
729       pSymbolDictDecoder->SDHUFFDH = Table_B4;
730     } else if (cSDHUFFDH == 1) {
731       JBIG2_ALLOC(Table_B5, CJBig2_HuffmanTable(HuffmanTable_B5,
732                                                 sizeof(HuffmanTable_B5) /
733                                                     sizeof(JBig2TableLine),
734                                                 HuffmanTable_HTOOB_B5));
735       pSymbolDictDecoder->SDHUFFDH = Table_B5;
736     } else {
737       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
738       if (!pSeg) {
739         m_pModule->JBig2_Error(
740             "symbol dictionary segment : SDHUFFDH can't find user supplied "
741             "table.");
742         nRet = JBIG2_ERROR_FATAL;
743         goto failed;
744       }
745       pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht;
746     }
747     if (cSDHUFFDW == 0) {
748       JBIG2_ALLOC(Table_B2, CJBig2_HuffmanTable(HuffmanTable_B2,
749                                                 sizeof(HuffmanTable_B2) /
750                                                     sizeof(JBig2TableLine),
751                                                 HuffmanTable_HTOOB_B2));
752       pSymbolDictDecoder->SDHUFFDW = Table_B2;
753     } else if (cSDHUFFDW == 1) {
754       JBIG2_ALLOC(Table_B3, CJBig2_HuffmanTable(HuffmanTable_B3,
755                                                 sizeof(HuffmanTable_B3) /
756                                                     sizeof(JBig2TableLine),
757                                                 HuffmanTable_HTOOB_B3));
758       pSymbolDictDecoder->SDHUFFDW = Table_B3;
759     } else {
760       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
761       if (!pSeg) {
762         m_pModule->JBig2_Error(
763             "symbol dictionary segment : SDHUFFDW can't find user supplied "
764             "table.");
765         nRet = JBIG2_ERROR_FATAL;
766         goto failed;
767       }
768       pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht;
769     }
770     if (cSDHUFFBMSIZE == 0) {
771       JBIG2_ALLOC(Table_B1, CJBig2_HuffmanTable(HuffmanTable_B1,
772                                                 sizeof(HuffmanTable_B1) /
773                                                     sizeof(JBig2TableLine),
774                                                 HuffmanTable_HTOOB_B1));
775       pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1;
776     } else {
777       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
778       if (!pSeg) {
779         m_pModule->JBig2_Error(
780             "symbol dictionary segment : SDHUFFBMSIZE can't find user supplied "
781             "table.");
782         nRet = JBIG2_ERROR_FATAL;
783         goto failed;
784       }
785       pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht;
786     }
787     if (pSymbolDictDecoder->SDREFAGG == 1) {
788       if (cSDHUFFAGGINST == 0) {
789         if (!Table_B1) {
790           JBIG2_ALLOC(Table_B1, CJBig2_HuffmanTable(HuffmanTable_B1,
791                                                     sizeof(HuffmanTable_B1) /
792                                                         sizeof(JBig2TableLine),
793                                                     HuffmanTable_HTOOB_B1));
794         }
795         pSymbolDictDecoder->SDHUFFAGGINST = Table_B1;
796       } else {
797         pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
798         if (!pSeg) {
799           m_pModule->JBig2_Error(
800               "symbol dictionary segment : SDHUFFAGGINST can't find user "
801               "supplied table.");
802           nRet = JBIG2_ERROR_FATAL;
803           goto failed;
804         }
805         pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht;
806       }
807     }
808   }
809   if ((wFlags & 0x0100) && pLRSeg && pLRSeg->m_Result.sd->m_bContextRetained) {
810     if (pSymbolDictDecoder->SDHUFF == 0) {
811       dwTemp = pSymbolDictDecoder->SDTEMPLATE == 0
812                    ? 65536
813                    : pSymbolDictDecoder->SDTEMPLATE == 1 ? 8192 : 1024;
814       gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(
815           sizeof(JBig2ArithCtx), dwTemp);
816       JBIG2_memcpy(gbContext, pLRSeg->m_Result.sd->m_gbContext,
817                    sizeof(JBig2ArithCtx) * dwTemp);
818     }
819     if (pSymbolDictDecoder->SDREFAGG == 1) {
820       dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
821       grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(
822           sizeof(JBig2ArithCtx), dwTemp);
823       JBIG2_memcpy(grContext, pLRSeg->m_Result.sd->m_grContext,
824                    sizeof(JBig2ArithCtx) * dwTemp);
825     }
826   } else {
827     if (pSymbolDictDecoder->SDHUFF == 0) {
828       dwTemp = pSymbolDictDecoder->SDTEMPLATE == 0
829                    ? 65536
830                    : pSymbolDictDecoder->SDTEMPLATE == 1 ? 8192 : 1024;
831       gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(
832           sizeof(JBig2ArithCtx), dwTemp);
833       JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
834     }
835     if (pSymbolDictDecoder->SDREFAGG == 1) {
836       dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
837       grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(
838           sizeof(JBig2ArithCtx), dwTemp);
839       JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
840     }
841   }
842   pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
843   for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin();
844        it != m_pSymbolDictCache->end(); ++it) {
845     if (it->first == key) {
846       pSegment->m_Result.sd = it->second->DeepCopy();
847       m_pSymbolDictCache->push_front(*it);
848       m_pSymbolDictCache->erase(it);
849       cache_hit = true;
850       break;
851     }
852   }
853   if (!cache_hit) {
854     if (pSymbolDictDecoder->SDHUFF == 0) {
855       JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream));
856       pSegment->m_Result.sd =
857           pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext);
858       delete pArithDecoder;
859       if (pSegment->m_Result.sd == NULL) {
860         nRet = JBIG2_ERROR_FATAL;
861         goto failed;
862       }
863       m_pStream->alignByte();
864       m_pStream->offset(2);
865     } else {
866       pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
867           m_pStream, gbContext, grContext, pPause);
868       if (pSegment->m_Result.sd == NULL) {
869         nRet = JBIG2_ERROR_FATAL;
870         goto failed;
871       }
872       m_pStream->alignByte();
873     }
874     CJBig2_SymbolDict* value = pSegment->m_Result.sd->DeepCopy();
875     if (value && kSymbolDictCacheMaxSize > 0) {
876       while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) {
877         delete m_pSymbolDictCache->back().second;
878         m_pSymbolDictCache->pop_back();
879       }
880       m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value));
881     }
882   }
883   if (wFlags & 0x0200) {
884     pSegment->m_Result.sd->m_bContextRetained = TRUE;
885     if (pSymbolDictDecoder->SDHUFF == 0) {
886       pSegment->m_Result.sd->m_gbContext = gbContext;
887     }
888     if (pSymbolDictDecoder->SDREFAGG == 1) {
889       pSegment->m_Result.sd->m_grContext = grContext;
890     }
891     bUsed = TRUE;
892   } else {
893     bUsed = FALSE;
894   }
895   delete pSymbolDictDecoder;
896   if (SDINSYMS) {
897     m_pModule->JBig2_Free(SDINSYMS);
898   }
899   delete Table_B1;
900   delete Table_B2;
901   delete Table_B3;
902   delete Table_B4;
903   delete Table_B5;
904   if (bUsed == FALSE) {
905     if (gbContext) {
906       m_pModule->JBig2_Free(gbContext);
907     }
908     if (grContext) {
909       m_pModule->JBig2_Free(grContext);
910     }
911   }
912   return JBIG2_SUCCESS;
913 failed:
914   delete pSymbolDictDecoder;
915   if (SDINSYMS) {
916     m_pModule->JBig2_Free(SDINSYMS);
917   }
918   delete Table_B1;
919   delete Table_B2;
920   delete Table_B3;
921   delete Table_B4;
922   delete Table_B5;
923   if (gbContext) {
924     m_pModule->JBig2_Free(gbContext);
925   }
926   if (grContext) {
927     m_pModule->JBig2_Free(grContext);
928   }
929   return nRet;
930 }
931
932 int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
933   FX_DWORD dwTemp;
934   FX_WORD wFlags;
935   int32_t i, nIndex, nRet;
936   JBig2RegionInfo ri;
937   CJBig2_Segment* pSeg;
938   CJBig2_Image** SBSYMS = NULL;
939   JBig2HuffmanCode* SBSYMCODES = NULL;
940   uint8_t cSBHUFFFS, cSBHUFFDS, cSBHUFFDT, cSBHUFFRDW, cSBHUFFRDH, cSBHUFFRDX,
941       cSBHUFFRDY, cSBHUFFRSIZE;
942   CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B6 = NULL, *Table_B7 = NULL,
943                       *Table_B8 = NULL, *Table_B9 = NULL, *Table_B10 = NULL,
944                       *Table_B11 = NULL, *Table_B12 = NULL, *Table_B13 = NULL,
945                       *Table_B14 = NULL, *Table_B15 = NULL;
946   JBig2ArithCtx* grContext = NULL;
947   CJBig2_ArithDecoder* pArithDecoder;
948   CJBig2_TRDProc* pTRD;
949   JBIG2_ALLOC(pTRD, CJBig2_TRDProc());
950   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
951       (m_pStream->readShortInteger(&wFlags) != 0)) {
952     m_pModule->JBig2_Error("text region segment : data header too short.");
953     nRet = JBIG2_ERROR_TOO_SHORT;
954     goto failed;
955   }
956   pTRD->SBW = ri.width;
957   pTRD->SBH = ri.height;
958   pTRD->SBHUFF = wFlags & 0x0001;
959   pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
960   dwTemp = (wFlags >> 2) & 0x0003;
961   pTRD->SBSTRIPS = 1 << dwTemp;
962   pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
963   pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
964   pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
965   pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
966   pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
967   if (pTRD->SBDSOFFSET >= 0x0010) {
968     pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
969   }
970   pTRD->SBRTEMPLATE = (wFlags >> 15) & 0x0001;
971   if (pTRD->SBHUFF == 1) {
972     if (m_pStream->readShortInteger(&wFlags) != 0) {
973       m_pModule->JBig2_Error("text region segment : data header too short.");
974       nRet = JBIG2_ERROR_TOO_SHORT;
975       goto failed;
976     }
977     cSBHUFFFS = wFlags & 0x0003;
978     cSBHUFFDS = (wFlags >> 2) & 0x0003;
979     cSBHUFFDT = (wFlags >> 4) & 0x0003;
980     cSBHUFFRDW = (wFlags >> 6) & 0x0003;
981     cSBHUFFRDH = (wFlags >> 8) & 0x0003;
982     cSBHUFFRDX = (wFlags >> 10) & 0x0003;
983     cSBHUFFRDY = (wFlags >> 12) & 0x0003;
984     cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
985   }
986   if ((pTRD->SBREFINE == 1) && (pTRD->SBRTEMPLATE == 0)) {
987     for (i = 0; i < 4; i++) {
988       if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0) {
989         m_pModule->JBig2_Error("text region segment : data header too short.");
990         nRet = JBIG2_ERROR_TOO_SHORT;
991         goto failed;
992       }
993     }
994   }
995   if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0) {
996     m_pModule->JBig2_Error("text region segment : data header too short.");
997     nRet = JBIG2_ERROR_TOO_SHORT;
998     goto failed;
999   }
1000   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
1001     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) {
1002       m_pModule->JBig2_Error(
1003           "text region segment : can't find refered to segments");
1004       nRet = JBIG2_ERROR_FATAL;
1005       goto failed;
1006     }
1007   }
1008   pTRD->SBNUMSYMS = 0;
1009   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
1010     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
1011     if (pSeg->m_cFlags.s.type == 0) {
1012       pTRD->SBNUMSYMS += pSeg->m_Result.sd->SDNUMEXSYMS;
1013     }
1014   }
1015   if (pTRD->SBNUMSYMS > 0) {
1016     SBSYMS = (CJBig2_Image**)m_pModule->JBig2_Malloc2(sizeof(CJBig2_Image*),
1017                                                       pTRD->SBNUMSYMS);
1018     dwTemp = 0;
1019     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
1020       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
1021       if (pSeg->m_cFlags.s.type == 0) {
1022         JBIG2_memcpy(SBSYMS + dwTemp, pSeg->m_Result.sd->SDEXSYMS,
1023                      pSeg->m_Result.sd->SDNUMEXSYMS * sizeof(CJBig2_Image*));
1024         dwTemp += pSeg->m_Result.sd->SDNUMEXSYMS;
1025       }
1026     }
1027     pTRD->SBSYMS = SBSYMS;
1028   } else {
1029     pTRD->SBSYMS = NULL;
1030   }
1031   if (pTRD->SBHUFF == 1) {
1032     SBSYMCODES = decodeSymbolIDHuffmanTable(m_pStream, pTRD->SBNUMSYMS);
1033     if (SBSYMCODES == NULL) {
1034       m_pModule->JBig2_Error(
1035           "text region segment: symbol ID huffman table decode failure!");
1036       nRet = JBIG2_ERROR_FATAL;
1037       goto failed;
1038     }
1039     m_pStream->alignByte();
1040     pTRD->SBSYMCODES = SBSYMCODES;
1041   } else {
1042     dwTemp = 0;
1043     while ((FX_DWORD)(1 << dwTemp) < pTRD->SBNUMSYMS) {
1044       dwTemp++;
1045     }
1046     pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
1047   }
1048   if (pTRD->SBHUFF == 1) {
1049     if ((cSBHUFFFS == 2) || (cSBHUFFRDW == 2) || (cSBHUFFRDH == 2) ||
1050         (cSBHUFFRDX == 2) || (cSBHUFFRDY == 2)) {
1051       m_pModule->JBig2_Error(
1052           "text region segment : SBHUFFFS=2 or SBHUFFRDW=2 or "
1053           "SBHUFFRDH=2 or SBHUFFRDX=2 or SBHUFFRDY=2 is not permitted");
1054       nRet = JBIG2_ERROR_FATAL;
1055       goto failed;
1056     }
1057     nIndex = 0;
1058     if (cSBHUFFFS == 0) {
1059       JBIG2_ALLOC(Table_B6, CJBig2_HuffmanTable(HuffmanTable_B6,
1060                                                 sizeof(HuffmanTable_B6) /
1061                                                     sizeof(JBig2TableLine),
1062                                                 HuffmanTable_HTOOB_B6));
1063       pTRD->SBHUFFFS = Table_B6;
1064     } else if (cSBHUFFFS == 1) {
1065       JBIG2_ALLOC(Table_B7, CJBig2_HuffmanTable(HuffmanTable_B7,
1066                                                 sizeof(HuffmanTable_B7) /
1067                                                     sizeof(JBig2TableLine),
1068                                                 HuffmanTable_HTOOB_B7));
1069       pTRD->SBHUFFFS = Table_B7;
1070     } else {
1071       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1072       if (!pSeg) {
1073         m_pModule->JBig2_Error(
1074             "text region segment : SBHUFFFS can't find user supplied table");
1075         nRet = JBIG2_ERROR_FATAL;
1076         goto failed;
1077       }
1078       pTRD->SBHUFFFS = pSeg->m_Result.ht;
1079     }
1080     if (cSBHUFFDS == 0) {
1081       JBIG2_ALLOC(Table_B8, CJBig2_HuffmanTable(HuffmanTable_B8,
1082                                                 sizeof(HuffmanTable_B8) /
1083                                                     sizeof(JBig2TableLine),
1084                                                 HuffmanTable_HTOOB_B8));
1085       pTRD->SBHUFFDS = Table_B8;
1086     } else if (cSBHUFFDS == 1) {
1087       JBIG2_ALLOC(Table_B9, CJBig2_HuffmanTable(HuffmanTable_B9,
1088                                                 sizeof(HuffmanTable_B9) /
1089                                                     sizeof(JBig2TableLine),
1090                                                 HuffmanTable_HTOOB_B9));
1091       pTRD->SBHUFFDS = Table_B9;
1092     } else if (cSBHUFFDS == 2) {
1093       JBIG2_ALLOC(Table_B10, CJBig2_HuffmanTable(HuffmanTable_B10,
1094                                                  sizeof(HuffmanTable_B10) /
1095                                                      sizeof(JBig2TableLine),
1096                                                  HuffmanTable_HTOOB_B10));
1097       pTRD->SBHUFFDS = Table_B10;
1098     } else {
1099       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1100       if (!pSeg) {
1101         m_pModule->JBig2_Error(
1102             "text region segment : SBHUFFDS can't find user supplied table");
1103         nRet = JBIG2_ERROR_FATAL;
1104         goto failed;
1105       }
1106       pTRD->SBHUFFDS = pSeg->m_Result.ht;
1107     }
1108     if (cSBHUFFDT == 0) {
1109       JBIG2_ALLOC(Table_B11, CJBig2_HuffmanTable(HuffmanTable_B11,
1110                                                  sizeof(HuffmanTable_B11) /
1111                                                      sizeof(JBig2TableLine),
1112                                                  HuffmanTable_HTOOB_B11));
1113       pTRD->SBHUFFDT = Table_B11;
1114     } else if (cSBHUFFDT == 1) {
1115       JBIG2_ALLOC(Table_B12, CJBig2_HuffmanTable(HuffmanTable_B12,
1116                                                  sizeof(HuffmanTable_B12) /
1117                                                      sizeof(JBig2TableLine),
1118                                                  HuffmanTable_HTOOB_B12));
1119       pTRD->SBHUFFDT = Table_B12;
1120     } else if (cSBHUFFDT == 2) {
1121       JBIG2_ALLOC(Table_B13, CJBig2_HuffmanTable(HuffmanTable_B13,
1122                                                  sizeof(HuffmanTable_B13) /
1123                                                      sizeof(JBig2TableLine),
1124                                                  HuffmanTable_HTOOB_B13));
1125       pTRD->SBHUFFDT = Table_B13;
1126     } else {
1127       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1128       if (!pSeg) {
1129         m_pModule->JBig2_Error(
1130             "text region segment : SBHUFFDT can't find user supplied table");
1131         nRet = JBIG2_ERROR_FATAL;
1132         goto failed;
1133       }
1134       pTRD->SBHUFFDT = pSeg->m_Result.ht;
1135     }
1136     if (cSBHUFFRDW == 0) {
1137       JBIG2_ALLOC(Table_B14, CJBig2_HuffmanTable(HuffmanTable_B14,
1138                                                  sizeof(HuffmanTable_B14) /
1139                                                      sizeof(JBig2TableLine),
1140                                                  HuffmanTable_HTOOB_B14));
1141       pTRD->SBHUFFRDW = Table_B14;
1142     } else if (cSBHUFFRDW == 1) {
1143       JBIG2_ALLOC(Table_B15, CJBig2_HuffmanTable(HuffmanTable_B15,
1144                                                  sizeof(HuffmanTable_B15) /
1145                                                      sizeof(JBig2TableLine),
1146                                                  HuffmanTable_HTOOB_B15));
1147       pTRD->SBHUFFRDW = Table_B15;
1148     } else {
1149       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1150       if (!pSeg) {
1151         m_pModule->JBig2_Error(
1152             "text region segment : SBHUFFRDW can't find user supplied table");
1153         nRet = JBIG2_ERROR_FATAL;
1154         goto failed;
1155       }
1156       pTRD->SBHUFFRDW = pSeg->m_Result.ht;
1157     }
1158     if (cSBHUFFRDH == 0) {
1159       if (!Table_B14) {
1160         JBIG2_ALLOC(Table_B14, CJBig2_HuffmanTable(HuffmanTable_B14,
1161                                                    sizeof(HuffmanTable_B14) /
1162                                                        sizeof(JBig2TableLine),
1163                                                    HuffmanTable_HTOOB_B14));
1164       }
1165       pTRD->SBHUFFRDH = Table_B14;
1166     } else if (cSBHUFFRDH == 1) {
1167       if (!Table_B15) {
1168         JBIG2_ALLOC(Table_B15, CJBig2_HuffmanTable(HuffmanTable_B15,
1169                                                    sizeof(HuffmanTable_B15) /
1170                                                        sizeof(JBig2TableLine),
1171                                                    HuffmanTable_HTOOB_B15));
1172       }
1173       pTRD->SBHUFFRDH = Table_B15;
1174     } else {
1175       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1176       if (!pSeg) {
1177         m_pModule->JBig2_Error(
1178             "text region segment : SBHUFFRDH can't find user supplied table");
1179         nRet = JBIG2_ERROR_FATAL;
1180         goto failed;
1181       }
1182       pTRD->SBHUFFRDH = pSeg->m_Result.ht;
1183     }
1184     if (cSBHUFFRDX == 0) {
1185       if (!Table_B14) {
1186         JBIG2_ALLOC(Table_B14, CJBig2_HuffmanTable(HuffmanTable_B14,
1187                                                    sizeof(HuffmanTable_B14) /
1188                                                        sizeof(JBig2TableLine),
1189                                                    HuffmanTable_HTOOB_B14));
1190       }
1191       pTRD->SBHUFFRDX = Table_B14;
1192     } else if (cSBHUFFRDX == 1) {
1193       if (!Table_B15) {
1194         JBIG2_ALLOC(Table_B15, CJBig2_HuffmanTable(HuffmanTable_B15,
1195                                                    sizeof(HuffmanTable_B15) /
1196                                                        sizeof(JBig2TableLine),
1197                                                    HuffmanTable_HTOOB_B15));
1198       }
1199       pTRD->SBHUFFRDX = Table_B15;
1200     } else {
1201       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1202       if (!pSeg) {
1203         m_pModule->JBig2_Error(
1204             "text region segment : SBHUFFRDX can't find user supplied table");
1205         nRet = JBIG2_ERROR_FATAL;
1206         goto failed;
1207       }
1208       pTRD->SBHUFFRDX = pSeg->m_Result.ht;
1209     }
1210     if (cSBHUFFRDY == 0) {
1211       if (!Table_B14) {
1212         JBIG2_ALLOC(Table_B14, CJBig2_HuffmanTable(HuffmanTable_B14,
1213                                                    sizeof(HuffmanTable_B14) /
1214                                                        sizeof(JBig2TableLine),
1215                                                    HuffmanTable_HTOOB_B14));
1216       }
1217       pTRD->SBHUFFRDY = Table_B14;
1218     } else if (cSBHUFFRDY == 1) {
1219       if (!Table_B15) {
1220         JBIG2_ALLOC(Table_B15, CJBig2_HuffmanTable(HuffmanTable_B15,
1221                                                    sizeof(HuffmanTable_B15) /
1222                                                        sizeof(JBig2TableLine),
1223                                                    HuffmanTable_HTOOB_B15));
1224       }
1225       pTRD->SBHUFFRDY = Table_B15;
1226     } else {
1227       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1228       if (!pSeg) {
1229         m_pModule->JBig2_Error(
1230             "text region segment : SBHUFFRDY can't find user supplied table");
1231         nRet = JBIG2_ERROR_FATAL;
1232         goto failed;
1233       }
1234       pTRD->SBHUFFRDY = pSeg->m_Result.ht;
1235     }
1236     if (cSBHUFFRSIZE == 0) {
1237       JBIG2_ALLOC(Table_B1, CJBig2_HuffmanTable(HuffmanTable_B1,
1238                                                 sizeof(HuffmanTable_B1) /
1239                                                     sizeof(JBig2TableLine),
1240                                                 HuffmanTable_HTOOB_B1));
1241       pTRD->SBHUFFRSIZE = Table_B1;
1242     } else {
1243       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1244       if (!pSeg) {
1245         m_pModule->JBig2_Error(
1246             "text region segment : SBHUFFRSIZE can't find user supplied table");
1247         nRet = JBIG2_ERROR_FATAL;
1248         goto failed;
1249       }
1250       pTRD->SBHUFFRSIZE = pSeg->m_Result.ht;
1251     }
1252   }
1253   if (pTRD->SBREFINE == 1) {
1254     dwTemp = pTRD->SBRTEMPLATE ? 1 << 10 : 1 << 13;
1255     grContext =
1256         (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2ArithCtx), dwTemp);
1257     JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1258   }
1259   if (pTRD->SBHUFF == 0) {
1260     JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream));
1261     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1262     pSegment->m_Result.im = pTRD->decode_Arith(pArithDecoder, grContext);
1263     delete pArithDecoder;
1264     if (pSegment->m_Result.im == NULL) {
1265       nRet = JBIG2_ERROR_FATAL;
1266       goto failed;
1267     }
1268     m_pStream->alignByte();
1269     m_pStream->offset(2);
1270   } else {
1271     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1272     pSegment->m_Result.im = pTRD->decode_Huffman(m_pStream, grContext);
1273     if (pSegment->m_Result.im == NULL) {
1274       nRet = JBIG2_ERROR_FATAL;
1275       goto failed;
1276     }
1277     m_pStream->alignByte();
1278   }
1279   if (pSegment->m_cFlags.s.type != 4) {
1280     if (!m_bBufSpecified) {
1281       JBig2PageInfo* pPageInfo = m_pPageInfoList->getLast();
1282       if ((pPageInfo->m_bIsStriped == 1) &&
1283           (ri.y + ri.height > m_pPage->m_nHeight)) {
1284         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1285       }
1286     }
1287     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1288                          (JBig2ComposeOp)(ri.flags & 0x03));
1289     delete pSegment->m_Result.im;
1290     pSegment->m_Result.im = NULL;
1291   }
1292   delete pTRD;
1293   if (SBSYMS) {
1294     m_pModule->JBig2_Free(SBSYMS);
1295   }
1296   if (SBSYMCODES) {
1297     m_pModule->JBig2_Free(SBSYMCODES);
1298   }
1299   if (grContext) {
1300     m_pModule->JBig2_Free(grContext);
1301   }
1302   delete Table_B1;
1303   delete Table_B6;
1304   delete Table_B7;
1305   delete Table_B8;
1306   delete Table_B9;
1307   delete Table_B10;
1308   delete Table_B11;
1309   delete Table_B12;
1310   delete Table_B13;
1311   delete Table_B14;
1312   delete Table_B15;
1313   return JBIG2_SUCCESS;
1314 failed:
1315   delete pTRD;
1316   if (SBSYMS) {
1317     m_pModule->JBig2_Free(SBSYMS);
1318   }
1319   if (SBSYMCODES) {
1320     m_pModule->JBig2_Free(SBSYMCODES);
1321   }
1322   if (grContext) {
1323     m_pModule->JBig2_Free(grContext);
1324   }
1325   delete Table_B1;
1326   delete Table_B6;
1327   delete Table_B7;
1328   delete Table_B8;
1329   delete Table_B9;
1330   delete Table_B10;
1331   delete Table_B11;
1332   delete Table_B12;
1333   delete Table_B13;
1334   delete Table_B14;
1335   delete Table_B15;
1336   return nRet;
1337 }
1338
1339 int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
1340                                          IFX_Pause* pPause) {
1341   FX_DWORD dwTemp;
1342   uint8_t cFlags;
1343   JBig2ArithCtx* gbContext;
1344   CJBig2_ArithDecoder* pArithDecoder;
1345   CJBig2_PDDProc* pPDD;
1346   int32_t nRet;
1347   JBIG2_ALLOC(pPDD, CJBig2_PDDProc());
1348   if ((m_pStream->read1Byte(&cFlags) != 0) ||
1349       (m_pStream->read1Byte(&pPDD->HDPW) != 0) ||
1350       (m_pStream->read1Byte(&pPDD->HDPH) != 0) ||
1351       (m_pStream->readInteger(&pPDD->GRAYMAX) != 0)) {
1352     m_pModule->JBig2_Error(
1353         "pattern dictionary segment : data header too short.");
1354     nRet = JBIG2_ERROR_TOO_SHORT;
1355     goto failed;
1356   }
1357   if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX) {
1358     m_pModule->JBig2_Error("pattern dictionary segment : too max gray max.");
1359     nRet = JBIG2_ERROR_LIMIT;
1360     goto failed;
1361   }
1362   pPDD->HDMMR = cFlags & 0x01;
1363   pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
1364   pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
1365   if (pPDD->HDMMR == 0) {
1366     dwTemp =
1367         pPDD->HDTEMPLATE == 0 ? 65536 : pPDD->HDTEMPLATE == 1 ? 8192 : 1024;
1368     gbContext =
1369         (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2ArithCtx), dwTemp);
1370     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1371     JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream));
1372     pSegment->m_Result.pd =
1373         pPDD->decode_Arith(pArithDecoder, gbContext, pPause);
1374     delete pArithDecoder;
1375     if (pSegment->m_Result.pd == NULL) {
1376       m_pModule->JBig2_Free(gbContext);
1377       nRet = JBIG2_ERROR_FATAL;
1378       goto failed;
1379     }
1380     m_pModule->JBig2_Free(gbContext);
1381     m_pStream->alignByte();
1382     m_pStream->offset(2);
1383   } else {
1384     pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream, pPause);
1385     if (pSegment->m_Result.pd == NULL) {
1386       nRet = JBIG2_ERROR_FATAL;
1387       goto failed;
1388     }
1389     m_pStream->alignByte();
1390   }
1391   delete pPDD;
1392   return JBIG2_SUCCESS;
1393 failed:
1394   delete pPDD;
1395   return nRet;
1396 }
1397 int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
1398                                             IFX_Pause* pPause) {
1399   FX_DWORD dwTemp;
1400   uint8_t cFlags;
1401   JBig2RegionInfo ri;
1402   CJBig2_Segment* pSeg;
1403   CJBig2_PatternDict* pPatternDict;
1404   JBig2ArithCtx* gbContext;
1405   CJBig2_ArithDecoder* pArithDecoder;
1406   CJBig2_HTRDProc* pHRD;
1407   int32_t nRet;
1408   JBIG2_ALLOC(pHRD, CJBig2_HTRDProc());
1409   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
1410       (m_pStream->read1Byte(&cFlags) != 0) ||
1411       (m_pStream->readInteger(&pHRD->HGW) != 0) ||
1412       (m_pStream->readInteger(&pHRD->HGH) != 0) ||
1413       (m_pStream->readInteger((FX_DWORD*)&pHRD->HGX) != 0) ||
1414       (m_pStream->readInteger((FX_DWORD*)&pHRD->HGY) != 0) ||
1415       (m_pStream->readShortInteger(&pHRD->HRX) != 0) ||
1416       (m_pStream->readShortInteger(&pHRD->HRY) != 0)) {
1417     m_pModule->JBig2_Error("halftone region segment : data header too short.");
1418     nRet = JBIG2_ERROR_TOO_SHORT;
1419     goto failed;
1420   }
1421   pHRD->HBW = ri.width;
1422   pHRD->HBH = ri.height;
1423   pHRD->HMMR = cFlags & 0x01;
1424   pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
1425   pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
1426   pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
1427   pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
1428   if (pSegment->m_nReferred_to_segment_count != 1) {
1429     m_pModule->JBig2_Error(
1430         "halftone region segment : refered to segment count not equals 1");
1431     nRet = JBIG2_ERROR_FATAL;
1432     goto failed;
1433   }
1434   pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1435   if ((pSeg == NULL) || (pSeg->m_cFlags.s.type != 16)) {
1436     m_pModule->JBig2_Error(
1437         "halftone region segment : refered to segment is not pattern dict");
1438     nRet = JBIG2_ERROR_FATAL;
1439     goto failed;
1440   }
1441   pPatternDict = pSeg->m_Result.pd;
1442   if ((pPatternDict == NULL) || (pPatternDict->NUMPATS == 0)) {
1443     m_pModule->JBig2_Error("halftone region segment : has no patterns input");
1444     nRet = JBIG2_ERROR_FATAL;
1445     goto failed;
1446   }
1447   pHRD->HNUMPATS = pPatternDict->NUMPATS;
1448   pHRD->HPATS = pPatternDict->HDPATS;
1449   pHRD->HPW = pPatternDict->HDPATS[0]->m_nWidth;
1450   pHRD->HPH = pPatternDict->HDPATS[0]->m_nHeight;
1451   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1452   if (pHRD->HMMR == 0) {
1453     dwTemp = pHRD->HTEMPLATE == 0 ? 65536 : pHRD->HTEMPLATE == 1 ? 8192 : 1024;
1454     gbContext =
1455         (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2ArithCtx), dwTemp);
1456     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1457     JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream));
1458     pSegment->m_Result.im =
1459         pHRD->decode_Arith(pArithDecoder, gbContext, pPause);
1460     delete pArithDecoder;
1461     if (pSegment->m_Result.im == NULL) {
1462       m_pModule->JBig2_Free(gbContext);
1463       nRet = JBIG2_ERROR_FATAL;
1464       goto failed;
1465     }
1466     m_pModule->JBig2_Free(gbContext);
1467     m_pStream->alignByte();
1468     m_pStream->offset(2);
1469   } else {
1470     pSegment->m_Result.im = pHRD->decode_MMR(m_pStream, pPause);
1471     if (pSegment->m_Result.im == NULL) {
1472       nRet = JBIG2_ERROR_FATAL;
1473       goto failed;
1474     }
1475     m_pStream->alignByte();
1476   }
1477   if (pSegment->m_cFlags.s.type != 20) {
1478     if (!m_bBufSpecified) {
1479       JBig2PageInfo* pPageInfo = m_pPageInfoList->getLast();
1480       if ((pPageInfo->m_bIsStriped == 1) &&
1481           (ri.y + ri.height > m_pPage->m_nHeight)) {
1482         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1483       }
1484     }
1485     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1486                          (JBig2ComposeOp)(ri.flags & 0x03));
1487     delete pSegment->m_Result.im;
1488     pSegment->m_Result.im = NULL;
1489   }
1490   delete pHRD;
1491   return JBIG2_SUCCESS;
1492 failed:
1493   delete pHRD;
1494   return nRet;
1495 }
1496
1497 int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
1498                                            IFX_Pause* pPause) {
1499   FX_DWORD dwTemp;
1500   uint8_t cFlags;
1501   int32_t i, nRet;
1502   if (m_pGRD == NULL) {
1503     JBIG2_ALLOC(m_pGRD, CJBig2_GRDProc());
1504     if ((parseRegionInfo(&m_ri) != JBIG2_SUCCESS) ||
1505         (m_pStream->read1Byte(&cFlags) != 0)) {
1506       m_pModule->JBig2_Error("generic region segment : data header too short.");
1507       nRet = JBIG2_ERROR_TOO_SHORT;
1508       goto failed;
1509     }
1510     if (m_ri.height < 0 || m_ri.width < 0) {
1511       m_pModule->JBig2_Error("generic region segment : wrong data.");
1512       nRet = JBIG2_FAILED;
1513       goto failed;
1514     }
1515     m_pGRD->GBW = m_ri.width;
1516     m_pGRD->GBH = m_ri.height;
1517     m_pGRD->MMR = cFlags & 0x01;
1518     m_pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
1519     m_pGRD->TPGDON = (cFlags >> 3) & 0x01;
1520     if (m_pGRD->MMR == 0) {
1521       if (m_pGRD->GBTEMPLATE == 0) {
1522         for (i = 0; i < 8; i++) {
1523           if (m_pStream->read1Byte((uint8_t*)&m_pGRD->GBAT[i]) != 0) {
1524             m_pModule->JBig2_Error(
1525                 "generic region segment : data header too short.");
1526             nRet = JBIG2_ERROR_TOO_SHORT;
1527             goto failed;
1528           }
1529         }
1530       } else {
1531         for (i = 0; i < 2; i++) {
1532           if (m_pStream->read1Byte((uint8_t*)&m_pGRD->GBAT[i]) != 0) {
1533             m_pModule->JBig2_Error(
1534                 "generic region segment : data header too short.");
1535             nRet = JBIG2_ERROR_TOO_SHORT;
1536             goto failed;
1537           }
1538         }
1539       }
1540     }
1541     m_pGRD->USESKIP = 0;
1542   }
1543   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1544   if (m_pGRD->MMR == 0) {
1545     dwTemp =
1546         m_pGRD->GBTEMPLATE == 0 ? 65536 : m_pGRD->GBTEMPLATE == 1 ? 8192 : 1024;
1547     if (m_gbContext == NULL) {
1548       m_gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc(
1549           sizeof(JBig2ArithCtx) * dwTemp);
1550       JBIG2_memset(m_gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1551     }
1552     if (m_pArithDecoder == NULL) {
1553       JBIG2_ALLOC(m_pArithDecoder, CJBig2_ArithDecoder(m_pStream));
1554       m_ProcessiveStatus = m_pGRD->Start_decode_Arith(
1555           &pSegment->m_Result.im, m_pArithDecoder, m_gbContext, pPause);
1556     } else {
1557       m_ProcessiveStatus = m_pGRD->Continue_decode(pPause);
1558     }
1559     OutputBitmap(pSegment->m_Result.im);
1560     if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1561       if (pSegment->m_cFlags.s.type != 36) {
1562         if (!m_bBufSpecified) {
1563           JBig2PageInfo* pPageInfo = m_pPageInfoList->getLast();
1564           if ((pPageInfo->m_bIsStriped == 1) &&
1565               (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1566             m_pPage->expand(m_ri.y + m_ri.height,
1567                             (pPageInfo->m_cFlags & 4) ? 1 : 0);
1568           }
1569         }
1570         FX_RECT Rect = m_pGRD->GetReplaceRect();
1571         m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1572                              pSegment->m_Result.im,
1573                              (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1574       }
1575       return JBIG2_SUCCESS;
1576     } else {
1577       delete m_pArithDecoder;
1578       m_pArithDecoder = NULL;
1579       if (pSegment->m_Result.im == NULL) {
1580         m_pModule->JBig2_Free(m_gbContext);
1581         nRet = JBIG2_ERROR_FATAL;
1582         m_gbContext = NULL;
1583         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
1584         goto failed;
1585       }
1586       m_pModule->JBig2_Free(m_gbContext);
1587       m_gbContext = NULL;
1588       m_pStream->alignByte();
1589       m_pStream->offset(2);
1590     }
1591   } else {
1592     FXCODEC_STATUS status =
1593         m_pGRD->Start_decode_MMR(&pSegment->m_Result.im, m_pStream, pPause);
1594     while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1595       m_pGRD->Continue_decode(pPause);
1596     }
1597     if (pSegment->m_Result.im == NULL) {
1598       nRet = JBIG2_ERROR_FATAL;
1599       goto failed;
1600     }
1601     m_pStream->alignByte();
1602   }
1603   if (pSegment->m_cFlags.s.type != 36) {
1604     if (!m_bBufSpecified) {
1605       JBig2PageInfo* pPageInfo = m_pPageInfoList->getLast();
1606       if ((pPageInfo->m_bIsStriped == 1) &&
1607           (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1608         m_pPage->expand(m_ri.y + m_ri.height,
1609                         (pPageInfo->m_cFlags & 4) ? 1 : 0);
1610       }
1611     }
1612     FX_RECT Rect = m_pGRD->GetReplaceRect();
1613     m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1614                          pSegment->m_Result.im,
1615                          (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1616     delete pSegment->m_Result.im;
1617     pSegment->m_Result.im = NULL;
1618   }
1619   delete m_pGRD;
1620   m_pGRD = NULL;
1621   return JBIG2_SUCCESS;
1622 failed:
1623   delete m_pGRD;
1624   m_pGRD = NULL;
1625   return nRet;
1626 }
1627
1628 int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
1629   FX_DWORD dwTemp;
1630   JBig2RegionInfo ri;
1631   CJBig2_Segment* pSeg;
1632   int32_t i, nRet;
1633   uint8_t cFlags;
1634   JBig2ArithCtx* grContext;
1635   CJBig2_GRRDProc* pGRRD;
1636   CJBig2_ArithDecoder* pArithDecoder;
1637   JBIG2_ALLOC(pGRRD, CJBig2_GRRDProc());
1638   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
1639       (m_pStream->read1Byte(&cFlags) != 0)) {
1640     m_pModule->JBig2_Error(
1641         "generic refinement region segment : data header too short.");
1642     nRet = JBIG2_ERROR_TOO_SHORT;
1643     goto failed;
1644   }
1645   pGRRD->GRW = ri.width;
1646   pGRRD->GRH = ri.height;
1647   pGRRD->GRTEMPLATE = cFlags & 0x01;
1648   pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1649   if (pGRRD->GRTEMPLATE == 0) {
1650     for (i = 0; i < 4; i++) {
1651       if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0) {
1652         m_pModule->JBig2_Error(
1653             "generic refinement region segment : data header too short.");
1654         nRet = JBIG2_ERROR_TOO_SHORT;
1655         goto failed;
1656       }
1657     }
1658   }
1659   pSeg = NULL;
1660   if (pSegment->m_nReferred_to_segment_count > 0) {
1661     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
1662       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1663       if (pSeg == NULL) {
1664         m_pModule->JBig2_Error(
1665             "generic refinement region segment : can't find refered to "
1666             "segments");
1667         nRet = JBIG2_ERROR_FATAL;
1668         goto failed;
1669       }
1670       if ((pSeg->m_cFlags.s.type == 4) || (pSeg->m_cFlags.s.type == 20) ||
1671           (pSeg->m_cFlags.s.type == 36) || (pSeg->m_cFlags.s.type == 40)) {
1672         break;
1673       }
1674     }
1675     if (i >= pSegment->m_nReferred_to_segment_count) {
1676       m_pModule->JBig2_Error(
1677           "generic refinement region segment : can't find refered to "
1678           "intermediate region");
1679       nRet = JBIG2_ERROR_FATAL;
1680       goto failed;
1681     }
1682     pGRRD->GRREFERENCE = pSeg->m_Result.im;
1683   } else {
1684     pGRRD->GRREFERENCE = m_pPage;
1685   }
1686   pGRRD->GRREFERENCEDX = 0;
1687   pGRRD->GRREFERENCEDY = 0;
1688   dwTemp = pGRRD->GRTEMPLATE ? 1 << 10 : 1 << 13;
1689   grContext =
1690       (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2ArithCtx), dwTemp);
1691   JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1692   JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream));
1693   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1694   pSegment->m_Result.im = pGRRD->decode(pArithDecoder, grContext);
1695   delete pArithDecoder;
1696   if (pSegment->m_Result.im == NULL) {
1697     m_pModule->JBig2_Free(grContext);
1698     nRet = JBIG2_ERROR_FATAL;
1699     goto failed;
1700   }
1701   m_pModule->JBig2_Free(grContext);
1702   m_pStream->alignByte();
1703   m_pStream->offset(2);
1704   if (pSegment->m_cFlags.s.type != 40) {
1705     if (!m_bBufSpecified) {
1706       JBig2PageInfo* pPageInfo = m_pPageInfoList->getLast();
1707       if ((pPageInfo->m_bIsStriped == 1) &&
1708           (ri.y + ri.height > m_pPage->m_nHeight)) {
1709         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1710       }
1711     }
1712     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1713                          (JBig2ComposeOp)(ri.flags & 0x03));
1714     delete pSegment->m_Result.im;
1715     pSegment->m_Result.im = NULL;
1716   }
1717   delete pGRRD;
1718   return JBIG2_SUCCESS;
1719 failed:
1720   delete pGRRD;
1721   return nRet;
1722 }
1723 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
1724   pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
1725   JBIG2_ALLOC(pSegment->m_Result.ht, CJBig2_HuffmanTable(m_pStream));
1726   if (!pSegment->m_Result.ht->isOK()) {
1727     delete pSegment->m_Result.ht;
1728     pSegment->m_Result.ht = NULL;
1729     return JBIG2_ERROR_FATAL;
1730   }
1731   m_pStream->alignByte();
1732   return JBIG2_SUCCESS;
1733 }
1734 int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) {
1735   if ((m_pStream->readInteger((FX_DWORD*)&pRI->width) != 0) ||
1736       (m_pStream->readInteger((FX_DWORD*)&pRI->height) != 0) ||
1737       (m_pStream->readInteger((FX_DWORD*)&pRI->x) != 0) ||
1738       (m_pStream->readInteger((FX_DWORD*)&pRI->y) != 0) ||
1739       (m_pStream->read1Byte(&pRI->flags) != 0)) {
1740     return JBIG2_ERROR_TOO_SHORT;
1741   }
1742   return JBIG2_SUCCESS;
1743 }
1744 JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable(
1745     CJBig2_BitStream* pStream,
1746     FX_DWORD SBNUMSYMS) {
1747   JBig2HuffmanCode* SBSYMCODES;
1748   int32_t runcodes[35];
1749   int32_t runcodes_len[35];
1750   int32_t runcode;
1751   int32_t i;
1752   int32_t j;
1753   int32_t nVal;
1754   int32_t nBits;
1755   int32_t run;
1756   FX_DWORD nTemp;
1757   SBSYMCODES = (JBig2HuffmanCode*)m_pModule->JBig2_Malloc2(
1758       sizeof(JBig2HuffmanCode), SBNUMSYMS);
1759   for (i = 0; i < 35; i++) {
1760     if (pStream->readNBits(4, &runcodes_len[i]) != 0) {
1761       goto failed;
1762     }
1763   }
1764   huffman_assign_code(runcodes, runcodes_len, 35);
1765   i = 0;
1766   while (i < (int)SBNUMSYMS) {
1767     nVal = 0;
1768     nBits = 0;
1769     for (;;) {
1770       if (pStream->read1Bit(&nTemp) != 0) {
1771         goto failed;
1772       }
1773       nVal = (nVal << 1) | nTemp;
1774       nBits++;
1775       for (j = 0; j < 35; j++) {
1776         if ((nBits == runcodes_len[j]) && (nVal == runcodes[j])) {
1777           break;
1778         }
1779       }
1780       if (j < 35) {
1781         break;
1782       }
1783     }
1784     runcode = j;
1785     if (runcode < 32) {
1786       SBSYMCODES[i].codelen = runcode;
1787       run = 0;
1788     } else if (runcode == 32) {
1789       if (pStream->readNBits(2, &nTemp) != 0) {
1790         goto failed;
1791       }
1792       run = nTemp + 3;
1793     } else if (runcode == 33) {
1794       if (pStream->readNBits(3, &nTemp) != 0) {
1795         goto failed;
1796       }
1797       run = nTemp + 3;
1798     } else if (runcode == 34) {
1799       if (pStream->readNBits(7, &nTemp) != 0) {
1800         goto failed;
1801       }
1802       run = nTemp + 11;
1803     }
1804     if (run > 0) {
1805       if (i + run > (int)SBNUMSYMS) {
1806         goto failed;
1807       }
1808       for (j = 0; j < run; j++) {
1809         if (runcode == 32 && i > 0) {
1810           SBSYMCODES[i + j].codelen = SBSYMCODES[i - 1].codelen;
1811         } else {
1812           SBSYMCODES[i + j].codelen = 0;
1813         }
1814       }
1815       i += run;
1816     } else {
1817       i++;
1818     }
1819   }
1820   huffman_assign_code(SBSYMCODES, SBNUMSYMS);
1821   return SBSYMCODES;
1822 failed:
1823   m_pModule->JBig2_Free(SBSYMCODES);
1824   return NULL;
1825 }
1826 void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) {
1827   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1828   int* LENCOUNT;
1829   int* FIRSTCODE;
1830   LENMAX = 0;
1831   for (i = 0; i < NTEMP; i++) {
1832     if (PREFLEN[i] > LENMAX) {
1833       LENMAX = PREFLEN[i];
1834     }
1835   }
1836   LENCOUNT = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
1837   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1838   FIRSTCODE = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
1839   for (i = 0; i < NTEMP; i++) {
1840     LENCOUNT[PREFLEN[i]]++;
1841   }
1842   CURLEN = 1;
1843   FIRSTCODE[0] = 0;
1844   LENCOUNT[0] = 0;
1845   while (CURLEN <= LENMAX) {
1846     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1847     CURCODE = FIRSTCODE[CURLEN];
1848     CURTEMP = 0;
1849     while (CURTEMP < NTEMP) {
1850       if (PREFLEN[CURTEMP] == CURLEN) {
1851         CODES[CURTEMP] = CURCODE;
1852         CURCODE = CURCODE + 1;
1853       }
1854       CURTEMP = CURTEMP + 1;
1855     }
1856     CURLEN = CURLEN + 1;
1857   }
1858   m_pModule->JBig2_Free(LENCOUNT);
1859   m_pModule->JBig2_Free(FIRSTCODE);
1860 }
1861 void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES,
1862                                          int NTEMP) {
1863   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1864   int* LENCOUNT;
1865   int* FIRSTCODE;
1866   LENMAX = 0;
1867   for (i = 0; i < NTEMP; i++) {
1868     if (SBSYMCODES[i].codelen > LENMAX) {
1869       LENMAX = SBSYMCODES[i].codelen;
1870     }
1871   }
1872   LENCOUNT = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
1873   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1874   FIRSTCODE = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
1875   for (i = 0; i < NTEMP; i++) {
1876     LENCOUNT[SBSYMCODES[i].codelen]++;
1877   }
1878   CURLEN = 1;
1879   FIRSTCODE[0] = 0;
1880   LENCOUNT[0] = 0;
1881   while (CURLEN <= LENMAX) {
1882     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1883     CURCODE = FIRSTCODE[CURLEN];
1884     CURTEMP = 0;
1885     while (CURTEMP < NTEMP) {
1886       if (SBSYMCODES[CURTEMP].codelen == CURLEN) {
1887         SBSYMCODES[CURTEMP].code = CURCODE;
1888         CURCODE = CURCODE + 1;
1889       }
1890       CURTEMP = CURTEMP + 1;
1891     }
1892     CURLEN = CURLEN + 1;
1893   }
1894   m_pModule->JBig2_Free(LENCOUNT);
1895   m_pModule->JBig2_Free(FIRSTCODE);
1896 }