bug 631479 (part 3) - allow graphite tables to be passed through OTS for downloadable fonts. r=jdaggett
authorJonathan Kew <jfkthame@gmail.com>
Fri, 09 Dec 2011 22:32:29 +0000
changeset 82404 f51fc55403ba
parent 82403 c25e81047a9e
child 82405 afb24aa8ed2e
push id4016
push userjkew@mozilla.com
push dateFri, 09 Dec 2011 22:35:34 +0000
treeherdermozilla-inbound@17787cebcac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett
bugs631479
milestone11.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 631479 (part 3) - allow graphite tables to be passed through OTS for downloadable fonts. r=jdaggett
gfx/ots/include/opentype-sanitiser.h
gfx/ots/src/Makefile.in
gfx/ots/src/graphite.cc
gfx/ots/src/graphite.h
gfx/ots/src/ots.cc
gfx/ots/src/ots.h
gfx/thebes/gfxUserFontSet.cpp
--- a/gfx/ots/include/opentype-sanitiser.h
+++ b/gfx/ots/include/opentype-sanitiser.h
@@ -176,18 +176,20 @@ class OTSStream {
 
 // -----------------------------------------------------------------------------
 // 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|
+//   preserve_graphite_tables: whether to preserve Graphite Layout tables
 // -----------------------------------------------------------------------------
-bool Process(OTSStream *output, const uint8_t *input, size_t length);
+bool Process(OTSStream *output, const uint8_t *input, size_t length,
+             bool preserve_graphite_tables = false);
 
 // Force to disable debug output even when the library is compiled with
 // -DOTS_DEBUG.
 void DisableDebugOutput();
 
 }  // namespace ots
 
 #endif  // OPENTYPE_SANITISER_H_
--- a/gfx/ots/src/Makefile.in
+++ b/gfx/ots/src/Makefile.in
@@ -64,16 +64,17 @@ CPPSRCS	= \
   prep.cc \
   vdmx.cc \
   vhea.cc \
   vmtx.cc \
   vorg.cc \
   gdef.cc \
   gpos.cc \
   gsub.cc \
+  graphite.cc \
   $(NULL)
 
 EXPORTS = \
   ../include/opentype-sanitiser.h \
   ../include/ots-memory-stream.h  \
   $(NULL)
 
 LOCAL_INCLUDES  += -I$(srcdir) 
new file mode 100644
--- /dev/null
+++ b/gfx/ots/src/graphite.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "graphite.h"
+
+// Support for preserving (NOT sanitizing) the Graphite tables
+
+namespace ots {
+
+// 'Silf'
+bool ots_silf_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  Buffer table(data, length);
+
+  OpenTypeSILF *silf = new OpenTypeSILF;
+  file->silf = silf;
+
+  if (!table.Skip(length)) {
+    return OTS_FAILURE();
+  }
+
+  silf->data = data;
+  silf->length = length;
+  return true;
+}
+
+bool ots_silf_should_serialise(OpenTypeFile *file) {
+  return file->preserve_graphite && file->silf;
+}
+
+bool ots_silf_serialise(OTSStream *out, OpenTypeFile *file) {
+  const OpenTypeSILF *silf = file->silf;
+
+  if (!out->Write(silf->data, silf->length)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+void ots_silf_free(OpenTypeFile *file) {
+  delete file->silf;
+}
+
+// 'Sill'
+bool ots_sill_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  Buffer table(data, length);
+
+  OpenTypeSILL *sill = new OpenTypeSILL;
+  file->sill = sill;
+
+  if (!table.Skip(length)) {
+    return OTS_FAILURE();
+  }
+
+  sill->data = data;
+  sill->length = length;
+  return true;
+}
+
+bool ots_sill_should_serialise(OpenTypeFile *file) {
+  return file->preserve_graphite && file->sill;
+}
+
+bool ots_sill_serialise(OTSStream *out, OpenTypeFile *file) {
+  const OpenTypeSILL *sill = file->sill;
+
+  if (!out->Write(sill->data, sill->length)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+void ots_sill_free(OpenTypeFile *file) {
+  delete file->sill;
+}
+
+// 'Gloc'
+bool ots_gloc_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  Buffer table(data, length);
+
+  OpenTypeGLOC *gloc = new OpenTypeGLOC;
+  file->gloc = gloc;
+
+  if (!table.Skip(length)) {
+    return OTS_FAILURE();
+  }
+
+  gloc->data = data;
+  gloc->length = length;
+  return true;
+}
+
+bool ots_gloc_should_serialise(OpenTypeFile *file) {
+  return file->preserve_graphite && file->gloc;
+}
+
+bool ots_gloc_serialise(OTSStream *out, OpenTypeFile *file) {
+  const OpenTypeGLOC *gloc = file->gloc;
+
+  if (!out->Write(gloc->data, gloc->length)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+void ots_gloc_free(OpenTypeFile *file) {
+  delete file->gloc;
+}
+
+// 'Glat'
+bool ots_glat_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  Buffer table(data, length);
+
+  OpenTypeGLAT *glat = new OpenTypeGLAT;
+  file->glat = glat;
+
+  if (!table.Skip(length)) {
+    return OTS_FAILURE();
+  }
+
+  glat->data = data;
+  glat->length = length;
+  return true;
+}
+
+bool ots_glat_should_serialise(OpenTypeFile *file) {
+  return file->preserve_graphite && file->glat;
+}
+
+bool ots_glat_serialise(OTSStream *out, OpenTypeFile *file) {
+  const OpenTypeGLAT *glat = file->glat;
+
+  if (!out->Write(glat->data, glat->length)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+void ots_glat_free(OpenTypeFile *file) {
+  delete file->glat;
+}
+
+// 'Feat'
+bool ots_feat_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  Buffer table(data, length);
+
+  OpenTypeFEAT *feat = new OpenTypeFEAT;
+  file->feat = feat;
+
+  if (!table.Skip(length)) {
+    return OTS_FAILURE();
+  }
+
+  feat->data = data;
+  feat->length = length;
+  return true;
+}
+
+bool ots_feat_should_serialise(OpenTypeFile *file) {
+  return file->preserve_graphite && file->feat;
+}
+
+bool ots_feat_serialise(OTSStream *out, OpenTypeFile *file) {
+  const OpenTypeFEAT *feat = file->feat;
+
+  if (!out->Write(feat->data, feat->length)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+void ots_feat_free(OpenTypeFile *file) {
+  delete file->feat;
+}
+
+}  // namespace ots
new file mode 100644
--- /dev/null
+++ b/gfx/ots/src/graphite.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef OTS_GRAPHITE_H_
+#define OTS_GRAPHITE_H_
+
+#include "ots.h"
+
+namespace ots {
+
+struct OpenTypeSILF {
+  const uint8_t *data;
+  uint32_t length;
+};
+
+struct OpenTypeSILL {
+  const uint8_t *data;
+  uint32_t length;
+};
+
+struct OpenTypeGLOC {
+  const uint8_t *data;
+  uint32_t length;
+};
+
+struct OpenTypeGLAT {
+  const uint8_t *data;
+  uint32_t length;
+};
+
+struct OpenTypeFEAT {
+  const uint8_t *data;
+  uint32_t length;
+};
+
+}  // namespace ots
+
+#endif  // OTS_GRAPHITE_H_
--- a/gfx/ots/src/ots.cc
+++ b/gfx/ots/src/ots.cc
@@ -138,16 +138,27 @@ const struct {
   { Tag("GPOS"), ots::ots_gpos_parse, ots::ots_gpos_serialise,
     ots::ots_gpos_should_serialise, ots::ots_gpos_free, false },
   { Tag("GSUB"), ots::ots_gsub_parse, ots::ots_gsub_serialise,
     ots::ots_gsub_should_serialise, ots::ots_gsub_free, false },
   { Tag("vhea"), ots::ots_vhea_parse, ots::ots_vhea_serialise,
     ots::ots_vhea_should_serialise, ots::ots_vhea_free, false },
   { Tag("vmtx"), ots::ots_vmtx_parse, ots::ots_vmtx_serialise,
     ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false },
+  // SILGraphite layout tables - not actually parsed, just copied
+  { Tag("Silf"), ots::ots_silf_parse, ots::ots_silf_serialise,
+    ots::ots_silf_should_serialise, ots::ots_silf_free, false },
+  { Tag("Sill"), ots::ots_sill_parse, ots::ots_sill_serialise,
+    ots::ots_sill_should_serialise, ots::ots_sill_free, false },
+  { Tag("Gloc"), ots::ots_gloc_parse, ots::ots_gloc_serialise,
+    ots::ots_gloc_should_serialise, ots::ots_gloc_free, false },
+  { Tag("Glat"), ots::ots_glat_parse, ots::ots_glat_serialise,
+    ots::ots_glat_should_serialise, ots::ots_glat_free, false },
+  { Tag("Feat"), ots::ots_feat_parse, ots::ots_feat_serialise,
+    ots::ots_feat_should_serialise, ots::ots_feat_free, false },
   // TODO(bashi): Support mort, base, and jstf tables.
   { 0, NULL, NULL, NULL, NULL, false },
 };
 
 bool IsValidVersionTag(uint32_t tag) {
   return tag == Tag("\x00\x01\x00\x00") ||
          // OpenType fonts with CFF data have 'OTTO' tag.
          tag == Tag("OTTO") ||
@@ -581,22 +592,25 @@ bool ProcessGeneric(ots::OpenTypeFile *h
 }  // namespace
 
 namespace ots {
 
 void DisableDebugOutput() {
   g_debug_output = false;
 }
 
-bool Process(OTSStream *output, const uint8_t *data, size_t length) {
+bool Process(OTSStream *output, const uint8_t *data, size_t length,
+             bool preserveGraphite) {
   OpenTypeFile header;
   if (length < 4) {
     return OTS_FAILURE();
   }
 
+  header.preserve_graphite = preserveGraphite;
+
   bool result;
   if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
     result = ProcessWOFF(&header, output, data, length);
   } else {
     result = ProcessTTF(&header, output, data, length);
   }
 
   for (unsigned i = 0; ; ++i) {
--- a/gfx/ots/src/ots.h
+++ b/gfx/ots/src/ots.h
@@ -178,17 +178,22 @@ class Buffer {
   F(maxp, MAXP) \
   F(name, NAME) \
   F(os2, OS2) \
   F(post, POST) \
   F(prep, PREP) \
   F(vdmx, VDMX) \
   F(vorg, VORG) \
   F(vhea, VHEA) \
-  F(vmtx, VMTX)
+  F(vmtx, VMTX) \
+  F(silf, SILF) \
+  F(sill, SILL) \
+  F(glat, GLAT) \
+  F(gloc, GLOC) \
+  F(feat, FEAT)
 
 #define F(name, capname) struct OpenType##capname;
 FOR_EACH_TABLE_TYPE
 #undef F
 
 struct OpenTypeFile {
   OpenTypeFile() {
 #define F(name, capname) name = NULL;
@@ -197,16 +202,20 @@ struct OpenTypeFile {
   }
 
   uint32_t version;
   uint16_t num_tables;
   uint16_t search_range;
   uint16_t entry_selector;
   uint16_t range_shift;
 
+  // This is used to tell the relevant parsers whether to preserve the
+  // Graphite layout tables (currently _without_ any checking)
+  bool preserve_graphite;
+
 #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); \
 bool ots_##name##_should_serialise(OpenTypeFile *f); \
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -358,17 +358,22 @@ private:
 // Returns a newly-allocated block, or NULL in case of fatal errors.
 static const PRUint8*
 SanitizeOpenTypeData(const PRUint8* aData, PRUint32 aLength,
                      PRUint32& aSaneLength, bool aIsCompressed)
 {
     // limit output/expansion to 256MB
     ExpandingMemoryStream output(aIsCompressed ? aLength * 2 : aLength,
                                  1024 * 1024 * 256);
-    if (ots::Process(&output, aData, aLength)) {
+#ifdef MOZ_GRAPHITE
+#define PRESERVE_GRAPHITE true
+#else
+#define PRESERVE_GRAPHITE false
+#endif
+    if (ots::Process(&output, aData, aLength, PRESERVE_GRAPHITE)) {
         aSaneLength = output.Tell();
         return static_cast<PRUint8*>(output.forget());
     } else {
         aSaneLength = 0;
         return nsnull;
     }
 }