[repacker] Expose on internal method in the repacker that allows the caller to pass in/out a graph.

Will be used in testing so we can compare graphs instead of packed result.
diff --git a/src/graph/graph.hh b/src/graph/graph.hh
index 5f23414..0d3dae2 100644
--- a/src/graph/graph.hh
+++ b/src/graph/graph.hh
@@ -196,7 +196,8 @@
       : parents_invalid (true),
         distance_invalid (true),
         positions_invalid (true),
-        successful (true)
+        successful (true),
+        buffers ()
   {
     num_roots_for_space_.push (1);
     bool removed_nil = false;
@@ -228,6 +229,8 @@
   ~graph_t ()
   {
     vertices_.fini ();
+    for (char* b : buffers)
+      hb_free (b);
   }
 
   bool in_error () const
@@ -255,6 +258,11 @@
     return vertices_[i].obj;
   }
 
+  void add_buffer (char* buffer)
+  {
+    buffers.push (buffer);
+  }
+
   /*
    * Adds a 16 bit link from parent_id to child_id
    */
@@ -1127,6 +1135,7 @@
   bool positions_invalid;
   bool successful;
   hb_vector_t<unsigned> num_roots_for_space_;
+  hb_vector_t<char*> buffers;
 };
 
 }
diff --git a/src/graph/gsubgpos-context.cc b/src/graph/gsubgpos-context.cc
index e0ff6ff..b204442 100644
--- a/src/graph/gsubgpos-context.cc
+++ b/src/graph/gsubgpos-context.cc
@@ -33,8 +33,7 @@
     : table_tag (table_tag_),
       graph (graph_),
       lookup_list_index (0),
-      lookups (),
-      buffers ()
+      lookups ()
 {
   if (table_tag_ != HB_OT_TAG_GPOS
       &&  table_tag_ != HB_OT_TAG_GSUB)
@@ -53,7 +52,7 @@
   if (!buffer)
     return -1;
 
-  buffers.push (buffer);
+  add_buffer (buffer);
 
   return graph.new_node (buffer, buffer + size);
 }
diff --git a/src/graph/gsubgpos-context.hh b/src/graph/gsubgpos-context.hh
index 49b2419..9fe9662 100644
--- a/src/graph/gsubgpos-context.hh
+++ b/src/graph/gsubgpos-context.hh
@@ -40,22 +40,16 @@
   graph_t& graph;
   unsigned lookup_list_index;
   hb_hashmap_t<unsigned, graph::Lookup*> lookups;
-  hb_vector_t<char*> buffers;
+
 
   HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
                                         graph_t& graph_);
 
-  ~gsubgpos_graph_context_t ()
-  {
-    for (char* b : buffers)
-      hb_free (b);
-  }
-
   HB_INTERNAL unsigned create_node (unsigned size);
 
   void add_buffer (char* buffer)
   {
-    buffers.push (buffer);
+    graph.add_buffer (buffer);
   }
 
  private:
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index 61b1422..48a3fe4 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -276,35 +276,20 @@
   return resolution_attempted;
 }
 
-/*
- * Attempts to modify the topological sorting of the provided object graph to
- * eliminate offset overflows in the links between objects of the graph. If a
- * non-overflowing ordering is found the updated graph is serialized it into the
- * provided serialization context.
- *
- * If necessary the structure of the graph may be modified in ways that do not
- * affect the functionality of the graph. For example shared objects may be
- * duplicated.
- *
- * For a detailed writeup describing how the algorithm operates see:
- * docs/repacker.md
- */
-template<typename T>
-inline hb_blob_t*
-hb_resolve_overflows (const T& packed,
-                      hb_tag_t table_tag,
-                      unsigned max_rounds = 20,
-                      bool recalculate_extensions = false) {
-  graph_t sorted_graph (packed);
+inline bool
+hb_resolve_graph_overflows (hb_tag_t table_tag,
+                            unsigned max_rounds ,
+                            bool recalculate_extensions,
+                            graph_t& sorted_graph /* IN/OUT */)
+{
   sorted_graph.sort_shortest_distance ();
 
   bool will_overflow = graph::will_overflow (sorted_graph);
   if (!will_overflow)
-  {
-    return graph::serialize (sorted_graph);
-  }
+    return true;
 
-  graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
+  // TODO attach to graph? or just move buffers to the graph?
+  graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph); // TODO lifetime
   if ((table_tag == HB_OT_TAG_GPOS
        ||  table_tag == HB_OT_TAG_GSUB)
       && will_overflow)
@@ -314,13 +299,13 @@
       DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
       if (!_presplit_subtables_if_needed (ext_context)) {
         DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
-        return nullptr;
+        return false;
       }
 
       DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
       if (!_promote_extensions_if_needed (ext_context)) {
         DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed.");
-        return nullptr;
+        return false;
       }
     }
 
@@ -360,15 +345,41 @@
   if (sorted_graph.in_error ())
   {
     DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state.");
-    return nullptr;
+    return false;
   }
 
   if (graph::will_overflow (sorted_graph))
   {
     DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
-    return nullptr;
+    return false;
   }
 
+  return true;
+}
+
+/*
+ * Attempts to modify the topological sorting of the provided object graph to
+ * eliminate offset overflows in the links between objects of the graph. If a
+ * non-overflowing ordering is found the updated graph is serialized it into the
+ * provided serialization context.
+ *
+ * If necessary the structure of the graph may be modified in ways that do not
+ * affect the functionality of the graph. For example shared objects may be
+ * duplicated.
+ *
+ * For a detailed writeup describing how the algorithm operates see:
+ * docs/repacker.md
+ */
+template<typename T>
+inline hb_blob_t*
+hb_resolve_overflows (const T& packed,
+                      hb_tag_t table_tag,
+                      unsigned max_rounds = 20,
+                      bool recalculate_extensions = false) {
+  graph_t sorted_graph (packed);
+  if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph))
+    return nullptr;
+
   return graph::serialize (sorted_graph);
 }