Merge pull request #2163 from harfbuzz/absolute-link
added add_link_abs()
This commit is contained in:
commit
c21eb86bfd
|
@ -338,11 +338,15 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
}
|
||||
|
||||
/* 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 <typename ...Ts>
|
||||
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;
|
||||
|
@ -353,11 +357,17 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
|
||||
bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
|
||||
|
||||
c->add_link (*this, c->pop_pack (), dst_base);
|
||||
c->add_link (*this, c->pop_pack (), dst_base, whence);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool serialize_copy (hb_serialize_context_t *c,
|
||||
const OffsetTo& src,
|
||||
const void *src_base,
|
||||
const void *dst_base)
|
||||
{ return serialize_copy (c, src, src_base, dst_base, hb_serialize_context_t::Head); }
|
||||
|
||||
bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -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<NameRecord> 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);
|
||||
}
|
||||
|
|
|
@ -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 (); }
|
||||
|
@ -70,7 +76,9 @@ struct hb_serialize_context_t
|
|||
struct link_t
|
||||
{
|
||||
bool is_wide: 1;
|
||||
unsigned position : 31;
|
||||
bool is_signed: 1;
|
||||
unsigned whence: 2;
|
||||
unsigned position: 28;
|
||||
unsigned bias;
|
||||
objidx_t objidx;
|
||||
};
|
||||
|
@ -269,7 +277,9 @@ struct hb_serialize_context_t
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void add_link (T &ofs, objidx_t objidx, const void *base = nullptr)
|
||||
void add_link (T &ofs, objidx_t objidx,
|
||||
const void *base = nullptr,
|
||||
whence_t whence = Head)
|
||||
{
|
||||
static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
|
||||
|
||||
|
@ -279,15 +289,24 @@ struct hb_serialize_context_t
|
|||
assert (current);
|
||||
assert (current->head <= (const char *) &ofs);
|
||||
|
||||
if (!base)
|
||||
base = current->head;
|
||||
else
|
||||
assert (current->head <= (const char *) base);
|
||||
|
||||
auto& link = *current->links.push ();
|
||||
|
||||
link.is_wide = sizeof (T) == 4;
|
||||
link.is_signed = hb_is_signed (hb_unwrap_type (T));
|
||||
link.whence = (unsigned)whence;
|
||||
link.position = (const char *) &ofs - current->head;
|
||||
link.bias = (const char *) base - current->head;
|
||||
if (whence == Head)
|
||||
{
|
||||
if (base == nullptr)
|
||||
link.bias = 0;
|
||||
else
|
||||
{
|
||||
assert (current->head <= (const char *)base);
|
||||
link.bias = (const char *) base - current->head;
|
||||
}
|
||||
}
|
||||
else
|
||||
link.bias = 0;
|
||||
link.objidx = objidx;
|
||||
}
|
||||
|
||||
|
@ -302,20 +321,28 @@ struct hb_serialize_context_t
|
|||
for (const object_t::link_t &link : parent->links)
|
||||
{
|
||||
const object_t* child = packed[link.objidx];
|
||||
assert (link.bias <= (size_t) (parent->tail - parent->head));
|
||||
unsigned offset = (child->head - parent->head) - link.bias;
|
||||
if (unlikely (!child)) { err_other_error(); return; }
|
||||
unsigned offset;
|
||||
switch ((whence_t)link.whence) {
|
||||
case Head: offset = (child->head - parent->head) - link.bias; break;
|
||||
case Tail: offset = child->head - parent->tail; break;
|
||||
case Absolute: offset = (head - start) + (child->head - tail); break;
|
||||
default: assert (0);
|
||||
}
|
||||
|
||||
if (link.is_wide)
|
||||
if (link.is_signed)
|
||||
{
|
||||
auto &off = * ((BEInt<uint32_t, 4> *) (parent->head + link.position));
|
||||
assert (0 == off);
|
||||
check_assign (off, offset);
|
||||
if (link.is_wide)
|
||||
assign_offset<int32_t> (parent, link, offset);
|
||||
else
|
||||
assign_offset<int16_t> (parent, link, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &off = * ((BEInt<uint16_t, 2> *) (parent->head + link.position));
|
||||
assert (0 == off);
|
||||
check_assign (off, offset);
|
||||
if (link.is_wide)
|
||||
assign_offset<uint32_t> (parent, link, offset);
|
||||
else
|
||||
assign_offset<uint16_t> (parent, link, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -456,6 +483,15 @@ struct hb_serialize_context_t
|
|||
(char *) b.arrayZ, free);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
|
||||
{
|
||||
auto &off = * ((BEInt<T, sizeof (T)> *) (parent->head + link.position));
|
||||
assert (0 == off);
|
||||
check_assign (off, offset);
|
||||
}
|
||||
|
||||
public: /* TODO Make private. */
|
||||
char *start, *head, *tail, *end;
|
||||
unsigned int debug_depth;
|
||||
|
|
Loading…
Reference in New Issue