| 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 |