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 <map> | |
8 #include <list> | |
7 #include "JBig2_Context.h" | 9 #include "JBig2_Context.h" |
10 | |
11 // Implement a very small least recently used (LRU) cache. It is very | |
12 // common for a JBIG2 dictionary to span multiple page in a PDF file, | |
13 // and we do not want to decode the same dictionary over an over | |
14 // again. We key off of the memory location of the dictionary. The | |
15 // list keeps track of the freshness of enties, with freshest ones are | |
16 // at the front. Even a tiny cache size like 2 makes a dramatic | |
17 // difference for Google Books PDF files. | |
18 const int kMaxCacheSize = 2; | |
Tom Sepez
2014/12/10 00:14:46
nit: Let's rename this something like kMaxKBIG2Dic
jab
2014/12/11 04:40:46
Done.
| |
19 static std::map<FX_BYTE*, CJBig2_SymbolDict*> cache; | |
Tom Sepez
2014/12/10 00:14:46
Others have mentioned it, but let's not add any st
jab
2014/12/10 07:16:17
Based on Bo's comment, this requires refactoring b
| |
20 static list<FX_BYTE*> cache_keys; | |
Tom Sepez
2014/12/10 00:14:46
why do we need both a map and a list if there's on
jab
2014/12/11 04:40:46
Done.
| |
21 | |
8 void OutputBitmap(CJBig2_Image* pImage) | 22 void OutputBitmap(CJBig2_Image* pImage) |
9 { | 23 { |
10 if(!pImage) { | 24 if(!pImage) { |
11 return; | 25 return; |
12 } | 26 } |
13 } | 27 } |
14 CJBig2_Context *CJBig2_Context::CreateContext(CJBig2_Module *pModule, FX_BYTE *p GlobalData, FX_DWORD dwGlobalLength, | 28 CJBig2_Context *CJBig2_Context::CreateContext(CJBig2_Module *pModule, FX_BYTE *p GlobalData, FX_DWORD dwGlobalLength, |
15 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStreamType, IFX_Pause* pPau se) | 29 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStreamType, IFX_Pause* pPau se) |
16 { | 30 { |
17 return new(pModule) CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLen gth, nStreamType, pPause); | 31 return new(pModule) CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLen gth, nStreamType, pPause); |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
607 FX_BYTE cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST; | 621 FX_BYTE cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST; |
608 CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL, *T able_B4 = NULL, *Table_B5 = NULL; | 622 CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL, *T able_B4 = NULL, *Table_B5 = NULL; |
609 FX_INT32 i, nIndex, nRet; | 623 FX_INT32 i, nIndex, nRet; |
610 CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL; | 624 CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL; |
611 FX_BOOL bUsed; | 625 FX_BOOL bUsed; |
612 CJBig2_Image ** SDINSYMS = NULL; | 626 CJBig2_Image ** SDINSYMS = NULL; |
613 CJBig2_SDDProc *pSymbolDictDecoder; | 627 CJBig2_SDDProc *pSymbolDictDecoder; |
614 JBig2ArithCtx *gbContext = NULL, *grContext = NULL; | 628 JBig2ArithCtx *gbContext = NULL, *grContext = NULL; |
615 CJBig2_ArithDecoder *pArithDecoder; | 629 CJBig2_ArithDecoder *pArithDecoder; |
616 JBIG2_ALLOC(pSymbolDictDecoder, CJBig2_SDDProc()); | 630 JBIG2_ALLOC(pSymbolDictDecoder, CJBig2_SDDProc()); |
631 FX_BYTE *key = pSegment->m_pData; | |
617 if(m_pStream->readShortInteger(&wFlags) != 0) { | 632 if(m_pStream->readShortInteger(&wFlags) != 0) { |
618 m_pModule->JBig2_Error("symbol dictionary segment : data header too shor t."); | 633 m_pModule->JBig2_Error("symbol dictionary segment : data header too shor t."); |
619 nRet = JBIG2_ERROR_TOO_SHORT; | 634 nRet = JBIG2_ERROR_TOO_SHORT; |
620 goto failed; | 635 goto failed; |
621 } | 636 } |
622 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001; | 637 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001; |
623 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001; | 638 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001; |
624 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003; | 639 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003; |
625 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003; | 640 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003; |
626 cSDHUFFDH = (wFlags >> 2) & 0x0003; | 641 cSDHUFFDH = (wFlags >> 2) & 0x0003; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
784 gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp); | 799 gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp); |
785 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx)*dwTemp); | 800 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx)*dwTemp); |
786 } | 801 } |
787 if (pSymbolDictDecoder->SDREFAGG == 1) { | 802 if (pSymbolDictDecoder->SDREFAGG == 1) { |
788 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13; | 803 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13; |
789 grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp); | 804 grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp); |
790 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx)*dwTemp); | 805 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx)*dwTemp); |
791 } | 806 } |
792 } | 807 } |
793 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; | 808 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; |
794 if(pSymbolDictDecoder->SDHUFF == 0) { | 809 if (cache.find(key) != cache.end()) { |
810 pSegment->m_Result.sd = cache[key]->DeepCopy(); | |
811 for(std::list<FX_BYTE*>::iterator it = cache_keys.begin(); | |
812 it != cache_keys.end(); ++it) { | |
813 if (*it == key) { | |
814 cache_keys.erase(it); | |
815 break; | |
816 } | |
817 } | |
818 cache_keys.push_front(key); | |
819 } else if(pSymbolDictDecoder->SDHUFF == 0) { | |
795 JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream)); | 820 JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream)); |
796 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext); | 821 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext); |
797 delete pArithDecoder; | 822 delete pArithDecoder; |
798 if(pSegment->m_Result.sd == NULL) { | 823 if(pSegment->m_Result.sd == NULL) { |
799 nRet = JBIG2_ERROR_FETAL; | 824 nRet = JBIG2_ERROR_FETAL; |
800 goto failed; | 825 goto failed; |
801 } | 826 } |
802 m_pStream->alignByte(); | 827 m_pStream->alignByte(); |
803 m_pStream->offset(2); | 828 m_pStream->offset(2); |
804 } else { | 829 } else { |
805 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(m_pStream, gb Context, grContext, pPause); | 830 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(m_pStream, gb Context, grContext, pPause); |
806 if(pSegment->m_Result.sd == NULL) { | 831 if(pSegment->m_Result.sd == NULL) { |
807 nRet = JBIG2_ERROR_FETAL; | 832 nRet = JBIG2_ERROR_FETAL; |
808 goto failed; | 833 goto failed; |
809 } | 834 } |
810 m_pStream->alignByte(); | 835 m_pStream->alignByte(); |
811 } | 836 } |
837 if (cache.find(key) == cache.end()) { | |
838 CJBig2_SymbolDict *value = pSegment->m_Result.sd->DeepCopy(); | |
839 if (value) { | |
840 while (cache_keys.size() >= kMaxCacheSize) { | |
841 delete cache[cache_keys.back()]; | |
842 cache.erase(cache_keys.back()); | |
843 cache_keys.pop_back(); | |
844 } | |
845 cache.insert(std::pair<FX_BYTE*, CJBig2_SymbolDict*>(key, value)); | |
846 cache_keys.push_front(key); | |
847 } | |
848 } | |
812 if(wFlags & 0x0200) { | 849 if(wFlags & 0x0200) { |
813 pSegment->m_Result.sd->m_bContextRetained = TRUE; | 850 pSegment->m_Result.sd->m_bContextRetained = TRUE; |
814 if(pSymbolDictDecoder->SDHUFF == 0) { | 851 if(pSymbolDictDecoder->SDHUFF == 0) { |
815 pSegment->m_Result.sd->m_gbContext = gbContext; | 852 pSegment->m_Result.sd->m_gbContext = gbContext; |
816 } | 853 } |
817 if(pSymbolDictDecoder->SDREFAGG == 1) { | 854 if(pSymbolDictDecoder->SDREFAGG == 1) { |
818 pSegment->m_Result.sd->m_grContext = grContext; | 855 pSegment->m_Result.sd->m_grContext = grContext; |
819 } | 856 } |
820 bUsed = TRUE; | 857 bUsed = TRUE; |
821 } else { | 858 } else { |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1803 SBSYMCODES[CURTEMP].code = CURCODE; | 1840 SBSYMCODES[CURTEMP].code = CURCODE; |
1804 CURCODE = CURCODE + 1; | 1841 CURCODE = CURCODE + 1; |
1805 } | 1842 } |
1806 CURTEMP = CURTEMP + 1; | 1843 CURTEMP = CURTEMP + 1; |
1807 } | 1844 } |
1808 CURLEN = CURLEN + 1; | 1845 CURLEN = CURLEN + 1; |
1809 } | 1846 } |
1810 m_pModule->JBig2_Free(LENCOUNT); | 1847 m_pModule->JBig2_Free(LENCOUNT); |
1811 m_pModule->JBig2_Free(FIRSTCODE); | 1848 m_pModule->JBig2_Free(FIRSTCODE); |
1812 } | 1849 } |
OLD | NEW |