[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);
|
HB_INTERNAL unsigned create_node (unsigned size);
|
||||||
|
|
||||||
|
void add_buffer (char* buffer)
|
||||||
|
{
|
||||||
|
buffers.push (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HB_INTERNAL unsigned num_non_ext_subtables ();
|
HB_INTERNAL unsigned num_non_ext_subtables ();
|
||||||
};
|
};
|
||||||
|
|
|
@ -119,6 +119,7 @@ struct Lookup : public OT::Lookup
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO check subtable type.
|
// TODO check subtable type.
|
||||||
|
hb_vector_t<unsigned> all_new_subtables;
|
||||||
for (unsigned i = 0; i < subTable.len; i++)
|
for (unsigned i = 0; i < subTable.len; i++)
|
||||||
{
|
{
|
||||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[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;
|
PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head;
|
||||||
// TODO sanitize
|
// 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;
|
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,
|
bool make_subtable_extension (gsubgpos_graph_context_t& c,
|
||||||
unsigned lookup_index,
|
unsigned lookup_index,
|
||||||
unsigned subtable_index)
|
unsigned subtable_index)
|
||||||
{
|
{
|
||||||
unsigned type = lookupType;
|
unsigned type = lookupType;
|
||||||
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
|
||||||
|
|
||||||
|
unsigned ext_index = create_extension_subtable(c, lookup_index, subtable_index, type);
|
||||||
unsigned ext_index = c.create_node (extension_size);
|
|
||||||
if (ext_index == (unsigned) -1)
|
if (ext_index == (unsigned) -1)
|
||||||
return false;
|
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];
|
auto& lookup_vertex = c.graph.vertices_[lookup_index];
|
||||||
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
||||||
{
|
{
|
||||||
|
@ -171,15 +226,6 @@ struct Lookup : public OT::Lookup
|
||||||
// Make extension point at the subtable.
|
// Make extension point at the subtable.
|
||||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||||
auto& subtable_vertex = c.graph.vertices_[subtable_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);
|
ext_vertex.parents.push (lookup_index);
|
||||||
subtable_vertex.remap_parent (lookup_index, ext_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>
|
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);
|
printf("Checking if pair pos %u needs splits...\n", this_index);
|
||||||
hb_set_t visited;
|
hb_set_t visited;
|
||||||
|
@ -59,10 +59,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: do the split
|
return do_split (c, this_index, split_points);
|
||||||
do_split (c, this_index, split_points);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -82,29 +79,53 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
||||||
{
|
{
|
||||||
unsigned start = split_points[i];
|
unsigned start = split_points[i];
|
||||||
unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len;
|
unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len;
|
||||||
new_objects.push (clone_range (c, this_index, start, end));
|
unsigned id = clone_range (c, this_index, start, end);
|
||||||
// TODO error checking.
|
|
||||||
|
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;
|
return new_objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shrink (gsubgpos_graph_context_t& c,
|
bool shrink (gsubgpos_graph_context_t& c,
|
||||||
unsigned this_index,
|
unsigned this_index,
|
||||||
unsigned count)
|
unsigned count)
|
||||||
{
|
{
|
||||||
printf(" shrink to [0, %u).\n", count);
|
printf(" shrink to [0, %u).\n", count);
|
||||||
unsigned old_count = pairSet.len;
|
unsigned old_count = pairSet.len;
|
||||||
if (count >= old_count)
|
if (count >= old_count)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
pairSet.len = count;
|
pairSet.len = count;
|
||||||
c.graph.vertices_[this_index].obj.tail -= (count - old_count) * SmallTypes::size;
|
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).
|
// 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]);
|
&pair_pos_prime->pairSet[i - start]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||||
OT::Layout::Common::Coverage* coverage_table =
|
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)
|
| 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];
|
auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
|
||||||
hb_serialize_context_t serializer = hb_serialize_context_t (coverage_prime_vertex.obj.head,
|
if (!make_coverage (c, new_coverage, coverage_prime_id, coverage_size))
|
||||||
coverage_size);
|
|
||||||
Coverage_serialize (&serializer, new_coverage);
|
|
||||||
serializer.end_serialize ();
|
|
||||||
if (serializer.in_error ())
|
|
||||||
return -1;
|
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 ();
|
auto* coverage_link = c.graph.vertices_[pair_pos_prime_id].obj.real_links.push ();
|
||||||
coverage_link->width = SmallTypes::size;
|
coverage_link->width = SmallTypes::size;
|
||||||
coverage_link->objidx = coverage_prime_id;
|
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;
|
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
|
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]);
|
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>
|
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
|
// TODO
|
||||||
return true;
|
return hb_vector_t<unsigned> ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
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;
|
unsigned format = u.format;
|
||||||
printf("PairPos::format = %u\n", 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.
|
// Don't split 24bit PairPos's.
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return true;
|
return hb_vector_t<unsigned> ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue