[repack] more PairPos split implementation.
This commit is contained in:
parent
510b8ab101
commit
5024d4de67
|
@ -53,6 +53,11 @@ struct gsubgpos_graph_context_t
|
|||
|
||||
HB_INTERNAL unsigned create_node (unsigned size);
|
||||
|
||||
void add_buffer (char* buffer)
|
||||
{
|
||||
buffers.push (buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
HB_INTERNAL unsigned num_non_ext_subtables ();
|
||||
};
|
||||
|
|
|
@ -119,6 +119,7 @@ struct Lookup : public OT::Lookup
|
|||
return true;
|
||||
|
||||
// TODO check subtable type.
|
||||
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]);
|
||||
|
@ -136,30 +137,84 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head;
|
||||
// TODO sanitize
|
||||
pairPos->split_subtables (c, subtable_index);
|
||||
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);
|
||||
}
|
||||
|
||||
add_sub_tables (c, this_index, all_new_subtables);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void add_sub_tables (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
hb_vector_t<unsigned> subtable_indices)
|
||||
{
|
||||
// bool is_ext = is_extension (c.table_tag);
|
||||
auto& v = c.graph.vertices_[this_index];
|
||||
|
||||
size_t new_size = v.table_size ()
|
||||
+ subtable_indices.length * OT::Offset16::static_size;
|
||||
char* buffer = (char*) hb_calloc (1, new_size);
|
||||
c.add_buffer (buffer);
|
||||
v.obj.head = buffer;
|
||||
v.obj.tail = buffer + new_size;
|
||||
|
||||
memcpy (buffer, v.obj.head, v.table_size());
|
||||
|
||||
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)
|
||||
{
|
||||
// TODO: add extension subtable if needed
|
||||
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->subTable[0];
|
||||
c.graph.vertices_[subtable_id].parents.push (this_index);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned create_extension_subtable (gsubgpos_graph_context_t& c,
|
||||
unsigned lookup_index,
|
||||
unsigned subtable_index,
|
||||
unsigned type)
|
||||
{
|
||||
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
||||
|
||||
unsigned ext_index = c.create_node (extension_size);
|
||||
if (ext_index == (unsigned) -1)
|
||||
return -1;
|
||||
|
||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) ext_vertex.obj.head;
|
||||
extension->reset (type);
|
||||
|
||||
// Make extension point at the subtable.
|
||||
auto* l = ext_vertex.obj.real_links.push ();
|
||||
|
||||
l->width = 4;
|
||||
l->objidx = subtable_index;
|
||||
l->position = 4;
|
||||
|
||||
return ext_index;
|
||||
}
|
||||
|
||||
bool make_subtable_extension (gsubgpos_graph_context_t& c,
|
||||
unsigned lookup_index,
|
||||
unsigned subtable_index)
|
||||
{
|
||||
unsigned type = lookupType;
|
||||
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
||||
|
||||
|
||||
unsigned ext_index = c.create_node (extension_size);
|
||||
unsigned ext_index = create_extension_subtable(c, lookup_index, subtable_index, type);
|
||||
if (ext_index == (unsigned) -1)
|
||||
return false;
|
||||
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) c.graph.object (ext_index).head;
|
||||
extension->reset (type);
|
||||
|
||||
if (ext_index == (unsigned) -1) return false;
|
||||
|
||||
auto& lookup_vertex = c.graph.vertices_[lookup_index];
|
||||
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
||||
{
|
||||
|
@ -171,15 +226,6 @@ struct Lookup : public OT::Lookup
|
|||
// Make extension point at the subtable.
|
||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||
auto& subtable_vertex = c.graph.vertices_[subtable_index];
|
||||
auto* l = ext_vertex.obj.real_links.push ();
|
||||
|
||||
l->width = 4;
|
||||
l->objidx = subtable_index;
|
||||
l->is_signed = 0;
|
||||
l->whence = 0;
|
||||
l->position = 4;
|
||||
l->bias = 0;
|
||||
|
||||
ext_vertex.parents.push (lookup_index);
|
||||
subtable_vertex.remap_parent (lookup_index, ext_index);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace graph {
|
|||
|
||||
struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>
|
||||
{
|
||||
bool split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
{
|
||||
printf("Checking if pair pos %u needs splits...\n", this_index);
|
||||
hb_set_t visited;
|
||||
|
@ -59,10 +59,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: do the split
|
||||
do_split (c, this_index, split_points);
|
||||
|
||||
return true;
|
||||
return do_split (c, this_index, split_points);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -82,29 +79,53 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
{
|
||||
unsigned start = split_points[i];
|
||||
unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len;
|
||||
new_objects.push (clone_range (c, this_index, start, end));
|
||||
// TODO error checking.
|
||||
unsigned id = clone_range (c, this_index, start, end);
|
||||
|
||||
if (id == (unsigned) -1)
|
||||
{
|
||||
new_objects.reset ();
|
||||
new_objects.allocated = -1; // mark error
|
||||
return new_objects;
|
||||
}
|
||||
new_objects.push (id);
|
||||
}
|
||||
|
||||
shrink (c, this_index, split_points[0]);
|
||||
if (!shrink (c, this_index, split_points[0]))
|
||||
{
|
||||
new_objects.reset ();
|
||||
new_objects.allocated = -1; // mark error
|
||||
}
|
||||
|
||||
return new_objects;
|
||||
}
|
||||
|
||||
void shrink (gsubgpos_graph_context_t& c,
|
||||
bool shrink (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
unsigned count)
|
||||
{
|
||||
printf(" shrink to [0, %u).\n", count);
|
||||
unsigned old_count = pairSet.len;
|
||||
if (count >= old_count)
|
||||
return;
|
||||
return true;
|
||||
|
||||
pairSet.len = count;
|
||||
c.graph.vertices_[this_index].obj.tail -= (count - old_count) * SmallTypes::size;
|
||||
|
||||
|
||||
// TODO
|
||||
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
OT::Layout::Common::Coverage* coverage_table =
|
||||
(OT::Layout::Common::Coverage*) c.graph.object (coverage_id).head;
|
||||
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second < count;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return make_coverage (c, new_coverage, coverage_id, coverage_size);
|
||||
}
|
||||
|
||||
// Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
|
||||
|
@ -136,7 +157,6 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
&pair_pos_prime->pairSet[i - start]);
|
||||
}
|
||||
|
||||
|
||||
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
OT::Layout::Common::Coverage* coverage_table =
|
||||
|
@ -150,21 +170,11 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
unsigned coverage_prime_id = c.create_node (coverage_size);
|
||||
unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
|
||||
auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
|
||||
hb_serialize_context_t serializer = hb_serialize_context_t (coverage_prime_vertex.obj.head,
|
||||
coverage_size);
|
||||
Coverage_serialize (&serializer, new_coverage);
|
||||
serializer.end_serialize ();
|
||||
if (serializer.in_error ())
|
||||
if (!make_coverage (c, new_coverage, coverage_prime_id, coverage_size))
|
||||
return -1;
|
||||
|
||||
hb_blob_ptr_t<char*> coverage_copy = serializer.copy_blob ();
|
||||
memcpy (coverage_prime_vertex.obj.head,
|
||||
coverage_copy.get (),
|
||||
coverage_copy.get_length ());
|
||||
coverage_prime_vertex.obj.tail = coverage_prime_vertex.obj.head + coverage_copy.get_length ();
|
||||
|
||||
auto* coverage_link = c.graph.vertices_[pair_pos_prime_id].obj.real_links.push ();
|
||||
coverage_link->width = SmallTypes::size;
|
||||
coverage_link->objidx = coverage_prime_id;
|
||||
|
@ -174,6 +184,34 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
return pair_pos_prime_id;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
bool make_coverage (gsubgpos_graph_context_t& c,
|
||||
It glyphs,
|
||||
unsigned dest_obj,
|
||||
unsigned max_size) const
|
||||
{
|
||||
char* buffer = (char*) hb_calloc (1, max_size);
|
||||
hb_serialize_context_t serializer = hb_serialize_context_t (buffer,
|
||||
max_size);
|
||||
Coverage_serialize (&serializer, glyphs);
|
||||
serializer.end_serialize ();
|
||||
if (serializer.in_error ())
|
||||
{
|
||||
hb_free (buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_bytes_t coverage_copy = serializer.copy_bytes ();
|
||||
c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
|
||||
|
||||
auto& obj = c.graph.vertices_[dest_obj].obj;
|
||||
obj.head = (char *) coverage_copy.arrayZ;
|
||||
obj.tail = obj.head + coverage_copy.length;
|
||||
|
||||
hb_free (buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const
|
||||
{
|
||||
return c.graph.index_for_offset (this_index, &pairSet[i]);
|
||||
|
@ -182,16 +220,16 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
|
||||
struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>
|
||||
{
|
||||
bool split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
return hb_vector_t<unsigned> ();
|
||||
}
|
||||
};
|
||||
|
||||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||
{
|
||||
bool split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
{
|
||||
unsigned format = u.format;
|
||||
printf("PairPos::format = %u\n", format);
|
||||
|
@ -206,7 +244,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
|||
// Don't split 24bit PairPos's.
|
||||
#endif
|
||||
default:
|
||||
return true;
|
||||
return hb_vector_t<unsigned> ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue