diff --git a/src/graph/pairpos-graph.hh b/src/graph/pairpos-graph.hh index 245d519ec..ae18fbd03 100644 --- a/src/graph/pairpos-graph.hh +++ b/src/graph/pairpos-graph.hh @@ -273,6 +273,9 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4& device_tables; const hb_vector_t& format1_device_table_indices; @@ -307,7 +310,10 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4valueFormat2 = this->valueFormat2; pair_pos_prime->class1Count = this->class1Count; pair_pos_prime->class2Count = this->class2Count; - clone_class1_records (split_context, pair_pos_prime, start, end); + clone_class1_records (split_context, + pair_pos_prime_id, + start, + end); unsigned coverage_id = split_context.c.graph.index_for_offset (split_context.this_index, &coverage); @@ -330,16 +336,82 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter ())) return -1; - // TODO: class def 2 (just link to existing) + // classDef2 + unsigned class_def_2_id = + split_context.c.graph.index_for_offset (split_context.this_index, &classDef2); + auto* class_def_link = split_context.c.graph.vertices_[pair_pos_prime_id].obj.real_links.push (); + class_def_link->width = SmallTypes::size; + class_def_link->objidx = class_def_2_id; + class_def_link->position = 10; + split_context.c.graph.vertices_[class_def_2_id].parents.push (pair_pos_prime_id); - return -1; // TODO + return pair_pos_prime_id; } void clone_class1_records (split_context& split_context, - PairPosFormat2* pair_pos_prime, + unsigned pair_pos_prime_id, unsigned start, unsigned end) const { - // TODO: implement, in addition to copying the records, also move device tables as needed. + PairPosFormat2* pair_pos_prime = + (PairPosFormat2*) split_context.c.graph.object (pair_pos_prime_id).head; + + char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size; + unsigned num_records = end - start; + memcpy (&pair_pos_prime->values[0], + start_addr, + num_records * split_context.class1_record_size); + + if (!split_context.format1_device_table_indices + && !split_context.format2_device_table_indices) + // No device tables to move over. + return; + + unsigned class2_count = class2Count; + for (unsigned i = start; i < end; i++) + { + for (unsigned j = 0; j < class2_count; j++) + { + unsigned value1_index = split_context.value_record_len * (class2_count * i + j); + unsigned value2_index = value1_index + split_context.value1_record_len; + + unsigned new_value1_index = split_context.value_record_len * (class2_count * (i - start) + j); + unsigned new_value2_index = new_value1_index + split_context.value1_record_len; + + transfer_device_tables (split_context, + pair_pos_prime_id, + split_context.format1_device_table_indices, + value1_index, + new_value1_index); + + transfer_device_tables (split_context, + pair_pos_prime_id, + split_context.format2_device_table_indices, + value2_index, + new_value2_index); + } + } + } + + void transfer_device_tables (split_context& split_context, + unsigned pair_pos_prime_id, + const hb_vector_t& device_table_indices, + unsigned old_value_record_index, + unsigned new_value_record_index) const + { + PairPosFormat2* pair_pos_prime = + (PairPosFormat2*) split_context.c.graph.object (pair_pos_prime_id).head; + + for (unsigned i : device_table_indices) + { + OT::Offset16* record = (OT::Offset16*) &values[old_value_record_index + i]; + if (!split_context.device_tables.has ((void*) record)) continue; + + split_context.c.graph.move_child ( + split_context.this_index, + record, + pair_pos_prime_id, + (OT::Offset16*) &pair_pos_prime->values[new_value_record_index + i]); + } } bool shrink (gsubgpos_graph_context_t& c,