Bug 1554819 - Ensure fontgroups attached to CanvasRenderingContext2D get reset after a shared-fontlist rebuild. r=jwatt
authorJonathan Kew <jkew@mozilla.com>
Sun, 17 Nov 2019 11:49:20 +0000
changeset 502341 e6e016592c81510432cdaf2d159f363dd4b9eb45
parent 502340 8b55cc4b13369229e7cf0b81310eef1f79e9ed93
child 502342 0f821db6009844d9234c28c02de86000bf5003de
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs1554819
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1554819 - Ensure fontgroups attached to CanvasRenderingContext2D get reset after a shared-fontlist rebuild. r=jwatt Differential Revision: https://phabricator.services.mozilla.com/D53264
dom/canvas/CanvasRenderingContext2D.cpp
gfx/thebes/gfxPlatformFontList.cpp
gfx/thebes/gfxPlatformFontList.h
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3973,16 +3973,19 @@ gfxFontGroup* CanvasRenderingContext2D::
           FontFamilyList(StyleGenericFontFamily::SansSerif), &style, tp,
           nullptr, devToCssSize);
       if (CurrentState().fontGroup) {
         CurrentState().font = kDefaultFontStyle;
       } else {
         NS_ERROR("Default canvas font is invalid");
       }
     }
+  } else {
+    // The fontgroup needs to check if its cached families/faces are valid.
+    CurrentState().fontGroup->CheckForUpdatedPlatformList();
   }
 
   return CurrentState().fontGroup;
 }
 
 //
 // line caps/joins
 //
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -2314,10 +2314,14 @@ void gfxPlatformFontList::InitOtherFamil
     return;
   }
   if (list->GetGeneration() != aGeneration) {
     return;
   }
   InitOtherFamilyNames(aDefer);
 }
 
+uint32_t gfxPlatformFontList::GetGeneration() const {
+  return SharedFontList() ? SharedFontList()->GetGeneration() : 0;
+}
+
 #undef LOG
 #undef LOG_ENABLED
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -439,16 +439,24 @@ class gfxPlatformFontList : public gfxFo
 
   static const char* GetGenericName(
       mozilla::StyleGenericFontFamily aGenericType);
 
   bool SkipFontFallbackForChar(uint32_t aCh) const {
     return mCodepointsWithNoFonts.test(aCh);
   }
 
+  // If using the shared font list, returns a generation count that is
+  // incremented if/when the platform list is reinitialized (e.g. because
+  // fonts are installed/removed while the browser is running), such that
+  // existing references to shared font family or face objects and character
+  // maps will no longer be valid.
+  // (The legacy (non-shared) list just returns 0 here.)
+  uint32_t GetGeneration() const;
+
  protected:
   friend class mozilla::fontlist::FontList;
   friend class InitOtherFamilyNamesForStylo;
 
   class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable {
    public:
     InitOtherFamilyNamesRunnable()
         : CancelableRunnable(
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -1729,16 +1729,18 @@ void gfxFontGroup::BuildFontList() {
   // build the fontlist from the specified families
   for (const auto& f : fonts) {
     if (f.mFamily.mIsShared) {
       AddFamilyToFontList(f.mFamily.mShared, f.mGeneric);
     } else {
       AddFamilyToFontList(f.mFamily.mUnshared, f.mGeneric);
     }
   }
+
+  mFontListGeneration = pfl->GetGeneration();
 }
 
 void gfxFontGroup::AddPlatformFont(const nsACString& aName, bool aQuotedName,
                                    nsTArray<FamilyAndGeneric>& aFamilyList) {
   // First, look up in the user font set...
   // If the fontSet matches the family, we must not look for a platform
   // font of the same name, even if we fail to actually get a fontEntry
   // here; we'll fall back to the next name in the CSS font-family list.
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -1044,16 +1044,27 @@ class gfxFontGroup final : public gfxTex
   // It is only guaranteed to exist until the next call to GetEllipsisTextRun
   // (which might use a different appUnitsPerDev value or flags) for the font
   // group, or until UpdateUserFonts is called, or the fontgroup is destroyed.
   // Get it/use it/forget it :) - don't keep a reference that might go stale.
   gfxTextRun* GetEllipsisTextRun(
       int32_t aAppUnitsPerDevPixel, mozilla::gfx::ShapedTextFlags aFlags,
       LazyReferenceDrawTargetGetter& aRefDrawTargetGetter);
 
+  void CheckForUpdatedPlatformList() {
+    auto* pfl = gfxPlatformFontList::PlatformFontList();
+    if (mFontListGeneration != pfl->GetGeneration()) {
+      // Forget cached fonts that may no longer be valid.
+      mLastPrefFamily = FontFamily();
+      mLastPrefFont = nullptr;
+      mFonts.Clear();
+      BuildFontList();
+    }
+  }
+
  protected:
   friend class mozilla::PostTraversalTask;
 
   struct TextRange {
     TextRange(uint32_t aStart, uint32_t aEnd, gfxFont* aFont,
               FontMatchType aMatchType,
               mozilla::gfx::ShapedTextFlags aOrientation)
         : start(aStart),
@@ -1352,16 +1363,19 @@ class gfxFontGroup final : public gfxTex
   eFontPrefLang mPageLang;
   bool mLastPrefFirstFont;  // is this the first font in the list of pref fonts
                             // for this lang group?
 
   bool mSkipDrawing;  // hide text while waiting for a font
                       // download to complete (or fallback
                       // timer to fire)
 
+  uint32_t mFontListGeneration = 0;  // platform font list generation for this
+                                     // fontgroup
+
   /**
    * Textrun creation short-cuts for special cases where we don't need to
    * call a font shaper to generate glyphs.
    */
   already_AddRefed<gfxTextRun> MakeEmptyTextRun(
       const Parameters* aParams, mozilla::gfx::ShapedTextFlags aFlags,
       nsTextFrameUtils::Flags aFlags2);