Bug 1380014. Add the ability to record UnscaledFonts by index. r=lsalzman
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Fri, 27 Oct 2017 18:21:26 -0400
changeset 688147 006a45a50d903db5a3bfd9e4a70832ae3fd7519c
parent 688146 630968b6201ed6e633506966c58daa30f7e60b84
child 688148 2a824a8a2277bc8f725b959be4b1962d8593b02f
push id86669
push userhikezoe@mozilla.com
push dateSat, 28 Oct 2017 10:13:18 +0000
reviewerslsalzman
bugs1380014
milestone58.0a1
Bug 1380014. Add the ability to record UnscaledFonts by index. r=lsalzman
gfx/2d/DrawEventRecorder.cpp
gfx/2d/DrawEventRecorder.h
gfx/2d/DrawTargetRecording.cpp
gfx/2d/InlineTranslator.h
gfx/2d/RecordedEvent.cpp
gfx/2d/RecordedEvent.h
gfx/2d/RecordedEventImpl.h
--- a/gfx/2d/DrawEventRecorder.cpp
+++ b/gfx/2d/DrawEventRecorder.cpp
@@ -7,17 +7,17 @@
 #include "PathRecording.h"
 #include "RecordingTypes.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace std;
 
-DrawEventRecorderPrivate::DrawEventRecorderPrivate()
+DrawEventRecorderPrivate::DrawEventRecorderPrivate() : mExternalFonts(false)
 {
 }
 
 void
 DrawEventRecorderFile::RecordEvent(const RecordedEvent &aEvent)
 {
   WriteElement(mOutputStream, aEvent.mType);
 
--- a/gfx/2d/DrawEventRecorder.h
+++ b/gfx/2d/DrawEventRecorder.h
@@ -8,16 +8,17 @@
 
 #include "2D.h"
 #include "RecordedEvent.h"
 #include "RecordingTypes.h"
 #include <ostream>
 #include <fstream>
 
 #include <unordered_set>
+#include <unordered_map>
 
 namespace mozilla {
 namespace gfx {
 
 class PathRecording;
 
 class DrawEventRecorderPrivate : public DrawEventRecorder
 {
@@ -80,23 +81,42 @@ public:
   void AddStoredFontData(const uint64_t aFontDataKey) {
     mStoredFontData.insert(aFontDataKey);
   }
 
   bool HasStoredFontData(const uint64_t aFontDataKey) {
     return mStoredFontData.find(aFontDataKey) != mStoredFontData.end();
   }
 
+  // Returns the index of the UnscaledFont
+  size_t GetUnscaledFontIndex(UnscaledFont *aFont) {
+    auto i = mUnscaledFontMap.find(aFont);
+    size_t index;
+    if (i == mUnscaledFontMap.end()) {
+      mUnscaledFonts.push_back(aFont);
+      index = mUnscaledFonts.size() - 1;
+      mUnscaledFontMap.insert({{aFont, index}});
+    } else {
+      index = i->second;
+    }
+    return index;
+  }
+
+  bool WantsExternalFonts() { return mExternalFonts; }
+
 protected:
   virtual void Flush() = 0;
 
   std::unordered_set<const void*> mStoredObjects;
   std::unordered_set<uint64_t> mStoredFontData;
   std::unordered_set<ScaledFont*> mStoredFonts;
   std::unordered_set<SourceSurface*> mStoredSurfaces;
+  std::vector<RefPtr<UnscaledFont>> mUnscaledFonts;
+  std::unordered_map<UnscaledFont*, size_t> mUnscaledFontMap;
+  bool mExternalFonts;
 };
 
 class DrawEventRecorderFile : public DrawEventRecorderPrivate
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderFile, override)
   explicit DrawEventRecorderFile(const char *aFilename);
   ~DrawEventRecorderFile();
--- a/gfx/2d/DrawTargetRecording.cpp
+++ b/gfx/2d/DrawTargetRecording.cpp
@@ -327,42 +327,44 @@ DrawTargetRecording::FillGlyphs(ScaledFo
                                 const DrawOptions &aOptions,
                                 const GlyphRenderingOptions *aRenderingOptions)
 {
   EnsurePatternDependenciesStored(aPattern);
 
   UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
   if (!aFont->GetUserData(userDataKey)) {
     UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
-    if (!mRecorder->HasStoredObject(unscaledFont)) {
-      RecordedFontData fontData(unscaledFont);
-      RecordedFontDetails fontDetails;
-      if (fontData.GetFontDetails(fontDetails)) {
-        // Try to serialise the whole font, just in case this is a web font that
-        // is not present on the system.
-        if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
-          mRecorder->RecordEvent(fontData);
-          mRecorder->AddStoredFontData(fontDetails.fontDataKey);
-        }
-        mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
-      } else {
-        // If that fails, record just the font description and try to load it from
-        // the system on the other side.
-        RecordedFontDescriptor fontDesc(unscaledFont);
-        if (fontDesc.IsValid()) {
-          mRecorder->RecordEvent(fontDesc);
-        } else {
-          gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
-        }
+    if (mRecorder->WantsExternalFonts()) {
+      size_t index = mRecorder->GetUnscaledFontIndex(unscaledFont);
+      mRecorder->RecordEvent(RecordedScaledFontCreationByIndex(aFont, index));
+    } else {
+      if (!mRecorder->HasStoredObject(unscaledFont)) {
+	RecordedFontData fontData(unscaledFont);
+	RecordedFontDetails fontDetails;
+	if (fontData.GetFontDetails(fontDetails)) {
+	  // Try to serialise the whole font, just in case this is a web font that
+	  // is not present on the system.
+	  if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
+	    mRecorder->RecordEvent(fontData);
+	    mRecorder->AddStoredFontData(fontDetails.fontDataKey);
+	  }
+	  mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
+	} else {
+	  // If that fails, record just the font description and try to load it from
+	  // the system on the other side.
+	  RecordedFontDescriptor fontDesc(unscaledFont);
+	  if (fontDesc.IsValid()) {
+	    mRecorder->RecordEvent(fontDesc);
+	  } else {
+	    gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
+	  }
+	}
+	mRecorder->AddStoredObject(unscaledFont);
       }
-      mRecorder->AddStoredObject(unscaledFont);
     }
-
-    mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
-
     RecordingFontUserData *userData = new RecordingFontUserData;
     userData->refPtr = aFont;
     userData->recorder = mRecorder;
     aFont->AddUserData(userDataKey, userData, &RecordingFontUserDataDestroyFunc);
     userData->recorder->AddScaledFont(aFont);
   }
 
   mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
--- a/gfx/2d/InlineTranslator.h
+++ b/gfx/2d/InlineTranslator.h
@@ -71,23 +71,29 @@ public:
 
   ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final
   {
     ScaledFont* result = mScaledFonts.GetWeak(aRefPtr);
     MOZ_ASSERT(result);
     return result;
   }
 
-  UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final
+  UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) override final
   {
     UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr);
     MOZ_ASSERT(result);
     return result;
   }
 
+  virtual UnscaledFont* LookupUnscaledFontByIndex(size_t index) override final
+  {
+    UnscaledFont* result = mUnscaledFontTable[index];
+    return result;
+  }
+
   NativeFontResource* LookupNativeFontResource(uint64_t aKey) final
   {
     NativeFontResource* result = mNativeFontResources.GetWeak(aKey);
     MOZ_ASSERT(result);
     return result;
   }
 
   void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final
@@ -174,16 +180,17 @@ public:
   mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
 
   void* GetFontContext() final { return mFontContext; }
 
 private:
   RefPtr<DrawTarget> mBaseDT;
   void*              mFontContext;
 
+  std::vector<RefPtr<UnscaledFont>> mUnscaledFontTable;
   nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
   nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
   nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
   nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
   nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
   nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
   nsRefPtrHashtable<nsPtrHashKey<void>, UnscaledFont> mUnscaledFonts;
   nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -83,16 +83,18 @@ RecordedEvent::GetEventName(EventType aT
   case GRADIENTSTOPSCREATION:
     return "GradientStopsCreation";
   case GRADIENTSTOPSDESTRUCTION:
     return "GradientStopsDestruction";
   case SNAPSHOT:
     return "Snapshot";
   case SCALEDFONTCREATION:
     return "ScaledFontCreation";
+  case SCALEDFONTCREATIONBYINDEX:
+    return "ScaledFontCreationByIndex";
   case SCALEDFONTDESTRUCTION:
     return "ScaledFontDestruction";
   case MASKSURFACE:
     return "MaskSurface";
   case FILTERNODESETATTRIBUTE:
     return "SetAttribute";
   case FILTERNODESETINPUT:
     return "SetInput";
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -84,16 +84,17 @@ public:
 
   virtual DrawTarget *LookupDrawTarget(ReferencePtr aRefPtr) = 0;
   virtual Path *LookupPath(ReferencePtr aRefPtr) = 0;
   virtual SourceSurface *LookupSourceSurface(ReferencePtr aRefPtr) = 0;
   virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0;
   virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0;
   virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0;
   virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0;
+  virtual UnscaledFont* LookupUnscaledFontByIndex(size_t aIndex) { return nullptr; }
   virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0;
   virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0;
   virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0;
   virtual void AddPath(ReferencePtr aRefPtr, Path *aPath) = 0;
   virtual void RemovePath(ReferencePtr aRefPtr) = 0;
   virtual void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aPath) = 0;
   virtual void RemoveSourceSurface(ReferencePtr aRefPtr) = 0;
   virtual void AddFilterNode(mozilla::gfx::ReferencePtr aRefPtr, FilterNode *aSurface) = 0;
@@ -236,16 +237,17 @@ public:
     PATHCREATION,
     PATHDESTRUCTION,
     SOURCESURFACECREATION,
     SOURCESURFACEDESTRUCTION,
     GRADIENTSTOPSCREATION,
     GRADIENTSTOPSDESTRUCTION,
     SNAPSHOT,
     SCALEDFONTCREATION,
+    SCALEDFONTCREATIONBYINDEX,
     SCALEDFONTDESTRUCTION,
     MASKSURFACE,
     FILTERNODECREATION,
     FILTERNODEDESTRUCTION,
     DRAWFILTER,
     FILTERNODESETATTRIBUTE,
     FILTERNODESETINPUT,
     CREATESIMILARDRAWTARGET,
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -1063,16 +1063,59 @@ private:
   Float mGlyphSize;
   std::vector<uint8_t> mInstanceData;
   std::vector<FontVariation> mVariations;
 
   template<class S>
   MOZ_IMPLICIT RecordedScaledFontCreation(S &aStream);
 };
 
+class RecordedScaledFontCreationByIndex : public RecordedEventDerived<RecordedScaledFontCreationByIndex> {
+public:
+
+  static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize,
+                                   const FontVariation* aVariations, uint32_t aNumVariations,
+                                   void* aBaton)
+  {
+    auto recordedScaledFontCreation = static_cast<RecordedScaledFontCreation*>(aBaton);
+    recordedScaledFontCreation->SetFontInstanceData(aData, aSize, aVariations, aNumVariations);
+  }
+
+  RecordedScaledFontCreationByIndex(ScaledFont* aScaledFont, size_t aUnscaledFontIndex)
+    : RecordedEventDerived(SCALEDFONTCREATIONBYINDEX)
+    , mRefPtr(aScaledFont)
+    , mUnscaledFontIndex(aUnscaledFontIndex)
+    , mGlyphSize(aScaledFont->GetSize())
+  {
+    aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
+  }
+
+  virtual bool PlayEvent(Translator *aTranslator) const;
+
+  template<class S> void Record(S &aStream) const;
+  virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
+
+  virtual std::string GetName() const { return "ScaledFont Creation"; }
+  virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
+
+  void SetFontInstanceData(const uint8_t *aData, uint32_t aSize);
+
+private:
+  friend class RecordedEvent;
+
+  ReferencePtr mRefPtr;
+  size_t mUnscaledFontIndex;
+  Float mGlyphSize;
+  std::vector<uint8_t> mInstanceData;
+  std::vector<FontVariation> mVariations;
+
+  template<class S>
+  MOZ_IMPLICIT RecordedScaledFontCreationByIndex(S &aStream);
+};
+
 class RecordedScaledFontDestruction : public RecordedEventDerived<RecordedScaledFontDestruction> {
 public:
   MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr)
     : RecordedEventDerived(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
   virtual bool PlayEvent(Translator *aTranslator) const;
@@ -2950,16 +2993,78 @@ RecordedScaledFontCreation::RecordedScal
   aStream.read((char*)mInstanceData.data(), size);
   size_t numVariations;
   ReadElement(aStream, numVariations);
   mVariations.resize(numVariations);
   aStream.read((char*)mVariations.data(), sizeof(FontVariation) * numVariations);
 }
 
 inline bool
+RecordedScaledFontCreationByIndex::PlayEvent(Translator *aTranslator) const
+{
+  UnscaledFont* unscaledFont = aTranslator->LookupUnscaledFontByIndex(mUnscaledFontIndex);
+  if (!unscaledFont) {
+    gfxDevCrash(LogReason::UnscaledFontNotFound) <<
+      "UnscaledFont lookup failed for key |" << hexa(mUnscaledFontIndex) << "|.";
+    return false;
+  }
+
+  RefPtr<ScaledFont> scaledFont =
+    unscaledFont->CreateScaledFont(mGlyphSize,
+                                   mInstanceData.data(), mInstanceData.size(),
+                                   mVariations.data(), mVariations.size());
+
+  aTranslator->AddScaledFont(mRefPtr, scaledFont);
+  return true;
+}
+
+template<class S>
+void
+RecordedScaledFontCreationByIndex::Record(S &aStream) const
+{
+  WriteElement(aStream, mRefPtr);
+  WriteElement(aStream, mUnscaledFontIndex);
+  WriteElement(aStream, mGlyphSize);
+  WriteElement(aStream, (size_t)mInstanceData.size());
+  aStream.write((char*)mInstanceData.data(), mInstanceData.size());
+  WriteElement(aStream, (size_t)mVariations.size());
+  aStream.write((char*)mVariations.data(), sizeof(FontVariation) * mVariations.size());
+}
+
+inline void
+RecordedScaledFontCreationByIndex::OutputSimpleEventInfo(std::stringstream &aStringStream) const
+{
+  aStringStream << "[" << mRefPtr << "] ScaledFont Created By Index";
+}
+
+inline void
+RecordedScaledFontCreationByIndex::SetFontInstanceData(const uint8_t *aData, uint32_t aSize)
+{
+  mInstanceData.assign(aData, aData + aSize);
+}
+
+template<class S>
+RecordedScaledFontCreationByIndex::RecordedScaledFontCreationByIndex(S &aStream)
+  : RecordedEventDerived(SCALEDFONTCREATIONBYINDEX)
+{
+  ReadElement(aStream, mRefPtr);
+  ReadElement(aStream, mUnscaledFontIndex);
+  ReadElement(aStream, mGlyphSize);
+
+  size_t size;
+  ReadElement(aStream, size);
+  mInstanceData.resize(size);
+  aStream.read((char*)mInstanceData.data(), size);
+  size_t numVariations;
+  ReadElement(aStream, numVariations);
+  mVariations.resize(numVariations);
+  aStream.read((char*)mVariations.data(), sizeof(FontVariation) * numVariations);
+}
+
+inline bool
 RecordedScaledFontDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveScaledFont(mRefPtr);
   return true;
 }
 
 template<class S>
 void
@@ -3164,16 +3269,17 @@ RecordedFilterNodeSetInput::OutputSimple
     f(SOURCESURFACECREATION, RecordedSourceSurfaceCreation); \
     f(SOURCESURFACEDESTRUCTION, RecordedSourceSurfaceDestruction); \
     f(FILTERNODECREATION, RecordedFilterNodeCreation); \
     f(FILTERNODEDESTRUCTION, RecordedFilterNodeDestruction); \
     f(GRADIENTSTOPSCREATION, RecordedGradientStopsCreation); \
     f(GRADIENTSTOPSDESTRUCTION, RecordedGradientStopsDestruction); \
     f(SNAPSHOT, RecordedSnapshot); \
     f(SCALEDFONTCREATION, RecordedScaledFontCreation); \
+    f(SCALEDFONTCREATIONBYINDEX, RecordedScaledFontCreationByIndex); \
     f(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction); \
     f(MASKSURFACE, RecordedMaskSurface); \
     f(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute); \
     f(FILTERNODESETINPUT, RecordedFilterNodeSetInput); \
     f(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget); \
     f(FONTDATA, RecordedFontData); \
     f(FONTDESC, RecordedFontDescriptor); \
     f(PUSHLAYER, RecordedPushLayer); \