Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: core/src/fxcodec/jbig2/JBig2_Context.cpp

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

Powered by Google App Engine
This is Rietveld 408576698