OLD | NEW |
---|---|
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "JBig2_Context.h" | 7 #include "JBig2_Context.h" |
8 | 8 |
9 #include <list> | 9 #include <list> |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... | |
27 | 27 |
28 } // namespace | 28 } // namespace |
29 | 29 |
30 // Implement a very small least recently used (LRU) cache. It is very | 30 // Implement a very small least recently used (LRU) cache. It is very |
31 // common for a JBIG2 dictionary to span multiple pages in a PDF file, | 31 // common for a JBIG2 dictionary to span multiple pages in a PDF file, |
32 // and we do not want to decode the same dictionary over and over | 32 // and we do not want to decode the same dictionary over and over |
33 // again. We key off of the memory location of the dictionary. The | 33 // again. We key off of the memory location of the dictionary. The |
34 // list keeps track of the freshness of entries, with freshest ones | 34 // list keeps track of the freshness of entries, with freshest ones |
35 // at the front. Even a tiny cache size like 2 makes a dramatic | 35 // at the front. Even a tiny cache size like 2 makes a dramatic |
36 // difference for typical JBIG2 documents. | 36 // difference for typical JBIG2 documents. |
37 // | |
38 // Disabled until we can figure out how to clear cache between documents. | |
39 // https://code.google.com/p/pdfium/issues/detail?id=207 | |
40 #define DISABLE_SYMBOL_CACHE | |
41 #ifndef DISABLE_SYMBOL_CACHE | |
42 static const int kSymbolDictCacheMaxSize = 2; | 37 static const int kSymbolDictCacheMaxSize = 2; |
43 #endif | |
44 | 38 |
45 CJBig2_Context* CJBig2_Context::CreateContext( | 39 CJBig2_Context* CJBig2_Context::CreateContext( |
46 const uint8_t* pGlobalData, | 40 CPDF_StreamAcc* pGlobalStream, |
47 FX_DWORD dwGlobalLength, | 41 CPDF_StreamAcc* pSrcStream, |
48 const uint8_t* pData, | |
49 FX_DWORD dwLength, | |
50 std::list<CJBig2_CachePair>* pSymbolDictCache, | 42 std::list<CJBig2_CachePair>* pSymbolDictCache, |
51 IFX_Pause* pPause) { | 43 IFX_Pause* pPause) { |
52 return new CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLength, | 44 return new CJBig2_Context(pGlobalStream, pSrcStream, pSymbolDictCache, pPause, |
53 pSymbolDictCache, pPause); | 45 false); |
54 } | 46 } |
55 | 47 |
56 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) { | 48 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) { |
57 delete pContext; | 49 delete pContext; |
58 } | 50 } |
59 | 51 |
60 CJBig2_Context::CJBig2_Context(const uint8_t* pGlobalData, | 52 CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream, |
61 FX_DWORD dwGlobalLength, | 53 CPDF_StreamAcc* pSrcStream, |
62 const uint8_t* pData, | |
63 FX_DWORD dwLength, | |
64 std::list<CJBig2_CachePair>* pSymbolDictCache, | 54 std::list<CJBig2_CachePair>* pSymbolDictCache, |
65 IFX_Pause* pPause) | 55 IFX_Pause* pPause, |
56 bool bIsGlobal) | |
66 : m_nSegmentDecoded(0), | 57 : m_nSegmentDecoded(0), |
67 m_bInPage(false), | 58 m_bInPage(false), |
68 m_bBufSpecified(false), | 59 m_bBufSpecified(false), |
69 m_PauseStep(10), | 60 m_PauseStep(10), |
70 m_pPause(pPause), | 61 m_pPause(pPause), |
71 m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY), | 62 m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY), |
72 m_gbContext(NULL), | 63 m_gbContext(NULL), |
73 m_dwOffset(0), | 64 m_dwOffset(0), |
74 m_pSymbolDictCache(pSymbolDictCache) { | 65 m_pSymbolDictCache(pSymbolDictCache), |
75 if (pGlobalData && (dwGlobalLength > 0)) { | 66 m_bIsGlobal(bIsGlobal) { |
76 m_pGlobalContext = new CJBig2_Context( | 67 if (pGlobalStream && (pGlobalStream->GetSize() > 0)) { |
77 nullptr, 0, pGlobalData, dwGlobalLength, pSymbolDictCache, pPause); | 68 m_pGlobalContext = |
69 new CJBig2_Context(NULL, pGlobalStream, pSymbolDictCache, pPause, true); | |
Lei Zhang
2015/10/08 03:22:44
nit: nullptr
David Lattimore
2015/10/08 03:44:39
Done.
| |
78 } else { | 70 } else { |
79 m_pGlobalContext = nullptr; | 71 m_pGlobalContext = nullptr; |
80 } | 72 } |
81 | 73 |
82 m_pStream.reset(new CJBig2_BitStream(pData, dwLength)); | 74 m_pStream.reset(new CJBig2_BitStream(pSrcStream)); |
83 } | 75 } |
84 | 76 |
85 CJBig2_Context::~CJBig2_Context() { | 77 CJBig2_Context::~CJBig2_Context() { |
86 FX_Free(m_gbContext); | 78 FX_Free(m_gbContext); |
87 m_gbContext = NULL; | 79 m_gbContext = NULL; |
88 delete m_pGlobalContext; | 80 delete m_pGlobalContext; |
89 m_pGlobalContext = NULL; | 81 m_pGlobalContext = NULL; |
90 } | 82 } |
91 | 83 |
92 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) { | 84 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) { |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 return JBIG2_ERROR_TOO_SHORT; | 315 return JBIG2_ERROR_TOO_SHORT; |
324 pSegment->m_dwPage_association = cTemp; | 316 pSegment->m_dwPage_association = cTemp; |
325 } else { | 317 } else { |
326 if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) { | 318 if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) { |
327 return JBIG2_ERROR_TOO_SHORT; | 319 return JBIG2_ERROR_TOO_SHORT; |
328 } | 320 } |
329 } | 321 } |
330 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) | 322 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) |
331 return JBIG2_ERROR_TOO_SHORT; | 323 return JBIG2_ERROR_TOO_SHORT; |
332 | 324 |
333 pSegment->m_pData = m_pStream->getPointer(); | 325 pSegment->m_dwObjNum = m_pStream->getObjNum(); |
326 pSegment->m_dwDataOffset = m_pStream->getOffset(); | |
334 pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED; | 327 pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED; |
335 return JBIG2_SUCCESS; | 328 return JBIG2_SUCCESS; |
336 } | 329 } |
337 | 330 |
338 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment, | 331 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment, |
339 IFX_Pause* pPause) { | 332 IFX_Pause* pPause) { |
340 int32_t ret = ProcessingParseSegmentData(pSegment, pPause); | 333 int32_t ret = ProcessingParseSegmentData(pSegment, pPause); |
341 while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE && | 334 while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE && |
342 m_pStream->getByteLeft() > 0) { | 335 m_pStream->getByteLeft() > 0) { |
343 ret = ProcessingParseSegmentData(pSegment, pPause); | 336 ret = ProcessingParseSegmentData(pSegment, pPause); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 const size_t size = GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE); | 586 const size_t size = GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE); |
594 gbContext.reset(FX_Alloc(JBig2ArithCtx, size)); | 587 gbContext.reset(FX_Alloc(JBig2ArithCtx, size)); |
595 JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size); | 588 JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size); |
596 } | 589 } |
597 if (pSymbolDictDecoder->SDREFAGG == 1) { | 590 if (pSymbolDictDecoder->SDREFAGG == 1) { |
598 const size_t size = GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE); | 591 const size_t size = GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE); |
599 grContext.reset(FX_Alloc(JBig2ArithCtx, size)); | 592 grContext.reset(FX_Alloc(JBig2ArithCtx, size)); |
600 JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); | 593 JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); |
601 } | 594 } |
602 } | 595 } |
603 const uint8_t* key = pSegment->m_pData; | 596 CJBig2_CacheKey key = |
597 CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset); | |
604 FX_BOOL cache_hit = false; | 598 FX_BOOL cache_hit = false; |
605 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; | 599 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; |
606 for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin(); | 600 if (m_bIsGlobal) { |
607 it != m_pSymbolDictCache->end(); ++it) { | 601 for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end(); |
608 if (it->first == key) { | 602 ++it) { |
609 nonstd::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy()); | 603 if (it->first == key) { |
610 pSegment->m_Result.sd = copy.release(); | 604 nonstd::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy()); |
611 m_pSymbolDictCache->push_front(*it); | 605 pSegment->m_Result.sd = copy.release(); |
612 m_pSymbolDictCache->erase(it); | 606 m_pSymbolDictCache->push_front(*it); |
613 cache_hit = true; | 607 m_pSymbolDictCache->erase(it); |
614 break; | 608 cache_hit = true; |
609 break; | |
610 } | |
615 } | 611 } |
616 } | 612 } |
617 if (!cache_hit) { | 613 if (!cache_hit) { |
618 if (pSymbolDictDecoder->SDHUFF == 0) { | 614 if (pSymbolDictDecoder->SDHUFF == 0) { |
619 nonstd::unique_ptr<CJBig2_ArithDecoder> pArithDecoder( | 615 nonstd::unique_ptr<CJBig2_ArithDecoder> pArithDecoder( |
620 new CJBig2_ArithDecoder(m_pStream.get())); | 616 new CJBig2_ArithDecoder(m_pStream.get())); |
621 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith( | 617 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith( |
622 pArithDecoder.get(), gbContext.get(), grContext.get()); | 618 pArithDecoder.get(), gbContext.get(), grContext.get()); |
623 if (!pSegment->m_Result.sd) | 619 if (!pSegment->m_Result.sd) |
624 return JBIG2_ERROR_FATAL; | 620 return JBIG2_ERROR_FATAL; |
625 | 621 |
626 m_pStream->alignByte(); | 622 m_pStream->alignByte(); |
627 m_pStream->offset(2); | 623 m_pStream->offset(2); |
628 } else { | 624 } else { |
629 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman( | 625 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman( |
630 m_pStream.get(), gbContext.get(), grContext.get(), pPause); | 626 m_pStream.get(), gbContext.get(), grContext.get(), pPause); |
631 if (!pSegment->m_Result.sd) | 627 if (!pSegment->m_Result.sd) |
632 return JBIG2_ERROR_FATAL; | 628 return JBIG2_ERROR_FATAL; |
633 m_pStream->alignByte(); | 629 m_pStream->alignByte(); |
634 } | 630 } |
635 #ifndef DISABLE_SYMBOL_CACHE | 631 if (m_bIsGlobal && kSymbolDictCacheMaxSize > 0) { |
636 nonstd::unique_ptr<CJBig2_SymbolDict> value = | 632 nonstd::unique_ptr<CJBig2_SymbolDict> value = |
637 pSegment->m_Result.sd->DeepCopy(); | 633 pSegment->m_Result.sd->DeepCopy(); |
638 if (value && kSymbolDictCacheMaxSize > 0) { | 634 if (value) { |
639 while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) { | 635 while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) { |
640 delete m_pSymbolDictCache->back().second; | 636 delete m_pSymbolDictCache->back().second; |
641 m_pSymbolDictCache->pop_back(); | 637 m_pSymbolDictCache->pop_back(); |
638 } | |
639 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release())); | |
642 } | 640 } |
643 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release())); | |
644 } | 641 } |
645 #endif | |
646 } | 642 } |
647 if (wFlags & 0x0200) { | 643 if (wFlags & 0x0200) { |
648 pSegment->m_Result.sd->m_bContextRetained = TRUE; | 644 pSegment->m_Result.sd->m_bContextRetained = TRUE; |
649 if (pSymbolDictDecoder->SDHUFF == 0) { | 645 if (pSymbolDictDecoder->SDHUFF == 0) { |
650 pSegment->m_Result.sd->m_gbContext = gbContext.release(); | 646 pSegment->m_Result.sd->m_gbContext = gbContext.release(); |
651 } | 647 } |
652 if (pSymbolDictDecoder->SDREFAGG == 1) { | 648 if (pSymbolDictDecoder->SDREFAGG == 1) { |
653 pSegment->m_Result.sd->m_grContext = grContext.release(); | 649 pSegment->m_Result.sd->m_grContext = grContext.release(); |
654 } | 650 } |
655 } | 651 } |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1427 SBSYMCODES[CURTEMP].code = CURCODE; | 1423 SBSYMCODES[CURTEMP].code = CURCODE; |
1428 CURCODE = CURCODE + 1; | 1424 CURCODE = CURCODE + 1; |
1429 } | 1425 } |
1430 CURTEMP = CURTEMP + 1; | 1426 CURTEMP = CURTEMP + 1; |
1431 } | 1427 } |
1432 CURLEN = CURLEN + 1; | 1428 CURLEN = CURLEN + 1; |
1433 } | 1429 } |
1434 FX_Free(LENCOUNT); | 1430 FX_Free(LENCOUNT); |
1435 FX_Free(FIRSTCODE); | 1431 FX_Free(FIRSTCODE); |
1436 } | 1432 } |
OLD | NEW |