[subset] Caclculate head table checksum adjustment
authorBehdad Esfahbod <behdad@behdad.org>
Sat, 24 Feb 2018 00:42:06 +0000 (16:42 -0800)
committerGarret Rieger <grieger@google.com>
Sat, 24 Feb 2018 00:59:53 +0000 (16:59 -0800)
Test still fails, because we do not serialize tables in the same
order that fonttools subsetter does.

src/hb-open-file-private.hh
src/hb-ot-head-table.hh
src/hb-subset.cc

index 701935b..e2644ea 100644 (file)
@@ -30,6 +30,7 @@
 #define HB_OPEN_FILE_PRIVATE_HH
 
 #include "hb-open-type-private.hh"
+#include "hb-ot-head-table.hh"
 
 
 namespace OT {
@@ -135,13 +136,15 @@ typedef struct OffsetTable
     TRACE_SERIALIZE (this);
     /* Alloc 12 for the OTHeader. */
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    /* Write sfntVersion (bytes 0..3) */
+    /* Write sfntVersion (bytes 0..3). */
     sfnt_version.set (sfnt_tag);
     /* Take space for numTables, searchRange, entrySelector, RangeShift
-     * and the TableRecords themselves
-     */
+     * and the TableRecords themselves.  */
     if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
 
+    const char *dir_end = (const char *) c->head;
+    HBUINT32 *checksum_adjustment = nullptr;
+
     /* Write OffsetTables, alloc for and write actual table blobs. */
     for (unsigned int i = 0; i < table_count; i++)
     {
@@ -150,24 +153,48 @@ typedef struct OffsetTable
       rec.tag.set (tags[i]);
       rec.length.set (hb_blob_get_length (blob));
       rec.offset.serialize (c, this);
-      /* Allocate room for the table. */
-      void *p = c->allocate_size<void> (rec.length);
-      const char *start = (const char *) p;
-      if (unlikely (!p)) {return false;}
-      /* copy the actual table. */
-      memcpy (p, hb_blob_get_data (blob, nullptr), rec.length);
+
+      /* Allocate room for the table and copy it. */
+      char *start = (char *) c->allocate_size<void> (rec.length);
+      if (unlikely (!start)) {return false;}
+
+      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
+
       /* 4-byte allignment. */
       if (rec.length % 4)
-       p = c->allocate_size<void> (4 - rec.length % 4);
+       c->allocate_size<void> (4 - rec.length % 4);
       const char *end = (const char *) c->head;
+
+      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
+      {
+       head *h = (head *) start;
+       checksum_adjustment = &h->checkSumAdjustment;
+       checksum_adjustment->set (0);
+      }
+
       rec.checkSum.set_for_data (start, end - start);
     }
     tags += table_count;
     blobs += table_count;
 
-    /* TODO: update head table checkSumAdjustment. */
-
     tables.qsort ();
+
+    if (checksum_adjustment)
+    {
+      CheckSum checksum;
+
+      /* The following line is a slower version of the following block. */
+      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
+      checksum.set_for_data (this, dir_end - (const char *) this);
+      for (unsigned int i = 0; i < table_count; i++)
+      {
+       TableRecord &rec = tables.array[i];
+       checksum.set (checksum + rec.checkSum);
+      }
+
+      checksum_adjustment->set (0xB1B0AFBAu - checksum);
+    }
+
     return_trace (true);
   }
 
index 2024cea..1d45840 100644 (file)
@@ -43,6 +43,8 @@ namespace OT {
 
 struct head
 {
+  friend struct OffsetTable;
+
   static const hb_tag_t tableTag       = HB_OT_TAG_head;
 
   inline unsigned int get_upem (void) const
index 3a0ddb0..12cdb1d 100644 (file)
@@ -198,6 +198,8 @@ _hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
   return nullptr;
 }
 
+/* TODO: Move this to hb-face.h and rename to hb_face_builder_create()
+ * with hb_face_builder_add_table(). */
 hb_face_t *
 hb_subset_face_create (void)
 {