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