diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 743a736d8..bf8a90c54 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -338,6 +338,30 @@ struct OffsetTo : Offset } /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */ + /* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029 + * Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&... + */ + template + bool serialize_copy (hb_serialize_context_t *c, + const OffsetTo& src, + const void *src_base, + const void *dst_base, + hb_serialize_context_t::whence_t whence, + Ts&&... ds) + { + *this = 0; + if (src.is_null ()) + return false; + + c->push (); + + bool ret = c->copy (src_base+src, hb_forward (ds)...); + + c->add_link (*this, c->pop_pack (), dst_base, whence); + + return ret; + } + template bool serialize_copy (hb_serialize_context_t *c, const OffsetTo& src, diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index 46f87d930..d43b84cb0 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -98,13 +98,12 @@ struct NameRecord } NameRecord* copy (hb_serialize_context_t *c, - const void *src_base, - const void *dst_base) const + const void *src_base) const { TRACE_SERIALIZE (this); auto *out = c->embed (this); if (unlikely (!out)) return_trace (nullptr); - out->offset.serialize_copy (c, offset, src_base, dst_base, length); + out->offset.serialize_copy (c, offset, src_base, nullptr, hb_serialize_context_t::Tail, length); return_trace (out); } @@ -216,13 +215,6 @@ struct name this->format = 0; this->count = it.len (); - auto snap = c->snapshot (); - this->nameRecordZ.serialize (c, this->count); - if (unlikely (!c->check_assign (this->stringOffset, c->length ()))) return_trace (false); - c->revert (snap); - - const void *dst_string_pool = &(this + this->stringOffset); - NameRecord *name_records = (NameRecord *) calloc (it.len (), NameRecord::static_size); hb_array_t records (name_records, it.len ()); @@ -234,12 +226,12 @@ struct name records.qsort (); - c->copy_all (records, src_string_pool, dst_string_pool); + c->copy_all (records, src_string_pool); free (records.arrayZ); if (unlikely (c->ran_out_of_room)) return_trace (false); - assert (this->stringOffset == c->length ()); + this->stringOffset = c->length (); return_trace (true); } diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index c36c435d3..4bece6487 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -50,6 +50,12 @@ struct hb_serialize_context_t char *head, *tail; }; + enum whence_t { + Head, /* Relative to the current object head (default). */ + Tail, /* Relative to the current object tail after packed. */ + Absolute /* Absolute: from the start of the serialize buffer. */ + }; + struct object_t : range_t { void fini () { links.fini (); } @@ -71,7 +77,7 @@ struct hb_serialize_context_t { bool is_wide: 1; bool is_signed: 1; - bool is_absolute: 1; + whence_t whence: 2; unsigned position: 29; unsigned bias; objidx_t objidx; @@ -270,16 +276,10 @@ struct hb_serialize_context_t assert (packed.tail ()->head == tail); } - enum base_mode_t { - Head, /* Relative to the current object head (default). */ - Tail, /* Relative to the current object tail. */ - Absolute /* Absolute: from the start of the serialize buffer. */ - }; - template void add_link (T &ofs, objidx_t objidx, const void *base = nullptr, - base_mode_t mode = Head) + whence_t whence = Head) { static_assert (sizeof (T) == 2 || sizeof (T) == 4, ""); @@ -289,34 +289,19 @@ struct hb_serialize_context_t assert (current); assert (current->head <= (const char *) &ofs); - const char *dflt_base; auto& link = *current->links.push (); - switch (mode) - { - case Head: - dflt_base = current->head; - link.is_absolute = false; - break; - case Tail: - dflt_base = current->tail; - link.is_absolute = false; - break; - case Absolute: - dflt_base = start; - link.is_absolute = true; - break; - default: return; - } - if (!base) - base = dflt_base; - else - assert (dflt_base <= (const char *) base); - link.is_wide = sizeof (T) == 4; link.is_signed = hb_is_signed (hb_unwrap_type (T)); + link.whence = whence; link.position = (const char *) &ofs - current->head; - link.bias = (const char *) base - dflt_base; + if (whence == Head) + { + assert (current->head <= (const char *)base); + link.bias = (const char *) base - current->head; + } + else + link.bias = 0; link.objidx = objidx; } @@ -333,12 +318,11 @@ struct hb_serialize_context_t const object_t* child = packed[link.objidx]; if (unlikely (!child)) { err_other_error(); return; } unsigned offset; - if (link.is_absolute) - offset = (head - start) + (child->head - tail); - else - { - assert (link.bias <= (size_t) (parent->tail - parent->head)); - offset = (child->head - parent->head) - link.bias; + switch (link.whence) { + case Head: offset = child->head - parent->head; break; + case Tail: offset = child->head - parent->tail; break; + case Absolute: offset = (head - start) + (child->head - tail); break; + default: assert (0); } if (link.is_signed)