1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fpdfapi/fpdf_render.h"
8 #include "../../../include/fpdfapi/fpdf_pageobj.h"
9 #include "../../../include/fxge/fx_ge.h"
10 #include "../fpdf_page/pageint.h"
11 #include "render_int.h"
17 static int compare(const void* data1, const void* data2)
19 return ((CACHEINFO*)data1)->time - ((CACHEINFO*)data2)->time;
22 void CPDF_Page::ClearRenderCache()
25 m_pPageRender->ClearAll();
28 void CPDF_PageRenderCache::ClearAll()
30 FX_POSITION pos = m_ImageCaches.GetStartPosition();
33 m_ImageCaches.GetNextAssoc(pos, key, value);
34 delete (CPDF_ImageCache*)value;
36 m_ImageCaches.RemoveAll();
40 void CPDF_PageRenderCache::CacheOptimization(FX_INT32 dwLimitCacheSize)
42 if (m_nCacheSize <= (FX_DWORD)dwLimitCacheSize) {
45 int nCount = m_ImageCaches.GetCount();
46 CACHEINFO* pCACHEINFO = (CACHEINFO*)FX_Alloc(FX_BYTE, (sizeof (CACHEINFO)) * nCount);
47 FX_POSITION pos = m_ImageCaches.GetStartPosition();
51 m_ImageCaches.GetNextAssoc(pos, key, value);
52 pCACHEINFO[i].time = ((CPDF_ImageCache*)value)->GetTimeCount();
53 pCACHEINFO[i++].pStream = ((CPDF_ImageCache*)value)->GetStream();
55 FXSYS_qsort(pCACHEINFO, nCount, sizeof (CACHEINFO), compare);
56 FX_DWORD nTimeCount = m_nTimeCount;
57 if (nTimeCount + 1 < nTimeCount) {
58 for (i = 0; i < nCount; i ++) {
59 ((CPDF_ImageCache*)(m_ImageCaches[pCACHEINFO[i].pStream]))->m_dwTimeCount = i;
61 m_nTimeCount = nCount;
65 ClearImageCache(pCACHEINFO[i++].pStream);
68 while (m_nCacheSize > (FX_DWORD)dwLimitCacheSize) {
69 ClearImageCache(pCACHEINFO[i++].pStream);
73 void CPDF_PageRenderCache::ClearImageCache(CPDF_Stream* pStream)
75 FX_LPVOID value = m_ImageCaches.GetValueAt(pStream);
77 m_ImageCaches.RemoveKey(pStream);
80 m_nCacheSize -= ((CPDF_ImageCache*)value)->EstimateSize();
81 delete (CPDF_ImageCache*)value;
82 m_ImageCaches.RemoveKey(pStream);
84 FX_DWORD CPDF_PageRenderCache::EstimateSize()
87 FX_POSITION pos = m_ImageCaches.GetStartPosition();
90 m_ImageCaches.GetNextAssoc(pos, key, value);
91 dwSize += ((CPDF_ImageCache*)value)->EstimateSize();
93 m_nCacheSize = dwSize;
96 FX_DWORD CPDF_PageRenderCache::GetCachedSize(CPDF_Stream* pStream) const
98 if (pStream == NULL) {
101 CPDF_ImageCache* pImageCache;
102 if (!m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache)) {
105 return pImageCache->EstimateSize();
107 void CPDF_PageRenderCache::GetCachedBitmap(CPDF_Stream* pStream, CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor,
108 FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus,
109 FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
111 CPDF_ImageCache* pImageCache;
112 FX_BOOL bFind = m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache);
114 pImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream);
117 FX_BOOL bCached = pImageCache->GetCachedBitmap(pBitmap, pMask, MatteColor, m_pPage->m_pPageResources, bStdCS, GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight);
119 m_ImageCaches.SetAt(pStream, pImageCache);
122 m_nCacheSize += pImageCache->EstimateSize();
125 FX_BOOL CPDF_PageRenderCache::StartGetCachedBitmap(CPDF_Stream* pStream, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
127 m_bCurFindCache = m_ImageCaches.Lookup(pStream, (FX_LPVOID&)m_pCurImageCache);
128 if (!m_bCurFindCache) {
129 m_pCurImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream);
131 int ret = m_pCurImageCache->StartGetCachedBitmap(pRenderStatus->m_pFormResource, m_pPage->m_pPageResources, bStdCS, GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight);
136 if (!m_bCurFindCache) {
137 m_ImageCaches.SetAt(pStream, m_pCurImageCache);
140 m_nCacheSize += m_pCurImageCache->EstimateSize();
144 FX_BOOL CPDF_PageRenderCache::Continue(IFX_Pause* pPause)
146 int ret = m_pCurImageCache->Continue(pPause);
151 if (!m_bCurFindCache) {
152 m_ImageCaches.SetAt(m_pCurImageCache->GetStream(), m_pCurImageCache);
155 m_nCacheSize += m_pCurImageCache->EstimateSize();
159 void CPDF_PageRenderCache::ResetBitmap(CPDF_Stream* pStream, const CFX_DIBitmap* pBitmap)
161 CPDF_ImageCache* pImageCache;
162 if (!m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache)) {
163 if (pBitmap == NULL) {
166 pImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream);
167 m_ImageCaches.SetAt(pStream, pImageCache);
169 int oldsize = pImageCache->EstimateSize();
170 pImageCache->Reset(pBitmap);
171 m_nCacheSize = pImageCache->EstimateSize() - oldsize;
173 CPDF_ImageCache::CPDF_ImageCache(CPDF_Document* pDoc, CPDF_Stream* pStream)
178 , m_pRenderStatus(NULL)
181 , m_pCachedBitmap(NULL)
182 , m_pCachedMask(NULL)
186 CPDF_ImageCache::~CPDF_ImageCache()
188 if (m_pCachedBitmap) {
189 delete m_pCachedBitmap;
190 m_pCachedBitmap = NULL;
193 delete m_pCachedMask;
194 m_pCachedMask = NULL;
197 void CPDF_ImageCache::Reset(const CFX_DIBitmap* pBitmap)
199 if (m_pCachedBitmap) {
200 delete m_pCachedBitmap;
202 m_pCachedBitmap = NULL;
204 m_pCachedBitmap = pBitmap->Clone();
208 void CPDF_PageRenderCache::ClearImageData()
210 FX_POSITION pos = m_ImageCaches.GetStartPosition();
212 FX_LPVOID key, value;
213 m_ImageCaches.GetNextAssoc(pos, key, value);
214 ((CPDF_ImageCache*)value)->ClearImageData();
217 void CPDF_ImageCache::ClearImageData()
219 if (m_pCachedBitmap && m_pCachedBitmap->GetBuffer() == NULL) {
220 ((CPDF_DIBSource*)m_pCachedBitmap)->ClearImageData();
223 static FX_DWORD FPDF_ImageCache_EstimateImageSize(const CFX_DIBSource* pDIB)
225 return pDIB && pDIB->GetBuffer() ? (FX_DWORD)pDIB->GetHeight() * pDIB->GetPitch() + (FX_DWORD)pDIB->GetPaletteSize() * 4 : 0;
227 FX_BOOL CPDF_ImageCache::GetCachedBitmap(CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor, CPDF_Dictionary* pPageResources,
228 FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus,
229 FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
231 if (m_pCachedBitmap) {
232 pBitmap = m_pCachedBitmap;
233 pMask = m_pCachedMask;
234 MatteColor = m_MatteColor;
237 if (!pRenderStatus) {
240 CPDF_RenderContext*pContext = pRenderStatus->GetContext();
241 CPDF_PageRenderCache* pPageRenderCache = pContext->m_pPageCache;
242 m_dwTimeCount = pPageRenderCache->GetTimeCount();
243 CPDF_DIBSource* pSrc = FX_NEW CPDF_DIBSource;
244 CPDF_DIBSource* pMaskSrc = NULL;
245 if (!pSrc->Load(m_pDocument, m_pStream, &pMaskSrc, &MatteColor, pRenderStatus->m_pFormResource, pPageResources, bStdCS, GroupFamily, bLoadMask)) {
250 m_MatteColor = MatteColor;
251 #if !defined(_FPDFAPI_MINI_)
252 if (pSrc->GetPitch() * pSrc->GetHeight() < FPDF_HUGE_IMAGE_SIZE) {
253 m_pCachedBitmap = pSrc->Clone();
256 m_pCachedBitmap = pSrc;
259 m_pCachedMask = pMaskSrc->Clone();
263 if (pSrc->GetFormat() == FXDIB_8bppRgb && pSrc->GetPalette() &&
264 pSrc->GetHeight() * pSrc->GetWidth() * 3 < 1024) {
265 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
266 m_pCachedBitmap = pSrc->CloneConvert(FXDIB_Rgb32);
268 m_pCachedBitmap = pSrc->CloneConvert(FXDIB_Rgb);
271 } else if (pSrc->GetPitch() * pSrc->GetHeight() < 102400) {
272 m_pCachedBitmap = pSrc->Clone();
275 m_pCachedBitmap = pSrc;
277 m_pCachedMask = pMaskSrc;
279 pBitmap = m_pCachedBitmap;
280 pMask = m_pCachedMask;
284 CFX_DIBSource* CPDF_ImageCache::DetachBitmap()
286 CFX_DIBSource* pDIBSource = m_pCurBitmap;
290 CFX_DIBSource* CPDF_ImageCache::DetachMask()
292 CFX_DIBSource* pDIBSource = m_pCurMask;
296 int CPDF_ImageCache::StartGetCachedBitmap(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, FX_BOOL bStdCS,
297 FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus,
298 FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
300 if (m_pCachedBitmap) {
301 m_pCurBitmap = m_pCachedBitmap;
302 m_pCurMask = m_pCachedMask;
305 if (!pRenderStatus) {
308 m_pRenderStatus = pRenderStatus;
309 m_pCurBitmap = FX_NEW CPDF_DIBSource;
310 int ret = ((CPDF_DIBSource*)m_pCurBitmap)->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResources, pPageResources, bStdCS, GroupFamily, bLoadMask);
319 ContinueGetCachedBitmap();
322 int CPDF_ImageCache::ContinueGetCachedBitmap()
324 m_MatteColor = ((CPDF_DIBSource*)m_pCurBitmap)->m_MatteColor;
325 m_pCurMask = ((CPDF_DIBSource*)m_pCurBitmap)->DetachMask();
326 CPDF_RenderContext*pContext = m_pRenderStatus->GetContext();
327 CPDF_PageRenderCache* pPageRenderCache = pContext->m_pPageCache;
328 m_dwTimeCount = pPageRenderCache->GetTimeCount();
329 #if !defined(_FPDFAPI_MINI_)
330 if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < FPDF_HUGE_IMAGE_SIZE) {
331 m_pCachedBitmap = m_pCurBitmap->Clone();
335 m_pCachedBitmap = m_pCurBitmap;
338 m_pCachedMask = m_pCurMask->Clone();
343 if (m_pCurBitmap->GetFormat() == FXDIB_8bppRgb && m_pCurBitmap->GetPalette() &&
344 m_pCurBitmap->GetHeight() * m_pCurBitmap->GetWidth() * 3 < 1024) {
345 m_pCachedBitmap = m_pCurBitmap->CloneConvert(FXDIB_Rgb32);
346 m_pCachedBitmap = m_pCurBitmap->CloneConvert(FXDIB_Rgb);
349 } else if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < 102400) {
350 m_pCachedBitmap = m_pCurBitmap->Clone();
354 m_pCachedBitmap = m_pCurBitmap;
356 m_pCachedMask = m_pCurMask;
358 m_pCurBitmap = m_pCachedBitmap;
359 m_pCurMask = m_pCachedMask;
363 int CPDF_ImageCache::Continue(IFX_Pause* pPause)
365 int ret = ((CPDF_DIBSource*)m_pCurBitmap)->ContinueLoadDIBSource(pPause);
374 ContinueGetCachedBitmap();
377 void CPDF_ImageCache::CalcSize()
379 m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap) + FPDF_ImageCache_EstimateImageSize(m_pCachedMask);
381 void CPDF_Document::ClearRenderFont()
384 CFX_FontCache* pCache = m_pDocRender->GetFontCache();
386 pCache->FreeCache(FALSE);