Bug 1256678 - Fall back to loading GDI fonts from system in DrawTargetRecording - r=bas
authorEdwin Flores <edwin@mozilla.com>
Fri, 22 Apr 2016 13:23:25 +0100
changeset 332413 ed251ff578cd53fe8a862a487aa7b7bd422c9dfb
parent 332412 0a64b841be88b591fc8c86b99e4fbc01cd5fc22d
child 332414 4307f2ac86811069f1ca9fa21b0200fcae3f4fe2
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1256678
milestone48.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 1256678 - Fall back to loading GDI fonts from system in DrawTargetRecording - r=bas
gfx/2d/2D.h
gfx/2d/DrawTargetRecording.cpp
gfx/2d/RecordedEvent.cpp
gfx/2d/RecordedEvent.h
gfx/2d/ScaledFontWin.cpp
gfx/2d/ScaledFontWin.h
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -640,16 +640,17 @@ struct GlyphBuffer
  */
 class ScaledFont : public RefCounted<ScaledFont>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
   virtual ~ScaledFont() {}
 
   typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void *aBaton);
+  typedef void (*FontDescriptorOutput)(const uint8_t *aData, uint32_t aLength, Float aFontSize, void *aBaton);
 
   virtual FontType GetType() const = 0;
 
   /** This allows getting a path that describes the outline of a set of glyphs.
    * A target is passed in so that the guarantee is made the returned path
    * can be used with any DrawTarget that has the same backend as the one
    * passed in.
    */
@@ -659,16 +660,18 @@ public:
    * API rather than a generic API to append paths because it allows easier
    * implementation in some backends, and more efficient implementation in
    * others.
    */
   virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint = nullptr) = 0;
 
   virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; }
 
+  virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; }
+
   void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
     mUserData.Add(key, userData, destroy);
   }
   void *GetUserData(UserDataKey *key) {
     return mUserData.Get(key);
   }
 
 protected:
--- a/gfx/2d/DrawTargetRecording.cpp
+++ b/gfx/2d/DrawTargetRecording.cpp
@@ -390,21 +390,32 @@ DrawTargetRecording::FillGlyphs(ScaledFo
   EnsurePatternDependenciesStored(aPattern);
 
   if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()))) {
   // TODO support font in b2g recordings
 #ifndef MOZ_WIDGET_GONK
     RecordedFontData fontData(aFont);
     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(RecordedScaledFontCreation(aFont, fontDetails));
+    } else {
+      // If that fails, record just the font description and try to load it from
+      // the system on the other side.
+      RecordedFontDescriptor fontDesc(aFont);
+      if (fontDesc.IsValid()) {
+        mRecorder->RecordEvent(fontDesc);
+      } else {
+        gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise ScaledFont";
+      }
     }
 #endif
     RecordingFontUserData *userData = new RecordingFontUserData;
     userData->refPtr = aFont;
     userData->recorder = mRecorder;
     aFont->AddUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()), userData, 
                        &RecordingFontUserDataDestroyFunc);
   }
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -5,16 +5,17 @@
 
 #include "RecordedEvent.h"
 
 #include "PathRecording.h"
 #include "RecordingTypes.h"
 #include "Tools.h"
 #include "Filters.h"
 #include "Logging.h"
+#include "ScaledFontBase.h"
 #include "SFNTData.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace std;
 
 static std::string NameFromBackend(BackendType aType)
@@ -75,16 +76,17 @@ RecordedEvent::LoadEventFromStream(std::
     LOAD_EVENT_TYPE(SNAPSHOT, RecordedSnapshot);
     LOAD_EVENT_TYPE(SCALEDFONTCREATION, RecordedScaledFontCreation);
     LOAD_EVENT_TYPE(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction);
     LOAD_EVENT_TYPE(MASKSURFACE, RecordedMaskSurface);
     LOAD_EVENT_TYPE(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute);
     LOAD_EVENT_TYPE(FILTERNODESETINPUT, RecordedFilterNodeSetInput);
     LOAD_EVENT_TYPE(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget);
     LOAD_EVENT_TYPE(FONTDATA, RecordedFontData);
+    LOAD_EVENT_TYPE(FONTDESC, RecordedFontDescriptor);
     LOAD_EVENT_TYPE(PUSHLAYER, RecordedPushLayer);
     LOAD_EVENT_TYPE(POPLAYER, RecordedPopLayer);
   default:
     return nullptr;
   }
 }
 
 string
@@ -154,16 +156,18 @@ RecordedEvent::GetEventName(EventType aT
   case FILTERNODESETATTRIBUTE:
     return "SetAttribute";
   case FILTERNODESETINPUT:
     return "SetInput";
   case CREATESIMILARDRAWTARGET:
     return "CreateSimilarDrawTarget";
   case FONTDATA:
     return "FontData";
+  case FONTDESC:
+    return "FontDescriptor";
   case PUSHLAYER:
     return "PushLayer";
   case POPLAYER:
     return "PopLayer";
   default:
     return "Unknown";
   }
 }
@@ -1518,16 +1522,76 @@ RecordedFontData::RecordedFontData(istre
   : RecordedEvent(FONTDATA)
 {
   ReadElement(aStream, mFontDetails.fontDataKey);
   ReadElement(aStream, mFontDetails.size);
   mData = new uint8_t[mFontDetails.size];
   aStream.read((char*)mData, mFontDetails.size);
 }
 
+RecordedFontDescriptor::~RecordedFontDescriptor()
+{
+}
+
+void
+RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const
+{
+  MOZ_ASSERT(mType == FontType::GDI);
+
+  NativeFont nativeFont;
+  nativeFont.mType = (NativeFontType)mType;
+  nativeFont.mFont = (void*)&mData[0];
+
+  RefPtr<ScaledFont> font =
+    Factory::CreateScaledFontForNativeFont(nativeFont, mFontSize);
+
+#ifdef USE_CAIRO_SCALED_FONT
+  static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont();
+#endif
+
+  aTranslator->AddScaledFont(mRefPtr, font);
+}
+
+void
+RecordedFontDescriptor::RecordToStream(std::ostream &aStream) const
+{
+  MOZ_ASSERT(mHasDesc);
+  WriteElement(aStream, mType);
+  WriteElement(aStream, mFontSize);
+  WriteElement(aStream, mRefPtr);
+  WriteElement(aStream, (size_t)mData.size());
+  aStream.write((char*)&mData[0], mData.size());
+}
+
+void
+RecordedFontDescriptor::OutputSimpleEventInfo(stringstream &aStringStream) const
+{
+  aStringStream << "[" << mRefPtr << "] Font Descriptor";
+}
+
+void
+RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData, uint32_t aSize, Float aFontSize)
+{
+  mData.assign(aData, aData + aSize);
+  mFontSize = aFontSize;
+}
+
+RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream)
+  : RecordedEvent(FONTDATA)
+{
+  ReadElement(aStream, mType);
+  ReadElement(aStream, mFontSize);
+  ReadElement(aStream, mRefPtr);
+
+  size_t size;
+  ReadElement(aStream, size);
+  mData.resize(size);
+  aStream.read((char*)&mData[0], size);
+}
+
 void
 RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const
 {
   NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey);
   RefPtr<ScaledFont> scaledFont = fontResource->CreateScaledFont(mIndex, mGlyphSize);
   aTranslator->AddScaledFont(mRefPtr, scaledFont);
 }
 
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -187,16 +187,17 @@ public:
     MASKSURFACE,
     FILTERNODECREATION,
     FILTERNODEDESTRUCTION,
     DRAWFILTER,
     FILTERNODESETATTRIBUTE,
     FILTERNODESETINPUT,
     CREATESIMILARDRAWTARGET,
     FONTDATA,
+    FONTDESC,
     PUSHLAYER,
     POPLAYER,
   };
   static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1;
 
   virtual ~RecordedEvent() {}
 
   static std::string GetEventName(EventType aType);
@@ -1037,16 +1038,61 @@ private:
   uint8_t *mData;
   RecordedFontDetails mFontDetails;
 
   bool mGetFontFileDataSucceeded = false;
 
   MOZ_IMPLICIT RecordedFontData(std::istream &aStream);
 };
 
+class RecordedFontDescriptor : public RecordedEvent {
+public:
+
+  static void FontDescCb(const uint8_t *aData, uint32_t aSize,
+                         Float aFontSize, void* aBaton)
+  {
+    auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton);
+    recordedFontDesc->SetFontDescriptor(aData, aSize, aFontSize);
+  }
+
+  explicit RecordedFontDescriptor(ScaledFont* aScaledFont)
+    : RecordedEvent(FONTDESC)
+    , mType(aScaledFont->GetType())
+    , mRefPtr(aScaledFont)
+  {
+    mHasDesc = aScaledFont->GetFontDescriptor(FontDescCb, this);
+  }
+
+  ~RecordedFontDescriptor();
+
+  bool IsValid() const { return mHasDesc; }
+
+  virtual void PlayEvent(Translator *aTranslator) const;
+
+  virtual void RecordToStream(std::ostream &aStream) const;
+  virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
+
+  virtual std::string GetName() const { return "Font Desc"; }
+  virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
+
+private:
+  friend class RecordedEvent;
+
+  void SetFontDescriptor(const uint8_t* aData, uint32_t aSize, Float aFontSize);
+
+  bool mHasDesc;
+
+  FontType mType;
+  Float mFontSize;
+  std::vector<uint8_t> mData;
+  ReferencePtr mRefPtr;
+
+  MOZ_IMPLICIT RecordedFontDescriptor(std::istream &aStream);
+};
+
 class RecordedScaledFontCreation : public RecordedEvent {
 public:
 
   RecordedScaledFontCreation(ReferencePtr aRefPtr,
                              RecordedFontDetails aFontDetails)
     : RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr)
     , mFontDataKey(aFontDetails.fontDataKey)
     , mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index)
--- a/gfx/2d/ScaledFontWin.cpp
+++ b/gfx/2d/ScaledFontWin.cpp
@@ -70,16 +70,23 @@ ScaledFontWin::GetFontFileData(FontFileD
       return false;
     }
   }
 
   aDataCallback(fontData.get(), tableSize, index, mSize, aBaton);
   return true;
 }
 
+bool
+ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
+{
+  aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), mSize, aBaton);
+  return true;
+}
+
 #ifdef USE_SKIA
 SkTypeface* ScaledFontWin::GetSkTypeface()
 {
   if (!mTypeface) {
     mTypeface = SkCreateTypefaceFromLOGFONT(mLogFont);
   }
   return mTypeface;
 }
--- a/gfx/2d/ScaledFontWin.h
+++ b/gfx/2d/ScaledFontWin.h
@@ -16,16 +16,18 @@ class ScaledFontWin : public ScaledFontB
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin)
   ScaledFontWin(LOGFONT* aFont, Float aSize);
 
   virtual FontType GetType() const { return FontType::GDI; }
 
   bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
 
+  virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
+
 #ifdef USE_SKIA
   virtual SkTypeface* GetSkTypeface();
 #endif
 
 protected:
 #ifdef USE_CAIRO_SCALED_FONT
   cairo_font_face_t* GetCairoFontFace() override;
 #endif