7#include "core/fxcodec/jbig2/JBig2_Context.h"
17#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
18#include "core/fxcodec/jbig2/JBig2_BitStream.h"
19#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
20#include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
21#include "core/fxcodec/jbig2/JBig2_HtrdProc.h"
22#include "core/fxcodec/jbig2/JBig2_PddProc.h"
23#include "core/fxcodec/jbig2/JBig2_SddProc.h"
24#include "core/fxcodec/jbig2/JBig2_TrdProc.h"
25#include "core/fxcrt/fx_memory_wrappers.h"
26#include "core/fxcrt/fx_safe_types.h"
27#include "core/fxcrt/pauseindicator_iface.h"
28#include "third_party/base/check.h"
29#include "third_party/base/memory/ptr_util.h"
33size_t GetHuffContextSize(uint8_t val) {
34 return val == 0 ? 65536 : val == 1 ? 8192 : 1024;
37size_t GetRefAggContextSize(
bool val) {
38 return val ? 1024 : 8192;
51static_assert(kSymbolDictCacheMaxSize > 0,
52 "Symbol Dictionary Cache must have non-zero size");
56 pdfium::span<
const uint8_t> pGlobalSpan,
58 pdfium::span<
const uint8_t> pSrcSpan,
60 std::list<CJBig2_CachePair>* pSymbolDictCache) {
61 auto result = pdfium::WrapUnique(
63 if (!pGlobalSpan.empty()) {
64 result->m_pGlobalContext = pdfium::WrapUnique(
65 new CJBig2_Context(pGlobalSpan, global_key, pSymbolDictCache,
true));
70CJBig2_Context::CJBig2_Context(pdfium::span<
const uint8_t> pSrcSpan,
72 std::list<CJBig2_CachePair>* pSymbolDictCache,
74 : m_pStream(std::make_unique<CJBig2_BitStream>(pSrcSpan, src_key)),
75 m_HuffmanTables(CJBig2_HuffmanTable::kNumHuffmanTables),
76 m_bIsGlobal(bIsGlobal),
77 m_pSymbolDictCache(pSymbolDictCache) {}
82 if (m_pStream->getByteLeft() <= 0)
88 m_pSegment = std::make_unique<CJBig2_Segment>();
89 nRet = ParseSegmentHeader(m_pSegment.get());
94 m_nOffset = m_pStream->getOffset();
96 nRet = ParseSegmentData(m_pSegment.get(), pPause);
109 if (m_pSegment->m_dwData_length != 0xffffffff) {
110 FX_SAFE_UINT32 new_offset = m_nOffset;
111 new_offset += m_pSegment->m_dwData_length;
112 if (!new_offset.IsValid())
114 m_nOffset = new_offset.ValueOrDie();
115 m_pStream->setOffset(m_nOffset);
117 m_pStream->offset(4);
119 m_SegmentList.push_back(std::move(m_pSegment));
120 if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
121 pPause->NeedToPauseNow()) {
135 if (m_pGlobalContext) {
136 JBig2_Result nRet = m_pGlobalContext->DecodeSequential(pPause);
143 m_pPage = std::make_unique<CJBig2_Image>(width, height, stride, pBuf);
144 m_bBufSpecified =
true;
156 if (m_PauseStep == 5) {
161 if (m_PauseStep <= 2)
162 nRet = DecodeSequential(pPause);
178 if (m_pGlobalContext) {
179 CJBig2_Segment* pSeg = m_pGlobalContext->FindSegmentByNumber(dwNumber);
183 for (
const auto& pSeg : m_SegmentList) {
184 if (pSeg->m_dwNumber == dwNumber)
193 static const uint8_t kTableType = 53;
197 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
198 if (pSeg && pSeg->m_cFlags.s
.type == kTableType) {
208 if (m_pStream->readInteger(&pSegment->m_dwNumber) != 0 ||
209 m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0) {
213 uint8_t cTemp = m_pStream->getCurByte();
214 if ((cTemp >> 5) == 7) {
215 if (m_pStream->readInteger(
216 (uint32_t*)&pSegment->m_nReferred_to_segment_count) != 0) {
225 if (m_pStream->read1Byte(&cTemp) != 0)
234 pSegment->m_Referred_to_segment_numbers.resize(
239 if (m_pStream->read1Byte(&cTemp) != 0)
242 pSegment->m_Referred_to_segment_numbers[i] = cTemp;
246 if (m_pStream->readShortInteger(&wTemp) != 0)
249 pSegment->m_Referred_to_segment_numbers[i] = wTemp;
253 if (m_pStream->readInteger(&dwTemp) != 0)
256 pSegment->m_Referred_to_segment_numbers[i] = dwTemp;
259 if (pSegment->m_Referred_to_segment_numbers[i] >= pSegment
->m_dwNumber)
264 if (m_pStream->read1Byte(&cTemp) != 0)
267 }
else if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
270 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
273 pSegment->m_Key = m_pStream->getKey();
274 pSegment->m_dwDataOffset = m_pStream->getOffset();
281 JBig2_Result ret = ProcessingParseSegmentData(pSegment, pPause);
282 while (m_ProcessingStatus == FXCODEC_STATUS::kDecodeToBeContinued &&
283 m_pStream->getByteLeft() > 0) {
284 ret = ProcessingParseSegmentData(pSegment, pPause);
292 switch (pSegment->m_cFlags.s
.type) {
294 return ParseSymbolDict(pSegment);
300 return ParseTextRegion(pSegment);
302 return ParsePatternDict(pSegment, pPause);
308 return ParseHalftoneRegion(pSegment, pPause);
314 return ParseGenericRegion(pSegment, pPause);
320 return ParseGenericRefinementRegion(pSegment);
322 uint8_t segment_flags;
323 uint16_t striping_info;
325 if (m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0 ||
326 m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0 ||
327 m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0 ||
328 m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0 ||
329 m_pStream->read1Byte(&segment_flags) != 0 ||
330 m_pStream->readShortInteger(&striping_info) != 0) {
334 pPageInfo->m_bDefaultPixelValue = !!(segment_flags & 4);
335 pPageInfo->m_bIsStriped = !!(striping_info & 0x8000);
336 pPageInfo->m_wMaxStripeSize = striping_info & 0x7fff;
337 bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff);
338 if (bMaxHeight && !pPageInfo->m_bIsStriped)
339 pPageInfo->m_bIsStriped =
true;
341 if (!m_bBufSpecified) {
343 bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
344 m_pPage = std::make_unique<CJBig2_Image>(pPageInfo->m_dwWidth, height);
347 if (!m_pPage->data()) {
352 m_pPage->Fill(pPageInfo->m_bDefaultPixelValue);
353 m_PageInfoList.push_back(std::move(pPageInfo));
361 m_pStream->offset(pSegment->m_dwData_length);
366 m_pStream->offset(pSegment->m_dwData_length);
369 return ParseTable(pSegment);
371 m_pStream->offset(pSegment->m_dwData_length);
381 if (m_pStream->readShortInteger(&wFlags) != 0)
385 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
386 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
387 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
388 pSymbolDictDecoder->SDRTEMPLATE = !!((wFlags >> 12) & 0x0003);
389 if (!pSymbolDictDecoder->SDHUFF) {
390 const uint32_t dwTemp = (pSymbolDictDecoder->SDTEMPLATE == 0) ? 8 : 2;
391 for (uint32_t i = 0; i < dwTemp; ++i) {
392 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0)
396 if (pSymbolDictDecoder->SDREFAGG && !pSymbolDictDecoder->SDRTEMPLATE) {
397 for (int32_t i = 0; i < 4; ++i) {
398 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0)
402 if (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0 ||
403 m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0) {
411 if (!FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]))
415 FX_SAFE_UINT32 dwNumSyms = 0;
418 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
419 if (pSeg->m_cFlags.s
.type == 0) {
420 dwNumSyms += pSeg->m_SymbolDict->NumImages();
424 pSymbolDictDecoder->SDNUMINSYMS = dwNumSyms.ValueOrDie();
427 if (pSymbolDictDecoder->SDNUMINSYMS != 0) {
428 SDINSYMS.reset(FX_Alloc(
CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS));
432 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
433 if (pSeg->m_cFlags.s
.type == 0) {
435 for (uint32_t j = 0; j < dict.NumImages(); ++j) {
436 uint32_t dwTemp = (dwNumSyms + j).ValueOrDie();
437 SDINSYMS.get()[dwTemp] = dict.GetImage(j);
439 dwNumSyms += dict.NumImages();
443 pSymbolDictDecoder->SDINSYMS = SDINSYMS.get();
445 uint8_t cSDHUFFDH = (wFlags >> 2) & 0x0003;
446 uint8_t cSDHUFFDW = (wFlags >> 4) & 0x0003;
447 if (pSymbolDictDecoder->SDHUFF) {
448 if (cSDHUFFDH == 2 || cSDHUFFDW == 2)
452 if (cSDHUFFDH == 0) {
453 pSymbolDictDecoder->SDHUFFDH = GetHuffmanTable(4);
454 }
else if (cSDHUFFDH == 1) {
455 pSymbolDictDecoder->SDHUFFDH = GetHuffmanTable(5);
458 FindReferredTableSegmentByIndex(pSegment, nIndex++);
461 pSymbolDictDecoder->SDHUFFDH = pSeg->m_HuffmanTable.get();
463 if (cSDHUFFDW == 0) {
464 pSymbolDictDecoder->SDHUFFDW = GetHuffmanTable(2);
465 }
else if (cSDHUFFDW == 1) {
466 pSymbolDictDecoder->SDHUFFDW = GetHuffmanTable(3);
469 FindReferredTableSegmentByIndex(pSegment, nIndex++);
472 pSymbolDictDecoder->SDHUFFDW = pSeg->m_HuffmanTable.get();
474 uint8_t cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
475 if (cSDHUFFBMSIZE == 0) {
476 pSymbolDictDecoder->SDHUFFBMSIZE = GetHuffmanTable(1);
479 FindReferredTableSegmentByIndex(pSegment, nIndex++);
482 pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_HuffmanTable.get();
484 if (pSymbolDictDecoder->SDREFAGG) {
485 uint8_t cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
486 if (cSDHUFFAGGINST == 0) {
487 pSymbolDictDecoder->SDHUFFAGGINST = GetHuffmanTable(1);
490 FindReferredTableSegmentByIndex(pSegment, nIndex++);
493 pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_HuffmanTable.get();
498 const bool bUseGbContext = !pSymbolDictDecoder->SDHUFF;
499 const bool bUseGrContext = pSymbolDictDecoder->SDREFAGG;
500 const size_t gbContextSize =
501 GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE);
502 const size_t grContextSize =
503 GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE);
504 std::vector<JBig2ArithCtx> gbContext;
505 std::vector<JBig2ArithCtx> grContext;
506 if ((wFlags & 0x0100) && pLRSeg) {
508 gbContext = pLRSeg->m_SymbolDict->GbContext();
509 if (gbContext.size() != gbContextSize)
513 grContext = pLRSeg->m_SymbolDict->GrContext();
514 if (grContext.size() != grContextSize)
519 gbContext.resize(gbContextSize);
521 grContext.resize(grContextSize);
524 CJBig2_CompoundKey key(pSegment->m_Key, pSegment->m_dwDataOffset);
525 bool cache_hit =
false;
527 if (m_bIsGlobal && key.first != 0) {
528 for (
auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end();
530 if (it->first == key) {
531 pSegment->m_SymbolDict = it->second->DeepCopy();
532 m_pSymbolDictCache->emplace_front(key, std::move(it->second));
533 m_pSymbolDictCache->erase(it);
542 std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
543 pSegment->m_SymbolDict = pSymbolDictDecoder->DecodeArith(
544 pArithDecoder.get(), &gbContext, &grContext);
545 if (!pSegment->m_SymbolDict)
548 m_pStream->alignByte();
549 m_pStream->offset(2);
551 pSegment->m_SymbolDict = pSymbolDictDecoder->DecodeHuffman(
552 m_pStream.get(), &gbContext, &grContext);
553 if (!pSegment->m_SymbolDict)
555 m_pStream->alignByte();
558 std::unique_ptr<CJBig2_SymbolDict> value =
559 pSegment->m_SymbolDict->DeepCopy();
560 size_t size = m_pSymbolDictCache->size();
561 while (size >= kSymbolDictCacheMaxSize) {
562 m_pSymbolDictCache->pop_back();
565 m_pSymbolDictCache->emplace_front(key, std::move(value));
568 if (wFlags & 0x0200) {
570 pSegment->m_SymbolDict->SetGbContext(
std::move(gbContext));
572 pSegment->m_SymbolDict->SetGrContext(
std::move(grContext));
580 if (ParseRegionInfo(&ri) != JBig2_Result::kSuccess ||
581 m_pStream->readShortInteger(&wFlags) != 0) {
590 pTRD->SBHUFF = wFlags & 0x0001;
591 pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
592 uint32_t dwTemp = (wFlags >> 2) & 0x0003;
593 pTRD->SBSTRIPS = 1 << dwTemp;
594 pTRD->REFCORNER = (
JBig2Corner)((wFlags >> 4) & 0x0003);
595 pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
597 pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
598 pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
599 if (pTRD->SBDSOFFSET >= 0x0010) {
600 pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
602 pTRD->SBRTEMPLATE = !!((wFlags >> 15) & 0x0001);
604 if (pTRD->SBHUFF && m_pStream->readShortInteger(&wFlags) != 0) {
607 if (pTRD->SBREFINE && !pTRD->SBRTEMPLATE) {
608 for (int32_t i = 0; i < 4; ++i) {
609 if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0)
613 if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0)
621 FX_SAFE_INT32 nMaxStripInstances = m_pStream->getLength();
622 nMaxStripInstances *= 32;
623 if (pTRD->SBNUMINSTANCES > nMaxStripInstances.ValueOrDie())
627 if (!FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]))
631 FX_SAFE_UINT32 dwNumSyms = 0;
634 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
635 if (pSeg->m_cFlags.s
.type == 0) {
636 dwNumSyms += pSeg->m_SymbolDict->NumImages();
639 pTRD->SBNUMSYMS = dwNumSyms.ValueOrDie();
642 if (pTRD->SBNUMSYMS > 0) {
647 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
648 if (pSeg->m_cFlags.s
.type == 0) {
650 for (uint32_t j = 0; j < dict.NumImages(); ++j) {
651 uint32_t dwIndex = (dwNumSyms + j).ValueOrDie();
652 SBSYMS.get()[dwIndex] = dict.GetImage(j);
654 dwNumSyms += dict.NumImages();
657 pTRD->SBSYMS = SBSYMS.get();
659 pTRD->SBSYMS =
nullptr;
663 std::vector<JBig2HuffmanCode> SBSYMCODES =
664 DecodeSymbolIDHuffmanTable(pTRD->SBNUMSYMS);
665 if (SBSYMCODES.empty())
668 m_pStream->alignByte();
669 pTRD->SBSYMCODES =
std::move(SBSYMCODES);
672 while ((uint32_t)(1 << dwTemp) < pTRD->SBNUMSYMS) {
675 pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
679 uint8_t cSBHUFFFS = wFlags & 0x0003;
680 uint8_t cSBHUFFDS = (wFlags >> 2) & 0x0003;
681 uint8_t cSBHUFFDT = (wFlags >> 4) & 0x0003;
682 uint8_t cSBHUFFRDW = (wFlags >> 6) & 0x0003;
683 uint8_t cSBHUFFRDH = (wFlags >> 8) & 0x0003;
684 uint8_t cSBHUFFRDX = (wFlags >> 10) & 0x0003;
685 uint8_t cSBHUFFRDY = (wFlags >> 12) & 0x0003;
686 uint8_t cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
687 if (cSBHUFFFS == 2 || cSBHUFFRDW == 2 || cSBHUFFRDH == 2 ||
688 cSBHUFFRDX == 2 || cSBHUFFRDY == 2) {
692 if (cSBHUFFFS == 0) {
693 pTRD->SBHUFFFS = GetHuffmanTable(6);
694 }
else if (cSBHUFFFS == 1) {
695 pTRD->SBHUFFFS = GetHuffmanTable(7);
698 FindReferredTableSegmentByIndex(pSegment, nIndex++);
701 pTRD->SBHUFFFS = pSeg->m_HuffmanTable.get();
703 if (cSBHUFFDS == 0) {
704 pTRD->SBHUFFDS = GetHuffmanTable(8);
705 }
else if (cSBHUFFDS == 1) {
706 pTRD->SBHUFFDS = GetHuffmanTable(9);
707 }
else if (cSBHUFFDS == 2) {
708 pTRD->SBHUFFDS = GetHuffmanTable(10);
711 FindReferredTableSegmentByIndex(pSegment, nIndex++);
714 pTRD->SBHUFFDS = pSeg->m_HuffmanTable.get();
716 if (cSBHUFFDT == 0) {
717 pTRD->SBHUFFDT = GetHuffmanTable(11);
718 }
else if (cSBHUFFDT == 1) {
719 pTRD->SBHUFFDT = GetHuffmanTable(12);
720 }
else if (cSBHUFFDT == 2) {
721 pTRD->SBHUFFDT = GetHuffmanTable(13);
724 FindReferredTableSegmentByIndex(pSegment, nIndex++);
727 pTRD->SBHUFFDT = pSeg->m_HuffmanTable.get();
729 if (cSBHUFFRDW == 0) {
730 pTRD->SBHUFFRDW = GetHuffmanTable(14);
731 }
else if (cSBHUFFRDW == 1) {
732 pTRD->SBHUFFRDW = GetHuffmanTable(15);
735 FindReferredTableSegmentByIndex(pSegment, nIndex++);
738 pTRD->SBHUFFRDW = pSeg->m_HuffmanTable.get();
740 if (cSBHUFFRDH == 0) {
741 pTRD->SBHUFFRDH = GetHuffmanTable(14);
742 }
else if (cSBHUFFRDH == 1) {
743 pTRD->SBHUFFRDH = GetHuffmanTable(15);
746 FindReferredTableSegmentByIndex(pSegment, nIndex++);
749 pTRD->SBHUFFRDH = pSeg->m_HuffmanTable.get();
751 if (cSBHUFFRDX == 0) {
752 pTRD->SBHUFFRDX = GetHuffmanTable(14);
753 }
else if (cSBHUFFRDX == 1) {
754 pTRD->SBHUFFRDX = GetHuffmanTable(15);
757 FindReferredTableSegmentByIndex(pSegment, nIndex++);
760 pTRD->SBHUFFRDX = pSeg->m_HuffmanTable.get();
762 if (cSBHUFFRDY == 0) {
763 pTRD->SBHUFFRDY = GetHuffmanTable(14);
764 }
else if (cSBHUFFRDY == 1) {
765 pTRD->SBHUFFRDY = GetHuffmanTable(15);
768 FindReferredTableSegmentByIndex(pSegment, nIndex++);
771 pTRD->SBHUFFRDY = pSeg->m_HuffmanTable.get();
773 if (cSBHUFFRSIZE == 0) {
774 pTRD->SBHUFFRSIZE = GetHuffmanTable(1);
777 FindReferredTableSegmentByIndex(pSegment, nIndex++);
780 pTRD->SBHUFFRSIZE = pSeg->m_HuffmanTable.get();
784 if (pTRD->SBREFINE) {
785 const size_t size = GetRefAggContextSize(pTRD->SBRTEMPLATE);
790 pSegment->m_Image = pTRD->DecodeHuffman(m_pStream.get(), grContext.get());
791 if (!pSegment->m_Image)
793 m_pStream->alignByte();
795 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
797 pTRD->DecodeArith(pArithDecoder.get(), grContext.get(),
nullptr);
798 if (!pSegment->m_Image)
800 m_pStream->alignByte();
801 m_pStream->offset(2);
803 if (pSegment->m_cFlags.s
.type != 4) {
804 if (!m_bBufSpecified) {
805 const auto& pPageInfo = m_PageInfoList.back();
806 if (pPageInfo->m_bIsStriped && ri.y + ri.height > m_pPage->height())
807 m_pPage->Expand(ri.y + ri.height, pPageInfo->m_bDefaultPixelValue);
809 m_pPage->ComposeFrom(ri.x, ri.y, pSegment->m_Image.get(),
810 (JBig2ComposeOp)(ri.flags & 0x03));
811 pSegment->m_Image.reset();
820 if (m_pStream->read1Byte(&cFlags) != 0 ||
821 m_pStream->read1Byte(&pPDD->HDPW) != 0 ||
822 m_pStream->read1Byte(&pPDD->HDPH) != 0 ||
823 m_pStream->readInteger(&pPDD->GRAYMAX) != 0) {
829 pPDD->HDMMR = cFlags & 0x01;
830 pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
833 pSegment->m_PatternDict = pPDD->DecodeMMR(m_pStream.get());
834 if (!pSegment->m_PatternDict)
836 m_pStream->alignByte();
838 const size_t size = GetHuffContextSize(pPDD->HDTEMPLATE);
840 FX_Alloc(JBig2ArithCtx, size));
841 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
842 pSegment->m_PatternDict =
843 pPDD->DecodeArith(pArithDecoder.get(), gbContext.get(), pPause);
844 if (!pSegment->m_PatternDict)
847 m_pStream->alignByte();
848 m_pStream->offset(2);
858 if (ParseRegionInfo(&ri) != JBig2_Result::kSuccess ||
859 m_pStream->read1Byte(&cFlags) != 0 ||
860 m_pStream->readInteger(&pHRD->HGW) != 0 ||
861 m_pStream->readInteger(&pHRD->HGH) != 0 ||
862 m_pStream->readInteger((uint32_t*)&pHRD->HGX) != 0 ||
863 m_pStream->readInteger((uint32_t*)&pHRD->HGY) != 0 ||
864 m_pStream->readShortInteger(&pHRD->HRX) != 0 ||
865 m_pStream->readShortInteger(&pHRD->HRY) != 0) {
877 pHRD->HMMR = cFlags & 0x01;
878 pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
879 pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
881 pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
886 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]);
887 if (!pSeg || (pSeg->m_cFlags.s
.type != 16))
891 if (!pPatternDict || (pPatternDict
->NUMPATS == 0))
895 pHRD->HPATS = &pPatternDict->HDPATS;
896 pHRD->HPW = pPatternDict->HDPATS[0]->width();
897 pHRD->HPH = pPatternDict->HDPATS[0]->height();
900 pSegment->m_Image = pHRD->DecodeMMR(m_pStream.get());
901 if (!pSegment->m_Image)
903 m_pStream->alignByte();
905 const size_t size = GetHuffContextSize(pHRD->HTEMPLATE);
907 FX_Alloc(JBig2ArithCtx, size));
908 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
910 pHRD->DecodeArith(pArithDecoder.get(), gbContext.get(), pPause);
911 if (!pSegment->m_Image)
914 m_pStream->alignByte();
915 m_pStream->offset(2);
917 if (pSegment->m_cFlags.s
.type != 20) {
918 if (!m_bBufSpecified) {
919 const auto& pPageInfo = m_PageInfoList.back();
920 if (pPageInfo->m_bIsStriped && ri.y + ri.height > m_pPage->height())
921 m_pPage->Expand(ri.y + ri.height, pPageInfo->m_bDefaultPixelValue);
923 m_pPage->ComposeFrom(ri.x, ri.y, pSegment->m_Image.get(),
924 (JBig2ComposeOp)(ri.flags & 0x03));
925 pSegment->m_Image.reset();
935 if (ParseRegionInfo(&m_ri) != JBig2_Result::kSuccess ||
936 m_pStream->read1Byte(&cFlags) != 0) {
943 pGRD->MMR = cFlags & 0x01;
944 pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
945 pGRD->TPGDON = (cFlags >> 3) & 0x01;
947 if (pGRD->GBTEMPLATE == 0) {
948 for (int32_t i = 0; i < 8; ++i) {
949 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0)
953 for (int32_t i = 0; i < 2; ++i) {
954 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0)
959 pGRD->USESKIP =
false;
960 m_pGRD = std::move(pGRD);
964 m_pGRD->StartDecodeMMR(&pSegment->m_Image, m_pStream.get());
965 if (!pSegment->m_Image) {
969 m_pStream->alignByte();
971 if (m_gbContext.empty())
972 m_gbContext.resize(GetHuffContextSize(m_pGRD->GBTEMPLATE));
974 bool bStart = !m_pArithDecoder;
976 m_pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
981 state.pImage = &pSegment->m_Image;
982 state.pArithDecoder = m_pArithDecoder.get();
983 state.gbContext = m_gbContext.data();
984 state.pPause = pPause;
985 m_ProcessingStatus = bStart ? m_pGRD->StartDecodeArith(&state)
986 : m_pGRD->ContinueDecode(&state);
988 if (pSegment->m_cFlags.s
.type != 36) {
989 if (!m_bBufSpecified) {
990 const auto& pPageInfo = m_PageInfoList.back();
991 if (pPageInfo->m_bIsStriped &&
992 m_ri.y + m_ri.height > m_pPage->height()) {
993 m_pPage->Expand(m_ri.y + m_ri.height,
994 pPageInfo->m_bDefaultPixelValue);
997 const FX_RECT& rect = m_pGRD->GetReplaceRect();
998 m_pPage->ComposeFromWithRect(m_ri.x + rect.left, m_ri.y + rect.top,
999 pSegment->m_Image.get(), rect,
1000 (JBig2ComposeOp)(m_ri.flags & 0x03));
1005 m_pArithDecoder.reset();
1006 m_gbContext.clear();
1007 if (!pSegment->m_Image) {
1012 m_pStream->alignByte();
1013 m_pStream->offset(2);
1015 if (pSegment->m_cFlags.s
.type != 36) {
1016 if (!m_bBufSpecified) {
1018 if (pPageInfo->m_bIsStriped && m_ri.y + m_ri.height > m_pPage->height())
1019 m_pPage->Expand(m_ri.y + m_ri.height, pPageInfo->m_bDefaultPixelValue);
1021 const FX_RECT& rect = m_pGRD->GetReplaceRect();
1022 m_pPage->ComposeFromWithRect(m_ri.x + rect.left, m_ri.y + rect.top,
1023 pSegment->m_Image.get(), rect,
1024 (JBig2ComposeOp)(m_ri.flags & 0x03));
1025 pSegment->m_Image.reset();
1035 if (ParseRegionInfo(&ri) != JBig2_Result::kSuccess ||
1036 m_pStream->read1Byte(&cFlags) != 0) {
1045 pGRRD->GRTEMPLATE = !!(cFlags & 0x01);
1046 pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1047 if (!pGRRD->GRTEMPLATE) {
1048 for (int32_t i = 0; i < 4; ++i) {
1049 if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0)
1057 pSeg = FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]);
1061 if (pSeg->m_cFlags.s
.type == 4 || pSeg->m_cFlags.s
.type == 20 ||
1062 pSeg->m_cFlags.s
.type == 36 || pSeg->m_cFlags.s
.type == 40) {
1069 pGRRD->GRREFERENCE = pSeg->m_Image.get();
1071 pGRRD->GRREFERENCE = m_pPage.get();
1073 pGRRD->GRREFERENCEDX = 0;
1074 pGRRD->GRREFERENCEDY = 0;
1075 const size_t size = GetRefAggContextSize(pGRRD->GRTEMPLATE);
1077 FX_Alloc(JBig2ArithCtx, size));
1078 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
1080 pSegment->m_Image = pGRRD->Decode(pArithDecoder.get(), grContext.get());
1081 if (!pSegment->m_Image)
1084 m_pStream->alignByte();
1085 m_pStream->offset(2);
1086 if (pSegment->m_cFlags.s
.type != 40) {
1087 if (!m_bBufSpecified) {
1089 if (pPageInfo->m_bIsStriped && ri.y + ri.height > m_pPage->height())
1090 m_pPage->Expand(ri.y + ri.height, pPageInfo->m_bDefaultPixelValue);
1092 m_pPage->ComposeFrom(ri.x, ri.y, pSegment->m_Image.get(),
1093 (JBig2ComposeOp)(ri.flags & 0x03));
1094 pSegment->m_Image.reset();
1101 pSegment->m_HuffmanTable.reset();
1102 auto pHuff = std::make_unique<CJBig2_HuffmanTable>(m_pStream.get());
1106 pSegment->m_HuffmanTable =
std::move(pHuff);
1107 m_pStream->alignByte();
1112 if (m_pStream->readInteger((uint32_t*)&pRI->width) != 0 ||
1113 m_pStream->readInteger((uint32_t*)&pRI->height) != 0 ||
1114 m_pStream->readInteger((uint32_t*)&pRI->x) != 0 ||
1115 m_pStream->readInteger((uint32_t*)&pRI->y) != 0 ||
1116 m_pStream->read1Byte(&pRI->flags) != 0) {
1122std::vector<JBig2HuffmanCode>
CJBig2_Context::DecodeSymbolIDHuffmanTable(
1123 uint32_t SBNUMSYMS) {
1124 const size_t kRunCodesSize = 35;
1126 for (size_t i = 0; i < kRunCodesSize; ++i) {
1127 if (m_pStream->readNBits(4, &huffman_codes[i].codelen) != 0)
1128 return std::vector<JBig2HuffmanCode>();
1130 if (!HuffmanAssignCode(huffman_codes, kRunCodesSize))
1131 return std::vector<JBig2HuffmanCode>();
1133 std::vector<JBig2HuffmanCode> SBSYMCODES(SBNUMSYMS);
1136 while (i <
static_cast<
int>(SBNUMSYMS)) {
1138 FX_SAFE_INT32 nSafeVal = 0;
1142 if (m_pStream->read1Bit(&nTemp) != 0)
1143 return std::vector<JBig2HuffmanCode>();
1146 if (!nSafeVal.IsValid())
1147 return std::vector<JBig2HuffmanCode>();
1151 const int32_t nVal = nSafeVal.ValueOrDie();
1152 for (j = 0; j < kRunCodesSize; ++j) {
1153 if (nBits == huffman_codes[j].codelen && nVal == huffman_codes[j].code)
1156 if (j < kRunCodesSize)
1159 int32_t runcode =
static_cast<int32_t>(j);
1161 SBSYMCODES[i].codelen = runcode;
1163 }
else if (runcode == 32) {
1164 if (m_pStream->readNBits(2, &nTemp) != 0)
1165 return std::vector<JBig2HuffmanCode>();
1167 }
else if (runcode == 33) {
1168 if (m_pStream->readNBits(3, &nTemp) != 0)
1169 return std::vector<JBig2HuffmanCode>();
1171 }
else if (runcode == 34) {
1172 if (m_pStream->readNBits(7, &nTemp) != 0)
1173 return std::vector<JBig2HuffmanCode>();
1177 if (i + run > (
int)SBNUMSYMS)
1178 return std::vector<JBig2HuffmanCode>();
1179 for (int32_t k = 0; k < run; ++k) {
1180 if (runcode == 32 && i > 0)
1181 SBSYMCODES[i + k].codelen = SBSYMCODES[i - 1].codelen;
1183 SBSYMCODES[i + k].codelen = 0;
1190 if (!HuffmanAssignCode(SBSYMCODES.data(), SBNUMSYMS))
1191 return std::vector<JBig2HuffmanCode>();
1197 DCHECK(idx < CJBig2_HuffmanTable::kNumHuffmanTables);
1198 if (!m_HuffmanTables[idx].get())
1199 m_HuffmanTables[idx] = std::make_unique<CJBig2_HuffmanTable>(idx);
1200 return m_HuffmanTables[idx].get();
1207 for (uint32_t i = 0; i < NTEMP; ++i)
1210 std::vector<
int> LENCOUNT(LENMAX + 1);
1211 std::vector<
int> FIRSTCODE(LENMAX + 1);
1212 for (uint32_t i = 0; i < NTEMP; ++i)
1216 for (
int i = 1; i <= LENMAX; ++i) {
1217 FX_SAFE_INT32 shifted = FIRSTCODE[i - 1];
1218 shifted += LENCOUNT[i - 1];
1220 if (!shifted.IsValid())
1223 FIRSTCODE[i] = shifted.ValueOrDie();
1224 int CURCODE = FIRSTCODE[i];
1225 for (uint32_t j = 0; j < NTEMP; ++j) {
1227 SBSYMCODES[j]
.code = CURCODE++;
static const size_t kSymbolDictCacheMaxSize
#define JBIG2_MIN_SEGMENT_SIZE
constexpr uint32_t kJBig2MaxNewSymbols
constexpr int32_t kJBig2MaxReferredSegmentCount
constexpr uint32_t kJBig2MaxExportSymbols
constexpr uint32_t kJBig2MaxPatternIndex
@ JBIG2_HUFFMAN_TABLE_POINTER
@ JBIG2_SYMBOL_DICT_POINTER
@ JBIG2_PATTERN_DICT_POINTER
@ JBIG2_SEGMENT_DATA_UNPARSED
static bool HuffmanAssignCode(JBig2HuffmanCode *SBSYMCODES, uint32_t NTEMP)
bool GetFirstPage(pdfium::span< uint8_t > pBuf, int32_t width, int32_t height, int32_t stride, PauseIndicatorIface *pPause)
bool Continue(PauseIndicatorIface *pPause)
static bool IsValidImageSize(int32_t w, int32_t h)
JBig2_SegmentState m_State
JBig2_ResultType m_nResultType
uint8_t page_association_size
int32_t m_nReferred_to_segment_count
uint32_t m_dwPage_association
virtual bool NeedToPauseNow()=0