| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2016 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 "core/fpdfapi/render/cpdf_imagecacheentry.h" |
| 8 |
| 7 #include <memory> | 9 #include <memory> |
| 8 #include <utility> | 10 #include <utility> |
| 9 | 11 |
| 10 #include "core/fpdfapi/page/cpdf_page.h" | 12 #include "core/fpdfapi/page/cpdf_page.h" |
| 11 #include "core/fpdfapi/page/pageint.h" | 13 #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| 12 #include "core/fpdfapi/parser/cpdf_document.h" | 14 #include "core/fpdfapi/parser/cpdf_document.h" |
| 15 #include "core/fpdfapi/parser/cpdf_stream.h" |
| 13 #include "core/fpdfapi/render/cpdf_pagerendercache.h" | 16 #include "core/fpdfapi/render/cpdf_pagerendercache.h" |
| 14 #include "core/fpdfapi/render/cpdf_rendercontext.h" | 17 #include "core/fpdfapi/render/cpdf_rendercontext.h" |
| 15 #include "core/fpdfapi/render/cpdf_renderstatus.h" | 18 #include "core/fpdfapi/render/cpdf_renderstatus.h" |
| 16 #include "core/fpdfapi/render/render_int.h" | 19 #include "core/fpdfapi/render/render_int.h" |
| 17 | 20 |
| 18 struct CACHEINFO { | |
| 19 uint32_t time; | |
| 20 CPDF_Stream* pStream; | |
| 21 }; | |
| 22 | |
| 23 extern "C" { | |
| 24 static int compare(const void* data1, const void* data2) { | |
| 25 return ((CACHEINFO*)data1)->time - ((CACHEINFO*)data2)->time; | |
| 26 } | |
| 27 } // extern "C" | |
| 28 | |
| 29 CPDF_PageRenderCache::CPDF_PageRenderCache(CPDF_Page* pPage) | |
| 30 : m_pPage(pPage), | |
| 31 m_pCurImageCacheEntry(nullptr), | |
| 32 m_nTimeCount(0), | |
| 33 m_nCacheSize(0), | |
| 34 m_bCurFindCache(false) {} | |
| 35 | |
| 36 CPDF_PageRenderCache::~CPDF_PageRenderCache() { | |
| 37 for (const auto& it : m_ImageCache) | |
| 38 delete it.second; | |
| 39 } | |
| 40 void CPDF_PageRenderCache::CacheOptimization(int32_t dwLimitCacheSize) { | |
| 41 if (m_nCacheSize <= (uint32_t)dwLimitCacheSize) | |
| 42 return; | |
| 43 | |
| 44 size_t nCount = m_ImageCache.size(); | |
| 45 CACHEINFO* pCACHEINFO = FX_Alloc(CACHEINFO, nCount); | |
| 46 size_t i = 0; | |
| 47 for (const auto& it : m_ImageCache) { | |
| 48 pCACHEINFO[i].time = it.second->GetTimeCount(); | |
| 49 pCACHEINFO[i++].pStream = it.second->GetStream(); | |
| 50 } | |
| 51 FXSYS_qsort(pCACHEINFO, nCount, sizeof(CACHEINFO), compare); | |
| 52 uint32_t nTimeCount = m_nTimeCount; | |
| 53 | |
| 54 // Check if time value is about to roll over and reset all entries. | |
| 55 // The comparision is legal because uint32_t is an unsigned type. | |
| 56 if (nTimeCount + 1 < nTimeCount) { | |
| 57 for (i = 0; i < nCount; i++) | |
| 58 m_ImageCache[pCACHEINFO[i].pStream]->m_dwTimeCount = i; | |
| 59 m_nTimeCount = nCount; | |
| 60 } | |
| 61 | |
| 62 i = 0; | |
| 63 while (i + 15 < nCount) | |
| 64 ClearImageCacheEntry(pCACHEINFO[i++].pStream); | |
| 65 | |
| 66 while (i < nCount && m_nCacheSize > (uint32_t)dwLimitCacheSize) | |
| 67 ClearImageCacheEntry(pCACHEINFO[i++].pStream); | |
| 68 | |
| 69 FX_Free(pCACHEINFO); | |
| 70 } | |
| 71 void CPDF_PageRenderCache::ClearImageCacheEntry(CPDF_Stream* pStream) { | |
| 72 auto it = m_ImageCache.find(pStream); | |
| 73 if (it == m_ImageCache.end()) | |
| 74 return; | |
| 75 | |
| 76 m_nCacheSize -= it->second->EstimateSize(); | |
| 77 delete it->second; | |
| 78 m_ImageCache.erase(it); | |
| 79 } | |
| 80 uint32_t CPDF_PageRenderCache::EstimateSize() { | |
| 81 uint32_t dwSize = 0; | |
| 82 for (const auto& it : m_ImageCache) | |
| 83 dwSize += it.second->EstimateSize(); | |
| 84 | |
| 85 m_nCacheSize = dwSize; | |
| 86 return dwSize; | |
| 87 } | |
| 88 void CPDF_PageRenderCache::GetCachedBitmap(CPDF_Stream* pStream, | |
| 89 CFX_DIBSource*& pBitmap, | |
| 90 CFX_DIBSource*& pMask, | |
| 91 uint32_t& MatteColor, | |
| 92 bool bStdCS, | |
| 93 uint32_t GroupFamily, | |
| 94 bool bLoadMask, | |
| 95 CPDF_RenderStatus* pRenderStatus, | |
| 96 int32_t downsampleWidth, | |
| 97 int32_t downsampleHeight) { | |
| 98 CPDF_ImageCacheEntry* pEntry; | |
| 99 const auto it = m_ImageCache.find(pStream); | |
| 100 bool bFound = it != m_ImageCache.end(); | |
| 101 if (bFound) | |
| 102 pEntry = it->second; | |
| 103 else | |
| 104 pEntry = new CPDF_ImageCacheEntry(m_pPage->m_pDocument, pStream); | |
| 105 | |
| 106 m_nTimeCount++; | |
| 107 bool bAlreadyCached = pEntry->GetCachedBitmap( | |
| 108 pBitmap, pMask, MatteColor, m_pPage->m_pPageResources, bStdCS, | |
| 109 GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight); | |
| 110 | |
| 111 if (!bFound) | |
| 112 m_ImageCache[pStream] = pEntry; | |
| 113 | |
| 114 if (!bAlreadyCached) | |
| 115 m_nCacheSize += pEntry->EstimateSize(); | |
| 116 } | |
| 117 bool CPDF_PageRenderCache::StartGetCachedBitmap( | |
| 118 CPDF_Stream* pStream, | |
| 119 bool bStdCS, | |
| 120 uint32_t GroupFamily, | |
| 121 bool bLoadMask, | |
| 122 CPDF_RenderStatus* pRenderStatus, | |
| 123 int32_t downsampleWidth, | |
| 124 int32_t downsampleHeight) { | |
| 125 const auto it = m_ImageCache.find(pStream); | |
| 126 m_bCurFindCache = it != m_ImageCache.end(); | |
| 127 if (m_bCurFindCache) { | |
| 128 m_pCurImageCacheEntry = it->second; | |
| 129 } else { | |
| 130 m_pCurImageCacheEntry = | |
| 131 new CPDF_ImageCacheEntry(m_pPage->m_pDocument, pStream); | |
| 132 } | |
| 133 int ret = m_pCurImageCacheEntry->StartGetCachedBitmap( | |
| 134 pRenderStatus->m_pFormResource, m_pPage->m_pPageResources, bStdCS, | |
| 135 GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight); | |
| 136 if (ret == 2) | |
| 137 return true; | |
| 138 | |
| 139 m_nTimeCount++; | |
| 140 if (!m_bCurFindCache) | |
| 141 m_ImageCache[pStream] = m_pCurImageCacheEntry; | |
| 142 | |
| 143 if (!ret) | |
| 144 m_nCacheSize += m_pCurImageCacheEntry->EstimateSize(); | |
| 145 | |
| 146 return false; | |
| 147 } | |
| 148 bool CPDF_PageRenderCache::Continue(IFX_Pause* pPause) { | |
| 149 int ret = m_pCurImageCacheEntry->Continue(pPause); | |
| 150 if (ret == 2) | |
| 151 return true; | |
| 152 m_nTimeCount++; | |
| 153 if (!m_bCurFindCache) | |
| 154 m_ImageCache[m_pCurImageCacheEntry->GetStream()] = m_pCurImageCacheEntry; | |
| 155 if (!ret) | |
| 156 m_nCacheSize += m_pCurImageCacheEntry->EstimateSize(); | |
| 157 return false; | |
| 158 } | |
| 159 void CPDF_PageRenderCache::ResetBitmap(CPDF_Stream* pStream, | |
| 160 const CFX_DIBitmap* pBitmap) { | |
| 161 CPDF_ImageCacheEntry* pEntry; | |
| 162 const auto it = m_ImageCache.find(pStream); | |
| 163 if (it == m_ImageCache.end()) { | |
| 164 if (!pBitmap) | |
| 165 return; | |
| 166 pEntry = new CPDF_ImageCacheEntry(m_pPage->m_pDocument, pStream); | |
| 167 m_ImageCache[pStream] = pEntry; | |
| 168 } else { | |
| 169 pEntry = it->second; | |
| 170 } | |
| 171 m_nCacheSize -= pEntry->EstimateSize(); | |
| 172 pEntry->Reset(pBitmap); | |
| 173 m_nCacheSize += pEntry->EstimateSize(); | |
| 174 } | |
| 175 CPDF_ImageCacheEntry::CPDF_ImageCacheEntry(CPDF_Document* pDoc, | 21 CPDF_ImageCacheEntry::CPDF_ImageCacheEntry(CPDF_Document* pDoc, |
| 176 CPDF_Stream* pStream) | 22 CPDF_Stream* pStream) |
| 177 : m_dwTimeCount(0), | 23 : m_dwTimeCount(0), |
| 178 m_pCurBitmap(nullptr), | |
| 179 m_pCurMask(nullptr), | |
| 180 m_MatteColor(0), | 24 m_MatteColor(0), |
| 181 m_pRenderStatus(nullptr), | 25 m_pRenderStatus(nullptr), |
| 182 m_pDocument(pDoc), | 26 m_pDocument(pDoc), |
| 183 m_pStream(pStream), | 27 m_pStream(pStream), |
| 28 m_pCurBitmap(nullptr), |
| 29 m_pCurMask(nullptr), |
| 184 m_dwCacheSize(0) {} | 30 m_dwCacheSize(0) {} |
| 185 | 31 |
| 186 CPDF_ImageCacheEntry::~CPDF_ImageCacheEntry() {} | 32 CPDF_ImageCacheEntry::~CPDF_ImageCacheEntry() {} |
| 187 | 33 |
| 188 void CPDF_ImageCacheEntry::Reset(const CFX_DIBitmap* pBitmap) { | 34 void CPDF_ImageCacheEntry::Reset(const CFX_DIBitmap* pBitmap) { |
| 189 m_pCachedBitmap.reset(); | 35 m_pCachedBitmap.reset(); |
| 190 if (pBitmap) | 36 if (pBitmap) |
| 191 m_pCachedBitmap = pdfium::WrapUnique<CFX_DIBSource>(pBitmap->Clone()); | 37 m_pCachedBitmap = pdfium::WrapUnique<CFX_DIBSource>(pBitmap->Clone()); |
| 192 CalcSize(); | 38 CalcSize(); |
| 193 } | 39 } |
| 194 | 40 |
| 195 static uint32_t FPDF_ImageCache_EstimateImageSize(const CFX_DIBSource* pDIB) { | 41 static uint32_t FPDF_ImageCache_EstimateImageSize(const CFX_DIBSource* pDIB) { |
| 196 return pDIB && pDIB->GetBuffer() | 42 return pDIB && pDIB->GetBuffer() |
| 197 ? (uint32_t)pDIB->GetHeight() * pDIB->GetPitch() + | 43 ? (uint32_t)pDIB->GetHeight() * pDIB->GetPitch() + |
| 198 (uint32_t)pDIB->GetPaletteSize() * 4 | 44 (uint32_t)pDIB->GetPaletteSize() * 4 |
| 199 : 0; | 45 : 0; |
| 200 } | 46 } |
| 47 |
| 201 bool CPDF_ImageCacheEntry::GetCachedBitmap(CFX_DIBSource*& pBitmap, | 48 bool CPDF_ImageCacheEntry::GetCachedBitmap(CFX_DIBSource*& pBitmap, |
| 202 CFX_DIBSource*& pMask, | 49 CFX_DIBSource*& pMask, |
| 203 uint32_t& MatteColor, | 50 uint32_t& MatteColor, |
| 204 CPDF_Dictionary* pPageResources, | 51 CPDF_Dictionary* pPageResources, |
| 205 bool bStdCS, | 52 bool bStdCS, |
| 206 uint32_t GroupFamily, | 53 uint32_t GroupFamily, |
| 207 bool bLoadMask, | 54 bool bLoadMask, |
| 208 CPDF_RenderStatus* pRenderStatus, | 55 CPDF_RenderStatus* pRenderStatus, |
| 209 int32_t downsampleWidth, | 56 int32_t downsampleWidth, |
| 210 int32_t downsampleHeight) { | 57 int32_t downsampleHeight) { |
| 211 if (m_pCachedBitmap) { | 58 if (m_pCachedBitmap) { |
| 212 pBitmap = m_pCachedBitmap.get(); | 59 pBitmap = m_pCachedBitmap.get(); |
| 213 pMask = m_pCachedMask.get(); | 60 pMask = m_pCachedMask.get(); |
| 214 MatteColor = m_MatteColor; | 61 MatteColor = m_MatteColor; |
| 215 return true; | 62 return true; |
| 216 } | 63 } |
| 217 if (!pRenderStatus) { | 64 if (!pRenderStatus) |
| 218 return false; | 65 return false; |
| 219 } | 66 |
| 220 CPDF_RenderContext* pContext = pRenderStatus->GetContext(); | 67 CPDF_RenderContext* pContext = pRenderStatus->GetContext(); |
| 221 CPDF_PageRenderCache* pPageRenderCache = pContext->GetPageCache(); | 68 CPDF_PageRenderCache* pPageRenderCache = pContext->GetPageCache(); |
| 222 m_dwTimeCount = pPageRenderCache->GetTimeCount(); | 69 m_dwTimeCount = pPageRenderCache->GetTimeCount(); |
| 223 std::unique_ptr<CPDF_DIBSource> pSrc = pdfium::MakeUnique<CPDF_DIBSource>(); | 70 std::unique_ptr<CPDF_DIBSource> pSrc = pdfium::MakeUnique<CPDF_DIBSource>(); |
| 224 CPDF_DIBSource* pMaskSrc = nullptr; | 71 CPDF_DIBSource* pMaskSrc = nullptr; |
| 225 if (!pSrc->Load(m_pDocument, m_pStream, &pMaskSrc, &MatteColor, | 72 if (!pSrc->Load(m_pDocument, m_pStream, &pMaskSrc, &MatteColor, |
| 226 pRenderStatus->m_pFormResource, pPageResources, bStdCS, | 73 pRenderStatus->m_pFormResource, pPageResources, bStdCS, |
| 227 GroupFamily, bLoadMask)) { | 74 GroupFamily, bLoadMask)) { |
| 228 pBitmap = nullptr; | 75 pBitmap = nullptr; |
| 229 return false; | 76 return false; |
| 230 } | 77 } |
| 231 m_MatteColor = MatteColor; | 78 m_MatteColor = MatteColor; |
| 232 m_pCachedBitmap = std::move(pSrc); | 79 m_pCachedBitmap = std::move(pSrc); |
| 233 if (pMaskSrc) | 80 if (pMaskSrc) |
| 234 m_pCachedMask = pdfium::WrapUnique<CFX_DIBSource>(pMaskSrc); | 81 m_pCachedMask = pdfium::WrapUnique<CFX_DIBSource>(pMaskSrc); |
| 235 | 82 |
| 236 pBitmap = m_pCachedBitmap.get(); | 83 pBitmap = m_pCachedBitmap.get(); |
| 237 pMask = m_pCachedMask.get(); | 84 pMask = m_pCachedMask.get(); |
| 238 CalcSize(); | 85 CalcSize(); |
| 239 return false; | 86 return false; |
| 240 } | 87 } |
| 241 | 88 |
| 242 CFX_DIBSource* CPDF_ImageCacheEntry::DetachBitmap() { | 89 CFX_DIBSource* CPDF_ImageCacheEntry::DetachBitmap() { |
| 243 CFX_DIBSource* pDIBSource = m_pCurBitmap; | 90 CFX_DIBSource* pDIBSource = m_pCurBitmap; |
| 244 m_pCurBitmap = nullptr; | 91 m_pCurBitmap = nullptr; |
| 245 return pDIBSource; | 92 return pDIBSource; |
| 246 } | 93 } |
| 94 |
| 247 CFX_DIBSource* CPDF_ImageCacheEntry::DetachMask() { | 95 CFX_DIBSource* CPDF_ImageCacheEntry::DetachMask() { |
| 248 CFX_DIBSource* pDIBSource = m_pCurMask; | 96 CFX_DIBSource* pDIBSource = m_pCurMask; |
| 249 m_pCurMask = nullptr; | 97 m_pCurMask = nullptr; |
| 250 return pDIBSource; | 98 return pDIBSource; |
| 251 } | 99 } |
| 100 |
| 252 int CPDF_ImageCacheEntry::StartGetCachedBitmap(CPDF_Dictionary* pFormResources, | 101 int CPDF_ImageCacheEntry::StartGetCachedBitmap(CPDF_Dictionary* pFormResources, |
| 253 CPDF_Dictionary* pPageResources, | 102 CPDF_Dictionary* pPageResources, |
| 254 bool bStdCS, | 103 bool bStdCS, |
| 255 uint32_t GroupFamily, | 104 uint32_t GroupFamily, |
| 256 bool bLoadMask, | 105 bool bLoadMask, |
| 257 CPDF_RenderStatus* pRenderStatus, | 106 CPDF_RenderStatus* pRenderStatus, |
| 258 int32_t downsampleWidth, | 107 int32_t downsampleWidth, |
| 259 int32_t downsampleHeight) { | 108 int32_t downsampleHeight) { |
| 260 if (m_pCachedBitmap) { | 109 if (m_pCachedBitmap) { |
| 261 m_pCurBitmap = m_pCachedBitmap.get(); | 110 m_pCurBitmap = m_pCachedBitmap.get(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 292 m_pCachedBitmap = pdfium::WrapUnique<CFX_DIBSource>(m_pCurBitmap); | 141 m_pCachedBitmap = pdfium::WrapUnique<CFX_DIBSource>(m_pCurBitmap); |
| 293 if (m_pCurMask) | 142 if (m_pCurMask) |
| 294 m_pCachedMask = pdfium::WrapUnique<CFX_DIBSource>(m_pCurMask); | 143 m_pCachedMask = pdfium::WrapUnique<CFX_DIBSource>(m_pCurMask); |
| 295 else | 144 else |
| 296 m_pCurMask = m_pCachedMask.get(); | 145 m_pCurMask = m_pCachedMask.get(); |
| 297 CalcSize(); | 146 CalcSize(); |
| 298 } | 147 } |
| 299 | 148 |
| 300 int CPDF_ImageCacheEntry::Continue(IFX_Pause* pPause) { | 149 int CPDF_ImageCacheEntry::Continue(IFX_Pause* pPause) { |
| 301 int ret = ((CPDF_DIBSource*)m_pCurBitmap)->ContinueLoadDIBSource(pPause); | 150 int ret = ((CPDF_DIBSource*)m_pCurBitmap)->ContinueLoadDIBSource(pPause); |
| 302 if (ret == 2) { | 151 if (ret == 2) |
| 303 return ret; | 152 return ret; |
| 304 } | 153 |
| 305 if (!ret) { | 154 if (!ret) { |
| 306 delete m_pCurBitmap; | 155 delete m_pCurBitmap; |
| 307 m_pCurBitmap = nullptr; | 156 m_pCurBitmap = nullptr; |
| 308 return 0; | 157 return 0; |
| 309 } | 158 } |
| 310 ContinueGetCachedBitmap(); | 159 ContinueGetCachedBitmap(); |
| 311 return 0; | 160 return 0; |
| 312 } | 161 } |
| 162 |
| 313 void CPDF_ImageCacheEntry::CalcSize() { | 163 void CPDF_ImageCacheEntry::CalcSize() { |
| 314 m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap.get()) + | 164 m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap.get()) + |
| 315 FPDF_ImageCache_EstimateImageSize(m_pCachedMask.get()); | 165 FPDF_ImageCache_EstimateImageSize(m_pCachedMask.get()); |
| 316 } | 166 } |
| OLD | NEW |