Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(433)

Side by Side Diff: core/src/fxcodec/jbig2/JBig2_Context.cpp

Issue 761313004: Add a small LRU cache for the JBIG2 symbol dictionary. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: intial implementation Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <vector>
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 // vector keeps track of when an entry should be deleted, to make space
16 // for a new one. Even a tiny cache size like 2 makes a dramatic difference
17 // for Google Books PDF files.
18 const int kMaxCacheSize = 2;
19 static std::map<FX_BYTE*, CJBig2_SymbolDict*> cache;
20 static std::vector<FX_BYTE*> cache_keys;
21
22
8 void OutputBitmap(CJBig2_Image* pImage) 23 void OutputBitmap(CJBig2_Image* pImage)
9 { 24 {
10 if(!pImage) { 25 if(!pImage) {
11 return; 26 return;
12 } 27 }
13 } 28 }
14 CJBig2_Context *CJBig2_Context::CreateContext(CJBig2_Module *pModule, FX_BYTE *p GlobalData, FX_DWORD dwGlobalLength, 29 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) 30 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStreamType, IFX_Pause* pPau se)
16 { 31 {
17 return new(pModule) CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLen gth, nStreamType, pPause); 32 return new(pModule) CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLen gth, nStreamType, pPause);
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 FX_BYTE cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST; 622 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; 623 CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL, *T able_B4 = NULL, *Table_B5 = NULL;
609 FX_INT32 i, nIndex, nRet; 624 FX_INT32 i, nIndex, nRet;
610 CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL; 625 CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL;
611 FX_BOOL bUsed; 626 FX_BOOL bUsed;
612 CJBig2_Image ** SDINSYMS = NULL; 627 CJBig2_Image ** SDINSYMS = NULL;
613 CJBig2_SDDProc *pSymbolDictDecoder; 628 CJBig2_SDDProc *pSymbolDictDecoder;
614 JBig2ArithCtx *gbContext = NULL, *grContext = NULL; 629 JBig2ArithCtx *gbContext = NULL, *grContext = NULL;
615 CJBig2_ArithDecoder *pArithDecoder; 630 CJBig2_ArithDecoder *pArithDecoder;
616 JBIG2_ALLOC(pSymbolDictDecoder, CJBig2_SDDProc()); 631 JBIG2_ALLOC(pSymbolDictDecoder, CJBig2_SDDProc());
632 FX_BYTE *key = pSegment->m_pData;
617 if(m_pStream->readShortInteger(&wFlags) != 0) { 633 if(m_pStream->readShortInteger(&wFlags) != 0) {
618 m_pModule->JBig2_Error("symbol dictionary segment : data header too shor t."); 634 m_pModule->JBig2_Error("symbol dictionary segment : data header too shor t.");
619 nRet = JBIG2_ERROR_TOO_SHORT; 635 nRet = JBIG2_ERROR_TOO_SHORT;
620 goto failed; 636 goto failed;
621 } 637 }
622 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001; 638 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
623 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001; 639 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
624 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003; 640 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
625 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003; 641 pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
626 cSDHUFFDH = (wFlags >> 2) & 0x0003; 642 cSDHUFFDH = (wFlags >> 2) & 0x0003;
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp); 800 gbContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp);
785 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx)*dwTemp); 801 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx)*dwTemp);
786 } 802 }
787 if (pSymbolDictDecoder->SDREFAGG == 1) { 803 if (pSymbolDictDecoder->SDREFAGG == 1) {
788 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13; 804 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
789 grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp); 805 grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari thCtx), dwTemp);
790 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx)*dwTemp); 806 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx)*dwTemp);
791 } 807 }
792 } 808 }
793 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; 809 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
794 if(pSymbolDictDecoder->SDHUFF == 0) { 810 if (cache.find(key) != cache.end()) {
811 pSegment->m_Result.sd = cache[key]->DeepCopy();
812 for(std::vector<FX_BYTE*>::iterator it = cache_keys.begin();
813 it != cache_keys.end(); ++it) {
814 if (*it == key) {
815 cache_keys.erase(cache_keys.begin());
Bo Xu 2014/12/06 05:59:43 Should line 815 be: "cache_keys.erase(it);" ? I gu
jab 2014/12/08 21:00:02 Done. (I made the front hold the freshest entries
816 break;
Bo Xu 2014/12/07 19:22:50 Or can we use std:list to replace the std:vector h
jab 2014/12/08 21:00:02 Done.
817 }
818 }
819 cache_keys.push_back(key);
820 } else if(pSymbolDictDecoder->SDHUFF == 0) {
795 JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream)); 821 JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream));
796 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext); 822 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext);
797 delete pArithDecoder; 823 delete pArithDecoder;
798 if(pSegment->m_Result.sd == NULL) { 824 if(pSegment->m_Result.sd == NULL) {
799 nRet = JBIG2_ERROR_FETAL; 825 nRet = JBIG2_ERROR_FETAL;
800 goto failed; 826 goto failed;
801 } 827 }
802 m_pStream->alignByte(); 828 m_pStream->alignByte();
803 m_pStream->offset(2); 829 m_pStream->offset(2);
804 } else { 830 } else {
805 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(m_pStream, gb Context, grContext, pPause); 831 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(m_pStream, gb Context, grContext, pPause);
806 if(pSegment->m_Result.sd == NULL) { 832 if(pSegment->m_Result.sd == NULL) {
807 nRet = JBIG2_ERROR_FETAL; 833 nRet = JBIG2_ERROR_FETAL;
808 goto failed; 834 goto failed;
809 } 835 }
810 m_pStream->alignByte(); 836 m_pStream->alignByte();
811 } 837 }
838 if (cache.find(key) == cache.end()) {
839 CJBig2_SymbolDict *value = pSegment->m_Result.sd->DeepCopy();
Bo Xu 2014/12/06 05:59:43 should |value| be deleted after use?
jab 2014/12/08 21:00:02 That you. I think I need to free the memory when w
Bo Xu 2014/12/08 23:00:17 How about making the cache member variable of the
jab 2014/12/08 23:21:04 I made an explicit call to delete. Is that okay? I
Bo Xu 2014/12/08 23:29:54 Sure, the explicit delete is ok here. I am thinki
840 if (value) {
841 while (cache_keys.size() >= kMaxCacheSize) {
842 cache.erase(cache_keys[0]);
843 cache_keys.erase(cache_keys.begin());
844 }
845 cache.insert(std::pair<FX_BYTE*, CJBig2_SymbolDict*>(key, value));
846 cache_keys.push_back(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
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 }
OLDNEW
« no previous file with comments | « no previous file | core/src/fxcodec/jbig2/JBig2_SymbolDict.h » ('j') | core/src/fxcodec/jbig2/JBig2_SymbolDict.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698