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

Behdad Esfahbod behdad at kemper.freedesktop.org
Mon Dec 5 02:21:44 UTC 2016


 appveyor.yml                |    1 
 src/Makefile.sources        |    1 
 src/hb-open-type-private.hh |    3 
 src/hb-ot-cbdt-table.hh     |  347 ++++++++++++++++++++++++++++++++++++++++++++
 src/hb-ot-font.cc           |   93 +++++++++++
 win32/detectenv-msvc.mak    |    4 
 win32/generate-msvc.mak     |    2 
 7 files changed, 448 insertions(+), 3 deletions(-)

New commits:
commit c27d6fcf8db6f02e075dd1868ae67d878fff39d4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 22:43:05 2016 -0800

    [cbdt] Last of sanitization fixes
    
    Should be all good now..

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 5e02170..1a2d382 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -215,22 +215,25 @@ struct hb_ot_face_cbdt_accelerator_t
   const OT::CBLC *cblc;
   const OT::CBDT *cbdt;
 
-  float upem = 0.0f;
+  unsigned int cbdt_len;
+  float upem;
 
   inline void init (hb_face_t *face)
   {
-    this->cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
-    this->cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
+    upem = face->get_upem();
+
+    cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
+    cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
+    cbdt_len = hb_blob_get_length (cbdt_blob);
 
-    if (hb_blob_get_length (this->cblc_blob) == 0) {
+    if (hb_blob_get_length (cblc_blob) == 0) {
       cblc = NULL;
       cbdt = NULL;
       return;  /* Not a bitmap font. */
     }
-    cblc = OT::Sanitizer<OT::CBLC>::lock_instance (this->cblc_blob);
-    cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (this->cbdt_blob);
+    cblc = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob);
+    cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (cbdt_blob);
 
-    upem = face->get_upem();
   }
 
   inline void fini (void)
@@ -263,9 +266,15 @@ struct hb_ot_face_cbdt_accelerator_t
     if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
       return false;
 
+    if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+      return false;
+
     switch (image_format)
     {
       case 17: {
+	if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size))
+	  return false;
+
 	const OT::GlyphBitmapDataFormat17& glyphFormat17 =
 	    OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, image_offset);
 	glyphFormat17.glyphMetrics.get_extents (extents);
commit d495fc5e38038f4cfb20425b1109324fa70bf2f9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 21:36:42 2016 -0800

    [cbdt] Clean up some more
    
    Almost there..

diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
index 3a7cc99..4319067 100644
--- a/src/hb-ot-cbdt-table.hh
+++ b/src/hb-ot-cbdt-table.hh
@@ -39,6 +39,14 @@ struct SmallGlyphMetrics
     return_trace (c->check_struct (this));
   }
 
+  inline void get_extents (hb_glyph_extents_t *extents) const
+  {
+    extents->x_bearing = bearingX;
+    extents->y_bearing = bearingY;
+    extents->width = width;
+    extents->height = height;
+  }
+
   BYTE height;
   BYTE width;
   CHAR bearingX;
@@ -75,17 +83,14 @@ struct SBitLineMetrics
 /*
  * Index Subtables.
  */
-struct IndexSubtable
+struct IndexSubtableHeader
 {
-  USHORT firstGlyphIndex;
-  USHORT lastGlyphIndex;
-  ULONG offsetToSubtable;
-
-  DEFINE_SIZE_STATIC(8);
-};
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
 
-struct IndexSubHeader
-{
   USHORT indexFormat;
   USHORT imageFormat;
   ULONG imageDataOffset;
@@ -95,12 +100,108 @@ struct IndexSubHeader
 
 struct IndexSubtableFormat1
 {
-  IndexSubHeader header;
-  ULONG offsetArrayZ[VAR];
+  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
+  }
+
+  bool get_image_data (unsigned int idx,
+		       unsigned int *offset,
+		       unsigned int *length) const
+  {
+    if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
+      return false;
+
+    *offset = header.imageDataOffset + offsetArrayZ[idx];
+    *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
+    return true;
+  }
+
+  IndexSubtableHeader header;
+  Offset<ULONG> offsetArrayZ[VAR];
 
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
 
+struct IndexSubtable
+{
+  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.header.sanitize (c)) return_trace (false);
+    switch (u.header.indexFormat) {
+    case 1: return_trace (u.format1.sanitize (c, glyph_count));
+    default:return_trace (true);
+    }
+  }
+
+  inline bool get_extents (hb_glyph_extents_t *extents) const
+  {
+    switch (u.header.indexFormat) {
+    case 2: case 5: /* TODO */
+    case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
+    default:return (false);
+    }
+  }
+
+  bool get_image_data (unsigned int idx,
+		       unsigned int *offset,
+		       unsigned int *length,
+		       unsigned int *format) const
+  {
+    *format = u.header.imageFormat;
+    switch (u.header.indexFormat) {
+    case 1: return u.format1.get_image_data (idx, offset, length);
+    default: return false;
+    }
+  }
+
+  protected:
+  union {
+  IndexSubtableHeader	header;
+  IndexSubtableFormat1	format1;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (8, header);
+};
+
+struct IndexSubtableRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  firstGlyphIndex <= lastGlyphIndex &&
+		  offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
+  }
+
+  inline bool get_extents (hb_glyph_extents_t *extents) const
+  {
+    return (this+offsetToSubtable).get_extents (extents);
+  }
+
+  bool get_image_data (unsigned int gid,
+		       unsigned int *offset,
+		       unsigned int *length,
+		       unsigned int *format) const
+  {
+    if (gid < firstGlyphIndex || gid > lastGlyphIndex)
+    {
+      return false;
+    }
+    return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
+						   offset, length, format);
+  }
+
+  USHORT firstGlyphIndex;
+  USHORT lastGlyphIndex;
+  OffsetTo<IndexSubtable, ULONG> offsetToSubtable;
+
+  DEFINE_SIZE_STATIC(8);
+};
+
 /*
  * Glyph Bitmap Data Formats.
  */
@@ -119,11 +220,16 @@ struct IndexSubtableArray
   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this)); // XXX
+    if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, sizeof (count))))
+      return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
+	return_trace (false);
+    return_trace (true);
   }
 
   public:
-  const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const
+  const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
   {
     for (unsigned int i = 0; i < numTables; ++i)
     {
@@ -137,7 +243,7 @@ struct IndexSubtableArray
   }
 
   protected:
-  IndexSubtable indexSubtablesZ[VAR];
+  IndexSubtableRecord indexSubtablesZ[VAR];
 
   public:
   DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 2d1cf09..5e02170 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -250,41 +250,25 @@ struct hb_ot_face_cbdt_accelerator_t
       return false;
     }
 
-    const OT::IndexSubtableArray& subtables =
-            OT::StructAtOffset<OT::IndexSubtableArray> (this->cblc, sizeTable->indexSubtableArrayOffset);
-    const OT::IndexSubtable* subtable = subtables.find_table(glyph, sizeTable->numberOfIndexSubtables);
-    if (subtable == NULL) {
+    const OT::IndexSubtableArray& subtables = this->cblc + sizeTable->indexSubtableArrayOffset;
+    const OT::IndexSubtableRecord *subtable_record = subtables.find_table (glyph, sizeTable->numberOfIndexSubtables);
+    if (subtable_record == NULL) {
       return false;
     }
 
-    unsigned int offsetToSubtable = sizeTable->indexSubtableArrayOffset + subtable->offsetToSubtable;
-    const OT::IndexSubHeader& header =
-            OT::StructAtOffset<OT::IndexSubHeader> (this->cblc, offsetToSubtable);
+    if (subtable_record->get_extents (extents))
+      return true;
 
-    unsigned int imageDataOffset = header.imageDataOffset;
-    switch (header.indexFormat)
-    {
-      case 1:
-	{
-	  const OT::IndexSubtableFormat1& format1 =
-	      OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
-	  imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex];
-	}
-	break;
-      default:
-	// TODO: Support other index subtable format.
-	return false;
-    }
+    unsigned int image_offset = 0, image_length = 0, image_format = 0;
+    if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+      return false;
 
-    switch (header.imageFormat)
+    switch (image_format)
     {
       case 17: {
 	const OT::GlyphBitmapDataFormat17& glyphFormat17 =
-	    OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, imageDataOffset);
-	extents->x_bearing = glyphFormat17.glyphMetrics.bearingX;
-	extents->y_bearing = glyphFormat17.glyphMetrics.bearingY;
-	extents->width = glyphFormat17.glyphMetrics.width;
-	extents->height = -glyphFormat17.glyphMetrics.height;
+	    OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+	glyphFormat17.glyphMetrics.get_extents (extents);
       }
       break;
       default:
commit ce09e90e1502d5f944bafd64e51c29e365a963ae
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 20:12:57 2016 -0800

    [cbdt] More sanitize work

diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
index dda42f2..3a7cc99 100644
--- a/src/hb-ot-cbdt-table.hh
+++ b/src/hb-ot-cbdt-table.hh
@@ -72,32 +72,6 @@ struct SBitLineMetrics
   DEFINE_SIZE_STATIC(12);
 };
 
-struct BitmapSizeTable
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  horizontal.sanitize (c) &&
-		  vertical.sanitize (c));
-  }
-
-  ULONG indexSubtableArrayOffset;
-  ULONG indexTablesSize;
-  ULONG numberOfIndexSubtables;
-  ULONG colorRef;
-  SBitLineMetrics horizontal;
-  SBitLineMetrics vertical;
-  USHORT startGlyphIndex;
-  USHORT endGlyphIndex;
-  BYTE ppemX;
-  BYTE ppemY;
-  BYTE bitDepth;
-  CHAR flags;
-
-  DEFINE_SIZE_STATIC(48);
-};
-
 /*
  * Index Subtables.
  */
@@ -142,6 +116,12 @@ struct GlyphBitmapDataFormat17
 
 struct IndexSubtableArray
 {
+  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this)); // XXX
+  }
+
   public:
   const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const
   {
@@ -158,6 +138,37 @@ struct IndexSubtableArray
 
   protected:
   IndexSubtable indexSubtablesZ[VAR];
+
+  public:
+  DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
+};
+
+struct BitmapSizeTable
+{
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
+		  c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
+		  horizontal.sanitize (c) &&
+		  vertical.sanitize (c));
+  }
+
+  OffsetTo<IndexSubtableArray, ULONG> indexSubtableArrayOffset;
+  ULONG indexTablesSize;
+  ULONG numberOfIndexSubtables;
+  ULONG colorRef;
+  SBitLineMetrics horizontal;
+  SBitLineMetrics vertical;
+  USHORT startGlyphIndex;
+  USHORT endGlyphIndex;
+  BYTE ppemX;
+  BYTE ppemY;
+  BYTE bitDepth;
+  CHAR flags;
+
+  DEFINE_SIZE_STATIC(48);
 };
 
 /*
@@ -175,7 +186,7 @@ struct CBLC
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  likely (version.major == 2 || version.major == 3) &&
-		  sizeTables.sanitize (c));
+		  sizeTables.sanitize (c, this));
   }
 
   public:
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 25a1ef6..2d1cf09 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -262,30 +262,34 @@ struct hb_ot_face_cbdt_accelerator_t
             OT::StructAtOffset<OT::IndexSubHeader> (this->cblc, offsetToSubtable);
 
     unsigned int imageDataOffset = header.imageDataOffset;
-    switch (header.indexFormat) {
-      case 1: {
-        const OT::IndexSubtableFormat1& format1 =
-            OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
-        imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex];
-        switch (header.imageFormat) {
-          case 17: {
-            const OT::GlyphBitmapDataFormat17& glyphFormat17 =
-                OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, imageDataOffset);
-            extents->x_bearing = glyphFormat17.glyphMetrics.bearingX;
-            extents->y_bearing = glyphFormat17.glyphMetrics.bearingY;
-            extents->width = glyphFormat17.glyphMetrics.width;
-            extents->height = -glyphFormat17.glyphMetrics.height;
-          }
-          break;
-          default:
-            // TODO: Support other image formats.
-            return false;
-        }
+    switch (header.indexFormat)
+    {
+      case 1:
+	{
+	  const OT::IndexSubtableFormat1& format1 =
+	      OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
+	  imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex];
+	}
+	break;
+      default:
+	// TODO: Support other index subtable format.
+	return false;
+    }
+
+    switch (header.imageFormat)
+    {
+      case 17: {
+	const OT::GlyphBitmapDataFormat17& glyphFormat17 =
+	    OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, imageDataOffset);
+	extents->x_bearing = glyphFormat17.glyphMetrics.bearingX;
+	extents->y_bearing = glyphFormat17.glyphMetrics.bearingY;
+	extents->width = glyphFormat17.glyphMetrics.width;
+	extents->height = -glyphFormat17.glyphMetrics.height;
       }
       break;
       default:
-        // TODO: Support other index subtable format.
-        return false;
+	// TODO: Support other image formats.
+	return false;
     }
 
     /* Convert to the font units. */
commit 70eb2ff682344688635cebb716fee0b73557c925
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 19:51:23 2016 -0800

    Check for offset overflows during sanitize

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 6b64378..66f1c08 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -806,6 +806,7 @@ struct OffsetTo : Offset<OffsetType>
     if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int offset = *this;
     if (unlikely (!offset)) return_trace (true);
+    if (unlikely (!c->check_range (base, offset))) return_trace (false);
     const Type &obj = StructAtOffset<Type> (base, offset);
     return_trace (likely (obj.sanitize (c)) || neuter (c));
   }
@@ -816,6 +817,7 @@ struct OffsetTo : Offset<OffsetType>
     if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int offset = *this;
     if (unlikely (!offset)) return_trace (true);
+    if (unlikely (!c->check_range (base, offset))) return_trace (false);
     const Type &obj = StructAtOffset<Type> (base, offset);
     return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
   }
commit 4b58c9e326acde09d389c699014e4e7f6259f50a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 19:25:54 2016 -0800

    [cbdt] Start fixing sanitization (or lack thereof)

diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
index 7615138..dda42f2 100644
--- a/src/hb-ot-cbdt-table.hh
+++ b/src/hb-ot-cbdt-table.hh
@@ -33,6 +33,12 @@ namespace OT {
 
 struct SmallGlyphMetrics
 {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
   BYTE height;
   BYTE width;
   CHAR bearingX;
@@ -42,7 +48,14 @@ struct SmallGlyphMetrics
   DEFINE_SIZE_STATIC(5);
 };
 
-struct SBitLineMetrics {
+struct SBitLineMetrics
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
   CHAR ascender;
   CHAR decender;
   BYTE widthMax;
@@ -61,6 +74,14 @@ struct SBitLineMetrics {
 
 struct BitmapSizeTable
 {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  horizontal.sanitize (c) &&
+		  vertical.sanitize (c));
+  }
+
   ULONG indexSubtableArrayOffset;
   ULONG indexTablesSize;
   ULONG numberOfIndexSubtables;
@@ -94,41 +115,49 @@ struct IndexSubHeader
   USHORT indexFormat;
   USHORT imageFormat;
   ULONG imageDataOffset;
+
+  DEFINE_SIZE_STATIC(8);
 };
 
 struct IndexSubtableFormat1
 {
   IndexSubHeader header;
-  ULONG offsetArray[VAR];
+  ULONG offsetArrayZ[VAR];
+
+  DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
 
 /*
  * Glyph Bitmap Data Formats.
  */
+
 struct GlyphBitmapDataFormat17
 {
   SmallGlyphMetrics glyphMetrics;
   ULONG dataLen;
-  BYTE data[VAR];
+  BYTE dataZ[VAR];
+
+  DEFINE_SIZE_ARRAY(9, dataZ);
 };
 
 struct IndexSubtableArray
 {
   public:
-  const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const
+  const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const
   {
-    for (unsigned int i = 0; i < numTables; ++i) {
-      unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex;
-      unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex;
+    for (unsigned int i = 0; i < numTables; ++i)
+    {
+      unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
+      unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
       if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
-        return &indexSubtables[i];
+        return &indexSubtablesZ[i];
       }
     }
     return NULL;
   }
 
   protected:
-  IndexSubtable indexSubtables[VAR];
+  IndexSubtable indexSubtablesZ[VAR];
 };
 
 /*
@@ -144,17 +173,19 @@ struct CBLC
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (true);
+    return_trace (c->check_struct (this) &&
+		  likely (version.major == 2 || version.major == 3) &&
+		  sizeTables.sanitize (c));
   }
 
   public:
-  const BitmapSizeTable* find_table(hb_codepoint_t glyph) const
+  const BitmapSizeTable* find_table (hb_codepoint_t glyph) const
   {
     // TODO: Make it possible to select strike.
-    const uint32_t tableSize = numSizes;
-    for (uint32_t i = 0; i < tableSize; ++i) {
-      unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex;
+    unsigned int count = sizeTables.len;
+    for (uint32_t i = 0; i < count; ++i) {
+      unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex;
+      unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex;
       if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) {
         return &sizeTables[i];
       }
@@ -163,10 +194,11 @@ struct CBLC
   }
 
   protected:
-  ULONG version;
-  ULONG numSizes;
+  FixedVersion<>version;
+  ArrayOf<BitmapSizeTable, ULONG> sizeTables;
 
-  BitmapSizeTable sizeTables[VAR];
+  public:
+  DEFINE_SIZE_ARRAY(8, sizeTables);
 };
 
 /*
@@ -181,11 +213,16 @@ struct CBDT
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (true);
+    return_trace (c->check_struct (this) &&
+		  likely (version.major == 2 || version.major == 3));
   }
 
   protected:
-  BYTE data[VAR];
+  FixedVersion<>version;
+  BYTE dataZ[VAR];
+
+  public:
+  DEFINE_SIZE_ARRAY(4, dataZ);
 };
 
 } /* namespace OT */
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index c53fcd5..25a1ef6 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -210,10 +210,10 @@ struct hb_ot_face_glyf_accelerator_t
 
 struct hb_ot_face_cbdt_accelerator_t
 {
-  hb_blob_t *cblc_blob = NULL;
-  hb_blob_t *cbdt_blob = NULL;
-  const OT::CBLC *cblc = NULL;
-  const OT::CBDT *cbdt = NULL;
+  hb_blob_t *cblc_blob;
+  hb_blob_t *cbdt_blob;
+  const OT::CBLC *cblc;
+  const OT::CBDT *cbdt;
 
   float upem = 0.0f;
 
@@ -223,6 +223,8 @@ struct hb_ot_face_cbdt_accelerator_t
     this->cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
 
     if (hb_blob_get_length (this->cblc_blob) == 0) {
+      cblc = NULL;
+      cbdt = NULL;
       return;  /* Not a bitmap font. */
     }
     cblc = OT::Sanitizer<OT::CBLC>::lock_instance (this->cblc_blob);
@@ -233,10 +235,8 @@ struct hb_ot_face_cbdt_accelerator_t
 
   inline void fini (void)
   {
-    if (this->cblc_blob) {
-      hb_blob_destroy (this->cblc_blob);
-      hb_blob_destroy (this->cbdt_blob);
-    }
+    hb_blob_destroy (this->cblc_blob);
+    hb_blob_destroy (this->cbdt_blob);
   }
 
   inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
@@ -266,7 +266,7 @@ struct hb_ot_face_cbdt_accelerator_t
       case 1: {
         const OT::IndexSubtableFormat1& format1 =
             OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
-        imageDataOffset += format1.offsetArray[glyph - subtable->firstGlyphIndex];
+        imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex];
         switch (header.imageFormat) {
           case 17: {
             const OT::GlyphBitmapDataFormat17& glyphFormat17 =
@@ -288,7 +288,7 @@ struct hb_ot_face_cbdt_accelerator_t
         return false;
     }
 
-    // Convert to the font units.
+    /* Convert to the font units. */
     extents->x_bearing *= upem / (float)(sizeTable->ppemX);
     extents->y_bearing *= upem / (float)(sizeTable->ppemY);
     extents->width *= upem / (float)(sizeTable->ppemX);
@@ -558,7 +558,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   bool ret = ot_font->glyf->get_extents (glyph, extents);
-  if ( !ret )
+  if (!ret)
     ret = ot_font->cbdt->get_extents (glyph, extents);
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
commit b92ba7bafcd9545a401fb871eb342e6284032c47
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 15:21:43 2016 -0800

    [CBDT] Use CHAR instead of int8_t

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index df683ca..6b64378 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -650,6 +650,7 @@ struct IntType
   DEFINE_SIZE_STATIC (Size);
 };
 
+typedef	IntType<int8_t	, 1> CHAR;	/* 8-bit signed integer. */
 typedef	IntType<uint8_t	, 1> BYTE;	/* 8-bit unsigned integer. */
 typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
 typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
index 17f15dc..7615138 100644
--- a/src/hb-ot-cbdt-table.hh
+++ b/src/hb-ot-cbdt-table.hh
@@ -35,26 +35,26 @@ struct SmallGlyphMetrics
 {
   BYTE height;
   BYTE width;
-  int8_t bearingX;
-  int8_t bearingY;
+  CHAR bearingX;
+  CHAR bearingY;
   BYTE advance;
 
   DEFINE_SIZE_STATIC(5);
 };
 
 struct SBitLineMetrics {
-  int8_t ascender;
-  int8_t decender;
+  CHAR ascender;
+  CHAR decender;
   BYTE widthMax;
-  int8_t caretSlopeNumerator;
-  int8_t caretSlopeDenominator;
-  int8_t caretOffset;
-  int8_t minOriginSB;
-  int8_t minAdvanceSB;
-  int8_t maxBeforeBL;
-  int8_t minAfterBL;
-  int8_t padding1;
-  int8_t padding2;
+  CHAR caretSlopeNumerator;
+  CHAR caretSlopeDenominator;
+  CHAR caretOffset;
+  CHAR minOriginSB;
+  CHAR minAdvanceSB;
+  CHAR maxBeforeBL;
+  CHAR minAfterBL;
+  CHAR padding1;
+  CHAR padding2;
 
   DEFINE_SIZE_STATIC(12);
 };
@@ -72,7 +72,7 @@ struct BitmapSizeTable
   BYTE ppemX;
   BYTE ppemY;
   BYTE bitDepth;
-  int8_t flags;
+  CHAR flags;
 
   DEFINE_SIZE_STATIC(48);
 };
commit efca7bf97f9967af4fa399a6665b723af643cecd
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Dec 2 15:11:37 2016 -0800

    Rename 'ebdt' to 'cbdt' since we only support the PNG format

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 8d2f3c6..166793a 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -20,8 +20,8 @@ HB_BASE_sources = \
 	hb-object-private.hh \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
+	hb-ot-cbdt-table.hh \
 	hb-ot-cmap-table.hh \
-	hb-ot-ebdt-table.hh \
 	hb-ot-glyf-table.hh \
 	hb-ot-head-table.hh \
 	hb-ot-hhea-table.hh \
diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
new file mode 100644
index 0000000..17f15dc
--- /dev/null
+++ b/src/hb-ot-cbdt-table.hh
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2016  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Seigo Nonaka
+ */
+
+#ifndef HB_OT_CBDT_TABLE_HH
+#define HB_OT_CBDT_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+namespace OT {
+
+struct SmallGlyphMetrics
+{
+  BYTE height;
+  BYTE width;
+  int8_t bearingX;
+  int8_t bearingY;
+  BYTE advance;
+
+  DEFINE_SIZE_STATIC(5);
+};
+
+struct SBitLineMetrics {
+  int8_t ascender;
+  int8_t decender;
+  BYTE widthMax;
+  int8_t caretSlopeNumerator;
+  int8_t caretSlopeDenominator;
+  int8_t caretOffset;
+  int8_t minOriginSB;
+  int8_t minAdvanceSB;
+  int8_t maxBeforeBL;
+  int8_t minAfterBL;
+  int8_t padding1;
+  int8_t padding2;
+
+  DEFINE_SIZE_STATIC(12);
+};
+
+struct BitmapSizeTable
+{
+  ULONG indexSubtableArrayOffset;
+  ULONG indexTablesSize;
+  ULONG numberOfIndexSubtables;
+  ULONG colorRef;
+  SBitLineMetrics horizontal;
+  SBitLineMetrics vertical;
+  USHORT startGlyphIndex;
+  USHORT endGlyphIndex;
+  BYTE ppemX;
+  BYTE ppemY;
+  BYTE bitDepth;
+  int8_t flags;
+
+  DEFINE_SIZE_STATIC(48);
+};
+
+/*
+ * Index Subtables.
+ */
+struct IndexSubtable
+{
+  USHORT firstGlyphIndex;
+  USHORT lastGlyphIndex;
+  ULONG offsetToSubtable;
+
+  DEFINE_SIZE_STATIC(8);
+};
+
+struct IndexSubHeader
+{
+  USHORT indexFormat;
+  USHORT imageFormat;
+  ULONG imageDataOffset;
+};
+
+struct IndexSubtableFormat1
+{
+  IndexSubHeader header;
+  ULONG offsetArray[VAR];
+};
+
+/*
+ * Glyph Bitmap Data Formats.
+ */
+struct GlyphBitmapDataFormat17
+{
+  SmallGlyphMetrics glyphMetrics;
+  ULONG dataLen;
+  BYTE data[VAR];
+};
+
+struct IndexSubtableArray
+{
+  public:
+  const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const
+  {
+    for (unsigned int i = 0; i < numTables; ++i) {
+      unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex;
+      unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex;
+      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+        return &indexSubtables[i];
+      }
+    }
+    return NULL;
+  }
+
+  protected:
+  IndexSubtable indexSubtables[VAR];
+};
+
+/*
+ * CBLC -- Color Bitmap Location Table
+ */
+
+#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
+
+struct CBLC
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (true);
+  }
+
+  public:
+  const BitmapSizeTable* find_table(hb_codepoint_t glyph) const
+  {
+    // TODO: Make it possible to select strike.
+    const uint32_t tableSize = numSizes;
+    for (uint32_t i = 0; i < tableSize; ++i) {
+      unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex;
+      unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex;
+      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) {
+        return &sizeTables[i];
+      }
+    }
+    return NULL;
+  }
+
+  protected:
+  ULONG version;
+  ULONG numSizes;
+
+  BitmapSizeTable sizeTables[VAR];
+};
+
+/*
+ * CBDT -- Color Bitmap Data Table
+ */
+#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
+
+struct CBDT
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (true);
+  }
+
+  protected:
+  BYTE data[VAR];
+};
+
+} /* namespace OT */
+
+#endif /* HB_OT_CBDT_TABLE_HH */
diff --git a/src/hb-ot-ebdt-table.hh b/src/hb-ot-ebdt-table.hh
deleted file mode 100644
index f3d0de6..0000000
--- a/src/hb-ot-ebdt-table.hh
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright © 2016  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Seigo Nonaka
- */
-
-#ifndef HB_OT_EBDT_TABLE_HH
-#define HB_OT_EBDT_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-struct SmallGlyphMetrics
-{
-  BYTE height;
-  BYTE width;
-  int8_t bearingX;
-  int8_t bearingY;
-  BYTE advance;
-
-  DEFINE_SIZE_STATIC(5);
-};
-
-struct SBitLineMetrics {
-  int8_t ascender;
-  int8_t decender;
-  BYTE widthMax;
-  int8_t caretSlopeNumerator;
-  int8_t caretSlopeDenominator;
-  int8_t caretOffset;
-  int8_t minOriginSB;
-  int8_t minAdvanceSB;
-  int8_t maxBeforeBL;
-  int8_t minAfterBL;
-  int8_t padding1;
-  int8_t padding2;
-
-  DEFINE_SIZE_STATIC(12);
-};
-
-struct BitmapSizeTable
-{
-  ULONG indexSubtableArrayOffset;
-  ULONG indexTablesSize;
-  ULONG numberOfIndexSubtables;
-  ULONG colorRef;
-  SBitLineMetrics horizontal;
-  SBitLineMetrics vertical;
-  USHORT startGlyphIndex;
-  USHORT endGlyphIndex;
-  BYTE ppemX;
-  BYTE ppemY;
-  BYTE bitDepth;
-  int8_t flags;
-
-  DEFINE_SIZE_STATIC(48);
-};
-
-/*
- * Index Subtables.
- */
-struct IndexSubtable
-{
-  USHORT firstGlyphIndex;
-  USHORT lastGlyphIndex;
-  ULONG offsetToSubtable;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-struct IndexSubHeader
-{
-  USHORT indexFormat;
-  USHORT imageFormat;
-  ULONG imageDataOffset;
-};
-
-struct IndexSubtableFormat1
-{
-  IndexSubHeader header;
-  ULONG offsetArray[VAR];
-};
-
-/*
- * Glyph Bitmap Data Formats.
- */
-struct GlyphBitmapDataFormat17
-{
-  SmallGlyphMetrics glyphMetrics;
-  ULONG dataLen;
-  BYTE data[VAR];
-};
-
-struct IndexSubtableArray
-{
-  public:
-  const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const
-  {
-    for (unsigned int i = 0; i < numTables; ++i) {
-      unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex;
-      unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex;
-      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
-        return &indexSubtables[i];
-      }
-    }
-    return NULL;
-  }
-
-  protected:
-  IndexSubtable indexSubtables[VAR];
-};
-
-/*
- * CBLC -- Color Bitmap Location Table
- */
-
-#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
-
-struct CBLC
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (true);
-  }
-
-  public:
-  const BitmapSizeTable* find_table(hb_codepoint_t glyph) const
-  {
-    // TODO: Make it possible to select strike.
-    const uint32_t tableSize = numSizes;
-    for (uint32_t i = 0; i < tableSize; ++i) {
-      unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex;
-      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) {
-        return &sizeTables[i];
-      }
-    }
-    return NULL;
-  }
-
-  protected:
-  ULONG version;
-  ULONG numSizes;
-
-  BitmapSizeTable sizeTables[VAR];
-};
-
-/*
- * CBDT -- Color Bitmap Data Table
- */
-#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
-
-struct CBDT
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (true);
-  }
-
-  protected:
-  BYTE data[VAR];
-};
-
-} /* namespace OT */
-
-#endif /* HB_OT_EBDT_TABLE_HH */
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index d9be196..c53fcd5 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -31,7 +31,7 @@
 #include "hb-font-private.hh"
 
 #include "hb-ot-cmap-table.hh"
-#include "hb-ot-ebdt-table.hh"
+#include "hb-ot-cbdt-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-hhea-table.hh"
@@ -208,7 +208,7 @@ struct hb_ot_face_glyf_accelerator_t
   }
 };
 
-struct hb_ot_face_ebdt_accelerator_t
+struct hb_ot_face_cbdt_accelerator_t
 {
   hb_blob_t *cblc_blob = NULL;
   hb_blob_t *cbdt_blob = NULL;
@@ -470,7 +470,7 @@ struct hb_ot_font_t
   hb_ot_face_metrics_accelerator_t h_metrics;
   hb_ot_face_metrics_accelerator_t v_metrics;
   hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
-  hb_lazy_loader_t<hb_ot_face_ebdt_accelerator_t> ebdt;
+  hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
 };
 
 
@@ -487,7 +487,7 @@ _hb_ot_font_create (hb_face_t *face)
   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE,
 			   ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
   ot_font->glyf.init (face);
-  ot_font->ebdt.init (face);
+  ot_font->cbdt.init (face);
 
   return ot_font;
 }
@@ -499,7 +499,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
   ot_font->h_metrics.fini ();
   ot_font->v_metrics.fini ();
   ot_font->glyf.fini ();
-  ot_font->ebdt.fini ();
+  ot_font->cbdt.fini ();
 
   free (ot_font);
 }
@@ -559,7 +559,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   bool ret = ot_font->glyf->get_extents (glyph, extents);
   if ( !ret )
-    ret = ot_font->ebdt->get_extents (glyph, extents);
+    ret = ot_font->cbdt->get_extents (glyph, extents);
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
   extents->width     = font->em_scale_x (extents->width);
commit 831852594b777f250efedb76d19bee1cfc8eeaa4
Author: Seigo Nonaka <nona at google.com>
Date:   Fri Dec 2 15:03:50 2016 -0800

    Introduce get_extent support for color bitmap font. (#351)
    
    hb_font_get_glyph_extents now works for color bitmap fonts.
    Currently only font having index format 1 and image format 17
    is supported.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 5c695c5..8d2f3c6 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -21,6 +21,7 @@ HB_BASE_sources = \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
 	hb-ot-cmap-table.hh \
+	hb-ot-ebdt-table.hh \
 	hb-ot-glyf-table.hh \
 	hb-ot-head-table.hh \
 	hb-ot-hhea-table.hh \
diff --git a/src/hb-ot-ebdt-table.hh b/src/hb-ot-ebdt-table.hh
new file mode 100644
index 0000000..f3d0de6
--- /dev/null
+++ b/src/hb-ot-ebdt-table.hh
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2016  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Seigo Nonaka
+ */
+
+#ifndef HB_OT_EBDT_TABLE_HH
+#define HB_OT_EBDT_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+namespace OT {
+
+struct SmallGlyphMetrics
+{
+  BYTE height;
+  BYTE width;
+  int8_t bearingX;
+  int8_t bearingY;
+  BYTE advance;
+
+  DEFINE_SIZE_STATIC(5);
+};
+
+struct SBitLineMetrics {
+  int8_t ascender;
+  int8_t decender;
+  BYTE widthMax;
+  int8_t caretSlopeNumerator;
+  int8_t caretSlopeDenominator;
+  int8_t caretOffset;
+  int8_t minOriginSB;
+  int8_t minAdvanceSB;
+  int8_t maxBeforeBL;
+  int8_t minAfterBL;
+  int8_t padding1;
+  int8_t padding2;
+
+  DEFINE_SIZE_STATIC(12);
+};
+
+struct BitmapSizeTable
+{
+  ULONG indexSubtableArrayOffset;
+  ULONG indexTablesSize;
+  ULONG numberOfIndexSubtables;
+  ULONG colorRef;
+  SBitLineMetrics horizontal;
+  SBitLineMetrics vertical;
+  USHORT startGlyphIndex;
+  USHORT endGlyphIndex;
+  BYTE ppemX;
+  BYTE ppemY;
+  BYTE bitDepth;
+  int8_t flags;
+
+  DEFINE_SIZE_STATIC(48);
+};
+
+/*
+ * Index Subtables.
+ */
+struct IndexSubtable
+{
+  USHORT firstGlyphIndex;
+  USHORT lastGlyphIndex;
+  ULONG offsetToSubtable;
+
+  DEFINE_SIZE_STATIC(8);
+};
+
+struct IndexSubHeader
+{
+  USHORT indexFormat;
+  USHORT imageFormat;
+  ULONG imageDataOffset;
+};
+
+struct IndexSubtableFormat1
+{
+  IndexSubHeader header;
+  ULONG offsetArray[VAR];
+};
+
+/*
+ * Glyph Bitmap Data Formats.
+ */
+struct GlyphBitmapDataFormat17
+{
+  SmallGlyphMetrics glyphMetrics;
+  ULONG dataLen;
+  BYTE data[VAR];
+};
+
+struct IndexSubtableArray
+{
+  public:
+  const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const
+  {
+    for (unsigned int i = 0; i < numTables; ++i) {
+      unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex;
+      unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex;
+      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+        return &indexSubtables[i];
+      }
+    }
+    return NULL;
+  }
+
+  protected:
+  IndexSubtable indexSubtables[VAR];
+};
+
+/*
+ * CBLC -- Color Bitmap Location Table
+ */
+
+#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
+
+struct CBLC
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (true);
+  }
+
+  public:
+  const BitmapSizeTable* find_table(hb_codepoint_t glyph) const
+  {
+    // TODO: Make it possible to select strike.
+    const uint32_t tableSize = numSizes;
+    for (uint32_t i = 0; i < tableSize; ++i) {
+      unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex;
+      unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex;
+      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) {
+        return &sizeTables[i];
+      }
+    }
+    return NULL;
+  }
+
+  protected:
+  ULONG version;
+  ULONG numSizes;
+
+  BitmapSizeTable sizeTables[VAR];
+};
+
+/*
+ * CBDT -- Color Bitmap Data Table
+ */
+#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
+
+struct CBDT
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (true);
+  }
+
+  protected:
+  BYTE data[VAR];
+};
+
+} /* namespace OT */
+
+#endif /* HB_OT_EBDT_TABLE_HH */
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 20f2f89..d9be196 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -31,6 +31,7 @@
 #include "hb-font-private.hh"
 
 #include "hb-ot-cmap-table.hh"
+#include "hb-ot-ebdt-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-hhea-table.hh"
@@ -207,6 +208,96 @@ struct hb_ot_face_glyf_accelerator_t
   }
 };
 
+struct hb_ot_face_ebdt_accelerator_t
+{
+  hb_blob_t *cblc_blob = NULL;
+  hb_blob_t *cbdt_blob = NULL;
+  const OT::CBLC *cblc = NULL;
+  const OT::CBDT *cbdt = NULL;
+
+  float upem = 0.0f;
+
+  inline void init (hb_face_t *face)
+  {
+    this->cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
+    this->cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
+
+    if (hb_blob_get_length (this->cblc_blob) == 0) {
+      return;  /* Not a bitmap font. */
+    }
+    cblc = OT::Sanitizer<OT::CBLC>::lock_instance (this->cblc_blob);
+    cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (this->cbdt_blob);
+
+    upem = face->get_upem();
+  }
+
+  inline void fini (void)
+  {
+    if (this->cblc_blob) {
+      hb_blob_destroy (this->cblc_blob);
+      hb_blob_destroy (this->cbdt_blob);
+    }
+  }
+
+  inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+  {
+    if (cblc == NULL) {
+      return false;  // Not a color bitmap font.
+    }
+
+    const OT::BitmapSizeTable* sizeTable = this->cblc->find_table(glyph);
+    if (sizeTable == NULL) {
+      return false;
+    }
+
+    const OT::IndexSubtableArray& subtables =
+            OT::StructAtOffset<OT::IndexSubtableArray> (this->cblc, sizeTable->indexSubtableArrayOffset);
+    const OT::IndexSubtable* subtable = subtables.find_table(glyph, sizeTable->numberOfIndexSubtables);
+    if (subtable == NULL) {
+      return false;
+    }
+
+    unsigned int offsetToSubtable = sizeTable->indexSubtableArrayOffset + subtable->offsetToSubtable;
+    const OT::IndexSubHeader& header =
+            OT::StructAtOffset<OT::IndexSubHeader> (this->cblc, offsetToSubtable);
+
+    unsigned int imageDataOffset = header.imageDataOffset;
+    switch (header.indexFormat) {
+      case 1: {
+        const OT::IndexSubtableFormat1& format1 =
+            OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
+        imageDataOffset += format1.offsetArray[glyph - subtable->firstGlyphIndex];
+        switch (header.imageFormat) {
+          case 17: {
+            const OT::GlyphBitmapDataFormat17& glyphFormat17 =
+                OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, imageDataOffset);
+            extents->x_bearing = glyphFormat17.glyphMetrics.bearingX;
+            extents->y_bearing = glyphFormat17.glyphMetrics.bearingY;
+            extents->width = glyphFormat17.glyphMetrics.width;
+            extents->height = -glyphFormat17.glyphMetrics.height;
+          }
+          break;
+          default:
+            // TODO: Support other image formats.
+            return false;
+        }
+      }
+      break;
+      default:
+        // TODO: Support other index subtable format.
+        return false;
+    }
+
+    // Convert to the font units.
+    extents->x_bearing *= upem / (float)(sizeTable->ppemX);
+    extents->y_bearing *= upem / (float)(sizeTable->ppemY);
+    extents->width *= upem / (float)(sizeTable->ppemX);
+    extents->height *= upem / (float)(sizeTable->ppemY);
+
+    return true;
+  }
+};
+
 typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
 					  hb_codepoint_t codepoint,
 					  hb_codepoint_t *glyph);
@@ -379,6 +470,7 @@ struct hb_ot_font_t
   hb_ot_face_metrics_accelerator_t h_metrics;
   hb_ot_face_metrics_accelerator_t v_metrics;
   hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
+  hb_lazy_loader_t<hb_ot_face_ebdt_accelerator_t> ebdt;
 };
 
 
@@ -395,6 +487,7 @@ _hb_ot_font_create (hb_face_t *face)
   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE,
 			   ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
   ot_font->glyf.init (face);
+  ot_font->ebdt.init (face);
 
   return ot_font;
 }
@@ -406,6 +499,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
   ot_font->h_metrics.fini ();
   ot_font->v_metrics.fini ();
   ot_font->glyf.fini ();
+  ot_font->ebdt.fini ();
 
   free (ot_font);
 }
@@ -464,6 +558,8 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   bool ret = ot_font->glyf->get_extents (glyph, extents);
+  if ( !ret )
+    ret = ot_font->ebdt->get_extents (glyph, extents);
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
   extents->width     = font->em_scale_x (extents->width);
commit 261837e7202ec584f653f379851e1c6457396b07
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Oct 28 21:49:11 2016 +0330

    Fix "nmake install" when ADDITIONAL_LIB_DIR is provided and test it on CI (#356)

diff --git a/appveyor.yml b/appveyor.yml
index ddcc9a4..2a0e7c5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -43,6 +43,7 @@ build_script:
   - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"'
   - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32'
   - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib'
+  - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 install'
 
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"'
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"'
diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak
index 41f4bd0..80a5eed 100644
--- a/win32/detectenv-msvc.mak
+++ b/win32/detectenv-msvc.mak
@@ -129,10 +129,10 @@ LDFLAGS_ARCH = /machine:x86
 !if "$(VALID_CFGSET)" == "TRUE"
 CFLAGS = $(CFLAGS_ADD) /W3 /Zi /I.. /I..\src /I. /I$(PREFIX)\include
 
-LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib /DEBUG
 !if "$(ADDITIONAL_LIB_DIR)" != ""
-LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(ADDITIONAL_LIB_DIR)
+ADDITIONAL_LIB_ARG = /libpath:$(ADDITIONAL_LIB_DIR)
 !endif
+LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib $(ADDITIONAL_LIB_ARG) /DEBUG
 
 !if "$(CFG)" == "debug"
 LDFLAGS = $(LDFLAGS_BASE)
diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak
index 7c17a94..57cfb6e 100644
--- a/win32/generate-msvc.mak
+++ b/win32/generate-msvc.mak
@@ -23,4 +23,4 @@ $(HB_GOBJECT_ENUM_GENERATED_SOURCES): ..\src\hb-gobject-enums.h.tmpl ..\src\hb-g
 
 # Create the build directories
 $(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-icu $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util:
-	@-mkdir -p $@
+	@-md $@


More information about the HarfBuzz mailing list