Chromium Code Reviews| 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 |