|
|
|
@ -124,7 +124,7 @@ struct Lookup : public OT::Lookup |
|
|
|
|
if (!is_ext && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
hb_vector_t<unsigned> all_new_subtables; |
|
|
|
|
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>> all_new_subtables; |
|
|
|
|
for (unsigned i = 0; i < subTable.len; i++) |
|
|
|
|
{ |
|
|
|
|
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]); |
|
|
|
@ -147,11 +147,14 @@ struct Lookup : public OT::Lookup |
|
|
|
|
|
|
|
|
|
hb_vector_t<unsigned> new_sub_tables = pairPos->split_subtables (c, subtable_index); |
|
|
|
|
if (new_sub_tables.in_error ()) return false; |
|
|
|
|
+ new_sub_tables.iter() | hb_sink (all_new_subtables); |
|
|
|
|
hb_pair_t<unsigned, hb_vector_t<unsigned>>* entry = all_new_subtables.push (); |
|
|
|
|
entry->first = i; |
|
|
|
|
entry->second = std::move (new_sub_tables); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (all_new_subtables) |
|
|
|
|
if (all_new_subtables) { |
|
|
|
|
add_sub_tables (c, this_index, type, all_new_subtables); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -159,13 +162,18 @@ struct Lookup : public OT::Lookup |
|
|
|
|
void add_sub_tables (gsubgpos_graph_context_t& c, |
|
|
|
|
unsigned this_index, |
|
|
|
|
unsigned type, |
|
|
|
|
hb_vector_t<unsigned>& subtable_indices) |
|
|
|
|
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids) |
|
|
|
|
{ |
|
|
|
|
bool is_ext = is_extension (c.table_tag); |
|
|
|
|
auto& v = c.graph.vertices_[this_index]; |
|
|
|
|
fix_existing_subtable_links (c, this_index, subtable_ids); |
|
|
|
|
|
|
|
|
|
unsigned new_subtable_count = 0; |
|
|
|
|
for (const auto& p : subtable_ids) |
|
|
|
|
new_subtable_count += p.second.length; |
|
|
|
|
|
|
|
|
|
size_t new_size = v.table_size () |
|
|
|
|
+ subtable_indices.length * OT::Offset16::static_size; |
|
|
|
|
+ new_subtable_count * OT::Offset16::static_size; |
|
|
|
|
char* buffer = (char*) hb_calloc (1, new_size); |
|
|
|
|
c.add_buffer (buffer); |
|
|
|
|
memcpy (buffer, v.obj.head, v.table_size()); |
|
|
|
@ -175,30 +183,56 @@ struct Lookup : public OT::Lookup |
|
|
|
|
|
|
|
|
|
Lookup* new_lookup = (Lookup*) buffer; |
|
|
|
|
|
|
|
|
|
new_lookup->subTable.len = subTable.len + subtable_indices.length; |
|
|
|
|
unsigned offset_index = subTable.len; |
|
|
|
|
for (unsigned subtable_id : subtable_indices) |
|
|
|
|
new_lookup->subTable.len = subTable.len + new_subtable_count; |
|
|
|
|
for (const auto& p : subtable_ids) |
|
|
|
|
{ |
|
|
|
|
if (is_ext) |
|
|
|
|
unsigned offset_index = p.first + 1; |
|
|
|
|
for (unsigned subtable_id : p.second) |
|
|
|
|
{ |
|
|
|
|
unsigned ext_id = create_extension_subtable (c, subtable_id, type); |
|
|
|
|
c.graph.vertices_[subtable_id].parents.push (ext_id); |
|
|
|
|
subtable_id = ext_id; |
|
|
|
|
if (is_ext) |
|
|
|
|
{ |
|
|
|
|
unsigned ext_id = create_extension_subtable (c, subtable_id, type); |
|
|
|
|
c.graph.vertices_[subtable_id].parents.push (ext_id); |
|
|
|
|
subtable_id = ext_id; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto* link = v.obj.real_links.push (); |
|
|
|
|
link->width = 2; |
|
|
|
|
link->objidx = subtable_id; |
|
|
|
|
link->position = (char*) &new_lookup->subTable[offset_index++] - |
|
|
|
|
(char*) new_lookup; |
|
|
|
|
c.graph.vertices_[subtable_id].parents.push (this_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto* link = v.obj.real_links.push (); |
|
|
|
|
link->width = 2; |
|
|
|
|
link->objidx = subtable_id; |
|
|
|
|
link->position = (char*) &new_lookup->subTable[offset_index++] - |
|
|
|
|
(char*) new_lookup; |
|
|
|
|
c.graph.vertices_[subtable_id].parents.push (this_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Repacker sort order depends on link order, which we've messed up so resort it.
|
|
|
|
|
v.obj.real_links.qsort (); |
|
|
|
|
|
|
|
|
|
// The head location of the lookup has changed, invalidating the lookups map entry
|
|
|
|
|
// in the context. Update the map.
|
|
|
|
|
c.lookups.set (this_index, new_lookup); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void fix_existing_subtable_links (gsubgpos_graph_context_t& c, |
|
|
|
|
unsigned this_index, |
|
|
|
|
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids) |
|
|
|
|
{ |
|
|
|
|
auto& v = c.graph.vertices_[this_index]; |
|
|
|
|
Lookup* lookup = (Lookup*) v.obj.head; |
|
|
|
|
|
|
|
|
|
for (const auto& p : subtable_ids) |
|
|
|
|
{ |
|
|
|
|
unsigned insert_index = p.first; |
|
|
|
|
unsigned pos_offset = p.second.length * OT::Offset16::static_size; |
|
|
|
|
unsigned insert_offset = (char*) &lookup->subTable[insert_index] - (char*) lookup; |
|
|
|
|
|
|
|
|
|
for (auto& l : v.obj.all_links_writer ()) |
|
|
|
|
{ |
|
|
|
|
if (l.position > insert_offset) l.position += pos_offset; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
unsigned create_extension_subtable (gsubgpos_graph_context_t& c, |
|
|
|
|
unsigned subtable_index, |
|
|
|
|
unsigned type) |
|
|
|
|