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 |