Add SkShaper::PurgeCaches.
Allows the user to signal that any global outstanding cached data should be cleaned up to free resources. Change-Id: I59d4bb2bbb4356920dea8caf912d9cb5f13014cf Bug: skia:10763 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/360079 Commit-Queue: Ben Wagner <bungeman@google.com> Reviewed-by: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
parent
0ca2f599dd
commit
dd9449c23b
@ -3,6 +3,7 @@
|
|||||||
#include "modules/skparagraph/include/FontCollection.h"
|
#include "modules/skparagraph/include/FontCollection.h"
|
||||||
#include "modules/skparagraph/include/Paragraph.h"
|
#include "modules/skparagraph/include/Paragraph.h"
|
||||||
#include "modules/skparagraph/src/ParagraphImpl.h"
|
#include "modules/skparagraph/src/ParagraphImpl.h"
|
||||||
|
#include "modules/skshaper/include/SkShaper.h"
|
||||||
|
|
||||||
namespace skia {
|
namespace skia {
|
||||||
namespace textlayout {
|
namespace textlayout {
|
||||||
@ -150,6 +151,7 @@ void FontCollection::enableFontFallback() { fEnableFontFallback = true; }
|
|||||||
void FontCollection::clearCaches() {
|
void FontCollection::clearCaches() {
|
||||||
fParagraphCache.reset();
|
fParagraphCache.reset();
|
||||||
fTypefaces.reset();
|
fTypefaces.reset();
|
||||||
|
SkShaper::PurgeCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace textlayout
|
} // namespace textlayout
|
||||||
|
@ -41,12 +41,6 @@ class SkFont;
|
|||||||
class SkFontMgr;
|
class SkFontMgr;
|
||||||
class SkUnicode;
|
class SkUnicode;
|
||||||
|
|
||||||
/**
|
|
||||||
Shapes text using HarfBuzz and places the shaped text into a
|
|
||||||
client-managed buffer.
|
|
||||||
|
|
||||||
If compiled without HarfBuzz, fall back on SkPaint::textToGlyphs.
|
|
||||||
*/
|
|
||||||
class SKSHAPER_API SkShaper {
|
class SKSHAPER_API SkShaper {
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<SkShaper> MakePrimitive();
|
static std::unique_ptr<SkShaper> MakePrimitive();
|
||||||
@ -54,12 +48,14 @@ public:
|
|||||||
static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr);
|
static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr);
|
||||||
static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr);
|
static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr);
|
||||||
static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr);
|
static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr);
|
||||||
|
static void PurgeHarfBuzzCache();
|
||||||
#endif
|
#endif
|
||||||
#ifdef SK_SHAPER_CORETEXT_AVAILABLE
|
#ifdef SK_SHAPER_CORETEXT_AVAILABLE
|
||||||
static std::unique_ptr<SkShaper> MakeCoreText();
|
static std::unique_ptr<SkShaper> MakeCoreText();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr);
|
static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr);
|
||||||
|
static void PurgeCaches();
|
||||||
|
|
||||||
SkShaper();
|
SkShaper();
|
||||||
virtual ~SkShaper();
|
virtual ~SkShaper();
|
||||||
|
@ -36,6 +36,12 @@ std::unique_ptr<SkShaper> SkShaper::Make(sk_sp<SkFontMgr> fontmgr) {
|
|||||||
return SkShaper::MakePrimitive();
|
return SkShaper::MakePrimitive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkShaper::PurgeCaches() {
|
||||||
|
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
|
||||||
|
PurgeHarfBuzzCache();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<SkShaper::BiDiRunIterator>
|
std::unique_ptr<SkShaper::BiDiRunIterator>
|
||||||
SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
|
SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
|
||||||
#ifdef SK_UNICODE_AVAILABLE
|
#ifdef SK_UNICODE_AVAILABLE
|
||||||
|
@ -1256,6 +1256,41 @@ void ShapeDontWrapOrReorder::wrap(char const * const utf8, size_t utf8Bytes,
|
|||||||
handler->commitLine();
|
handler->commitLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HBLockedFaceCache {
|
||||||
|
public:
|
||||||
|
HBLockedFaceCache(SkLRUCache<SkFontID, HBFace>& lruCache, SkMutex& mutex)
|
||||||
|
: fLRUCache(lruCache), fMutex(mutex)
|
||||||
|
{
|
||||||
|
fMutex.acquire();
|
||||||
|
}
|
||||||
|
HBLockedFaceCache(const HBLockedFaceCache&) = delete;
|
||||||
|
HBLockedFaceCache& operator=(const HBLockedFaceCache&) = delete;
|
||||||
|
HBLockedFaceCache(HBLockedFaceCache&&) = delete;
|
||||||
|
HBLockedFaceCache& operator=(HBLockedFaceCache&&) = delete;
|
||||||
|
|
||||||
|
~HBLockedFaceCache() {
|
||||||
|
fMutex.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
HBFace* find(SkFontID fontId) {
|
||||||
|
return fLRUCache.find(fontId);
|
||||||
|
}
|
||||||
|
HBFace* insert(SkFontID fontId, HBFace hbFace) {
|
||||||
|
return fLRUCache.insert(fontId, std::move(hbFace));
|
||||||
|
}
|
||||||
|
void reset() {
|
||||||
|
fLRUCache.reset();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SkLRUCache<SkFontID, HBFace>& fLRUCache;
|
||||||
|
SkMutex& fMutex;
|
||||||
|
};
|
||||||
|
static HBLockedFaceCache get_hbFace_cache() {
|
||||||
|
static SkMutex gHBFaceCacheMutex;
|
||||||
|
static SkLRUCache<SkFontID, HBFace> gHBFaceCache(100);
|
||||||
|
return HBLockedFaceCache(gHBFaceCache, gHBFaceCacheMutex);
|
||||||
|
}
|
||||||
|
|
||||||
ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
|
ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
|
||||||
size_t const utf8Bytes,
|
size_t const utf8Bytes,
|
||||||
char const * const utf8Start,
|
char const * const utf8Start,
|
||||||
@ -1312,16 +1347,14 @@ ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
|
|||||||
// An HBFont is fairly inexpensive.
|
// An HBFont is fairly inexpensive.
|
||||||
// An HBFace is actually tied to the data, not the typeface.
|
// An HBFace is actually tied to the data, not the typeface.
|
||||||
// The size of 100 here is completely arbitrary and used to match libtxt.
|
// The size of 100 here is completely arbitrary and used to match libtxt.
|
||||||
static SkLRUCache<SkFontID, HBFace> gHBFaceCache(100);
|
|
||||||
static SkMutex gHBFaceCacheMutex;
|
|
||||||
HBFont hbFont;
|
HBFont hbFont;
|
||||||
{
|
{
|
||||||
SkAutoMutexExclusive lock(gHBFaceCacheMutex);
|
HBLockedFaceCache cache = get_hbFace_cache();
|
||||||
SkFontID dataId = font.currentFont().getTypeface()->uniqueID();
|
SkFontID dataId = font.currentFont().getTypeface()->uniqueID();
|
||||||
HBFace* hbFaceCached = gHBFaceCache.find(dataId);
|
HBFace* hbFaceCached = cache.find(dataId);
|
||||||
if (!hbFaceCached) {
|
if (!hbFaceCached) {
|
||||||
HBFace hbFace(create_hb_face(*font.currentFont().getTypeface()));
|
HBFace hbFace(create_hb_face(*font.currentFont().getTypeface()));
|
||||||
hbFaceCached = gHBFaceCache.insert(dataId, std::move(hbFace));
|
hbFaceCached = cache.insert(dataId, std::move(hbFace));
|
||||||
}
|
}
|
||||||
hbFont = create_hb_font(font.currentFont(), *hbFaceCached);
|
hbFont = create_hb_font(font.currentFont(), *hbFaceCached);
|
||||||
}
|
}
|
||||||
@ -1478,3 +1511,8 @@ std::unique_ptr<SkShaper> SkShaper::MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr>
|
|||||||
return std::make_unique<ShapeDontWrapOrReorder>
|
return std::make_unique<ShapeDontWrapOrReorder>
|
||||||
(std::move(unicode), nullptr, nullptr, std::move(buffer), std::move(fontmgr));
|
(std::move(unicode), nullptr, nullptr, std::move(buffer), std::move(fontmgr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkShaper::PurgeHarfBuzzCache() {
|
||||||
|
HBLockedFaceCache cache = get_hbFace_cache();
|
||||||
|
cache.reset();
|
||||||
|
}
|
||||||
|
@ -56,6 +56,7 @@ protected:
|
|||||||
paint.setColor(fg);
|
paint.setColor(fg);
|
||||||
|
|
||||||
for (int i = 9; i < 24; i += 2) {
|
for (int i = 9; i < 24; i += 2) {
|
||||||
|
SkShaper::PurgeCaches();
|
||||||
SkTextBlobBuilderRunHandler builder(gText, { margin, margin });
|
SkTextBlobBuilderRunHandler builder(gText, { margin, margin });
|
||||||
SkFont srcFont(nullptr, SkIntToScalar(i));
|
SkFont srcFont(nullptr, SkIntToScalar(i));
|
||||||
srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
|
srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
|
||||||
|
Loading…
Reference in New Issue
Block a user