OLD | NEW |
| (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 } | |
OLD | NEW |