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> | 7 #include <map> |
8 #include <list> | 8 #include <list> |
9 #include "JBig2_Context.h" | 9 #include "JBig2_Context.h" |
10 | 10 |
11 // Implement a very small least recently used (LRU) cache. It is very | 11 // Implement a very small least recently used (LRU) cache. It is very |
12 // common for a JBIG2 dictionary to span multiple pages in a PDF file, | 12 // common for a JBIG2 dictionary to span multiple pages in a PDF file, |
13 // and we do not want to decode the same dictionary over and over | 13 // and we do not want to decode the same dictionary over and over |
14 // again. We key off of the memory location of the dictionary. The | 14 // again. We key off of the memory location of the dictionary. The |
15 // list keeps track of the freshness of entries, with freshest ones | 15 // list keeps track of the freshness of entries, with freshest ones |
16 // at the front. Even a tiny cache size like 2 makes a dramatic | 16 // at the front. Even a tiny cache size like 2 makes a dramatic |
17 // difference for typical JBIG2 documents. | 17 // difference for typical JBIG2 documents. |
18 const int kSymbolDictCacheMaxSize = 2; | 18 const int kSymbolDictCacheMaxSize = 2; |
19 typedef std::pair<FX_BYTE*, CJBig2_SymbolDict*> CJBig2_CachePair; | |
20 static std::list<CJBig2_CachePair> SymbolDictCache; | |
21 | 19 |
22 void OutputBitmap(CJBig2_Image* pImage) | 20 void OutputBitmap(CJBig2_Image* pImage) |
23 { | 21 { |
24 if(!pImage) { | 22 if(!pImage) { |
25 return; | 23 return; |
26 } | 24 } |
27 } | 25 } |
28 CJBig2_Context *CJBig2_Context::CreateContext(CJBig2_Module *pModule, FX_BYTE *p
GlobalData, FX_DWORD dwGlobalLength, | 26 CJBig2_Context *CJBig2_Context::CreateContext(CJBig2_Module *pModule, FX_BYTE *p
GlobalData, FX_DWORD dwGlobalLength, |
29 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStreamType, IFX_Pause* pPau
se) | 27 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStreamType, std::list<CJBig
2_CachePair>* pSymbolDictCache, IFX_Pause* pPause) |
30 { | 28 { |
31 return new(pModule) CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLen
gth, nStreamType, pPause); | 29 return new(pModule)CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLeng
th, nStreamType, pSymbolDictCache, pPause); |
32 } | 30 } |
33 void CJBig2_Context::DestroyContext(CJBig2_Context *pContext) | 31 void CJBig2_Context::DestroyContext(CJBig2_Context *pContext) |
34 { | 32 { |
35 if(pContext) { | 33 if(pContext) { |
36 delete pContext; | 34 delete pContext; |
37 } | 35 } |
38 } | 36 } |
39 CJBig2_Context::CJBig2_Context(FX_BYTE *pGlobalData, FX_DWORD dwGlobalLength, | 37 CJBig2_Context::CJBig2_Context(FX_BYTE *pGlobalData, FX_DWORD dwGlobalLength, |
40 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStre
amType, IFX_Pause* pPause) | 38 FX_BYTE *pData, FX_DWORD dwLength, FX_INT32 nStre
amType, std::list<CJBig2_CachePair>* pSymbolDictCache, IFX_Pause* pPause) |
41 { | 39 { |
42 if(pGlobalData && (dwGlobalLength > 0)) { | 40 if(pGlobalData && (dwGlobalLength > 0)) { |
43 JBIG2_ALLOC(m_pGlobalContext, CJBig2_Context(NULL, 0, pGlobalData, dwGlo
balLength, | 41 JBIG2_ALLOC(m_pGlobalContext, CJBig2_Context(NULL, 0, pGlobalData, dwGlo
balLength, |
44 JBIG2_EMBED_STREAM, pPause)); | 42 JBIG2_EMBED_STREAM, pSymbolDictCache, pPause)); |
45 } else { | 43 } else { |
46 m_pGlobalContext = NULL; | 44 m_pGlobalContext = NULL; |
47 } | 45 } |
48 JBIG2_ALLOC(m_pStream, CJBig2_BitStream(pData, dwLength)); | 46 JBIG2_ALLOC(m_pStream, CJBig2_BitStream(pData, dwLength)); |
49 m_nStreamType = nStreamType; | 47 m_nStreamType = nStreamType; |
50 m_nState = JBIG2_OUT_OF_PAGE; | 48 m_nState = JBIG2_OUT_OF_PAGE; |
51 JBIG2_ALLOC(m_pSegmentList, CJBig2_List<CJBig2_Segment>); | 49 JBIG2_ALLOC(m_pSegmentList, CJBig2_List<CJBig2_Segment>); |
52 JBIG2_ALLOC(m_pPageInfoList, CJBig2_List<JBig2PageInfo>(1)); | 50 JBIG2_ALLOC(m_pPageInfoList, CJBig2_List<JBig2PageInfo>(1)); |
53 m_pPage = NULL; | 51 m_pPage = NULL; |
54 m_bBufSpecified = FALSE; | 52 m_bBufSpecified = FALSE; |
55 m_pPause = pPause; | 53 m_pPause = pPause; |
56 m_nSegmentDecoded = 0; | 54 m_nSegmentDecoded = 0; |
57 m_PauseStep = 10; | 55 m_PauseStep = 10; |
58 m_pArithDecoder = NULL; | 56 m_pArithDecoder = NULL; |
59 m_pGRD = NULL; | 57 m_pGRD = NULL; |
60 m_gbContext = NULL; | 58 m_gbContext = NULL; |
61 m_pSegment = NULL; | 59 m_pSegment = NULL; |
62 m_dwOffset = 0; | 60 m_dwOffset = 0; |
63 m_ProcessiveStatus = FXCODEC_STATUS_FRAME_READY; | 61 m_ProcessiveStatus = FXCODEC_STATUS_FRAME_READY; |
| 62 m_pSymbolDictCache = pSymbolDictCache; |
64 } | 63 } |
65 CJBig2_Context::~CJBig2_Context() | 64 CJBig2_Context::~CJBig2_Context() |
66 { | 65 { |
67 if(m_pArithDecoder) { | 66 if(m_pArithDecoder) { |
68 delete m_pArithDecoder; | 67 delete m_pArithDecoder; |
69 } | 68 } |
70 m_pArithDecoder = NULL; | 69 m_pArithDecoder = NULL; |
71 if(m_pGRD) { | 70 if(m_pGRD) { |
72 delete m_pGRD; | 71 delete m_pGRD; |
73 } | 72 } |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx)*dwTemp); | 800 JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx)*dwTemp); |
802 } | 801 } |
803 if (pSymbolDictDecoder->SDREFAGG == 1) { | 802 if (pSymbolDictDecoder->SDREFAGG == 1) { |
804 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13; | 803 dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13; |
805 grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari
thCtx), dwTemp); | 804 grContext = (JBig2ArithCtx*)m_pModule->JBig2_Malloc2(sizeof(JBig2Ari
thCtx), dwTemp); |
806 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx)*dwTemp); | 805 JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx)*dwTemp); |
807 } | 806 } |
808 } | 807 } |
809 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; | 808 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; |
810 for(std::list<CJBig2_CachePair>::iterator it = | 809 for(std::list<CJBig2_CachePair>::iterator it = |
811 SymbolDictCache.begin(); it != SymbolDictCache.end(); ++it) { | 810 m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end(); ++it)
{ |
812 if (it->first == key) { | 811 if (it->first == key) { |
813 pSegment->m_Result.sd = it->second->DeepCopy(); | 812 pSegment->m_Result.sd = it->second->DeepCopy(); |
814 SymbolDictCache.push_front(*it); | 813 m_pSymbolDictCache->push_front(*it); |
815 SymbolDictCache.erase(it); | 814 m_pSymbolDictCache->erase(it); |
816 cache_hit = true; | 815 cache_hit = true; |
817 break; | 816 break; |
818 } | 817 } |
819 } | 818 } |
820 if (!cache_hit) { | 819 if (!cache_hit) { |
821 if(pSymbolDictDecoder->SDHUFF == 0) { | 820 if(pSymbolDictDecoder->SDHUFF == 0) { |
822 JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream)); | 821 JBIG2_ALLOC(pArithDecoder, CJBig2_ArithDecoder(m_pStream)); |
823 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(pArithDecod
er, gbContext, grContext); | 822 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(pArithDecod
er, gbContext, grContext); |
824 delete pArithDecoder; | 823 delete pArithDecoder; |
825 if(pSegment->m_Result.sd == NULL) { | 824 if(pSegment->m_Result.sd == NULL) { |
826 nRet = JBIG2_ERROR_FETAL; | 825 nRet = JBIG2_ERROR_FETAL; |
827 goto failed; | 826 goto failed; |
828 } | 827 } |
829 m_pStream->alignByte(); | 828 m_pStream->alignByte(); |
830 m_pStream->offset(2); | 829 m_pStream->offset(2); |
831 } else { | 830 } else { |
832 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(m_pStream
, gbContext, grContext, pPause); | 831 pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(m_pStream
, gbContext, grContext, pPause); |
833 if(pSegment->m_Result.sd == NULL) { | 832 if(pSegment->m_Result.sd == NULL) { |
834 nRet = JBIG2_ERROR_FETAL; | 833 nRet = JBIG2_ERROR_FETAL; |
835 goto failed; | 834 goto failed; |
836 } | 835 } |
837 m_pStream->alignByte(); | 836 m_pStream->alignByte(); |
838 } | 837 } |
839 CJBig2_SymbolDict *value = pSegment->m_Result.sd->DeepCopy(); | 838 CJBig2_SymbolDict *value = pSegment->m_Result.sd->DeepCopy(); |
840 if (value) { | 839 if (value && kSymbolDictCacheMaxSize > 0) { |
841 while (SymbolDictCache.size() >= kSymbolDictCacheMaxSize) { | 840 while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) { |
842 delete SymbolDictCache.back().second; | 841 delete m_pSymbolDictCache->back().second; |
843 SymbolDictCache.pop_back(); | 842 m_pSymbolDictCache->pop_back(); |
844 } | 843 } |
845 SymbolDictCache.push_front(CJBig2_CachePair(key, value)); | 844 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value)); |
846 } | 845 } |
847 } | 846 } |
848 if(wFlags & 0x0200) { | 847 if(wFlags & 0x0200) { |
849 pSegment->m_Result.sd->m_bContextRetained = TRUE; | 848 pSegment->m_Result.sd->m_bContextRetained = TRUE; |
850 if(pSymbolDictDecoder->SDHUFF == 0) { | 849 if(pSymbolDictDecoder->SDHUFF == 0) { |
851 pSegment->m_Result.sd->m_gbContext = gbContext; | 850 pSegment->m_Result.sd->m_gbContext = gbContext; |
852 } | 851 } |
853 if(pSymbolDictDecoder->SDREFAGG == 1) { | 852 if(pSymbolDictDecoder->SDREFAGG == 1) { |
854 pSegment->m_Result.sd->m_grContext = grContext; | 853 pSegment->m_Result.sd->m_grContext = grContext; |
855 } | 854 } |
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1839 SBSYMCODES[CURTEMP].code = CURCODE; | 1838 SBSYMCODES[CURTEMP].code = CURCODE; |
1840 CURCODE = CURCODE + 1; | 1839 CURCODE = CURCODE + 1; |
1841 } | 1840 } |
1842 CURTEMP = CURTEMP + 1; | 1841 CURTEMP = CURTEMP + 1; |
1843 } | 1842 } |
1844 CURLEN = CURLEN + 1; | 1843 CURLEN = CURLEN + 1; |
1845 } | 1844 } |
1846 m_pModule->JBig2_Free(LENCOUNT); | 1845 m_pModule->JBig2_Free(LENCOUNT); |
1847 m_pModule->JBig2_Free(FIRSTCODE); | 1846 m_pModule->JBig2_Free(FIRSTCODE); |
1848 } | 1847 } |
OLD | NEW |