diff --git a/src/hb-priority-queue.hh b/src/hb-priority-queue.hh index 6fd1a8d0b..68b17fdc6 100644 --- a/src/hb-priority-queue.hh +++ b/src/hb-priority-queue.hh @@ -43,7 +43,7 @@ struct hb_priority_queue_t ~hb_priority_queue_t () { fini (); } private: - typedef hb_pair_t item_t; + typedef hb_pair_t item_t; hb_vector_t heap; public: @@ -55,7 +55,7 @@ struct hb_priority_queue_t bool in_error () const { return heap.in_error (); } - void insert (unsigned value, unsigned priority) + void insert (unsigned value, int64_t priority) { heap.push (item_t (value, priority)); bubble_up (heap.length - 1); diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh index 90d73b30c..1eebdd137 100644 --- a/src/hb-repacker.hh +++ b/src/hb-repacker.hh @@ -161,7 +161,7 @@ struct graph_t return; } - hb_hashmap_t distance_to; + hb_vector_t distance_to; compute_distances (&distance_to); hb_set_t queue; @@ -242,15 +242,16 @@ struct graph_t private: unsigned closest_object (const hb_set_t& queue, - const hb_hashmap_t& distance_to) + const hb_vector_t distance_to) { + // TODO(garretrieger): use a priority queue. int64_t closest_distance = hb_int_max (int64_t); unsigned closest_index = -1; for (unsigned i : queue) { - if (distance_to.get (i) < closest_distance) + if (distance_to[i] < closest_distance) { - closest_distance = distance_to.get (i); + closest_distance = distance_to[i]; closest_index = i; } } @@ -262,51 +263,41 @@ struct graph_t * Finds the distance too each object in the graph * from the initial node. */ - void compute_distances (hb_hashmap_t* distance_to) + void compute_distances (hb_vector_t* distance_to) { // Uses Dijkstra's algorithm to find all of the shortest distances. // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm - distance_to->clear (); + distance_to->resize (0); + distance_to->resize (objects_.length); + for (unsigned i = 0; i < objects_.length; i++) + (*distance_to)[i] = hb_int_max (int64_t); + (*distance_to)[objects_.length - 1] = 0; + hb_set_t unvisited; unvisited.add_range (0, objects_.length - 1); - unsigned current_idx = objects_.length - 1; - distance_to->set (current_idx, 0); - - while (unvisited.get_population ()) + while (!unvisited.is_empty ()) { - const auto& current = objects_[current_idx]; - int current_distance = (*distance_to)[current_idx]; + unsigned next_idx = closest_object (unvisited, *distance_to); + const auto& next = objects_[next_idx]; + int next_distance = (*distance_to)[next_idx]; + unvisited.del (next_idx); - for (const auto& link : current.links) + for (const auto& link : next.links) { if (!unvisited.has (link.objidx)) continue; const auto& child = objects_[link.objidx]; int64_t child_weight = child.tail - child.head + (!link.is_wide ? (1 << 16) : ((int64_t) 1 << 32)); - int64_t child_distance = current_distance + child_weight; + int64_t child_distance = next_distance + child_weight; - if (child_distance < distance_to->get (link.objidx)) - distance_to->set (link.objidx, child_distance); + if (child_distance < (*distance_to)[link.objidx]) + (*distance_to)[link.objidx] = child_distance; } - - unvisited.del (current_idx); - - // TODO(garretrieger): change this to use a priority queue. - int64_t smallest_distance = hb_int_max(int64_t); - for (hb_codepoint_t idx : unvisited) - { - if (distance_to->get (idx) < smallest_distance) - { - smallest_distance = distance_to->get (idx); - current_idx = idx; - } - } - - // TODO(garretrieger): this will trigger if graph is disconnected. Handle this. - assert (!unvisited.get_population () || smallest_distance != hb_int_max (int64_t)); } + // TODO(garretrieger): Handle this. If anything is left, part of the graph is disconnected. + assert (unvisited.is_empty ()); } int64_t compute_offset ( diff --git a/src/test-repacker.cc b/src/test-repacker.cc index 46554e1cd..a070cddaf 100644 --- a/src/test-repacker.cc +++ b/src/test-repacker.cc @@ -271,6 +271,8 @@ static void test_will_overflow_2 () assert (graph.will_overflow ()); } +// TODO(garretrieger): add a test(s) using a real font. + int main (int argc, char **argv) {