[HarfBuzz] harfbuzz: Branch 'master' - 6 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Feb 8 03:42:24 UTC 2018


 src/Makefile.am             |    2 -
 src/hb-open-file-private.hh |   50 ++++++++++++++++++++++++++++++++++++++++-
 src/hb-open-type-private.hh |   33 ++++++++++++++++++++++-----
 src/hb-ot-map-private.hh    |   10 ++++----
 src/hb-private.hh           |   20 ++++++++++------
 src/hb-set-private.hh       |   12 ++++-----
 src/hb-subset.cc            |   53 ++++++++++++++++++++++++++++++++++++++------
 test/api/test-subset.c      |    9 +++++--
 8 files changed, 154 insertions(+), 35 deletions(-)

New commits:
commit 931f8b7eb5e740ce81e5be6bfec60dbe3ac7ebc4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 21:42:03 2018 -0600

    Fix another thinko

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 63172399..c2e1f7de 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -145,7 +145,7 @@ typedef struct OffsetTable
       rec.checkSum.set_for_data (hb_blob_get_data (blob, nullptr), rec.length);
       rec.offset.serialize (c, this);
       void *p = c->allocate_size<void> (rec.length);
-      if (unlikely (!p)) return false;
+      if (unlikely (!p)) {return false;}
       memcpy (p, hb_blob_get_data (blob, nullptr), rec.length);
       if (rec.length % 4)
 	p = c->allocate_size<void> (4 - rec.length % 4);
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 118f2924..59d732af 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -383,7 +383,7 @@ _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
 static inline unsigned int
 _hb_ceil_to_4 (unsigned int v)
 {
-  return ((v - 1) & 3) + 1;
+  return ((v - 1) | 3) + 1;
 }
 
 
commit 39b86695cf56736170c772424c9a8b75bca0254c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 21:37:03 2018 -0600

    [subset] Fix thinko

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index ed4394da..8c1e43f7 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -221,7 +221,7 @@ hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
 
   hb_subset_face_data_t *data = (hb_subset_face_data_t *) face->user_data;
 
-  hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (tag);
+  hb_subset_face_data_t::table_entry_t *entry = data->tables.push ();
   if (unlikely (!entry))
     return false;
 
commit eeffabc87572193a9e95f22647e80ae44e5a0089
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 21:34:05 2018 -0600

    Build

diff --git a/src/Makefile.am b/src/Makefile.am
index 59ca6482..e450ea73 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,7 +14,7 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
 #AM_CXXFLAGS =
 
 # Convenience targets:
-lib: $(BUILT_SOURCES) libharfbuzz.la
+lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
 fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la
 
 lib_LTLIBRARIES = libharfbuzz.la
commit c479a59988b0cf3e557e22e97e1977962c803fa7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 21:13:10 2018 -0600

    [subset] Assemble font

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 762783f3..63172399 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -56,6 +56,13 @@ typedef struct TableRecord
   int cmp (Tag t) const
   { return t.cmp (tag); }
 
+  static int cmp (const void *pa, const void *pb)
+  {
+    const TableRecord *a = (const TableRecord *) pa;
+    const TableRecord *b = (const TableRecord *) pb;
+    return b->cmp (a->tag);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -64,7 +71,7 @@ typedef struct TableRecord
 
   Tag		tag;		/* 4-byte identifier. */
   CheckSum	checkSum;	/* CheckSum for this table. */
-  HBUINT32	offset;		/* Offset from beginning of TrueType font
+  Offset32	offset;		/* Offset from beginning of TrueType font
 				 * file. */
   HBUINT32	length;		/* Length of this table. */
   public:
@@ -118,6 +125,35 @@ typedef struct OffsetTable
   }
 
   public:
+
+  inline bool serialize (hb_serialize_context_t *c,
+			 hb_tag_t sfnt_tag,
+			 Supplier<hb_tag_t> &tags,
+			 Supplier<hb_blob_t *> &blobs,
+			 unsigned int table_count)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    sfnt_version.set (sfnt_tag);
+    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
+    for (unsigned int i = 0; i < table_count; i++)
+    {
+      TableRecord &rec = tables.array[i];
+      hb_blob_t *blob = blobs[i];
+      rec.tag.set (tags[0]);
+      rec.length.set (hb_blob_get_length (blob));
+      rec.checkSum.set_for_data (hb_blob_get_data (blob, nullptr), rec.length);
+      rec.offset.serialize (c, this);
+      void *p = c->allocate_size<void> (rec.length);
+      if (unlikely (!p)) return false;
+      memcpy (p, hb_blob_get_data (blob, nullptr), rec.length);
+      if (rec.length % 4)
+	p = c->allocate_size<void> (4 - rec.length % 4);
+    }
+    tables.qsort ();
+    return_trace (true);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -249,6 +285,18 @@ struct OpenTypeFontFile
     }
   }
 
+  inline bool serialize_single (hb_serialize_context_t *c,
+				hb_tag_t sfnt_tag,
+			        Supplier<hb_tag_t> &tags,
+			        Supplier<hb_blob_t *> &blobs,
+			        unsigned int table_count)
+  {
+    TRACE_SERIALIZE (this);
+    assert (sfnt_tag != TTCTag);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 04e4a4e1..be3ecb49 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -499,15 +499,16 @@ struct hb_serialize_context_t
 template <typename Type>
 struct Supplier
 {
-  inline Supplier (const Type *array, unsigned int len_)
+  inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
   {
     head = array;
     len = len_;
+    stride = stride_;
   }
   inline const Type operator [] (unsigned int i) const
   {
     if (unlikely (i >= len)) return Type ();
-    return head[i];
+    return * (const Type *) ((const char *) head + stride * i);
   }
 
   inline void advance (unsigned int count)
@@ -515,7 +516,7 @@ struct Supplier
     if (unlikely (count > len))
       count = len;
     len -= count;
-    head += count;
+    head = (const Type *) ((const char *) head + stride * count);
   }
 
   private:
@@ -523,6 +524,7 @@ struct Supplier
   inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
 
   unsigned int len;
+  unsigned int stride;
   const Type *head;
 };
 
@@ -717,6 +719,13 @@ struct Offset : Type
   inline bool is_null (void) const { return 0 == *this; }
   public:
   DEFINE_SIZE_STATIC (sizeof(Type));
+
+  inline void *serialize (hb_serialize_context_t *c, const void *base)
+  {
+    void *t = c->start_embed<void> ();
+    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
+    return t;
+  }
 };
 
 typedef Offset<HBUINT16> Offset16;
@@ -786,9 +795,7 @@ struct OffsetTo : Offset<OffsetType>
 
   inline Type& serialize (hb_serialize_context_t *c, const void *base)
   {
-    Type *t = c->start_embed<Type> ();
-    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
-    return *t;
+    return * (Type *) Offset<OffsetType>::serialize (c, base);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
@@ -928,6 +935,11 @@ struct ArrayOf
     return -1;
   }
 
+  inline void qsort (void)
+  {
+    ::qsort (array, len, sizeof (Type), Type::cmp);
+  }
+
   private:
   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
@@ -1072,6 +1084,15 @@ struct BinSearchHeader
     return_trace (c->check_struct (this));
   }
 
+  inline void set (unsigned int v)
+  {
+    len.set (v);
+    assert (len == v);
+    entrySelectorZ.set (MAX (1u, _hb_bit_storage (v)) - 1);
+    searchRangeZ.set (16 * (1u << entrySelectorZ));
+    rangeShiftZ.set (16 * MAX (0, (int) v - searchRangeZ));
+  }
+
   protected:
   HBUINT16	len;
   HBUINT16	searchRangeZ;
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index a80ac720..e6bd8ea5 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -84,28 +84,28 @@ struct hb_ot_map_t
   inline hb_mask_t get_global_mask (void) const { return global_mask; }
 
   inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const {
-    const feature_map_t *map = features.bsearch (&feature_tag);
+    const feature_map_t *map = features.bsearch (feature_tag);
     if (shift) *shift = map ? map->shift : 0;
     return map ? map->mask : 0;
   }
 
   inline bool needs_fallback (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (&feature_tag);
+    const feature_map_t *map = features.bsearch (feature_tag);
     return map ? map->needs_fallback : false;
   }
 
   inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (&feature_tag);
+    const feature_map_t *map = features.bsearch (feature_tag);
     return map ? map->_1_mask : 0;
   }
 
   inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (&feature_tag);
+    const feature_map_t *map = features.bsearch (feature_tag);
     return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
   }
 
   inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (&feature_tag);
+    const feature_map_t *map = features.bsearch (feature_tag);
     return map ? map->stage[table_index] : (unsigned int) -1;
   }
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 75cc38f7..118f2924 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -380,6 +380,12 @@ _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
   return (size > 0) && (count >= ((unsigned int) -1) / size);
 }
 
+static inline unsigned int
+_hb_ceil_to_4 (unsigned int v)
+{
+  return ((v - 1) & 3) + 1;
+}
+
 
 
 /* arrays and maps */
@@ -493,34 +499,34 @@ struct hb_prealloced_array_t
   }
 
   template <typename T>
-  inline Type *lsearch (T *x)
+  inline Type *lsearch (const T &x)
   {
     for (unsigned int i = 0; i < len; i++)
-      if (0 == this->array[i].cmp (x))
+      if (0 == this->array[i].cmp (&x))
 	return &array[i];
     return nullptr;
   }
 
   template <typename T>
-  inline Type *bsearch (T *x)
+  inline Type *bsearch (const T &x)
   {
     unsigned int i;
     return bfind (x, &i) ? &array[i] : nullptr;
   }
   template <typename T>
-  inline const Type *bsearch (T *x) const
+  inline const Type *bsearch (const T &x) const
   {
     unsigned int i;
     return bfind (x, &i) ? &array[i] : nullptr;
   }
   template <typename T>
-  inline bool bfind (T *x, unsigned int *i) const
+  inline bool bfind (const T &x, unsigned int *i) const
   {
     int min = 0, max = (int) this->len - 1;
     while (min <= max)
     {
       int mid = (min + max) / 2;
-      int c = this->array[mid].cmp (x);
+      int c = this->array[mid].cmp (&x);
       if (c < 0)
         max = mid - 1;
       else if (c > 0)
@@ -531,7 +537,7 @@ struct hb_prealloced_array_t
 	return true;
       }
     }
-    if (max < 0 || (max < (int) this->len && this->array[max].cmp (x) > 0))
+    if (max < 0 || (max < (int) this->len && this->array[max].cmp (&x) > 0))
       max++;
     *i = max;
     return false;
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 54dd610e..d71d4122 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -470,7 +470,7 @@ struct hb_set_t
 
     page_map_t map = {get_major (*codepoint), 0};
     unsigned int i;
-    page_map.bfind (&map, &i);
+    page_map.bfind (map, &i);
     if (i < page_map.len)
     {
       if (pages[page_map[i].index].next (codepoint))
@@ -541,7 +541,7 @@ struct hb_set_t
   {
     page_map_t map = {get_major (g), pages.len};
     unsigned int i;
-    if (!page_map.bfind (&map, &i))
+    if (!page_map.bfind (map, &i))
     {
       if (!resize (pages.len + 1))
 	return nullptr;
@@ -555,7 +555,7 @@ struct hb_set_t
   inline page_t *page_for (hb_codepoint_t g)
   {
     page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (&key);
+    const page_map_t *found = page_map.bsearch (key);
     if (found)
       return &pages[found->index];
     return nullptr;
@@ -563,7 +563,7 @@ struct hb_set_t
   inline const page_t *page_for (hb_codepoint_t g) const
   {
     page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (&key);
+    const page_map_t *found = page_map.bsearch (key);
     if (found)
       return &pages[found->index];
     return nullptr;
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index f9119c37..ed4394da 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -32,6 +32,7 @@
 #include "hb-subset-private.hh"
 #include "hb-subset-plan.hh"
 
+#include "hb-open-file-private.hh"
 #include "hb-ot-glyf-table.hh"
 
 
@@ -142,21 +143,59 @@ _hb_subset_face_data_destroy (void *user_data)
 {
   hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
 
+  data->tables.finish ();
+
   free (data);
 }
 
 static hb_blob_t *
-_hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+_hb_subset_face_data_reference_blob (hb_subset_face_data_t *data)
 {
-  hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
 
-  if (!tag)
+  unsigned int table_count = data->tables.len;
+  unsigned int face_length = table_count * 16 + 12;
+
+  for (unsigned int i = 0; i < table_count; i++)
+    face_length += _hb_ceil_to_4 (hb_blob_get_length (data->tables.array[i].blob));
+
+  char *buf = (char *) malloc (face_length);
+  if (unlikely (!buf))
+    return nullptr;
+
+  OT::hb_serialize_context_t c (buf, face_length);
+  OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
+
+  bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
+  hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
+
+  OT::Supplier<hb_tag_t>    tags_supplier  (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
+  OT::Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
+  bool ret = f->serialize_single (&c,
+				  sfnt_tag,
+				  tags_supplier,
+				  blobs_supplier,
+				  table_count);
+
+  c.end_serialize ();
+
+  if (unlikely (!ret))
   {
-    /* TODO Compile face blob... */
+    free (buf);
     return nullptr;
   }
 
-  hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (&tag);
+  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+}
+
+static hb_blob_t *
+_hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+{
+  hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
+
+  if (!tag)
+    return _hb_subset_face_data_reference_blob (data);
+
+  hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (tag);
   if (entry)
     return hb_blob_reference (entry->blob);
 
@@ -182,7 +221,7 @@ hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
 
   hb_subset_face_data_t *data = (hb_subset_face_data_t *) face->user_data;
 
-  hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (&tag);
+  hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (tag);
   if (unlikely (!entry))
     return false;
 
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
index db4bbe92..866a8333 100644
--- a/test/api/test-subset.c
+++ b/test/api/test-subset.c
@@ -32,7 +32,12 @@
 
 /* Unit tests for hb-subset.h */
 
-static const char test_data[] = { 0, 0, 1, 0 };
+static const char test_data[] = { 0, 1, 0, 0,	/* sfntVersion */
+				  0, 0,		/* numTables */
+				  0, 0x10,	/* searchRange */
+				  0, 0,		/* entrySelector */
+				  0, 0,		/* rangeShift */
+				};
 
 static void
 test_subset (void)
@@ -51,7 +56,7 @@ test_subset (void)
 
   unsigned int output_length;
   const char *output_data = hb_blob_get_data(output, &output_length);
-  g_assert_cmpmem(test_data, 4, output_data, output_length);
+  g_assert_cmpmem (test_data, sizeof (test_data), output_data, output_length);
 
   hb_blob_destroy(output);
   hb_subset_input_destroy(input);
commit 34ac3548b7c9dbc57f277cf9a7a337cd1a8a04bb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 18:07:45 2018 -0600

    [set] Respect stride
    
    Ouch!

diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 576c169e..54dd610e 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -273,7 +273,7 @@ struct hb_set_t
       {
 	page->add (g);
 
-	array++;
+	array = (const T *) ((const char *) array + stride);
 	count--;
       }
       while (count && (g = *array, start <= g && g < end));
@@ -302,7 +302,7 @@ struct hb_set_t
 	last_g = g;
 	page->add (g);
 
-	array++;
+	array = (const T *) ((const char *) array + stride);
 	count--;
       }
       while (count && (g = *array, g < end));
commit 577becaf7b5ccd9de8ba533447f944427b9e4452
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 17:38:40 2018 -0600

    [subset] Fixup

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 61f38a0a..f9119c37 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -216,7 +216,7 @@ hb_subset (hb_face_t *source,
     hb_tag_t table_tags[32];
     unsigned int offset = 0, count;
     do {
-      count == ARRAY_LENGTH (table_tags);
+      count = ARRAY_LENGTH (table_tags);
       hb_face_get_table_tags (source, offset, &count, table_tags);
       for (unsigned int i = 0; i < count; i++)
       {


More information about the HarfBuzz mailing list