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 "core/src/fxcodec/jbig2/JBig2_Context.h"
8
9 #include <algorithm>
10 #include <list>
11 #include <utility>
12 #include <vector>
13
14 #include "core/src/fxcodec/jbig2/JBig2_ArithDecoder.h"
15 #include "core/src/fxcodec/jbig2/JBig2_BitStream.h"
16 #include "core/src/fxcodec/jbig2/JBig2_GrdProc.h"
17 #include "core/src/fxcodec/jbig2/JBig2_GrrdProc.h"
18 #include "core/src/fxcodec/jbig2/JBig2_HtrdProc.h"
19 #include "core/src/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
20 #include "core/src/fxcodec/jbig2/JBig2_PddProc.h"
21 #include "core/src/fxcodec/jbig2/JBig2_SddProc.h"
22 #include "core/src/fxcodec/jbig2/JBig2_TrdProc.h"
23
24 namespace {
25
GetHuffContextSize(uint8_t val)26 size_t GetHuffContextSize(uint8_t val) {
27 return val == 0 ? 65536 : val == 1 ? 8192 : 1024;
28 }
29
GetRefAggContextSize(FX_BOOL val)30 size_t GetRefAggContextSize(FX_BOOL val) {
31 return val ? 1024 : 8192;
32 }
33
34 } // namespace
35
36 // Implement a very small least recently used (LRU) cache. It is very
37 // common for a JBIG2 dictionary to span multiple pages in a PDF file,
38 // and we do not want to decode the same dictionary over and over
39 // again. We key off of the memory location of the dictionary. The
40 // list keeps track of the freshness of entries, with freshest ones
41 // at the front. Even a tiny cache size like 2 makes a dramatic
42 // difference for typical JBIG2 documents.
43 static const int kSymbolDictCacheMaxSize = 2;
44
CreateContext(CPDF_StreamAcc * pGlobalStream,CPDF_StreamAcc * pSrcStream,std::list<CJBig2_CachePair> * pSymbolDictCache,IFX_Pause * pPause)45 CJBig2_Context* CJBig2_Context::CreateContext(
46 CPDF_StreamAcc* pGlobalStream,
47 CPDF_StreamAcc* pSrcStream,
48 std::list<CJBig2_CachePair>* pSymbolDictCache,
49 IFX_Pause* pPause) {
50 return new CJBig2_Context(pGlobalStream, pSrcStream, pSymbolDictCache, pPause,
51 false);
52 }
53
DestroyContext(CJBig2_Context * pContext)54 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) {
55 delete pContext;
56 }
57
CJBig2_Context(CPDF_StreamAcc * pGlobalStream,CPDF_StreamAcc * pSrcStream,std::list<CJBig2_CachePair> * pSymbolDictCache,IFX_Pause * pPause,bool bIsGlobal)58 CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream,
59 CPDF_StreamAcc* pSrcStream,
60 std::list<CJBig2_CachePair>* pSymbolDictCache,
61 IFX_Pause* pPause,
62 bool bIsGlobal)
63 : m_nSegmentDecoded(0),
64 m_bInPage(false),
65 m_bBufSpecified(false),
66 m_PauseStep(10),
67 m_pPause(pPause),
68 m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY),
69 m_gbContext(NULL),
70 m_dwOffset(0),
71 m_pSymbolDictCache(pSymbolDictCache),
72 m_bIsGlobal(bIsGlobal) {
73 if (pGlobalStream && (pGlobalStream->GetSize() > 0)) {
74 m_pGlobalContext = new CJBig2_Context(nullptr, pGlobalStream,
75 pSymbolDictCache, pPause, true);
76 } else {
77 m_pGlobalContext = nullptr;
78 }
79
80 m_pStream.reset(new CJBig2_BitStream(pSrcStream));
81 }
82
~CJBig2_Context()83 CJBig2_Context::~CJBig2_Context() {
84 FX_Free(m_gbContext);
85 m_gbContext = NULL;
86 delete m_pGlobalContext;
87 m_pGlobalContext = NULL;
88 }
89
decode_SquentialOrgnazation(IFX_Pause * pPause)90 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
91 int32_t nRet;
92 if (m_pStream->getByteLeft() <= 0)
93 return JBIG2_END_OF_FILE;
94
95 while (m_pStream->getByteLeft() >= JBIG2_MIN_SEGMENT_SIZE) {
96 if (!m_pSegment) {
97 m_pSegment.reset(new CJBig2_Segment);
98 nRet = parseSegmentHeader(m_pSegment.get());
99 if (nRet != JBIG2_SUCCESS) {
100 m_pSegment.reset();
101 return nRet;
102 }
103 m_dwOffset = m_pStream->getOffset();
104 }
105 nRet = parseSegmentData(m_pSegment.get(), pPause);
106 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
107 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
108 m_PauseStep = 2;
109 return JBIG2_SUCCESS;
110 }
111 if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE) {
112 m_pSegment.reset();
113 return JBIG2_SUCCESS;
114 }
115 if (nRet != JBIG2_SUCCESS) {
116 m_pSegment.reset();
117 return nRet;
118 }
119 if (m_pSegment->m_dwData_length != 0xffffffff) {
120 m_dwOffset += m_pSegment->m_dwData_length;
121 m_pStream->setOffset(m_dwOffset);
122 } else {
123 m_pStream->offset(4);
124 }
125 m_SegmentList.push_back(m_pSegment.release());
126 if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
127 pPause->NeedToPauseNow()) {
128 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
129 m_PauseStep = 2;
130 return JBIG2_SUCCESS;
131 }
132 }
133 return JBIG2_SUCCESS;
134 }
decode_EmbedOrgnazation(IFX_Pause * pPause)135 int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) {
136 return decode_SquentialOrgnazation(pPause);
137 }
decode_RandomOrgnazation_FirstPage(IFX_Pause * pPause)138 int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) {
139 int32_t nRet;
140 while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) {
141 std::unique_ptr<CJBig2_Segment> pSegment(new CJBig2_Segment);
142 nRet = parseSegmentHeader(pSegment.get());
143 if (nRet != JBIG2_SUCCESS) {
144 return nRet;
145 } else if (pSegment->m_cFlags.s.type == 51) {
146 break;
147 }
148 m_SegmentList.push_back(pSegment.release());
149 if (pPause && m_pPause && pPause->NeedToPauseNow()) {
150 m_PauseStep = 3;
151 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
152 return JBIG2_SUCCESS;
153 }
154 }
155 m_nSegmentDecoded = 0;
156 return decode_RandomOrgnazation(pPause);
157 }
decode_RandomOrgnazation(IFX_Pause * pPause)158 int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) {
159 for (; m_nSegmentDecoded < m_SegmentList.size(); ++m_nSegmentDecoded) {
160 int32_t nRet =
161 parseSegmentData(m_SegmentList.get(m_nSegmentDecoded), pPause);
162 if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE)
163 return JBIG2_SUCCESS;
164
165 if (nRet != JBIG2_SUCCESS)
166 return nRet;
167
168 if (m_pPage && pPause && pPause->NeedToPauseNow()) {
169 m_PauseStep = 4;
170 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
171 return JBIG2_SUCCESS;
172 }
173 }
174 return JBIG2_SUCCESS;
175 }
getFirstPage(uint8_t * pBuf,int32_t width,int32_t height,int32_t stride,IFX_Pause * pPause)176 int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf,
177 int32_t width,
178 int32_t height,
179 int32_t stride,
180 IFX_Pause* pPause) {
181 int32_t nRet = 0;
182 if (m_pGlobalContext) {
183 nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
184 if (nRet != JBIG2_SUCCESS) {
185 m_ProcessingStatus = FXCODEC_STATUS_ERROR;
186 return nRet;
187 }
188 }
189 m_PauseStep = 0;
190 m_pPage.reset(new CJBig2_Image(width, height, stride, pBuf));
191 m_bBufSpecified = true;
192 if (pPause && pPause->NeedToPauseNow()) {
193 m_PauseStep = 1;
194 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
195 return nRet;
196 }
197 return Continue(pPause);
198 }
Continue(IFX_Pause * pPause)199 int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
200 m_ProcessingStatus = FXCODEC_STATUS_DECODE_READY;
201 int32_t nRet;
202 if (m_PauseStep <= 1) {
203 nRet = decode_EmbedOrgnazation(pPause);
204 } else if (m_PauseStep == 2) {
205 nRet = decode_SquentialOrgnazation(pPause);
206 } else if (m_PauseStep == 3) {
207 nRet = decode_RandomOrgnazation_FirstPage(pPause);
208 } else if (m_PauseStep == 4) {
209 nRet = decode_RandomOrgnazation(pPause);
210 } else if (m_PauseStep == 5) {
211 m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
212 return JBIG2_SUCCESS;
213 }
214 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
215 return nRet;
216 }
217 m_PauseStep = 5;
218 if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) {
219 m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
220 return JBIG2_SUCCESS;
221 }
222 if (nRet == JBIG2_SUCCESS) {
223 m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
224 } else {
225 m_ProcessingStatus = FXCODEC_STATUS_ERROR;
226 }
227 return nRet;
228 }
229
findSegmentByNumber(FX_DWORD dwNumber)230 CJBig2_Segment* CJBig2_Context::findSegmentByNumber(FX_DWORD dwNumber) {
231 if (m_pGlobalContext) {
232 CJBig2_Segment* pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber);
233 if (pSeg) {
234 return pSeg;
235 }
236 }
237 for (size_t i = 0; i < m_SegmentList.size(); ++i) {
238 CJBig2_Segment* pSeg = m_SegmentList.get(i);
239 if (pSeg->m_dwNumber == dwNumber) {
240 return pSeg;
241 }
242 }
243 return nullptr;
244 }
findReferredSegmentByTypeAndIndex(CJBig2_Segment * pSegment,uint8_t cType,int32_t nIndex)245 CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex(
246 CJBig2_Segment* pSegment,
247 uint8_t cType,
248 int32_t nIndex) {
249 int32_t count = 0;
250 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
251 CJBig2_Segment* pSeg =
252 findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
253 if (pSeg && pSeg->m_cFlags.s.type == cType) {
254 if (count == nIndex)
255 return pSeg;
256 ++count;
257 }
258 }
259 return NULL;
260 }
parseSegmentHeader(CJBig2_Segment * pSegment)261 int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
262 if (m_pStream->readInteger(&pSegment->m_dwNumber) != 0 ||
263 m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0) {
264 return JBIG2_ERROR_TOO_SHORT;
265 }
266
267 FX_DWORD dwTemp;
268 uint8_t cTemp = m_pStream->getCurByte();
269 if ((cTemp >> 5) == 7) {
270 if (m_pStream->readInteger(
271 (FX_DWORD*)&pSegment->m_nReferred_to_segment_count) != 0) {
272 return JBIG2_ERROR_TOO_SHORT;
273 }
274 pSegment->m_nReferred_to_segment_count &= 0x1fffffff;
275 if (pSegment->m_nReferred_to_segment_count >
276 JBIG2_MAX_REFERRED_SEGMENT_COUNT) {
277 return JBIG2_ERROR_LIMIT;
278 }
279 dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8;
280 } else {
281 if (m_pStream->read1Byte(&cTemp) != 0)
282 return JBIG2_ERROR_TOO_SHORT;
283
284 pSegment->m_nReferred_to_segment_count = cTemp >> 5;
285 dwTemp = 5 + 1;
286 }
287 uint8_t cSSize =
288 pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1;
289 uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
290 if (pSegment->m_nReferred_to_segment_count) {
291 pSegment->m_pReferred_to_segment_numbers =
292 FX_Alloc(FX_DWORD, pSegment->m_nReferred_to_segment_count);
293 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
294 switch (cSSize) {
295 case 1:
296 if (m_pStream->read1Byte(&cTemp) != 0)
297 return JBIG2_ERROR_TOO_SHORT;
298
299 pSegment->m_pReferred_to_segment_numbers[i] = cTemp;
300 break;
301 case 2:
302 FX_WORD wTemp;
303 if (m_pStream->readShortInteger(&wTemp) != 0)
304 return JBIG2_ERROR_TOO_SHORT;
305
306 pSegment->m_pReferred_to_segment_numbers[i] = wTemp;
307 break;
308 case 4:
309 if (m_pStream->readInteger(&dwTemp) != 0)
310 return JBIG2_ERROR_TOO_SHORT;
311
312 pSegment->m_pReferred_to_segment_numbers[i] = dwTemp;
313 break;
314 }
315 if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber)
316 return JBIG2_ERROR_TOO_SHORT;
317 }
318 }
319 if (cPSize == 1) {
320 if (m_pStream->read1Byte(&cTemp) != 0)
321 return JBIG2_ERROR_TOO_SHORT;
322 pSegment->m_dwPage_association = cTemp;
323 } else {
324 if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
325 return JBIG2_ERROR_TOO_SHORT;
326 }
327 }
328 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
329 return JBIG2_ERROR_TOO_SHORT;
330
331 pSegment->m_dwObjNum = m_pStream->getObjNum();
332 pSegment->m_dwDataOffset = m_pStream->getOffset();
333 pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
334 return JBIG2_SUCCESS;
335 }
336
parseSegmentData(CJBig2_Segment * pSegment,IFX_Pause * pPause)337 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
338 IFX_Pause* pPause) {
339 int32_t ret = ProcessingParseSegmentData(pSegment, pPause);
340 while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
341 m_pStream->getByteLeft() > 0) {
342 ret = ProcessingParseSegmentData(pSegment, pPause);
343 }
344 return ret;
345 }
346
ProcessingParseSegmentData(CJBig2_Segment * pSegment,IFX_Pause * pPause)347 int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment,
348 IFX_Pause* pPause) {
349 switch (pSegment->m_cFlags.s.type) {
350 case 0:
351 return parseSymbolDict(pSegment, pPause);
352 case 4:
353 case 6:
354 case 7:
355 if (!m_bInPage)
356 return JBIG2_ERROR_FATAL;
357 return parseTextRegion(pSegment);
358 case 16:
359 return parsePatternDict(pSegment, pPause);
360 case 20:
361 case 22:
362 case 23:
363 if (!m_bInPage)
364 return JBIG2_ERROR_FATAL;
365 return parseHalftoneRegion(pSegment, pPause);
366 case 36:
367 case 38:
368 case 39:
369 if (!m_bInPage)
370 return JBIG2_ERROR_FATAL;
371 return parseGenericRegion(pSegment, pPause);
372 case 40:
373 case 42:
374 case 43:
375 if (!m_bInPage)
376 return JBIG2_ERROR_FATAL;
377 return parseGenericRefinementRegion(pSegment);
378 case 48: {
379 FX_WORD wTemp;
380 std::unique_ptr<JBig2PageInfo> pPageInfo(new JBig2PageInfo);
381 if (m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0 ||
382 m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0 ||
383 m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0 ||
384 m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0 ||
385 m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0 ||
386 m_pStream->readShortInteger(&wTemp) != 0) {
387 return JBIG2_ERROR_TOO_SHORT;
388 }
389 pPageInfo->m_bIsStriped = !!(wTemp & 0x8000);
390 pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff;
391 bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff);
392 if (bMaxHeight && pPageInfo->m_bIsStriped != TRUE)
393 pPageInfo->m_bIsStriped = TRUE;
394
395 if (!m_bBufSpecified) {
396 FX_DWORD height =
397 bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
398 m_pPage.reset(new CJBig2_Image(pPageInfo->m_dwWidth, height));
399 }
400
401 if (!m_pPage->m_pData) {
402 m_ProcessingStatus = FXCODEC_STATUS_ERROR;
403 return JBIG2_ERROR_TOO_SHORT;
404 }
405
406 m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
407 m_PageInfoList.push_back(pPageInfo.release());
408 m_bInPage = true;
409 } break;
410 case 49:
411 m_bInPage = false;
412 return JBIG2_END_OF_PAGE;
413 break;
414 case 50:
415 m_pStream->offset(pSegment->m_dwData_length);
416 break;
417 case 51:
418 return JBIG2_END_OF_FILE;
419 case 52:
420 m_pStream->offset(pSegment->m_dwData_length);
421 break;
422 case 53:
423 return parseTable(pSegment);
424 case 62:
425 m_pStream->offset(pSegment->m_dwData_length);
426 break;
427 default:
428 break;
429 }
430 return JBIG2_SUCCESS;
431 }
432
parseSymbolDict(CJBig2_Segment * pSegment,IFX_Pause * pPause)433 int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
434 IFX_Pause* pPause) {
435 FX_WORD wFlags;
436 if (m_pStream->readShortInteger(&wFlags) != 0)
437 return JBIG2_ERROR_TOO_SHORT;
438
439 std::unique_ptr<CJBig2_SDDProc> pSymbolDictDecoder(new CJBig2_SDDProc);
440 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
441 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
442 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
443 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
444 uint8_t cSDHUFFDH = (wFlags >> 2) & 0x0003;
445 uint8_t cSDHUFFDW = (wFlags >> 4) & 0x0003;
446 uint8_t cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
447 uint8_t cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
448 if (pSymbolDictDecoder->SDHUFF == 0) {
449 const FX_DWORD dwTemp = (pSymbolDictDecoder->SDTEMPLATE == 0) ? 8 : 2;
450 for (FX_DWORD i = 0; i < dwTemp; ++i) {
451 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0)
452 return JBIG2_ERROR_TOO_SHORT;
453 }
454 }
455 if (pSymbolDictDecoder->SDREFAGG == 1 &&
456 pSymbolDictDecoder->SDRTEMPLATE == 0) {
457 for (int32_t i = 0; i < 4; ++i) {
458 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0)
459 return JBIG2_ERROR_TOO_SHORT;
460 }
461 }
462 if (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0 ||
463 m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0) {
464 return JBIG2_ERROR_TOO_SHORT;
465 }
466 if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
467 pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
468 return JBIG2_ERROR_LIMIT;
469 }
470 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
471 if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]))
472 return JBIG2_ERROR_FATAL;
473 }
474 CJBig2_Segment* pLRSeg = nullptr;
475 pSymbolDictDecoder->SDNUMINSYMS = 0;
476 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
477 CJBig2_Segment* pSeg =
478 findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
479 if (pSeg->m_cFlags.s.type == 0) {
480 pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->NumImages();
481 pLRSeg = pSeg;
482 }
483 }
484
485 std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SDINSYMS;
486 if (pSymbolDictDecoder->SDNUMINSYMS != 0) {
487 SDINSYMS.reset(FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS));
488 FX_DWORD dwTemp = 0;
489 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
490 CJBig2_Segment* pSeg =
491 findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
492 if (pSeg->m_cFlags.s.type == 0) {
493 const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd;
494 for (size_t j = 0; j < dict.NumImages(); ++j)
495 SDINSYMS.get()[dwTemp + j] = dict.GetImage(j);
496 dwTemp += dict.NumImages();
497 }
498 }
499 }
500 pSymbolDictDecoder->SDINSYMS = SDINSYMS.get();
501
502 std::unique_ptr<CJBig2_HuffmanTable> Table_B1;
503 std::unique_ptr<CJBig2_HuffmanTable> Table_B2;
504 std::unique_ptr<CJBig2_HuffmanTable> Table_B3;
505 std::unique_ptr<CJBig2_HuffmanTable> Table_B4;
506 std::unique_ptr<CJBig2_HuffmanTable> Table_B5;
507 if (pSymbolDictDecoder->SDHUFF == 1) {
508 if (cSDHUFFDH == 2 || cSDHUFFDW == 2)
509 return JBIG2_ERROR_FATAL;
510
511 int32_t nIndex = 0;
512 if (cSDHUFFDH == 0) {
513 Table_B4.reset(new CJBig2_HuffmanTable(HuffmanTable_B4,
514 FX_ArraySize(HuffmanTable_B4),
515 HuffmanTable_HTOOB_B4));
516 pSymbolDictDecoder->SDHUFFDH = Table_B4.get();
517 } else if (cSDHUFFDH == 1) {
518 Table_B5.reset(new CJBig2_HuffmanTable(HuffmanTable_B5,
519 FX_ArraySize(HuffmanTable_B5),
520 HuffmanTable_HTOOB_B5));
521 pSymbolDictDecoder->SDHUFFDH = Table_B5.get();
522 } else {
523 CJBig2_Segment* pSeg =
524 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
525 if (!pSeg)
526 return JBIG2_ERROR_FATAL;
527 pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht;
528 }
529 if (cSDHUFFDW == 0) {
530 Table_B2.reset(new CJBig2_HuffmanTable(HuffmanTable_B2,
531 FX_ArraySize(HuffmanTable_B2),
532 HuffmanTable_HTOOB_B2));
533 pSymbolDictDecoder->SDHUFFDW = Table_B2.get();
534 } else if (cSDHUFFDW == 1) {
535 Table_B3.reset(new CJBig2_HuffmanTable(HuffmanTable_B3,
536 FX_ArraySize(HuffmanTable_B3),
537 HuffmanTable_HTOOB_B3));
538 pSymbolDictDecoder->SDHUFFDW = Table_B3.get();
539 } else {
540 CJBig2_Segment* pSeg =
541 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
542 if (!pSeg)
543 return JBIG2_ERROR_FATAL;
544 pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht;
545 }
546 if (cSDHUFFBMSIZE == 0) {
547 Table_B1.reset(new CJBig2_HuffmanTable(HuffmanTable_B1,
548 FX_ArraySize(HuffmanTable_B1),
549 HuffmanTable_HTOOB_B1));
550 pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1.get();
551 } else {
552 CJBig2_Segment* pSeg =
553 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
554 if (!pSeg)
555 return JBIG2_ERROR_FATAL;
556 pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht;
557 }
558 if (pSymbolDictDecoder->SDREFAGG == 1) {
559 if (cSDHUFFAGGINST == 0) {
560 if (!Table_B1) {
561 Table_B1.reset(new CJBig2_HuffmanTable(HuffmanTable_B1,
562 FX_ArraySize(HuffmanTable_B1),
563 HuffmanTable_HTOOB_B1));
564 }
565 pSymbolDictDecoder->SDHUFFAGGINST = Table_B1.get();
566 } else {
567 CJBig2_Segment* pSeg =
568 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
569 if (!pSeg)
570 return JBIG2_ERROR_FATAL;
571 pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht;
572 }
573 }
574 }
575
576 const bool bUseGbContext = (pSymbolDictDecoder->SDHUFF == 0);
577 const bool bUseGrContext = (pSymbolDictDecoder->SDREFAGG == 1);
578 const size_t gbContextSize =
579 GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE);
580 const size_t grContextSize =
581 GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE);
582 std::vector<JBig2ArithCtx> gbContext;
583 std::vector<JBig2ArithCtx> grContext;
584 if ((wFlags & 0x0100) && pLRSeg) {
585 if (bUseGbContext) {
586 gbContext = pLRSeg->m_Result.sd->GbContext();
587 if (gbContext.size() != gbContextSize)
588 return JBIG2_ERROR_FATAL;
589 }
590 if (bUseGrContext) {
591 grContext = pLRSeg->m_Result.sd->GrContext();
592 if (grContext.size() != grContextSize)
593 return JBIG2_ERROR_FATAL;
594 }
595 } else {
596 if (bUseGbContext)
597 gbContext.resize(gbContextSize);
598 if (bUseGrContext)
599 grContext.resize(grContextSize);
600 }
601
602 CJBig2_CacheKey key =
603 CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset);
604 FX_BOOL cache_hit = false;
605 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
606 if (m_bIsGlobal && key.first != 0) {
607 for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end();
608 ++it) {
609 if (it->first == key) {
610 std::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy());
611 pSegment->m_Result.sd = copy.release();
612 m_pSymbolDictCache->push_front(*it);
613 m_pSymbolDictCache->erase(it);
614 cache_hit = true;
615 break;
616 }
617 }
618 }
619 if (!cache_hit) {
620 if (bUseGbContext) {
621 std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
622 new CJBig2_ArithDecoder(m_pStream.get()));
623 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(
624 pArithDecoder.get(), &gbContext, &grContext);
625 if (!pSegment->m_Result.sd)
626 return JBIG2_ERROR_FATAL;
627
628 m_pStream->alignByte();
629 m_pStream->offset(2);
630 } else {
631 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
632 m_pStream.get(), &gbContext, &grContext, pPause);
633 if (!pSegment->m_Result.sd)
634 return JBIG2_ERROR_FATAL;
635 m_pStream->alignByte();
636 }
637 if (m_bIsGlobal && kSymbolDictCacheMaxSize > 0) {
638 std::unique_ptr<CJBig2_SymbolDict> value =
639 pSegment->m_Result.sd->DeepCopy();
640 while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) {
641 delete m_pSymbolDictCache->back().second;
642 m_pSymbolDictCache->pop_back();
643 }
644 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release()));
645 }
646 }
647 if (wFlags & 0x0200) {
648 if (bUseGbContext)
649 pSegment->m_Result.sd->SetGbContext(gbContext);
650 if (bUseGrContext)
651 pSegment->m_Result.sd->SetGrContext(grContext);
652 }
653 return JBIG2_SUCCESS;
654 }
655
parseTextRegion(CJBig2_Segment * pSegment)656 int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
657 FX_WORD wFlags;
658 JBig2RegionInfo ri;
659 if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
660 m_pStream->readShortInteger(&wFlags) != 0) {
661 return JBIG2_ERROR_TOO_SHORT;
662 }
663
664 std::unique_ptr<CJBig2_TRDProc> pTRD(new CJBig2_TRDProc);
665 pTRD->SBW = ri.width;
666 pTRD->SBH = ri.height;
667 pTRD->SBHUFF = wFlags & 0x0001;
668 pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
669 FX_DWORD dwTemp = (wFlags >> 2) & 0x0003;
670 pTRD->SBSTRIPS = 1 << dwTemp;
671 pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
672 pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
673 pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
674 pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
675 pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
676 if (pTRD->SBDSOFFSET >= 0x0010) {
677 pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
678 }
679 pTRD->SBRTEMPLATE = (wFlags >> 15) & 0x0001;
680
681 uint8_t cSBHUFFFS;
682 uint8_t cSBHUFFDS;
683 uint8_t cSBHUFFDT;
684 uint8_t cSBHUFFRDW;
685 uint8_t cSBHUFFRDH;
686 uint8_t cSBHUFFRDX;
687 uint8_t cSBHUFFRDY;
688 uint8_t cSBHUFFRSIZE;
689 if (pTRD->SBHUFF == 1) {
690 if (m_pStream->readShortInteger(&wFlags) != 0)
691 return JBIG2_ERROR_TOO_SHORT;
692
693 cSBHUFFFS = wFlags & 0x0003;
694 cSBHUFFDS = (wFlags >> 2) & 0x0003;
695 cSBHUFFDT = (wFlags >> 4) & 0x0003;
696 cSBHUFFRDW = (wFlags >> 6) & 0x0003;
697 cSBHUFFRDH = (wFlags >> 8) & 0x0003;
698 cSBHUFFRDX = (wFlags >> 10) & 0x0003;
699 cSBHUFFRDY = (wFlags >> 12) & 0x0003;
700 cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
701 }
702 if (pTRD->SBREFINE == 1 && pTRD->SBRTEMPLATE == 0) {
703 for (int32_t i = 0; i < 4; ++i) {
704 if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0)
705 return JBIG2_ERROR_TOO_SHORT;
706 }
707 }
708 if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0)
709 return JBIG2_ERROR_TOO_SHORT;
710
711 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
712 if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]))
713 return JBIG2_ERROR_FATAL;
714 }
715
716 pTRD->SBNUMSYMS = 0;
717 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
718 CJBig2_Segment* pSeg =
719 findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
720 if (pSeg->m_cFlags.s.type == 0) {
721 pTRD->SBNUMSYMS += pSeg->m_Result.sd->NumImages();
722 }
723 }
724
725 std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SBSYMS;
726 if (pTRD->SBNUMSYMS > 0) {
727 SBSYMS.reset(FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS));
728 dwTemp = 0;
729 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
730 CJBig2_Segment* pSeg =
731 findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
732 if (pSeg->m_cFlags.s.type == 0) {
733 const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd;
734 for (size_t j = 0; j < dict.NumImages(); ++j)
735 SBSYMS.get()[dwTemp + j] = dict.GetImage(j);
736 dwTemp += dict.NumImages();
737 }
738 }
739 pTRD->SBSYMS = SBSYMS.get();
740 } else {
741 pTRD->SBSYMS = NULL;
742 }
743
744 std::unique_ptr<JBig2HuffmanCode, FxFreeDeleter> SBSYMCODES;
745 if (pTRD->SBHUFF == 1) {
746 SBSYMCODES.reset(
747 decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS));
748 if (!SBSYMCODES)
749 return JBIG2_ERROR_FATAL;
750
751 m_pStream->alignByte();
752 pTRD->SBSYMCODES = SBSYMCODES.get();
753 } else {
754 dwTemp = 0;
755 while ((FX_DWORD)(1 << dwTemp) < pTRD->SBNUMSYMS) {
756 ++dwTemp;
757 }
758 pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
759 }
760
761 std::unique_ptr<CJBig2_HuffmanTable> Table_B1;
762 std::unique_ptr<CJBig2_HuffmanTable> Table_B6;
763 std::unique_ptr<CJBig2_HuffmanTable> Table_B7;
764 std::unique_ptr<CJBig2_HuffmanTable> Table_B8;
765 std::unique_ptr<CJBig2_HuffmanTable> Table_B9;
766 std::unique_ptr<CJBig2_HuffmanTable> Table_B10;
767 std::unique_ptr<CJBig2_HuffmanTable> Table_B11;
768 std::unique_ptr<CJBig2_HuffmanTable> Table_B12;
769 std::unique_ptr<CJBig2_HuffmanTable> Table_B13;
770 std::unique_ptr<CJBig2_HuffmanTable> Table_B14;
771 std::unique_ptr<CJBig2_HuffmanTable> Table_B15;
772 if (pTRD->SBHUFF == 1) {
773 if (cSBHUFFFS == 2 || cSBHUFFRDW == 2 || cSBHUFFRDH == 2 ||
774 cSBHUFFRDX == 2 || cSBHUFFRDY == 2) {
775 return JBIG2_ERROR_FATAL;
776 }
777 int32_t nIndex = 0;
778 if (cSBHUFFFS == 0) {
779 Table_B6.reset(new CJBig2_HuffmanTable(HuffmanTable_B6,
780 FX_ArraySize(HuffmanTable_B6),
781 HuffmanTable_HTOOB_B6));
782 pTRD->SBHUFFFS = Table_B6.get();
783 } else if (cSBHUFFFS == 1) {
784 Table_B7.reset(new CJBig2_HuffmanTable(HuffmanTable_B7,
785 FX_ArraySize(HuffmanTable_B7),
786 HuffmanTable_HTOOB_B7));
787 pTRD->SBHUFFFS = Table_B7.get();
788 } else {
789 CJBig2_Segment* pSeg =
790 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
791 if (!pSeg)
792 return JBIG2_ERROR_FATAL;
793 pTRD->SBHUFFFS = pSeg->m_Result.ht;
794 }
795 if (cSBHUFFDS == 0) {
796 Table_B8.reset(new CJBig2_HuffmanTable(HuffmanTable_B8,
797 FX_ArraySize(HuffmanTable_B8),
798 HuffmanTable_HTOOB_B8));
799 pTRD->SBHUFFDS = Table_B8.get();
800 } else if (cSBHUFFDS == 1) {
801 Table_B9.reset(new CJBig2_HuffmanTable(HuffmanTable_B9,
802 FX_ArraySize(HuffmanTable_B9),
803 HuffmanTable_HTOOB_B9));
804 pTRD->SBHUFFDS = Table_B9.get();
805 } else if (cSBHUFFDS == 2) {
806 Table_B10.reset(new CJBig2_HuffmanTable(HuffmanTable_B10,
807 FX_ArraySize(HuffmanTable_B10),
808 HuffmanTable_HTOOB_B10));
809 pTRD->SBHUFFDS = Table_B10.get();
810 } else {
811 CJBig2_Segment* pSeg =
812 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
813 if (!pSeg)
814 return JBIG2_ERROR_FATAL;
815 pTRD->SBHUFFDS = pSeg->m_Result.ht;
816 }
817 if (cSBHUFFDT == 0) {
818 Table_B11.reset(new CJBig2_HuffmanTable(HuffmanTable_B11,
819 FX_ArraySize(HuffmanTable_B11),
820 HuffmanTable_HTOOB_B11));
821 pTRD->SBHUFFDT = Table_B11.get();
822 } else if (cSBHUFFDT == 1) {
823 Table_B12.reset(new CJBig2_HuffmanTable(HuffmanTable_B12,
824 FX_ArraySize(HuffmanTable_B12),
825 HuffmanTable_HTOOB_B12));
826 pTRD->SBHUFFDT = Table_B12.get();
827 } else if (cSBHUFFDT == 2) {
828 Table_B13.reset(new CJBig2_HuffmanTable(HuffmanTable_B13,
829 FX_ArraySize(HuffmanTable_B13),
830 HuffmanTable_HTOOB_B13));
831 pTRD->SBHUFFDT = Table_B13.get();
832 } else {
833 CJBig2_Segment* pSeg =
834 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
835 if (!pSeg)
836 return JBIG2_ERROR_FATAL;
837 pTRD->SBHUFFDT = pSeg->m_Result.ht;
838 }
839 if (cSBHUFFRDW == 0) {
840 Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
841 FX_ArraySize(HuffmanTable_B14),
842 HuffmanTable_HTOOB_B14));
843 pTRD->SBHUFFRDW = Table_B14.get();
844 } else if (cSBHUFFRDW == 1) {
845 Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
846 FX_ArraySize(HuffmanTable_B15),
847 HuffmanTable_HTOOB_B15));
848 pTRD->SBHUFFRDW = Table_B15.get();
849 } else {
850 CJBig2_Segment* pSeg =
851 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
852 if (!pSeg)
853 return JBIG2_ERROR_FATAL;
854 pTRD->SBHUFFRDW = pSeg->m_Result.ht;
855 }
856 if (cSBHUFFRDH == 0) {
857 if (!Table_B14) {
858 Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
859 FX_ArraySize(HuffmanTable_B14),
860 HuffmanTable_HTOOB_B14));
861 }
862 pTRD->SBHUFFRDH = Table_B14.get();
863 } else if (cSBHUFFRDH == 1) {
864 if (!Table_B15) {
865 Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
866 FX_ArraySize(HuffmanTable_B15),
867 HuffmanTable_HTOOB_B15));
868 }
869 pTRD->SBHUFFRDH = Table_B15.get();
870 } else {
871 CJBig2_Segment* pSeg =
872 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
873 if (!pSeg)
874 return JBIG2_ERROR_FATAL;
875 pTRD->SBHUFFRDH = pSeg->m_Result.ht;
876 }
877 if (cSBHUFFRDX == 0) {
878 if (!Table_B14) {
879 Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
880 FX_ArraySize(HuffmanTable_B14),
881 HuffmanTable_HTOOB_B14));
882 }
883 pTRD->SBHUFFRDX = Table_B14.get();
884 } else if (cSBHUFFRDX == 1) {
885 if (!Table_B15) {
886 Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
887 FX_ArraySize(HuffmanTable_B15),
888 HuffmanTable_HTOOB_B15));
889 }
890 pTRD->SBHUFFRDX = Table_B15.get();
891 } else {
892 CJBig2_Segment* pSeg =
893 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
894 if (!pSeg)
895 return JBIG2_ERROR_FATAL;
896 pTRD->SBHUFFRDX = pSeg->m_Result.ht;
897 }
898 if (cSBHUFFRDY == 0) {
899 if (!Table_B14) {
900 Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
901 FX_ArraySize(HuffmanTable_B14),
902 HuffmanTable_HTOOB_B14));
903 }
904 pTRD->SBHUFFRDY = Table_B14.get();
905 } else if (cSBHUFFRDY == 1) {
906 if (!Table_B15) {
907 Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
908 FX_ArraySize(HuffmanTable_B15),
909 HuffmanTable_HTOOB_B15));
910 }
911 pTRD->SBHUFFRDY = Table_B15.get();
912 } else {
913 CJBig2_Segment* pSeg =
914 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
915 if (!pSeg)
916 return JBIG2_ERROR_FATAL;
917 pTRD->SBHUFFRDY = pSeg->m_Result.ht;
918 }
919 if (cSBHUFFRSIZE == 0) {
920 Table_B1.reset(new CJBig2_HuffmanTable(HuffmanTable_B1,
921 FX_ArraySize(HuffmanTable_B1),
922 HuffmanTable_HTOOB_B1));
923 pTRD->SBHUFFRSIZE = Table_B1.get();
924 } else {
925 CJBig2_Segment* pSeg =
926 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
927 if (!pSeg)
928 return JBIG2_ERROR_FATAL;
929 pTRD->SBHUFFRSIZE = pSeg->m_Result.ht;
930 }
931 }
932 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext;
933 if (pTRD->SBREFINE == 1) {
934 const size_t size = GetRefAggContextSize(pTRD->SBRTEMPLATE);
935 grContext.reset(FX_Alloc(JBig2ArithCtx, size));
936 JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size);
937 }
938 if (pTRD->SBHUFF == 0) {
939 std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
940 new CJBig2_ArithDecoder(m_pStream.get()));
941 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
942 pSegment->m_Result.im =
943 pTRD->decode_Arith(pArithDecoder.get(), grContext.get());
944 if (!pSegment->m_Result.im)
945 return JBIG2_ERROR_FATAL;
946 m_pStream->alignByte();
947 m_pStream->offset(2);
948 } else {
949 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
950 pSegment->m_Result.im =
951 pTRD->decode_Huffman(m_pStream.get(), grContext.get());
952 if (!pSegment->m_Result.im)
953 return JBIG2_ERROR_FATAL;
954 m_pStream->alignByte();
955 }
956 if (pSegment->m_cFlags.s.type != 4) {
957 if (!m_bBufSpecified) {
958 JBig2PageInfo* pPageInfo = m_PageInfoList.back();
959 if ((pPageInfo->m_bIsStriped == 1) &&
960 (ri.y + ri.height > m_pPage->m_nHeight)) {
961 m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
962 }
963 }
964 m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
965 (JBig2ComposeOp)(ri.flags & 0x03));
966 delete pSegment->m_Result.im;
967 pSegment->m_Result.im = NULL;
968 }
969 return JBIG2_SUCCESS;
970 }
971
parsePatternDict(CJBig2_Segment * pSegment,IFX_Pause * pPause)972 int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
973 IFX_Pause* pPause) {
974 uint8_t cFlags;
975 std::unique_ptr<CJBig2_PDDProc> pPDD(new CJBig2_PDDProc);
976 if (m_pStream->read1Byte(&cFlags) != 0 ||
977 m_pStream->read1Byte(&pPDD->HDPW) != 0 ||
978 m_pStream->read1Byte(&pPDD->HDPH) != 0 ||
979 m_pStream->readInteger(&pPDD->GRAYMAX) != 0) {
980 return JBIG2_ERROR_TOO_SHORT;
981 }
982 if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX)
983 return JBIG2_ERROR_LIMIT;
984
985 pPDD->HDMMR = cFlags & 0x01;
986 pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
987 pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
988 if (pPDD->HDMMR == 0) {
989 const size_t size = GetHuffContextSize(pPDD->HDTEMPLATE);
990 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
991 FX_Alloc(JBig2ArithCtx, size));
992 JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size);
993 std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
994 new CJBig2_ArithDecoder(m_pStream.get()));
995 pSegment->m_Result.pd =
996 pPDD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause);
997 if (!pSegment->m_Result.pd)
998 return JBIG2_ERROR_FATAL;
999
1000 m_pStream->alignByte();
1001 m_pStream->offset(2);
1002 } else {
1003 pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream.get(), pPause);
1004 if (!pSegment->m_Result.pd)
1005 return JBIG2_ERROR_FATAL;
1006 m_pStream->alignByte();
1007 }
1008 return JBIG2_SUCCESS;
1009 }
1010
parseHalftoneRegion(CJBig2_Segment * pSegment,IFX_Pause * pPause)1011 int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
1012 IFX_Pause* pPause) {
1013 uint8_t cFlags;
1014 JBig2RegionInfo ri;
1015 std::unique_ptr<CJBig2_HTRDProc> pHRD(new CJBig2_HTRDProc);
1016 if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
1017 m_pStream->read1Byte(&cFlags) != 0 ||
1018 m_pStream->readInteger(&pHRD->HGW) != 0 ||
1019 m_pStream->readInteger(&pHRD->HGH) != 0 ||
1020 m_pStream->readInteger((FX_DWORD*)&pHRD->HGX) != 0 ||
1021 m_pStream->readInteger((FX_DWORD*)&pHRD->HGY) != 0 ||
1022 m_pStream->readShortInteger(&pHRD->HRX) != 0 ||
1023 m_pStream->readShortInteger(&pHRD->HRY) != 0) {
1024 return JBIG2_ERROR_TOO_SHORT;
1025 }
1026
1027 if (pHRD->HGW == 0 || pHRD->HGH == 0)
1028 return JBIG2_ERROR_FATAL;
1029
1030 pHRD->HBW = ri.width;
1031 pHRD->HBH = ri.height;
1032 pHRD->HMMR = cFlags & 0x01;
1033 pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
1034 pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
1035 pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
1036 pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
1037 if (pSegment->m_nReferred_to_segment_count != 1)
1038 return JBIG2_ERROR_FATAL;
1039
1040 CJBig2_Segment* pSeg =
1041 findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1042 if (!pSeg || (pSeg->m_cFlags.s.type != 16))
1043 return JBIG2_ERROR_FATAL;
1044
1045 CJBig2_PatternDict* pPatternDict = pSeg->m_Result.pd;
1046 if (!pPatternDict || (pPatternDict->NUMPATS == 0))
1047 return JBIG2_ERROR_FATAL;
1048
1049 pHRD->HNUMPATS = pPatternDict->NUMPATS;
1050 pHRD->HPATS = pPatternDict->HDPATS;
1051 pHRD->HPW = pPatternDict->HDPATS[0]->m_nWidth;
1052 pHRD->HPH = pPatternDict->HDPATS[0]->m_nHeight;
1053 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1054 if (pHRD->HMMR == 0) {
1055 const size_t size = GetHuffContextSize(pHRD->HTEMPLATE);
1056 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
1057 FX_Alloc(JBig2ArithCtx, size));
1058 JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size);
1059 std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
1060 new CJBig2_ArithDecoder(m_pStream.get()));
1061 pSegment->m_Result.im =
1062 pHRD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause);
1063 if (!pSegment->m_Result.im)
1064 return JBIG2_ERROR_FATAL;
1065
1066 m_pStream->alignByte();
1067 m_pStream->offset(2);
1068 } else {
1069 pSegment->m_Result.im = pHRD->decode_MMR(m_pStream.get(), pPause);
1070 if (!pSegment->m_Result.im)
1071 return JBIG2_ERROR_FATAL;
1072 m_pStream->alignByte();
1073 }
1074 if (pSegment->m_cFlags.s.type != 20) {
1075 if (!m_bBufSpecified) {
1076 JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1077 if (pPageInfo->m_bIsStriped == 1 &&
1078 ri.y + ri.height > m_pPage->m_nHeight) {
1079 m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1080 }
1081 }
1082 m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1083 (JBig2ComposeOp)(ri.flags & 0x03));
1084 delete pSegment->m_Result.im;
1085 pSegment->m_Result.im = NULL;
1086 }
1087 return JBIG2_SUCCESS;
1088 }
1089
parseGenericRegion(CJBig2_Segment * pSegment,IFX_Pause * pPause)1090 int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
1091 IFX_Pause* pPause) {
1092 if (!m_pGRD) {
1093 std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc);
1094 uint8_t cFlags;
1095 if (parseRegionInfo(&m_ri) != JBIG2_SUCCESS ||
1096 m_pStream->read1Byte(&cFlags) != 0) {
1097 return JBIG2_ERROR_TOO_SHORT;
1098 }
1099 if (m_ri.height < 0 || m_ri.width < 0)
1100 return JBIG2_FAILED;
1101
1102 pGRD->GBW = m_ri.width;
1103 pGRD->GBH = m_ri.height;
1104 pGRD->MMR = cFlags & 0x01;
1105 pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
1106 pGRD->TPGDON = (cFlags >> 3) & 0x01;
1107 if (pGRD->MMR == 0) {
1108 if (pGRD->GBTEMPLATE == 0) {
1109 for (int32_t i = 0; i < 8; ++i) {
1110 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) {
1111 return JBIG2_ERROR_TOO_SHORT;
1112 }
1113 }
1114 } else {
1115 for (int32_t i = 0; i < 2; ++i) {
1116 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) {
1117 return JBIG2_ERROR_TOO_SHORT;
1118 }
1119 }
1120 }
1121 }
1122 pGRD->USESKIP = 0;
1123 m_pGRD = std::move(pGRD);
1124 }
1125 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1126 if (m_pGRD->MMR == 0) {
1127 if (!m_gbContext) {
1128 const size_t size = GetHuffContextSize(m_pGRD->GBTEMPLATE);
1129 m_gbContext = FX_Alloc(JBig2ArithCtx, size);
1130 JBIG2_memset(m_gbContext, 0, sizeof(JBig2ArithCtx) * size);
1131 }
1132 if (!m_pArithDecoder) {
1133 m_pArithDecoder.reset(new CJBig2_ArithDecoder(m_pStream.get()));
1134 m_ProcessingStatus = m_pGRD->Start_decode_Arith(
1135 &pSegment->m_Result.im, m_pArithDecoder.get(), m_gbContext, pPause);
1136 } else {
1137 m_ProcessingStatus = m_pGRD->Continue_decode(pPause);
1138 }
1139 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1140 if (pSegment->m_cFlags.s.type != 36) {
1141 if (!m_bBufSpecified) {
1142 JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1143 if ((pPageInfo->m_bIsStriped == 1) &&
1144 (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1145 m_pPage->expand(m_ri.y + m_ri.height,
1146 (pPageInfo->m_cFlags & 4) ? 1 : 0);
1147 }
1148 }
1149 FX_RECT Rect = m_pGRD->GetReplaceRect();
1150 m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1151 pSegment->m_Result.im,
1152 (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1153 }
1154 return JBIG2_SUCCESS;
1155 } else {
1156 m_pArithDecoder.reset();
1157 FX_Free(m_gbContext);
1158 m_gbContext = NULL;
1159 if (!pSegment->m_Result.im) {
1160 m_ProcessingStatus = FXCODEC_STATUS_ERROR;
1161 m_pGRD.reset();
1162 return JBIG2_ERROR_FATAL;
1163 }
1164 m_pStream->alignByte();
1165 m_pStream->offset(2);
1166 }
1167 } else {
1168 FXCODEC_STATUS status = m_pGRD->Start_decode_MMR(&pSegment->m_Result.im,
1169 m_pStream.get(), pPause);
1170 while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1171 m_pGRD->Continue_decode(pPause);
1172 }
1173 if (!pSegment->m_Result.im) {
1174 m_pGRD.reset();
1175 return JBIG2_ERROR_FATAL;
1176 }
1177 m_pStream->alignByte();
1178 }
1179 if (pSegment->m_cFlags.s.type != 36) {
1180 if (!m_bBufSpecified) {
1181 JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1182 if ((pPageInfo->m_bIsStriped == 1) &&
1183 (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1184 m_pPage->expand(m_ri.y + m_ri.height,
1185 (pPageInfo->m_cFlags & 4) ? 1 : 0);
1186 }
1187 }
1188 FX_RECT Rect = m_pGRD->GetReplaceRect();
1189 m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1190 pSegment->m_Result.im,
1191 (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1192 delete pSegment->m_Result.im;
1193 pSegment->m_Result.im = NULL;
1194 }
1195 m_pGRD.reset();
1196 return JBIG2_SUCCESS;
1197 }
1198
parseGenericRefinementRegion(CJBig2_Segment * pSegment)1199 int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
1200 JBig2RegionInfo ri;
1201 uint8_t cFlags;
1202 if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
1203 m_pStream->read1Byte(&cFlags) != 0) {
1204 return JBIG2_ERROR_TOO_SHORT;
1205 }
1206 std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc);
1207 pGRRD->GRW = ri.width;
1208 pGRRD->GRH = ri.height;
1209 pGRRD->GRTEMPLATE = cFlags & 0x01;
1210 pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1211 if (pGRRD->GRTEMPLATE == 0) {
1212 for (int32_t i = 0; i < 4; ++i) {
1213 if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0)
1214 return JBIG2_ERROR_TOO_SHORT;
1215 }
1216 }
1217 CJBig2_Segment* pSeg = nullptr;
1218 if (pSegment->m_nReferred_to_segment_count > 0) {
1219 int32_t i;
1220 for (i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
1221 pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1222 if (!pSeg)
1223 return JBIG2_ERROR_FATAL;
1224
1225 if (pSeg->m_cFlags.s.type == 4 || pSeg->m_cFlags.s.type == 20 ||
1226 pSeg->m_cFlags.s.type == 36 || pSeg->m_cFlags.s.type == 40) {
1227 break;
1228 }
1229 }
1230 if (i >= pSegment->m_nReferred_to_segment_count)
1231 return JBIG2_ERROR_FATAL;
1232
1233 pGRRD->GRREFERENCE = pSeg->m_Result.im;
1234 } else {
1235 pGRRD->GRREFERENCE = m_pPage.get();
1236 }
1237 pGRRD->GRREFERENCEDX = 0;
1238 pGRRD->GRREFERENCEDY = 0;
1239 const size_t size = GetRefAggContextSize(pGRRD->GRTEMPLATE);
1240 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext(
1241 FX_Alloc(JBig2ArithCtx, size));
1242 JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size);
1243 std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
1244 new CJBig2_ArithDecoder(m_pStream.get()));
1245 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1246 pSegment->m_Result.im = pGRRD->decode(pArithDecoder.get(), grContext.get());
1247 if (!pSegment->m_Result.im)
1248 return JBIG2_ERROR_FATAL;
1249
1250 m_pStream->alignByte();
1251 m_pStream->offset(2);
1252 if (pSegment->m_cFlags.s.type != 40) {
1253 if (!m_bBufSpecified) {
1254 JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1255 if ((pPageInfo->m_bIsStriped == 1) &&
1256 (ri.y + ri.height > m_pPage->m_nHeight)) {
1257 m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1258 }
1259 }
1260 m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1261 (JBig2ComposeOp)(ri.flags & 0x03));
1262 delete pSegment->m_Result.im;
1263 pSegment->m_Result.im = NULL;
1264 }
1265 return JBIG2_SUCCESS;
1266 }
1267
parseTable(CJBig2_Segment * pSegment)1268 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
1269 pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
1270 pSegment->m_Result.ht = nullptr;
1271 std::unique_ptr<CJBig2_HuffmanTable> pHuff(
1272 new CJBig2_HuffmanTable(m_pStream.get()));
1273 if (!pHuff->IsOK())
1274 return JBIG2_ERROR_FATAL;
1275
1276 pSegment->m_Result.ht = pHuff.release();
1277 m_pStream->alignByte();
1278 return JBIG2_SUCCESS;
1279 }
1280
parseRegionInfo(JBig2RegionInfo * pRI)1281 int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) {
1282 if (m_pStream->readInteger((FX_DWORD*)&pRI->width) != 0 ||
1283 m_pStream->readInteger((FX_DWORD*)&pRI->height) != 0 ||
1284 m_pStream->readInteger((FX_DWORD*)&pRI->x) != 0 ||
1285 m_pStream->readInteger((FX_DWORD*)&pRI->y) != 0 ||
1286 m_pStream->read1Byte(&pRI->flags) != 0) {
1287 return JBIG2_ERROR_TOO_SHORT;
1288 }
1289 return JBIG2_SUCCESS;
1290 }
1291
decodeSymbolIDHuffmanTable(CJBig2_BitStream * pStream,FX_DWORD SBNUMSYMS)1292 JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable(
1293 CJBig2_BitStream* pStream,
1294 FX_DWORD SBNUMSYMS) {
1295 const size_t kRunCodesSize = 35;
1296 int32_t runcodes[kRunCodesSize];
1297 int32_t runcodes_len[kRunCodesSize];
1298 for (int32_t i = 0; i < kRunCodesSize; ++i) {
1299 if (pStream->readNBits(4, &runcodes_len[i]) != 0)
1300 return nullptr;
1301 }
1302 huffman_assign_code(runcodes, runcodes_len, kRunCodesSize);
1303
1304 std::unique_ptr<JBig2HuffmanCode, FxFreeDeleter> SBSYMCODES(
1305 FX_Alloc(JBig2HuffmanCode, SBNUMSYMS));
1306 int32_t run;
1307 int32_t i = 0;
1308 while (i < (int)SBNUMSYMS) {
1309 int32_t j;
1310 int32_t nVal = 0;
1311 int32_t nBits = 0;
1312 FX_DWORD nTemp;
1313 while (true) {
1314 if (pStream->read1Bit(&nTemp) != 0)
1315 return nullptr;
1316
1317 nVal = (nVal << 1) | nTemp;
1318 ++nBits;
1319 for (j = 0; j < kRunCodesSize; ++j) {
1320 if (nBits == runcodes_len[j] && nVal == runcodes[j]) {
1321 break;
1322 }
1323 }
1324 if (j < kRunCodesSize) {
1325 break;
1326 }
1327 }
1328 int32_t runcode = j;
1329 if (runcode < 32) {
1330 SBSYMCODES.get()[i].codelen = runcode;
1331 run = 0;
1332 } else if (runcode == 32) {
1333 if (pStream->readNBits(2, &nTemp) != 0)
1334 return nullptr;
1335 run = nTemp + 3;
1336 } else if (runcode == 33) {
1337 if (pStream->readNBits(3, &nTemp) != 0)
1338 return nullptr;
1339 run = nTemp + 3;
1340 } else if (runcode == 34) {
1341 if (pStream->readNBits(7, &nTemp) != 0)
1342 return nullptr;
1343 run = nTemp + 11;
1344 }
1345 if (run > 0) {
1346 if (i + run > (int)SBNUMSYMS)
1347 return nullptr;
1348 for (j = 0; j < run; ++j) {
1349 if (runcode == 32 && i > 0) {
1350 SBSYMCODES.get()[i + j].codelen = SBSYMCODES.get()[i - 1].codelen;
1351 } else {
1352 SBSYMCODES.get()[i + j].codelen = 0;
1353 }
1354 }
1355 i += run;
1356 } else {
1357 ++i;
1358 }
1359 }
1360 huffman_assign_code(SBSYMCODES.get(), SBNUMSYMS);
1361 return SBSYMCODES.release();
1362 }
1363
huffman_assign_code(int * CODES,int * PREFLEN,int NTEMP)1364 void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) {
1365 // TODO(thestig) CJBig2_HuffmanTable::parseFromCodedBuffer() has similar code.
1366 int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1367 int* LENCOUNT;
1368 int* FIRSTCODE;
1369 LENMAX = 0;
1370 for (i = 0; i < NTEMP; ++i) {
1371 if (PREFLEN[i] > LENMAX) {
1372 LENMAX = PREFLEN[i];
1373 }
1374 }
1375 LENCOUNT = FX_Alloc(int, LENMAX + 1);
1376 JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1377 FIRSTCODE = FX_Alloc(int, LENMAX + 1);
1378 for (i = 0; i < NTEMP; ++i) {
1379 ++LENCOUNT[PREFLEN[i]];
1380 }
1381 CURLEN = 1;
1382 FIRSTCODE[0] = 0;
1383 LENCOUNT[0] = 0;
1384 while (CURLEN <= LENMAX) {
1385 FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1386 CURCODE = FIRSTCODE[CURLEN];
1387 CURTEMP = 0;
1388 while (CURTEMP < NTEMP) {
1389 if (PREFLEN[CURTEMP] == CURLEN) {
1390 CODES[CURTEMP] = CURCODE;
1391 CURCODE = CURCODE + 1;
1392 }
1393 CURTEMP = CURTEMP + 1;
1394 }
1395 CURLEN = CURLEN + 1;
1396 }
1397 FX_Free(LENCOUNT);
1398 FX_Free(FIRSTCODE);
1399 }
huffman_assign_code(JBig2HuffmanCode * SBSYMCODES,int NTEMP)1400 void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES,
1401 int NTEMP) {
1402 int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1403 int* LENCOUNT;
1404 int* FIRSTCODE;
1405 LENMAX = 0;
1406 for (i = 0; i < NTEMP; ++i) {
1407 if (SBSYMCODES[i].codelen > LENMAX) {
1408 LENMAX = SBSYMCODES[i].codelen;
1409 }
1410 }
1411 LENCOUNT = FX_Alloc(int, (LENMAX + 1));
1412 JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1413 FIRSTCODE = FX_Alloc(int, (LENMAX + 1));
1414 for (i = 0; i < NTEMP; ++i) {
1415 ++LENCOUNT[SBSYMCODES[i].codelen];
1416 }
1417 CURLEN = 1;
1418 FIRSTCODE[0] = 0;
1419 LENCOUNT[0] = 0;
1420 while (CURLEN <= LENMAX) {
1421 FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1422 CURCODE = FIRSTCODE[CURLEN];
1423 CURTEMP = 0;
1424 while (CURTEMP < NTEMP) {
1425 if (SBSYMCODES[CURTEMP].codelen == CURLEN) {
1426 SBSYMCODES[CURTEMP].code = CURCODE;
1427 CURCODE = CURCODE + 1;
1428 }
1429 CURTEMP = CURTEMP + 1;
1430 }
1431 CURLEN = CURLEN + 1;
1432 }
1433 FX_Free(LENCOUNT);
1434 FX_Free(FIRSTCODE);
1435 }
1436