[repacker] add 'virtual links' to the serializer.
These aren't associated with an offset field, but instead exist solely to add an ordering constraint to the object graph.
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index 72b3185..26faa56 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -828,8 +828,9 @@
if (visited[link.objidx]) continue;
const auto& child = vertices_[link.objidx].obj;
+ unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
int64_t child_weight = (child.tail - child.head) +
- ((int64_t) 1 << (link.width * 8)) * (vertices_[link.objidx].space + 1);
+ ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
int64_t child_distance = next_distance + child_weight;
if (child_distance < vertices_[link.objidx].distance)
@@ -874,6 +875,10 @@
bool is_valid_offset (int64_t offset,
const hb_serialize_context_t::object_t::link_t& link) const
{
+ if (unlikely (!link.width))
+ // Virtual links can't overflow.
+ return link.is_signed || offset >= 0;
+
if (link.is_signed)
{
if (link.width == 4)
@@ -966,6 +971,9 @@
{
switch (link.width)
{
+ case 0:
+ // Virtual links aren't serialized.
+ return;
case 4:
if (link.is_signed)
{
diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh
index 7b83fe1..f4c8fab 100644
--- a/src/hb-serialize.hh
+++ b/src/hb-serialize.hh
@@ -51,6 +51,12 @@
};
HB_MARK_AS_FLAG_T (hb_serialize_error_t);
+// This is a 0 byte wide offset, used to add virtual links to the serializer object graph.
+// It does not correspond to a real offset and exists soley to enforce an ordering constraint
+// in the graph's packed order.
+struct VirtualOffset {
+};
+
struct hb_serialize_context_t
{
typedef unsigned objidx_t;
@@ -376,11 +382,22 @@
err (HB_SERIALIZE_ERROR_OTHER);
link.width = sizeof (T);
+ link.objidx = objidx;
+ if (unlikely (!sizeof (T)))
+ {
+ // This link is not associated with an actual offset and exists merely to enforce
+ // an ordering constraint.
+ link.is_signed = 0;
+ link.whence = 0;
+ link.position = 0;
+ link.bias = 0;
+ return;
+ }
+
link.is_signed = std::is_signed<hb_unwrap_type (T)>::value;
link.whence = (unsigned) whence;
link.position = (const char *) &ofs - current->head;
link.bias = bias;
- link.objidx = objidx;
}
unsigned to_bias (const void *base) const
@@ -402,6 +419,8 @@
for (const object_t* parent : ++hb_iter (packed))
for (const object_t::link_t &link : parent->links)
{
+ if (unlikely (!link.width)) continue; // Don't need to resolve virtual offsets
+
const object_t* child = packed[link.objidx];
if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; }
unsigned offset = 0;