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