[subset] Caclculate head table checksum adjustment

Test still fails, because we do not serialize tables in the same
order that fonttools subsetter does.
This commit is contained in:
Behdad Esfahbod 2018-02-23 16:42:06 -08:00 committed by Garret Rieger
parent 7e5e1feb66
commit dc5c7927e7
3 changed files with 43 additions and 12 deletions

View File

@ -30,6 +30,7 @@
#define HB_OPEN_FILE_PRIVATE_HH #define HB_OPEN_FILE_PRIVATE_HH
#include "hb-open-type-private.hh" #include "hb-open-type-private.hh"
#include "hb-ot-head-table.hh"
namespace OT { namespace OT {
@ -135,13 +136,15 @@ typedef struct OffsetTable
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
/* Alloc 12 for the OTHeader. */ /* Alloc 12 for the OTHeader. */
if (unlikely (!c->extend_min (*this))) return_trace (false); if (unlikely (!c->extend_min (*this))) return_trace (false);
/* Write sfntVersion (bytes 0..3) */ /* Write sfntVersion (bytes 0..3). */
sfnt_version.set (sfnt_tag); sfnt_version.set (sfnt_tag);
/* Take space for numTables, searchRange, entrySelector, RangeShift /* 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); 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. */ /* Write OffsetTables, alloc for and write actual table blobs. */
for (unsigned int i = 0; i < table_count; i++) for (unsigned int i = 0; i < table_count; i++)
{ {
@ -150,24 +153,48 @@ typedef struct OffsetTable
rec.tag.set (tags[i]); rec.tag.set (tags[i]);
rec.length.set (hb_blob_get_length (blob)); rec.length.set (hb_blob_get_length (blob));
rec.offset.serialize (c, this); rec.offset.serialize (c, this);
/* Allocate room for the table. */
void *p = c->allocate_size<void> (rec.length); /* Allocate room for the table and copy it. */
const char *start = (const char *) p; char *start = (char *) c->allocate_size<void> (rec.length);
if (unlikely (!p)) {return false;} if (unlikely (!start)) {return false;}
/* copy the actual table. */
memcpy (p, hb_blob_get_data (blob, nullptr), rec.length); memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
/* 4-byte allignment. */ /* 4-byte allignment. */
if (rec.length % 4) 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; 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); rec.checkSum.set_for_data (start, end - start);
} }
tags += table_count; tags += table_count;
blobs += table_count; blobs += table_count;
/* TODO: update head table checkSumAdjustment. */
tables.qsort (); 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); return_trace (true);
} }

View File

@ -43,6 +43,8 @@ namespace OT {
struct head struct head
{ {
friend struct OffsetTable;
static const hb_tag_t tableTag = HB_OT_TAG_head; static const hb_tag_t tableTag = HB_OT_TAG_head;
inline unsigned int get_upem (void) const inline unsigned int get_upem (void) const

View File

@ -198,6 +198,8 @@ _hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
return nullptr; 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_face_t *
hb_subset_face_create (void) hb_subset_face_create (void)
{ {