Bug 1057488 - Part 3: Update OTS to 97d043dd8977751835ca8d33d773ae8416e456d5. r=jfkthame
authorFrédéric Wang <fred.wang@free.fr>
Sat, 23 Aug 2014 10:12:00 -0400
changeset 223055 96312bdb2fb49b5ff951b863944c8b6ba8840bde
parent 223054 a2a702cbbf55c796914404aa35660746e03fa145
child 223056 2bf8a805206e2bf6bf413fbce20c5d134a285bfa
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1057488
milestone34.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 1057488 - Part 3: Update OTS to 97d043dd8977751835ca8d33d773ae8416e456d5. r=jfkthame
gfx/ots/README.mozilla
gfx/ots/include/opentype-sanitiser.h
gfx/ots/ots-visibility.patch
gfx/ots/src/name.cc
gfx/ots/src/ots.cc
gfx/ots/src/ots.h
gfx/ots/src/woff2.cc
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxUserFontSet.h
--- a/gfx/ots/README.mozilla
+++ b/gfx/ots/README.mozilla
@@ -1,11 +1,11 @@
 This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
 
 Our reference repository is https://github.com/khaledhosny/ots/.
 
-Current revision: 2a1859a6629bdb6f2915b1d3041621dbd396a4f7
+Current revision: 97d043dd8977751835ca8d33d773ae8416e456d5
 
 Upstream files included: LICENSE, src/, include/
 
 Additional files: README.mozilla, src/moz.build
 
 Additional patch: ots-visibility.patch (bug 711079).
--- a/gfx/ots/include/opentype-sanitiser.h
+++ b/gfx/ots/include/opentype-sanitiser.h
@@ -194,77 +194,51 @@ class OTSStream {
   }
 
  protected:
   uint32_t chksum_;
   uint8_t chksum_buffer_[4];
   unsigned chksum_buffer_offset_;
 };
 
-// Signature of the function to be provided by the client in order to report errors.
-// The return type is a boolean so that it can be used within an expression,
-// but the actual value is ignored. (Suggested convention is to always return 'false'.)
 #ifdef __GCC__
 #define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3)))
 #else
 #define MSGFUNC_FMT_ATTR
 #endif
-typedef bool (*MessageFunc)(void *user_data, const char *format, ...)  MSGFUNC_FMT_ATTR;
 
 enum TableAction {
   TABLE_ACTION_DEFAULT,  // Use OTS's default action for that table
   TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
   TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
   TABLE_ACTION_DROP      // Drop the table
 };
 
-// Signature of the function to be provided by the client to decide what action
-// to do for a given table.
-//   tag: table tag as an integer in big-endian byte order, independent of platform endianness
-//   user_data: user defined data that are passed to SetTableActionCallback()
-typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data);
-
 class OTS_API OTSContext {
   public:
-    OTSContext()
-        : message_func(0),
-          message_user_data(0),
-          table_action_func(0),
-          table_action_user_data(0)
-        {}
-
+    OTSContext() {}
     ~OTSContext() {}
 
     // Process a given OpenType file and write out a sanitised version
     //   output: a pointer to an object implementing the OTSStream interface. The
     //     sanitisied output will be written to this. In the even of a failure,
     //     partial output may have been written.
     //   input: the OpenType file
     //   length: the size, in bytes, of |input|
     //   context: optional context that holds various OTS settings like user callbacks
     bool Process(OTSStream *output, const uint8_t *input, size_t length);
 
-    // Set a callback function that will be called when OTS is reporting an error.
-    void SetMessageCallback(MessageFunc func, void *user_data) {
-      message_func = func;
-      message_user_data = user_data;
-    }
+    // This function will be called when OTS is reporting an error.
+    virtual void Message(const char *format, ...) MSGFUNC_FMT_ATTR {}
 
-    // Set a callback function that will be called when OTS needs to decide what to
-    // do for a font table.
-    void SetTableActionCallback(TableActionFunc func, void *user_data) {
-      table_action_func = func;
-      table_action_user_data = user_data;
-    }
-
-  private:
-    MessageFunc      message_func;
-    void            *message_user_data;
-    TableActionFunc  table_action_func;
-    void            *table_action_user_data;
+    // This function will be called when OTS needs to decide what to do for a
+    // font table.
+    //   tag: table tag as an integer in big-endian byte order, independent of
+    //   platform endianness
+    virtual TableAction GetTableAction(uint32_t tag) { return ots::TABLE_ACTION_DEFAULT; }
 };
 
 // Force to disable debug output even when the library is compiled with
 // -DOTS_DEBUG.
 void DisableDebugOutput();
 
 // Enable WOFF2 support(experimental).
 void EnableWOFF2();
--- a/gfx/ots/ots-visibility.patch
+++ b/gfx/ots/ots-visibility.patch
@@ -32,27 +32,27 @@ diff --git a/gfx/ots/include/opentype-sa
  #if defined(_WIN32)
  #include <stdlib.h>
  typedef signed char int8_t;
  typedef unsigned char uint8_t;
  typedef short int16_t;
  typedef unsigned short uint16_t;
  typedef int int32_t;
  typedef unsigned int uint32_t;
-@@ -197,17 +217,17 @@ enum TableAction {
- };
+@@ -187,17 +187,17 @@ class OTSStream {
  
- // Signature of the function to be provided by the client to decide what action
- // to do for a given table.
- //   tag: table tag as an integer in big-endian byte order, independent of platform endianness
- //   user_data: user defined data that are passed to SetTableActionCallback()
- typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data);
+ enum TableAction {
+   TABLE_ACTION_DEFAULT,  // Use OTS's default action for that table
+   TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
+   TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
+   TABLE_ACTION_DROP      // Drop the table
+ };
  
 -class OTSContext {
 +class OTS_API OTSContext {
    public:
-     OTSContext()
-         : message_func(0),
-           message_user_data(0),
-           table_action_func(0),
-           table_action_user_data(0)
-         {}
+     OTSContext() {}
+     ~OTSContext() {}
  
+     // Process a given OpenType file and write out a sanitised version
+     //   output: a pointer to an object implementing the OTSStream interface. The
+     //     sanitisied output will be written to this. In the even of a failure,
+     //     partial output may have been written.
--- a/gfx/ots/src/name.cc
+++ b/gfx/ots/src/name.cc
@@ -85,17 +85,17 @@ bool ots_name_parse(OpenTypeFile* file, 
   bool sort_required = false;
 
   // Read all the names, discarding any with invalid IDs,
   // and any where the offset/length would be outside the table.
   // A stricter alternative would be to reject the font if there
   // are invalid name records, but it's not clear that is necessary.
   for (unsigned i = 0; i < count; ++i) {
     NameRecord rec;
-    uint16_t name_length, name_offset;
+    uint16_t name_length, name_offset = 0;
     if (!table.ReadU16(&rec.platform_id) ||
         !table.ReadU16(&rec.encoding_id) ||
         !table.ReadU16(&rec.language_id) ||
         !table.ReadU16(&rec.name_id) ||
         !table.ReadU16(&name_length) ||
         !table.ReadU16(&name_offset)) {
       return OTS_FAILURE_MSG("Failed to read name entry %d", i);
     }
--- a/gfx/ots/src/ots.cc
+++ b/gfx/ots/src/ots.cc
@@ -415,19 +415,17 @@ bool ProcessWOFF2(ots::OpenTypeFile *hea
   }
   return ProcessTTF(header, output, &decompressed_buffer[0], decompressed_size);
 }
 #endif
 
 ots::TableAction GetTableAction(ots::OpenTypeFile *header, uint32_t tag) {
   ots::TableAction action = ots::TABLE_ACTION_DEFAULT;
 
-  if (header->table_action_func != NULL) {
-    action = header->table_action_func(htonl(tag), header->table_action_user_data);
-  }
+  action = header->context->GetTableAction(htonl(tag));
 
   if (action == ots::TABLE_ACTION_DEFAULT) {
     action = ots::TABLE_ACTION_DROP;
 
     for (unsigned i = 0; ; ++i) {
       if (table_parsers[i].parse == NULL) break;
 
       if (Tag(table_parsers[i].tag) == tag) {
@@ -802,20 +800,17 @@ void EnableWOFF2() {
   g_enable_woff2 = true;
 }
 
 bool OTSContext::Process(OTSStream *output,
                          const uint8_t *data,
                          size_t length) {
   OpenTypeFile header;
 
-  header.message_func = message_func;
-  header.message_user_data = message_user_data;
-  header.table_action_func = table_action_func;
-  header.table_action_user_data = table_action_user_data;
+  header.context = this;
 
   if (length < 4) {
     return OTS_FAILURE_MSG_(&header, "file less than 4 bytes");
   }
 
   bool result;
   if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
     result = ProcessWOFF(&header, output, data, length);
--- a/gfx/ots/src/ots.h
+++ b/gfx/ots/src/ots.h
@@ -47,25 +47,21 @@ void Warning(const char *f, int l, const
 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
 // message-less OTS_FAILURE(), so that the current parser will return 'false' as
 // its result (indicating a failure).
 // If a message_func pointer has been provided, this will be called before returning
 // the 'false' status.
 
 // Generate a simple message
 #define OTS_FAILURE_MSG_(otf_,...) \
-  ((otf_)->message_func && \
-    (*(otf_)->message_func)((otf_)->message_user_data, __VA_ARGS__) && \
-    false)
+  ((otf_)->context->Message(__VA_ARGS__), false)
 
 // Generate a message with an associated table tag
 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
-  ((otf_)->message_func && \
-    (*(otf_)->message_func)((otf_)->message_user_data, "%4.4s: %s", tag_, msg_) && \
-    false)
+  ((otf_)->context->Message("%4.4s: %s", tag_, msg_), false)
 
 // Convenience macro for use in files that only handle a single table tag,
 // defined as TABLE_NAME at the top of the file; the 'file' variable is
 // expected to be the current OpenTypeFile pointer.
 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
 
 // Define OTS_NO_TRANSCODE_HINTS (i.e., g++ -DOTS_NO_TRANSCODE_HINTS) if you
 // want to omit TrueType hinting instructions and variables in glyf, fpgm, prep,
@@ -245,21 +241,17 @@ struct OpenTypeFile {
   }
 
   uint32_t version;
   uint16_t num_tables;
   uint16_t search_range;
   uint16_t entry_selector;
   uint16_t range_shift;
 
-  MessageFunc  message_func;
-  void        *message_user_data;
-
-  TableActionFunc  table_action_func;
-  void            *table_action_user_data;
+  OTSContext *context;
 
 #define F(name, capname) OpenType##capname *name;
 FOR_EACH_TABLE_TYPE
 #undef F
 };
 
 #define F(name, capname) \
 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \
--- a/gfx/ots/src/woff2.cc
+++ b/gfx/ots/src/woff2.cc
@@ -865,17 +865,17 @@ size_t ComputeWOFF2FinalSize(const uint8
 }
 
 bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
                        const uint8_t* data, size_t length) {
   static const uint32_t kWoff2Signature = 0x774f4632;  // "wOF2"
   ots::Buffer file(data, length);
 
   uint32_t signature;
-  uint32_t flavor;
+  uint32_t flavor = 0;
   if (!file.ReadU32(&signature) || signature != kWoff2Signature ||
       !file.ReadU32(&flavor)) {
     return OTS_FAILURE();
   }
 
   if (!IsValidVersionTag(ntohl(flavor))) {
     return OTS_FAILURE();
   }
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -167,77 +167,69 @@ gfxProxyFontEntry::Matches(const nsTArra
 
 gfxFont*
 gfxProxyFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
 {
     // cannot create an actual font for a proxy entry
     return nullptr;
 }
 
-static ots::TableAction
-OTSTableAction(uint32_t aTag, void *aUserData)
-{
-    // preserve Graphite, color glyph and SVG tables
-    if (aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') ||
-        aTag == TRUETYPE_TAG('S', 'i', 'l', 'l') ||
-        aTag == TRUETYPE_TAG('G', 'l', 'o', 'c') ||
-        aTag == TRUETYPE_TAG('G', 'l', 'a', 't') ||
-        aTag == TRUETYPE_TAG('F', 'e', 'a', 't') ||
-        aTag == TRUETYPE_TAG('S', 'V', 'G', ' ') ||
-        aTag == TRUETYPE_TAG('C', 'O', 'L', 'R') ||
-        aTag == TRUETYPE_TAG('C', 'P', 'A', 'L')) {
-        return ots::TABLE_ACTION_PASSTHRU;
+class gfxOTSContext : public ots::OTSContext {
+public:
+    gfxOTSContext(gfxMixedFontFamily *aFamily, gfxProxyFontEntry  *aProxy)
+        : mFamily(aFamily), mProxy(aProxy) {}
+
+    virtual ots::TableAction GetTableAction(uint32_t aTag) MOZ_OVERRIDE {
+        // preserve Graphite, color glyph and SVG tables
+        if (aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') ||
+            aTag == TRUETYPE_TAG('S', 'i', 'l', 'l') ||
+            aTag == TRUETYPE_TAG('G', 'l', 'o', 'c') ||
+            aTag == TRUETYPE_TAG('G', 'l', 'a', 't') ||
+            aTag == TRUETYPE_TAG('F', 'e', 'a', 't') ||
+            aTag == TRUETYPE_TAG('S', 'V', 'G', ' ') ||
+            aTag == TRUETYPE_TAG('C', 'O', 'L', 'R') ||
+            aTag == TRUETYPE_TAG('C', 'P', 'A', 'L')) {
+            return ots::TABLE_ACTION_PASSTHRU;
+        }
+        return ots::TABLE_ACTION_DEFAULT;
     }
-    return ots::TABLE_ACTION_DEFAULT;
-}
+
+    virtual void Message(const char *format, ...) MSGFUNC_FMT_ATTR MOZ_OVERRIDE {
+        va_list va;
+        va_start(va, format);
 
-struct OTSCallbackUserData {
+        // buf should be more than adequate for any message OTS generates,
+        // so we don't worry about checking the result of vsnprintf()
+        char buf[512];
+        (void)vsnprintf(buf, sizeof(buf), format, va);
+
+        va_end(va);
+
+        mProxy->mFontSet->LogMessage(mFamily, mProxy, buf);
+    }
+
+private:
     gfxMixedFontFamily *mFamily;
     gfxProxyFontEntry  *mProxy;
 };
 
-/* static */ bool
-gfxProxyFontEntry::OTSMessage(void *aUserData, const char *format, ...)
-{
-    va_list va;
-    va_start(va, format);
-
-    // buf should be more than adequate for any message OTS generates,
-    // so we don't worry about checking the result of vsnprintf()
-    char buf[512];
-    (void)vsnprintf(buf, sizeof(buf), format, va);
-
-    va_end(va);
-
-    OTSCallbackUserData *d = static_cast<OTSCallbackUserData*>(aUserData);
-    d->mProxy->mFontSet->LogMessage(d->mFamily, d->mProxy, buf);
-
-    return false;
-}
-
 // 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*
 gfxProxyFontEntry::SanitizeOpenTypeData(gfxMixedFontFamily *aFamily,
                                         const uint8_t* aData,
                                         uint32_t       aLength,
                                         uint32_t&      aSaneLength,
                                         bool           aIsCompressed)
 {
     // limit output/expansion to 256MB
     ExpandingMemoryStream output(aIsCompressed ? aLength * 2 : aLength,
                                  1024 * 1024 * 256);
 
-    OTSCallbackUserData userData;
-    userData.mFamily = aFamily;
-    userData.mProxy = this;
-
-    ots::OTSContext otsContext;
-    otsContext.SetTableActionCallback(&OTSTableAction, nullptr);
-    otsContext.SetMessageCallback(&OTSMessage, &userData);
+    gfxOTSContext otsContext(aFamily, this);
 
     if (otsContext.Process(&output, aData, aLength)) {
         aSaneLength = output.Tell();
         return static_cast<uint8_t*>(output.forget());
     } else {
         aSaneLength = 0;
         return nullptr;
     }
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -151,19 +151,21 @@ public:
 
     // Remove all font entries from the family
     void DetachFontEntries() {
         mAvailableFonts.Clear();
     }
 };
 
 class gfxProxyFontEntry;
+class gfxOTSContext;
 
 class gfxUserFontSet {
     friend class gfxProxyFontEntry;
+    friend class gfxOTSContext;
 
 public:
 
     NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet)
 
     gfxUserFontSet();
 
     enum {
@@ -512,16 +514,17 @@ protected:
 };
 
 // acts a placeholder until the real font is downloaded
 
 class gfxProxyFontEntry : public gfxFontEntry {
     friend class gfxUserFontSet;
     friend class nsUserFontSet;
     friend class nsFontFaceLoader;
+    friend class gfxOTSContext;
 
 public:
     enum LoadStatus {
         STATUS_LOADING = 0,
         STATUS_LOADED,
         STATUS_FORMAT_NOT_SUPPORTED,
         STATUS_ERROR,
         STATUS_END_OF_LIST
@@ -571,18 +574,16 @@ protected:
 
     // store metadata and src details for current src into aFontEntry
     void StoreUserFontData(gfxFontEntry*      aFontEntry,
                            bool               aPrivate,
                            const nsAString&   aOriginalName,
                            FallibleTArray<uint8_t>* aMetadata,
                            uint32_t           aMetaOrigLen);
 
-    static bool OTSMessage(void *aUserData, const char *format, ...);
-
     // note that code depends on the ordering of these values!
     enum LoadingState {
         NOT_LOADING = 0,     // not started to load any font resources yet
         LOADING_STARTED,     // loading has started; hide fallback font
         LOADING_ALMOST_DONE, // timeout happened but we're nearly done,
                              // so keep hiding fallback font
         LOADING_SLOWLY,      // timeout happened and we're not nearly done,
                              // so use the fallback font