Weakly cache CPDF_Type3Cache in CPDF_DocRenderData.
Typical Retainable/Observable pattern.
In order to keep fonts alive, let CPDF_Type3Cache directly manage
CPDF_CountedFont refcounts. Currently, this is being performed by
CPDF_RenderStatus outside the class with the use of something called
CPDF_RefType3Cache, which provides still yet another refcount.
This works because CPDF_RenderStatus::GetCachedType3() is the only
place a CPDF_Type3Cache might get created (and as a side-effect
introduces another unowned pointer into a font managed elsewhere
by a counted font object).
Ideally, CPDF_Font would be a Retainable, but there are circular
references to be resolved first. In the mean time, this makes things
a little cleaner.
Change-Id: I710815fe44bb0506fd8e35ae6dbe44517c171ba1
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/58110
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp
index 7e95724..cb37c69 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp
@@ -38,20 +38,14 @@
RetainPtr<CPDF_Type3Cache> CPDF_DocRenderData::GetCachedType3(
CPDF_Type3Font* pFont) {
auto it = m_Type3FaceMap.find(pFont);
- if (it != m_Type3FaceMap.end())
- return it->second;
+ if (it != m_Type3FaceMap.end() && it->second)
+ return pdfium::WrapRetain(it->second.Get());
auto pCache = pdfium::MakeRetain<CPDF_Type3Cache>(pFont);
- m_Type3FaceMap[pFont] = pCache;
+ m_Type3FaceMap[pFont].Reset(pCache.Get());
return pCache;
}
-void CPDF_DocRenderData::MaybePurgeCachedType3(CPDF_Type3Font* pFont) {
- auto it = m_Type3FaceMap.find(pFont);
- if (it != m_Type3FaceMap.end() && it->second->HasOneRef())
- m_Type3FaceMap.erase(it);
-}
-
RetainPtr<CPDF_TransferFunc> CPDF_DocRenderData::GetTransferFunc(
const CPDF_Object* pObj) {
if (!pObj)
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.h b/core/fpdfapi/render/cpdf_docrenderdata.h
index 1300dfe..32b90a3 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.h
+++ b/core/fpdfapi/render/cpdf_docrenderdata.h
@@ -9,9 +9,7 @@
#include <map>
-#include "core/fpdfapi/page/cpdf_countedobject.h"
#include "core/fpdfapi/parser/cpdf_document.h"
-#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
@@ -32,8 +30,6 @@
CPDF_DocRenderData& operator=(const CPDF_DocRenderData&) = delete;
RetainPtr<CPDF_Type3Cache> GetCachedType3(CPDF_Type3Font* pFont);
- void MaybePurgeCachedType3(CPDF_Type3Font* pFont);
-
RetainPtr<CPDF_TransferFunc> GetTransferFunc(const CPDF_Object* pObj);
protected:
@@ -42,7 +38,7 @@
const CPDF_Object* pObj) const;
private:
- std::map<CPDF_Font*, RetainPtr<CPDF_Type3Cache>> m_Type3FaceMap;
+ std::map<CPDF_Font*, ObservedPtr<CPDF_Type3Cache>> m_Type3FaceMap;
std::map<const CPDF_Object*, ObservedPtr<CPDF_TransferFunc>>
m_TransferFuncMap;
};
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 3eac9fa..f18b552 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -11,6 +11,7 @@
#include <cmath>
#include <limits>
#include <memory>
+#include <set>
#include <utility>
#include <vector>
@@ -81,26 +82,6 @@
constexpr int kRenderMaxRecursionDepth = 64;
int g_CurrentRecursionDepth = 0;
-void ReleaseCachedType3(CPDF_Type3Font* pFont) {
- CPDF_Document* pDoc = pFont->GetDocument();
- CPDF_DocRenderData::FromDocument(pDoc)->MaybePurgeCachedType3(pFont);
- CPDF_DocPageData::FromDocument(pDoc)->ReleaseFont(pFont->GetFontDict());
-}
-
-class CPDF_RefType3Cache {
- public:
- explicit CPDF_RefType3Cache(CPDF_Type3Font* pType3Font)
- : m_pType3Font(pType3Font) {}
-
- ~CPDF_RefType3Cache() {
- while (m_dwCount--)
- ReleaseCachedType3(m_pType3Font.Get());
- }
-
- uint32_t m_dwCount = 0;
- UnownedPtr<CPDF_Type3Font> const m_pType3Font;
-};
-
uint32_t CountOutputsFromFunctions(
const std::vector<std::unique_ptr<CPDF_Function>>& funcs) {
FX_SAFE_UINT32 total = 0;
@@ -1781,13 +1762,6 @@
font_size, text_matrix, fill_argb, m_Options);
}
-RetainPtr<CPDF_Type3Cache> CPDF_RenderStatus::GetCachedType3(
- CPDF_Type3Font* pFont) {
- CPDF_Document* pDoc = pFont->GetDocument();
- CPDF_DocPageData::FromDocument(pDoc)->GetFont(pFont->GetFontDict());
- return CPDF_DocRenderData::FromDocument(pDoc)->GetCachedType3(pFont);
-}
-
// TODO(npm): Font fallback for type 3 fonts? (Completely separate code!!)
bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj,
const CFX_Matrix& mtObj2Device) {
@@ -1807,7 +1781,7 @@
char_matrix.Scale(font_size, font_size);
// Must come before |glyphs|, because |glyphs| points into |refTypeCache|.
- CPDF_RefType3Cache refTypeCache(pType3Font);
+ std::set<RetainPtr<CPDF_Type3Cache>> refTypeCache;
std::vector<TextGlyphPos> glyphs;
if (device_type == DeviceType::kDisplay)
glyphs.resize(textobj->GetCharCodes().size());
@@ -1896,8 +1870,11 @@
}
} else if (pType3Char->GetBitmap()) {
if (device_type == DeviceType::kDisplay) {
- RetainPtr<CPDF_Type3Cache> pCache = GetCachedType3(pType3Font);
- refTypeCache.m_dwCount++;
+ CPDF_Document* pDoc = pType3Font->GetDocument();
+ RetainPtr<CPDF_Type3Cache> pCache =
+ CPDF_DocRenderData::FromDocument(pDoc)->GetCachedType3(pType3Font);
+ refTypeCache.insert(pCache);
+
const CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix);
if (!pBitmap)
continue;
diff --git a/core/fpdfapi/render/cpdf_renderstatus.h b/core/fpdfapi/render/cpdf_renderstatus.h
index 4e9476e..cb07221 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.h
+++ b/core/fpdfapi/render/cpdf_renderstatus.h
@@ -118,6 +118,10 @@
const CPDF_Transparency& transparency);
private:
+ static std::unique_ptr<CPDF_GraphicStates> CloneObjStates(
+ const CPDF_GraphicStates* pSrcStates,
+ bool bStroke);
+
FX_ARGB GetFillArgbInternal(CPDF_PageObject* pObj, bool bType3) const;
bool ProcessTransparency(CPDF_PageObject* PageObj,
const CFX_Matrix& mtObj2Device);
@@ -176,10 +180,6 @@
FX_ARGB GetBackColor(const CPDF_Dictionary* pSMaskDict,
const CPDF_Dictionary* pGroupDict,
int* pCSFamily);
- static RetainPtr<CPDF_Type3Cache> GetCachedType3(CPDF_Type3Font* pFont);
- static std::unique_ptr<CPDF_GraphicStates> CloneObjStates(
- const CPDF_GraphicStates* pSrcStates,
- bool bStroke);
FX_ARGB GetStrokeArgb(CPDF_PageObject* pObj) const;
FX_RECT GetObjectClippedRect(const CPDF_PageObject* pObj,
const CFX_Matrix& mtObj2Device) const;
diff --git a/core/fpdfapi/render/cpdf_type3cache.cpp b/core/fpdfapi/render/cpdf_type3cache.cpp
index d2d6cd6..3411416 100644
--- a/core/fpdfapi/render/cpdf_type3cache.cpp
+++ b/core/fpdfapi/render/cpdf_type3cache.cpp
@@ -12,6 +12,8 @@
#include "core/fpdfapi/font/cpdf_type3char.h"
#include "core/fpdfapi/font/cpdf_type3font.h"
+#include "core/fpdfapi/page/cpdf_docpagedata.h"
+#include "core/fpdfapi/render/cpdf_docrenderdata.h"
#include "core/fpdfapi/render/cpdf_type3glyphmap.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_safe_types.h"
@@ -83,9 +85,17 @@
} // namespace
-CPDF_Type3Cache::CPDF_Type3Cache(CPDF_Type3Font* pFont) : m_pFont(pFont) {}
+CPDF_Type3Cache::CPDF_Type3Cache(CPDF_Type3Font* pFont) : m_pFont(pFont) {
+ // Increments refcount in CPDF_DocPageData.
+ CPDF_Document* pDoc = m_pFont->GetDocument();
+ CPDF_DocPageData::FromDocument(pDoc)->GetFont(m_pFont->GetFontDict());
+}
-CPDF_Type3Cache::~CPDF_Type3Cache() {}
+CPDF_Type3Cache::~CPDF_Type3Cache() {
+ // Decrements refcount in CPDF_DocPageData.
+ CPDF_Document* pDoc = m_pFont->GetDocument();
+ CPDF_DocPageData::FromDocument(pDoc)->ReleaseFont(m_pFont->GetFontDict());
+}
const CFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(uint32_t charcode,
const CFX_Matrix* pMatrix) {
diff --git a/core/fpdfapi/render/cpdf_type3cache.h b/core/fpdfapi/render/cpdf_type3cache.h
index 2f5c9ca..1717e8a 100644
--- a/core/fpdfapi/render/cpdf_type3cache.h
+++ b/core/fpdfapi/render/cpdf_type3cache.h
@@ -12,6 +12,7 @@
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
class CFX_GlyphBitmap;
@@ -19,7 +20,7 @@
class CPDF_Type3Font;
class CPDF_Type3GlyphMap;
-class CPDF_Type3Cache final : public Retainable {
+class CPDF_Type3Cache final : public Retainable, public Observable {
public:
template <typename T, typename... Args>
friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);