Chromium Code Reviews| Index: src/ports/SkFontHost_fontconfig.cpp |
| diff --git a/src/ports/SkFontHost_fontconfig.cpp b/src/ports/SkFontHost_fontconfig.cpp |
| index 5c9e89661790be334309527212e2478aef5d92c9..7056438610a5b6d08ca82354428fb1dce84ab637 100644 |
| --- a/src/ports/SkFontHost_fontconfig.cpp |
| +++ b/src/ports/SkFontHost_fontconfig.cpp |
| @@ -56,36 +56,81 @@ SkFontConfigInterface* SkFontHost_fontconfig_ref_global() { |
| /////////////////////////////////////////////////////////////////////////////// |
| -struct NameStyle { |
| - NameStyle(const char* name, const SkFontStyle& style) |
| - : fFamilyName(name) // don't need to make a deep copy |
| - , fStyle(style) {} |
| - |
| - const char* fFamilyName; |
| - SkFontStyle fStyle; |
| -}; |
| - |
| -static bool find_by_NameStyle(SkTypeface* cachedTypeface, |
| - const SkFontStyle& cachedStyle, |
| - void* ctx) |
| -{ |
| - FontConfigTypeface* cachedFCTypeface = static_cast<FontConfigTypeface*>(cachedTypeface); |
| - const NameStyle* nameStyle = static_cast<const NameStyle*>(ctx); |
| - |
| - return nameStyle->fStyle == cachedStyle && |
| - cachedFCTypeface->isFamilyName(nameStyle->fFamilyName); |
| -} |
| - |
| static bool find_by_FontIdentity(SkTypeface* cachedTypeface, const SkFontStyle&, void* ctx) { |
| typedef SkFontConfigInterface::FontIdentity FontIdentity; |
| FontConfigTypeface* cachedFCTypeface = static_cast<FontConfigTypeface*>(cachedTypeface); |
| - FontIdentity* indentity = static_cast<FontIdentity*>(ctx); |
| + FontIdentity* identity = static_cast<FontIdentity*>(ctx); |
| - return cachedFCTypeface->getIdentity() == *indentity; |
| + return cachedFCTypeface->getIdentity() == *identity; |
| } |
| -SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char familyName[], |
| - SkTypeface::Style style) |
| +SK_DECLARE_STATIC_MUTEX(gSkFontHostRequestCacheMutex); |
| +class SkFontHostRequestCache { |
| +public: |
| + void add(SkTypeface* face, const char requestedFamilyName[], SkFontStyle requestedStyle) { |
| + if (fCachedResults.count() < maxEntries) { |
| + fCachedResults.emplace_back(face, Request(requestedFamilyName, requestedStyle)); |
|
mtklein
2016/02/10 16:14:10
I found myself wondering whether or not these type
bungeman-skia
2016/02/11 17:46:02
Hmmm... so the reason things are written the way t
|
| + } else { |
| + fCachedResults[fLRUIndex] = Result(face, Request(requestedFamilyName, requestedStyle)); |
| + fLRUIndex++; |
|
mtklein
2016/02/10 16:14:10
fLRUIndex seems like the wrong name here. There's
bungeman-skia
2016/02/11 17:46:02
Yeah, it's actually the fLRAIndex (least recently
|
| + if (fLRUIndex == maxEntries) { |
| + fLRUIndex = 0; |
| + } |
| + } |
| + } |
| + SkTypeface* findAndRef(const char requestedFamilyName[], SkFontStyle requestedStyle) const { |
| + for (const auto& cachedResult : fCachedResults) { |
| + if (cachedResult.fRequest.fStyle == requestedStyle && |
| + cachedResult.fRequest.fFamilyName.equals(requestedFamilyName)) |
| + { |
| + return SkSafeRef(cachedResult.fFace.get()); |
| + } |
| + } |
| + return nullptr; |
| + } |
| + |
| + static void Add(SkTypeface* face, const char requestedFamilyName[], SkFontStyle requestedStyle){ |
| + SkAutoMutexAcquire ama(gSkFontHostRequestCacheMutex); |
| + Get().add(face, requestedFamilyName, requestedStyle); |
| + } |
| + |
| + static SkTypeface* FindAndRef(const char requestedFamilyName[], SkFontStyle requestedStyle) { |
| + SkAutoMutexAcquire ama(gSkFontHostRequestCacheMutex); |
| + return Get().findAndRef(requestedFamilyName, requestedStyle); |
| + } |
| + |
| +private: |
| + static SkFontHostRequestCache& Get() { |
|
mtklein
2016/02/10 16:14:10
add
gSKFontHostRequestCacheMutex.assertHeld()
bungeman-skia
2016/02/11 17:46:02
Done.
|
| + static SkFontHostRequestCache gCache; |
| + return gCache; |
| + } |
| + |
| + // Set the maxEntries to a small value in debug to ensure testing of wrap around. |
|
mtklein
2016/02/10 16:14:10
// 64 for Release builds is... (arbitrary?) (pull
bungeman-skia
2016/02/11 17:46:02
A totally magic number.
|
| + static const int maxEntries = 64 SkDEBUGCODE( - 62); |
| + |
| + struct Request { |
| + Request(const char* name, const SkFontStyle& style) : fFamilyName(name), fStyle(style) {} |
| + Request(Request&&) = default; |
| + Request& operator=(Request&&) = default; |
| + SkString fFamilyName; |
| + SkFontStyle fStyle; |
| + }; |
| + struct Result { |
| + Result(SkTypeface* typeface, Request&& request) |
|
mtklein
2016/02/10 16:14:10
I'd slightly prefer passing (Request&&, SkTypeface
bungeman-skia
2016/02/11 17:46:02
Done.
|
| + : fFace(SkSafeRef(typeface)) |
| + , fRequest(std::move(request)) {} |
| + Result(Result&&) = default; |
| + Result& operator=(Result&&) = default; |
| + SkAutoTUnref<SkTypeface> fFace; |
| + Request fRequest; |
| + }; |
| + |
| + SkTArray<Result> fCachedResults; |
| + int fLRUIndex = 0; |
| +}; |
| + |
| +SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char requestedFamilyName[], |
| + SkTypeface::Style requestedOldStyle) |
| { |
| SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); |
| if (nullptr == fci.get()) { |
| @@ -93,35 +138,31 @@ SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char familyName[], |
| } |
| // Check if requested NameStyle is in the NameStyle cache. |
|
mtklein
2016/02/10 16:14:10
Needs an update / deletion?
bungeman-skia
2016/02/11 17:46:02
Done.
|
| - SkFontStyle requestedStyle(style); |
| - NameStyle nameStyle(familyName, requestedStyle); |
| - SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &nameStyle); |
|
mtklein
2016/02/10 16:14:10
Is this new request-caching approach something we
bungeman-skia
2016/02/11 17:46:02
Yeah, SkFontHost_mac has its own find_by_NameStyle
|
| + SkFontStyle requestedStyle(requestedOldStyle); |
| + SkTypeface* face = SkFontHostRequestCache::FindAndRef(requestedFamilyName, requestedStyle); |
| if (face) { |
| - //SkDebugf("found cached face <%s> <%s> %p [%d]\n", |
| - // familyName, ((FontConfigTypeface*)face)->getFamilyName(), |
| - // face, face->getRefCnt()); |
| return face; |
| } |
| - SkFontConfigInterface::FontIdentity indentity; |
| + SkFontConfigInterface::FontIdentity identity; |
| SkString outFamilyName; |
| - SkTypeface::Style outStyle; |
| - if (!fci->matchFamilyName(familyName, style, &indentity, &outFamilyName, &outStyle)) { |
| + SkTypeface::Style outOldStyle; |
| + if (!fci->matchFamilyName(requestedFamilyName, requestedOldStyle, |
| + &identity, &outFamilyName, &outOldStyle)) |
| + { |
| return nullptr; |
| } |
| // Check if a typeface with this FontIdentity is already in the FontIdentity cache. |
| - face = SkTypefaceCache::FindByProcAndRef(find_by_FontIdentity, &indentity); |
| + face = SkTypefaceCache::FindByProcAndRef(find_by_FontIdentity, &identity); |
| if (!face) { |
| - face = FontConfigTypeface::Create(SkFontStyle(outStyle), indentity, outFamilyName); |
| + face = FontConfigTypeface::Create(SkFontStyle(outOldStyle), identity, outFamilyName); |
| // Add this FontIdentity to the FontIdentity cache. |
| - SkTypefaceCache::Add(face, requestedStyle); |
| + SkTypefaceCache::Add(face, SkFontStyle(outOldStyle)); |
| } |
| - // TODO: Ensure requested NameStyle and resolved NameStyle are both in the NameStyle cache. |
| + // Add this NameStyle to the NameStyle cache. |
|
mtklein
2016/02/10 16:14:10
Update? Seems weird when there's no NameStyle obj
bungeman-skia
2016/02/11 17:46:02
Done.
|
| + SkFontHostRequestCache::Add(face, requestedFamilyName, requestedStyle); |
| - //SkDebugf("add face <%s> <%s> %p [%d]\n", |
| - // familyName, outFamilyName.c_str(), |
| - // face, face->getRefCnt()); |
| return face; |
| } |