aboutsummaryrefslogtreecommitdiff
path: root/core/fpdfapi/page/cpdf_pageimagecache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/page/cpdf_pageimagecache.cpp')
-rw-r--r--core/fpdfapi/page/cpdf_pageimagecache.cpp100
1 files changed, 97 insertions, 3 deletions
diff --git a/core/fpdfapi/page/cpdf_pageimagecache.cpp b/core/fpdfapi/page/cpdf_pageimagecache.cpp
index 497cd8be0..cebb8b1fa 100644
--- a/core/fpdfapi/page/cpdf_pageimagecache.cpp
+++ b/core/fpdfapi/page/cpdf_pageimagecache.cpp
@@ -6,6 +6,9 @@
#include "core/fpdfapi/page/cpdf_pageimagecache.h"
+#include <stddef.h>
+#include <stdint.h>
+
#include <algorithm>
#include <utility>
#include <vector>
@@ -16,8 +19,19 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/stl_util.h"
+#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
+#include "third_party/base/check.h"
+
+#if defined(_SKIA_SUPPORT_)
+#include "core/fxcrt/data_vector.h"
+#include "core/fxge/cfx_defaultrenderdevice.h"
+#include "third_party/base/notreached.h"
+#include "third_party/skia/include/core/SkImage.h" // nogncheck
+#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
+#endif
namespace {
@@ -31,6 +45,86 @@ struct CacheInfo {
bool operator<(const CacheInfo& other) const { return time < other.time; }
};
+#if defined(_SKIA_SUPPORT_)
+// Wrapper around a `CFX_DIBBase` that memoizes `RealizeSkImage()`. This is only
+// safe if the underlying `CFX_DIBBase` is not mutable.
+class CachedImage final : public CFX_DIBBase {
+ public:
+ explicit CachedImage(RetainPtr<CFX_DIBBase> image)
+ : image_(std::move(image)) {
+ m_Format = image_->GetFormat();
+ m_Width = image_->GetWidth();
+ m_Height = image_->GetHeight();
+ m_Pitch = image_->GetPitch();
+
+ if (image_->HasPalette()) {
+ pdfium::span<const uint32_t> palette = image_->GetPaletteSpan();
+ m_palette = DataVector<uint32_t>(palette.begin(), palette.end());
+ }
+ }
+
+ pdfium::span<const uint8_t> GetBuffer() const override {
+ // TODO(crbug.com/pdfium/2051): `CachedImage` is only used by Skia, which
+ // should call `RealizeSkImage()` instead. Consider removing this, or at
+ // least making it `NOTREACHED_NORETURN()`.
+ NOTREACHED();
+ return image_->GetBuffer();
+ }
+
+ pdfium::span<const uint8_t> GetScanline(int line) const override {
+ // TODO(crbug.com/pdfium/2050): Still needed for `Realize()` call in
+ // `CPDF_ImageRenderer`.
+ return image_->GetScanline(line);
+ }
+
+ bool SkipToScanline(int line, PauseIndicatorIface* pause) const override {
+ // TODO(crbug.com/pdfium/2051): `CachedImage` is only used by Skia, which
+ // should call `RealizeSkImage()` instead. Consider removing this, or at
+ // least making it `NOTREACHED_NORETURN()`.
+ NOTREACHED();
+ return image_->SkipToScanline(line, pause);
+ }
+
+ size_t GetEstimatedImageMemoryBurden() const override {
+ // A better estimate would account for realizing the `SkImage`.
+ return image_->GetEstimatedImageMemoryBurden();
+ }
+
+ sk_sp<SkImage> RealizeSkImage() const override {
+ if (!cached_skia_image_) {
+ cached_skia_image_ = image_->RealizeSkImage();
+ }
+ return cached_skia_image_;
+ }
+
+ private:
+ RetainPtr<CFX_DIBBase> image_;
+ mutable sk_sp<SkImage> cached_skia_image_;
+};
+#endif // defined(_SKIA_SUPPORT_)
+
+// Makes a `CachedImage` backed by `image` if Skia is the default renderer,
+// otherwise return the image itself. `realize_hint` indicates whether it would
+// be beneficial to realize `image` before caching.
+RetainPtr<CFX_DIBBase> MakeCachedImage(RetainPtr<CFX_DIBBase> image,
+ bool realize_hint) {
+#if defined(_SKIA_SUPPORT_)
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ // TODO(crbug.com/pdfium/2050): Ignore `realize_hint`, as `RealizeSkImage()`
+ // doesn't benefit from it. The current behavior masks a bug in `CPDF_DIB`
+ // in which `GetBuffer()` and `GetScanline()` don't give the same answer.
+ if (realize_hint) {
+ image = image->Realize();
+ if (!image) {
+ return nullptr;
+ }
+ }
+ return pdfium::MakeRetain<CachedImage>(std::move(image));
+ }
+#endif // defined(_SKIA_SUPPORT_)
+ return realize_hint ? image->Realize() : image;
+}
+
} // namespace
CPDF_PageImageCache::CPDF_PageImageCache(CPDF_Page* pPage) : m_pPage(pPage) {}
@@ -226,13 +320,13 @@ void CPDF_PageImageCache::Entry::ContinueGetCachedBitmap(
m_pCurMask = m_pCurBitmap.AsRaw<CPDF_DIB>()->DetachMask();
m_dwTimeCount = pPageImageCache->GetTimeCount();
if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < kHugeImageSize) {
- m_pCachedBitmap = m_pCurBitmap->Realize();
+ m_pCachedBitmap = MakeCachedImage(m_pCurBitmap, /*realize_hint=*/true);
m_pCurBitmap.Reset();
} else {
- m_pCachedBitmap = m_pCurBitmap;
+ m_pCachedBitmap = MakeCachedImage(m_pCurBitmap, /*realize_hint=*/false);
}
if (m_pCurMask) {
- m_pCachedMask = m_pCurMask->Realize();
+ m_pCachedMask = MakeCachedImage(m_pCurMask, /*realize_hint=*/true);
m_pCurMask.Reset();
}
m_pCurBitmap = m_pCachedBitmap;