提交 9275bd03 编写于 作者: R Rod Sheeter

First pass at building a cmap

上级 d2170d14
...@@ -254,6 +254,8 @@ struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {}; ...@@ -254,6 +254,8 @@ struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {};
template <typename T> template <typename T>
struct CmapSubtableLongSegmented struct CmapSubtableLongSegmented
{ {
friend struct cmap;
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{ {
int i = groups.bsearch (codepoint); int i = groups.bsearch (codepoint);
...@@ -269,6 +271,20 @@ struct CmapSubtableLongSegmented ...@@ -269,6 +271,20 @@ struct CmapSubtableLongSegmented
return_trace (c->check_struct (this) && groups.sanitize (c)); return_trace (c->check_struct (this) && groups.sanitize (c));
} }
inline bool serialize(hb_serialize_context_t *context,
unsigned int group_count,
Supplier<CmapSubtableLongGroup> &group_supplier)
{
TRACE_SERIALIZE (this);
if (unlikely(!context->extend_min (*this))) return_trace (false);
if (unlikely(!groups.serialize(context, group_count))) return_trace (false);
for (unsigned int i = 0; i < group_count; i++) {
const CmapSubtableLongGroup &group = group_supplier[i];
memcpy(&groups[i], &group, sizeof(group));
}
return true;
}
protected: protected:
HBUINT16 format; /* Subtable format; set to 12. */ HBUINT16 format; /* Subtable format; set to 12. */
HBUINT16 reservedZ; /* Reserved; set to 0. */ HBUINT16 reservedZ; /* Reserved; set to 0. */
...@@ -505,15 +521,15 @@ struct cmap ...@@ -505,15 +521,15 @@ struct cmap
encodingRecord.sanitize (c, this)); encodingRecord.sanitize (c, this));
} }
inline bool subset (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest) const inline void populate_groups(hb_auto_array_t<hb_codepoint_t> &codepoints,
hb_auto_array_t<CmapSubtableLongGroup> *groups) const
{ {
hb_auto_array_t<CmapSubtableLongGroup> groups;
CmapSubtableLongGroup *group = nullptr; CmapSubtableLongGroup *group = nullptr;
for (unsigned int i = 0; i < plan->codepoints.len; i++) { for (unsigned int i = 0; i < codepoints.len; i++) {
hb_codepoint_t cp = plan->codepoints[i]; hb_codepoint_t cp = codepoints[i];
if (!group) if (!group)
{ {
group = groups.push(); group = groups->push();
group->startCharCode.set(cp); group->startCharCode.set(cp);
group->endCharCode.set(cp); group->endCharCode.set(cp);
group->glyphID.set(i); // index in codepoints is new gid group->glyphID.set(i); // index in codepoints is new gid
...@@ -527,13 +543,84 @@ struct cmap ...@@ -527,13 +543,84 @@ struct cmap
} }
DEBUG_MSG(SUBSET, nullptr, "cmap"); DEBUG_MSG(SUBSET, nullptr, "cmap");
for (unsigned int i = 0; i < groups.len; i++) { for (unsigned int i = 0; i < groups->len; i++) {
CmapSubtableLongGroup& group = groups[i]; CmapSubtableLongGroup& group = (*groups)[i];
DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, first gid %d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID); DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
}
}
hb_bool_t _subset (hb_auto_array_t<CmapSubtableLongGroup> &groups,
size_t dest_sz,
void *dest) const
{
hb_serialize_context_t context(dest, dest_sz);
OT::cmap *cmap = context.start_serialize<OT::cmap> ();
if (unlikely(!context.extend_min(*cmap)))
{
return false;
}
cmap->version.set(0);
if (unlikely(!cmap->encodingRecord.serialize(&context, /* numTables */ 1)))
{
return false;
} }
EncodingRecord &rec = cmap->encodingRecord[0];
rec.platformID.set (3); // Windows
rec.encodingID.set (1); // Unicode BMP
CmapSubtable &subtable = rec.subtable.serialize(&context, &rec.subtable);
subtable.u.format.set(12);
CmapSubtableFormat12 &format12 = subtable.u.format12;
format12.format.set(12);
format12.reservedZ.set(0);
OT::Supplier<CmapSubtableLongGroup> group_supplier (&groups[0], groups.len, sizeof (CmapSubtableLongGroup));
if (unlikely(!format12.serialize(&context, groups.len, group_supplier)))
{
return false;
}
context.end_serialize ();
return true; return true;
} }
hb_blob_t * subset (hb_subset_plan_t *plan, hb_face_t *source) const
{
hb_auto_array_t<CmapSubtableLongGroup> groups;
populate_groups(plan->codepoints, &groups);
// We now know how big our blob needs to be
// TODO use APIs from the structs to get size?
size_t dest_sz = 4 // header
+ 8 // 1 EncodingRecord
+ 16 // Format 12 header
+ 12 * groups.len; // SequentialMapGroup records
void *dest = calloc(dest_sz, 1);
if (unlikely(!dest)) {
DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %ld for cmap subset output", dest_sz);
return nullptr;
}
if (unlikely(!_subset(groups, dest_sz, dest)))
{
free(dest);
return nullptr;
}
// all done, write the blob into dest
return hb_blob_create((const char *)dest,
dest_sz,
HB_MEMORY_MODE_READONLY,
/* userdata */ nullptr,
free);
}
struct accelerator_t struct accelerator_t
{ {
inline void init (hb_face_t *face) inline void init (hb_face_t *face)
......
...@@ -108,19 +108,19 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input) ...@@ -108,19 +108,19 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
} }
template<typename TableType> template<typename TableType>
hb_bool_t hb_blob_t *
subset (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest) _subset (hb_subset_plan_t *plan, hb_face_t *source)
{ {
OT::Sanitizer<TableType> sanitizer; OT::Sanitizer<TableType> sanitizer;
hb_blob_t *table_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag)); hb_blob_t *source_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag));
if (unlikely(!table_blob)) { if (unlikely(!source_blob)) {
DEBUG_MSG(SUBSET, nullptr, "Failed to reference table for tag %d", TableType::tableTag); DEBUG_MSG(SUBSET, nullptr, "Failed to reference table for tag %d", TableType::tableTag);
return false; return nullptr;
} }
const TableType *table = OT::Sanitizer<TableType>::lock_instance (table_blob); const TableType *table = OT::Sanitizer<TableType>::lock_instance (source_blob);
hb_bool_t result = table->subset(plan, source, dest); hb_blob_t *result = table->subset(plan, source);
hb_blob_destroy (table_blob); hb_blob_destroy (source_blob);
hb_tag_t tag = TableType::tableTag; hb_tag_t tag = TableType::tableTag;
DEBUG_MSG(SUBSET, nullptr, "Subset %c%c%c%c %s", HB_UNTAG(tag), result ? "success" : "FAILED!"); DEBUG_MSG(SUBSET, nullptr, "Subset %c%c%c%c %s", HB_UNTAG(tag), result ? "success" : "FAILED!");
...@@ -242,7 +242,6 @@ hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) ...@@ -242,7 +242,6 @@ hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
return false; return false;
hb_subset_face_data_t *data = (hb_subset_face_data_t *) face->user_data; 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.push (); hb_subset_face_data_t::table_entry_t *entry = data->tables.push ();
if (unlikely (!entry)) if (unlikely (!entry))
return false; return false;
...@@ -306,10 +305,12 @@ bool ...@@ -306,10 +305,12 @@ bool
_subset_table (hb_subset_plan_t *plan, _subset_table (hb_subset_plan_t *plan,
hb_face_t *source, hb_face_t *source,
hb_tag_t tag, hb_tag_t tag,
hb_blob_t *table_blob, hb_blob_t *source_blob,
hb_face_t *dest) hb_face_t *dest)
{ {
// TODO (grieger): Handle updating the head table (loca format + num glyphs) // TODO (grieger): Handle updating the head table (loca format + num glyphs)
DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG(tag));
hb_blob_t *dest_blob;
switch (tag) { switch (tag) {
case HB_OT_TAG_glyf: case HB_OT_TAG_glyf:
return _subset_glyf (plan, source, dest); return _subset_glyf (plan, source, dest);
...@@ -320,14 +321,16 @@ _subset_table (hb_subset_plan_t *plan, ...@@ -320,14 +321,16 @@ _subset_table (hb_subset_plan_t *plan,
// SKIP loca, it's handle by glyf // SKIP loca, it's handle by glyf
return true; return true;
case HB_OT_TAG_cmap: case HB_OT_TAG_cmap:
// TODO(rsheeter): remove hb_subset_face_add_table dest_blob = _subset<const OT::cmap> (plan, source);
// once cmap subsetting works. break;
hb_subset_face_add_table (dest, tag, table_blob);
return subset<const OT::cmap> (plan, source, dest);
default: default:
// Default action, copy table as is. dest_blob = source_blob;
return hb_subset_face_add_table (dest, tag, table_blob); break;
} }
DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), dest_blob ? "ok" : "FAILED");
if (unlikely(!dest_blob)) return false;
if (unlikely(!hb_subset_face_add_table (dest, tag, dest_blob))) return false;
return true;
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册