Bug 1639563 - factor out gfxOTSContext into reusable header file. r=jfkthame
☠☠ backed out by 3d2f5e8bb67e ☠ ☠
authorLee Salzman <lsalzman@mozilla.com>
Thu, 21 May 2020 21:12:37 +0000
changeset 531550 43abf0a9602a925e6a96b6510e8cb6197c32f5a2
parent 531549 0261162195643a968c73bdeffa0d8db3bfd38aec
child 531551 b2c8de06588675f9afe0d580e118a6f8591dc8c2
push id37440
push userabutkovits@mozilla.com
push dateFri, 22 May 2020 09:43:16 +0000
treeherdermozilla-central@fbf71e4d2e21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1639563
milestone78.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 1639563 - factor out gfxOTSContext into reusable header file. r=jfkthame Differential Revision: https://phabricator.services.mozilla.com/D76358
gfx/thebes/gfxOTSUtils.h
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxUserFontSet.h
gfx/thebes/moz.build
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/gfxOTSUtils.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_OTS_UTILS_H
+#define GFX_OTS_UTILS_H
+
+#include "gfxFontUtils.h"
+
+#include "opentype-sanitiser.h"
+
+struct gfxOTSMozAlloc {
+  void* Grow(void* aPtr, size_t aLength) { return moz_xrealloc(aPtr, aLength); }
+  void* ShrinkToFit(void* aPtr, size_t aLength) {
+    return moz_xrealloc(aPtr, aLength);
+  }
+  void Free(void* aPtr) { free(aPtr); }
+};
+
+// Based on ots::ExpandingMemoryStream from ots-memory-stream.h,
+// adapted to use Mozilla allocators and to allow the final
+// memory buffer to be adopted by the client.
+template <typename AllocT = gfxOTSMozAlloc>
+class gfxOTSExpandingMemoryStream : public ots::OTSStream {
+ public:
+  // limit output/expansion to 256MB by default
+  enum { DEFAULT_LIMIT = 256 * 1024 * 1024 };
+
+  gfxOTSExpandingMemoryStream(size_t initial, size_t limit = DEFAULT_LIMIT)
+      : mLength(initial), mLimit(limit), mOff(0) {
+    mPtr = mAlloc.Grow(nullptr, mLength);
+  }
+
+  ~gfxOTSExpandingMemoryStream() { mAlloc.Free(mPtr); }
+
+  // Return the buffer, resized to fit its contents (as it may have been
+  // over-allocated during growth), and give up ownership of it so the
+  // caller becomes responsible to call free() when finished with it.
+  auto forget() {
+    auto p = mAlloc.ShrinkToFit(mPtr, mOff);
+    mPtr = nullptr;
+    return p;
+  }
+
+  bool WriteRaw(const void* data, size_t length) override {
+    if ((mOff + length > mLength) ||
+        (mLength > std::numeric_limits<size_t>::max() - mOff)) {
+      if (mLength == mLimit) {
+        return false;
+      }
+      size_t newLength = (mLength + 1) * 2;
+      if (newLength < mLength) {
+        return false;
+      }
+      if (newLength > mLimit) {
+        newLength = mLimit;
+      }
+      mPtr = mAlloc.Grow(mPtr, newLength);
+      mLength = newLength;
+      return WriteRaw(data, length);
+    }
+    std::memcpy(static_cast<char*>(mPtr) + mOff, data, length);
+    mOff += length;
+    return true;
+  }
+
+  bool Seek(off_t position) override {
+    if (position < 0) {
+      return false;
+    }
+    if (static_cast<size_t>(position) > mLength) {
+      return false;
+    }
+    mOff = position;
+    return true;
+  }
+
+  off_t Tell() const override { return mOff; }
+
+ private:
+  AllocT mAlloc;
+  void* mPtr;
+  size_t mLength;
+  const size_t mLimit;
+  off_t mOff;
+};
+
+class MOZ_STACK_CLASS gfxOTSContext : public ots::OTSContext {
+ public:
+  gfxOTSContext() {
+    using namespace mozilla;
+
+    // Whether to apply OTS validation to OpenType Layout tables
+    mCheckOTLTables = StaticPrefs::gfx_downloadable_fonts_otl_validation();
+    // Whether to preserve Variation tables in downloaded fonts
+    mCheckVariationTables =
+        StaticPrefs::gfx_downloadable_fonts_validate_variation_tables();
+    // Whether to preserve color bitmap glyphs
+    mKeepColorBitmaps =
+        StaticPrefs::gfx_downloadable_fonts_keep_color_bitmaps();
+  }
+
+  virtual ots::TableAction GetTableAction(uint32_t aTag) override {
+    // Preserve Graphite, color glyph and SVG tables,
+    // and possibly OTL and Variation tables (depending on prefs)
+    if ((!mCheckOTLTables && (aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
+                              aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
+                              aTag == TRUETYPE_TAG('G', 'S', 'U', 'B'))) ||
+        (!mCheckVariationTables &&
+         (aTag == TRUETYPE_TAG('a', 'v', 'a', 'r') ||
+          aTag == TRUETYPE_TAG('c', 'v', 'a', 'r') ||
+          aTag == TRUETYPE_TAG('f', 'v', 'a', 'r') ||
+          aTag == TRUETYPE_TAG('g', 'v', 'a', 'r') ||
+          aTag == TRUETYPE_TAG('H', 'V', 'A', 'R') ||
+          aTag == TRUETYPE_TAG('M', 'V', 'A', 'R') ||
+          aTag == TRUETYPE_TAG('S', 'T', 'A', 'T') ||
+          aTag == TRUETYPE_TAG('V', 'V', 'A', 'R'))) ||
+        aTag == TRUETYPE_TAG('S', 'V', 'G', ' ') ||
+        aTag == TRUETYPE_TAG('C', 'O', 'L', 'R') ||
+        aTag == TRUETYPE_TAG('C', 'P', 'A', 'L') ||
+        (mKeepColorBitmaps && (aTag == TRUETYPE_TAG('C', 'B', 'D', 'T') ||
+                               aTag == TRUETYPE_TAG('C', 'B', 'L', 'C'))) ||
+        false) {
+      return ots::TABLE_ACTION_PASSTHRU;
+    }
+    return ots::TABLE_ACTION_DEFAULT;
+  }
+
+  static size_t GuessSanitizedFontSize(size_t aLength,
+                                       gfxUserFontType aFontType) {
+    switch (aFontType) {
+      case GFX_USERFONT_UNKNOWN:
+        return 0;
+      case GFX_USERFONT_WOFF:
+        return aLength * 2;
+      case GFX_USERFONT_WOFF2:
+        return aLength * 3;
+      default:
+        return aLength;
+    }
+  }
+
+  static size_t GuessSanitizedFontSize(const uint8_t* aData, size_t aLength) {
+    gfxUserFontType fontType =
+        gfxFontUtils::DetermineFontDataType(aData, aLength);
+    return GuessSanitizedFontSize(aLength, fontType);
+  }
+
+ private:
+  bool mCheckOTLTables;
+  bool mCheckVariationTables;
+  bool mKeepColorBitmaps;
+};
+
+#endif /* GFX_OTS_UTILS_H */
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -12,97 +12,32 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs_gfx.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/gfx/2D.h"
 #include "gfxPlatformFontList.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/PostTraversalTask.h"
-
-#include "opentype-sanitiser.h"
-#include "ots-memory-stream.h"
+#include "gfxOTSUtils.h"
 
 using namespace mozilla;
 
 mozilla::LogModule* gfxUserFontSet::GetUserFontsLog() {
   static LazyLogModule sLog("userfonts");
   return sLog;
 }
 
 #define LOG(args) \
   MOZ_LOG(gfxUserFontSet::GetUserFontsLog(), mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() \
   MOZ_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), mozilla::LogLevel::Debug)
 
 static uint64_t sFontSetGeneration = 0;
 
-// Based on ots::ExpandingMemoryStream from ots-memory-stream.h,
-// adapted to use Mozilla allocators and to allow the final
-// memory buffer to be adopted by the client.
-class ExpandingMemoryStream : public ots::OTSStream {
- public:
-  ExpandingMemoryStream(size_t initial, size_t limit)
-      : mLength(initial), mLimit(limit), mOff(0) {
-    mPtr = moz_xmalloc(mLength);
-  }
-
-  ~ExpandingMemoryStream() { free(mPtr); }
-
-  // Return the buffer, resized to fit its contents (as it may have been
-  // over-allocated during growth), and give up ownership of it so the
-  // caller becomes responsible to call free() when finished with it.
-  void* forget() {
-    void* p = moz_xrealloc(mPtr, mOff);
-    mPtr = nullptr;
-    return p;
-  }
-
-  bool WriteRaw(const void* data, size_t length) override {
-    if ((mOff + length > mLength) ||
-        (mLength > std::numeric_limits<size_t>::max() - mOff)) {
-      if (mLength == mLimit) {
-        return false;
-      }
-      size_t newLength = (mLength + 1) * 2;
-      if (newLength < mLength) {
-        return false;
-      }
-      if (newLength > mLimit) {
-        newLength = mLimit;
-      }
-      mPtr = moz_xrealloc(mPtr, newLength);
-      mLength = newLength;
-      return WriteRaw(data, length);
-    }
-    std::memcpy(static_cast<char*>(mPtr) + mOff, data, length);
-    mOff += length;
-    return true;
-  }
-
-  bool Seek(off_t position) override {
-    if (position < 0) {
-      return false;
-    }
-    if (static_cast<size_t>(position) > mLength) {
-      return false;
-    }
-    mOff = position;
-    return true;
-  }
-
-  off_t Tell() const override { return mOff; }
-
- private:
-  void* mPtr;
-  size_t mLength;
-  const size_t mLimit;
-  off_t mOff;
-};
-
 gfxUserFontEntry::gfxUserFontEntry(
     gfxUserFontSet* aFontSet, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
     WeightRange aWeight, StretchRange aStretch, SlantStyleRange aStyle,
     const nsTArray<gfxFontFeature>& aFeatureSettings,
     const nsTArray<gfxFontVariation>& aVariationSettings,
     uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
     StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags)
     : gfxFontEntry(NS_LITERAL_CSTRING("userfont")),
@@ -175,59 +110,22 @@ gfxFont* gfxUserFontEntry::CreateFontIns
   MOZ_ASSERT_UNREACHABLE(
       "should only be creating a gfxFont"
       " with an actual platform font entry");
 
   // userfont entry is a container, can't create font from the container
   return nullptr;
 }
 
-class MOZ_STACK_CLASS gfxOTSContext : public ots::OTSContext {
+class MOZ_STACK_CLASS gfxOTSMessageContext : public gfxOTSContext {
  public:
-  gfxOTSContext() {
-    // Whether to apply OTS validation to OpenType Layout tables
-    mCheckOTLTables = StaticPrefs::gfx_downloadable_fonts_otl_validation();
-    // Whether to preserve Variation tables in downloaded fonts
-    mCheckVariationTables =
-        StaticPrefs::gfx_downloadable_fonts_validate_variation_tables();
-    // Whether to preserve color bitmap glyphs
-    mKeepColorBitmaps =
-        StaticPrefs::gfx_downloadable_fonts_keep_color_bitmaps();
-  }
-
-  virtual ~gfxOTSContext() {
+  virtual ~gfxOTSMessageContext() {
     MOZ_ASSERT(mMessages.IsEmpty(), "should have called TakeMessages");
   }
 
-  virtual ots::TableAction GetTableAction(uint32_t aTag) override {
-    // Preserve Graphite, color glyph and SVG tables,
-    // and possibly OTL and Variation tables (depending on prefs)
-    if ((!mCheckOTLTables && (aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
-                              aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
-                              aTag == TRUETYPE_TAG('G', 'S', 'U', 'B'))) ||
-        (!mCheckVariationTables &&
-         (aTag == TRUETYPE_TAG('a', 'v', 'a', 'r') ||
-          aTag == TRUETYPE_TAG('c', 'v', 'a', 'r') ||
-          aTag == TRUETYPE_TAG('f', 'v', 'a', 'r') ||
-          aTag == TRUETYPE_TAG('g', 'v', 'a', 'r') ||
-          aTag == TRUETYPE_TAG('H', 'V', 'A', 'R') ||
-          aTag == TRUETYPE_TAG('M', 'V', 'A', 'R') ||
-          aTag == TRUETYPE_TAG('S', 'T', 'A', 'T') ||
-          aTag == TRUETYPE_TAG('V', 'V', 'A', 'R'))) ||
-        aTag == TRUETYPE_TAG('S', 'V', 'G', ' ') ||
-        aTag == TRUETYPE_TAG('C', 'O', 'L', 'R') ||
-        aTag == TRUETYPE_TAG('C', 'P', 'A', 'L') ||
-        (mKeepColorBitmaps && (aTag == TRUETYPE_TAG('C', 'B', 'D', 'T') ||
-                               aTag == TRUETYPE_TAG('C', 'B', 'L', 'C'))) ||
-        false) {
-      return ots::TABLE_ACTION_PASSTHRU;
-    }
-    return ots::TABLE_ACTION_DEFAULT;
-  }
-
   virtual void Message(int level, const char* format,
                        ...) MSGFUNC_FMT_ATTR override {
     va_list va;
     va_start(va, format);
 
     nsCString msg;
     msg.AppendPrintf(format, va);
 
@@ -254,45 +152,35 @@ class MOZ_STACK_CLASS gfxOTSContext : pu
 
   nsTArray<gfxUserFontEntry::OTSMessage>&& TakeMessages() {
     return std::move(mMessages);
   }
 
  private:
   nsTHashtable<nsCStringHashKey> mWarningsIssued;
   nsTArray<gfxUserFontEntry::OTSMessage> mMessages;
-  bool mCheckOTLTables;
-  bool mCheckVariationTables;
-  bool mKeepColorBitmaps;
 };
 
 // Call the OTS library to sanitize an sfnt before attempting to use it.
 // Returns a newly-allocated block, or nullptr in case of fatal errors.
 const uint8_t* gfxUserFontEntry::SanitizeOpenTypeData(
     const uint8_t* aData, uint32_t aLength, uint32_t& aSaneLength,
     gfxUserFontType& aFontType, nsTArray<OTSMessage>& aMessages) {
   aFontType = gfxFontUtils::DetermineFontDataType(aData, aLength);
   Telemetry::Accumulate(Telemetry::WEBFONT_FONTTYPE, uint32_t(aFontType));
 
-  if (aFontType == GFX_USERFONT_UNKNOWN) {
+  size_t lengthHint = gfxOTSContext::GuessSanitizedFontSize(aLength, aFontType);
+  if (!lengthHint) {
     aSaneLength = 0;
     return nullptr;
   }
 
-  uint32_t lengthHint = aLength;
-  if (aFontType == GFX_USERFONT_WOFF) {
-    lengthHint *= 2;
-  } else if (aFontType == GFX_USERFONT_WOFF2) {
-    lengthHint *= 3;
-  }
+  gfxOTSExpandingMemoryStream output(lengthHint);
 
-  // limit output/expansion to 256MB
-  ExpandingMemoryStream output(lengthHint, 1024 * 1024 * 256);
-
-  gfxOTSContext otsContext;
+  gfxOTSMessageContext otsContext;
   if (!otsContext.Process(&output, aData, aLength, aMessages)) {
     // Failed to decode/sanitize the font, so discard it.
     aSaneLength = 0;
     return nullptr;
   }
 
   aSaneLength = output.Tell();
   return static_cast<const uint8_t*>(output.forget());
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -176,21 +176,21 @@ class gfxUserFontFamily : public gfxFont
     mAvailableFonts.RemoveElement(aFontEntry);
   }
 
   // Remove all font entries from the family
   void DetachFontEntries() { mAvailableFonts.Clear(); }
 };
 
 class gfxUserFontEntry;
-class gfxOTSContext;
+class gfxOTSMessageContext;
 
 class gfxUserFontSet {
   friend class gfxUserFontEntry;
-  friend class gfxOTSContext;
+  friend class gfxOTSMessageContext;
 
  public:
   typedef mozilla::FontStretch FontStretch;
   typedef mozilla::StretchRange StretchRange;
   typedef mozilla::FontSlantStyle FontSlantStyle;
   typedef mozilla::SlantStyleRange SlantStyleRange;
   typedef mozilla::FontWeight FontWeight;
   typedef mozilla::WeightRange WeightRange;
@@ -526,17 +526,17 @@ class gfxUserFontSet {
 
 // acts a placeholder until the real font is downloaded
 
 class gfxUserFontEntry : public gfxFontEntry {
   friend class mozilla::PostTraversalTask;
   friend class gfxUserFontSet;
   friend class nsUserFontSet;
   friend class nsFontFaceLoader;
-  friend class gfxOTSContext;
+  friend class gfxOTSMessageContext;
 
  public:
   enum UserFontLoadState {
     STATUS_NOT_LOADED = 0,
     STATUS_LOAD_PENDING,
     STATUS_LOADING,
     STATUS_LOADED,
     STATUS_FAILED
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -39,16 +39,17 @@ EXPORTS += [
     'gfxFontSrcURI.h',
     'gfxFontUtils.h',
     'gfxFontVariations.h',
     'gfxGradientCache.h',
     'gfxImageSurface.h',
     'gfxLineSegment.h',
     'gfxMathTable.h',
     'gfxMatrix.h',
+    'gfxOTSUtils.h',
     'gfxPattern.h',
     'gfxPlatform.h',
     'gfxPlatformFontList.h',
     'gfxPoint.h',
     'gfxQuad.h',
     'gfxQuaternion.h',
     'gfxRect.h',
     'gfxSharedImageSurface.h',