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

First pass at building a cmap

上级 d2170d14
......@@ -254,6 +254,8 @@ struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {};
template <typename T>
struct CmapSubtableLongSegmented
{
friend struct cmap;
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
int i = groups.bsearch (codepoint);
......@@ -269,6 +271,20 @@ struct CmapSubtableLongSegmented
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:
HBUINT16 format; /* Subtable format; set to 12. */
HBUINT16 reservedZ; /* Reserved; set to 0. */
......@@ -505,15 +521,15 @@ struct cmap
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;
for (unsigned int i = 0; i < plan->codepoints.len; i++) {
hb_codepoint_t cp = plan->codepoints[i];
for (unsigned int i = 0; i < codepoints.len; i++) {
hb_codepoint_t cp = codepoints[i];
if (!group)
{
group = groups.push();
group = groups->push();
group->startCharCode.set(cp);
group->endCharCode.set(cp);
group->glyphID.set(i); // index in codepoints is new gid
......@@ -527,13 +543,84 @@ struct cmap
}
DEBUG_MSG(SUBSET, nullptr, "cmap");
for (unsigned int i = 0; i < groups.len; 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);
for (unsigned int i = 0; i < groups->len; i++) {
CmapSubtableLongGroup& group = (*groups)[i];
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;
}
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
{
inline void init (hb_face_t *face)
......
......@@ -108,19 +108,19 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
}
template<typename TableType>
hb_bool_t
subset (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
hb_blob_t *
_subset (hb_subset_plan_t *plan, hb_face_t *source)
{
OT::Sanitizer<TableType> sanitizer;
hb_blob_t *table_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag));
if (unlikely(!table_blob)) {
hb_blob_t *source_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag));
if (unlikely(!source_blob)) {
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);
hb_bool_t result = table->subset(plan, source, dest);
const TableType *table = OT::Sanitizer<TableType>::lock_instance (source_blob);
hb_blob_t *result = table->subset(plan, source);
hb_blob_destroy (table_blob);
hb_blob_destroy (source_blob);
hb_tag_t tag = TableType::tableTag;
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)
return false;
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 ();
if (unlikely (!entry))
return false;
......@@ -306,10 +305,12 @@ bool
_subset_table (hb_subset_plan_t *plan,
hb_face_t *source,
hb_tag_t tag,
hb_blob_t *table_blob,
hb_blob_t *source_blob,
hb_face_t *dest)
{
// 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) {
case HB_OT_TAG_glyf:
return _subset_glyf (plan, source, dest);
......@@ -320,14 +321,16 @@ _subset_table (hb_subset_plan_t *plan,
// SKIP loca, it's handle by glyf
return true;
case HB_OT_TAG_cmap:
// TODO(rsheeter): remove hb_subset_face_add_table
// once cmap subsetting works.
hb_subset_face_add_table (dest, tag, table_blob);
return subset<const OT::cmap> (plan, source, dest);
dest_blob = _subset<const OT::cmap> (plan, source);
break;
default:
// Default action, copy table as is.
return hb_subset_face_add_table (dest, tag, table_blob);
}
dest_blob = source_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.
先完成此消息的编辑!
想要评论请 注册