From 7ed492d2912581eb29a184e4d6da75aa579d70c2 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 9 Dec 2010 20:28:47 +1300 Subject: [PATCH] b=569770 part 3: provide public access to gfxFontEntry font table cache r=jfkthame --HG-- extra : rebase_source : ea989eec6d22c0201a58cbe0bb045470e14907f0 --- gfx/thebes/gfxDWriteFonts.cpp | 5 +++- gfx/thebes/gfxFont.cpp | 46 ++++++++++++++++++++++++++++------- gfx/thebes/gfxFont.h | 34 +++++++++++++++++--------- gfx/thebes/gfxMacFont.cpp | 5 +++- 4 files changed, 68 insertions(+), 22 deletions(-) diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index ad89b1991485..a57867d9af4c 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -419,7 +419,10 @@ gfxDWriteFont::GetFontTable(PRUint32 aTag) if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) { // for downloaded fonts, there may be layout tables cached in the entry // even though they're absent from the sanitized platform font - return mFontEntry->GetFontTable(aTag); + hb_blob_t *blob; + if (mFontEntry->GetExistingFontTable(aTag, &blob)) { + return blob; + } } return nsnull; diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index bbbce201f41a..5e6eda2355dc 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -317,8 +317,8 @@ gfxFontEntry::FontTableHashEntry::GetBlob() const return hb_blob_reference(mBlob); } -hb_blob_t * -gfxFontEntry::GetFontTable(PRUint32 aTag) +PRBool +gfxFontEntry::GetExistingFontTable(PRUint32 aTag, hb_blob_t **aBlob) { if (!mFontTableCache.IsInitialized()) { // we do this here rather than on fontEntry construction @@ -327,21 +327,36 @@ gfxFontEntry::GetFontTable(PRUint32 aTag) } FontTableHashEntry *entry = mFontTableCache.GetEntry(aTag); - if (entry) { - return entry->GetBlob(); + if (!entry) { + return PR_FALSE; } - entry = mFontTableCache.PutEntry(aTag); + *aBlob = entry->GetBlob(); + return PR_TRUE; +} + +hb_blob_t * +gfxFontEntry::ShareFontTableAndGetBlob(PRUint32 aTag, + nsTArray* aBuffer) +{ + if (NS_UNLIKELY(!mFontTableCache.IsInitialized())) { + // we do this here rather than on fontEntry construction + // because not all shapers will access the table cache at all + mFontTableCache.Init(10); + } + + FontTableHashEntry *entry = mFontTableCache.PutEntry(aTag); if (NS_UNLIKELY(!entry)) { // OOM return nsnull; } - nsTArray buffer; - if (NS_FAILED(GetFontTable(aTag, buffer))) { - return nsnull; // leaves the null entry cached in the hashtable + if (!aBuffer) { + // ensure the entry is null + entry->Clear(); + return nsnull; } - return entry->ShareTableAndGetBlob(buffer, &mFontTableCache); + return entry->ShareTableAndGetBlob(*aBuffer, &mFontTableCache); } void @@ -1037,6 +1052,19 @@ gfxFont::~gfxFont() } } +hb_blob_t * +gfxFont::GetFontTable(PRUint32 aTag) { + hb_blob_t *blob; + if (mFontEntry->GetExistingFontTable(aTag, &blob)) + return blob; + + nsTArray buffer; + PRBool haveTable = NS_SUCCEEDED(mFontEntry->GetFontTable(aTag, buffer)); + + return mFontEntry->ShareFontTableAndGetBlob(aTag, + haveTable ? &buffer : nsnull); +} + /** * A helper function in case we need to do any rounding or other * processing here. diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 354967f29cf8..26ceaadc1397 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -286,12 +286,23 @@ public: already_AddRefed FindOrMakeFont(const gfxFontStyle *aStyle, PRBool aNeedsBold); - // Subclasses should override this if they can do something more efficient - // than getting tables with GetFontTable() and caching them in the entry. + // Get an existing font table cache entry in aBlob if it has been + // registered, or return PR_FALSE if not. Callers must call + // hb_blob_destroy on aBlob if PR_TRUE is returned. // // Note that some gfxFont implementations may not call this at all, // if it is more efficient to get the table from the OS at that level. - virtual hb_blob_t *GetFontTable(PRUint32 aTag); + PRBool GetExistingFontTable(PRUint32 aTag, hb_blob_t** aBlob); + + // Elements of aTable are transferred (not copied) to and returned in a + // new hb_blob_t which is registered on the gfxFontEntry, but the initial + // reference is owned by the caller. Removing the last reference + // unregisters the table from the font entry. + // + // Pass NULL for aBuffer to indicate that the table is not present and + // NULL will be returned. Also returns NULL on OOM. + hb_blob_t *ShareFontTableAndGetBlob(PRUint32 aTag, + nsTArray* aTable); // Preload a font table into the cache (used to store layout tables for // harfbuzz, when they will be stripped from the actual sfnt being @@ -978,15 +989,16 @@ public: // returns a pointer to data owned by the fontEntry or the OS, // which will remain valid until released. // - // Default implementations forward to the font entry, which - // maintains a shared table cache; however, subclasses may - // override if they can provide more efficient table access. - - // Get pointer to a specific font table, or an empty blob if + // Default implementations forward to the font entry, + // and maintain a shared table. + // + // Subclasses should override this if they can provide more efficient + // access than getting tables with mFontEntry->GetFontTable() and sharing + // them via the entry. + // + // Get pointer to a specific font table, or NULL if // the table doesn't exist in the font - virtual hb_blob_t *GetFontTable(PRUint32 aTag) { - return mFontEntry->GetFontTable(aTag); - } + virtual hb_blob_t *GetFontTable(PRUint32 aTag); // subclasses may provide hinted glyph widths (in font units); // if they do not override this, harfbuzz will use unhinted widths diff --git a/gfx/thebes/gfxMacFont.cpp b/gfx/thebes/gfxMacFont.cpp index 1da12ab61750..0fe7d1920db4 100644 --- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -384,7 +384,10 @@ gfxMacFont::GetFontTable(PRUint32 aTag) if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) { // for downloaded fonts, there may be layout tables cached in the entry // even though they're absent from the sanitized platform font - return mFontEntry->GetFontTable(aTag); + hb_blob_t *blob; + if (mFontEntry->GetExistingFontTable(aTag, &blob)) { + return blob; + } } return nsnull;