From 9f2348de58f0f85593027378169bc03c4dd64e59 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 29 Aug 2012 21:08:59 -0400 Subject: [PATCH] [OT] Add serialize() for Coverage --- src/hb-open-type-private.hh | 34 +++++++++++++--- src/hb-ot-layout-common-private.hh | 62 ++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 7cd821212..10e777e73 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -337,7 +337,7 @@ struct Sanitizer #define TRACE_SERIALIZE() \ - hb_auto_trace_t trace (&c->debug_depth, "SERIALIZE", this, HB_FUNC, ""); + hb_auto_trace_t trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, ""); struct hb_serialize_context_t @@ -371,25 +371,43 @@ struct hb_serialize_context_t } template - inline Type *allocate (unsigned int size = -1, unsigned int alignment = 2) + inline Type *allocate (unsigned int size, unsigned int alignment = 2) { - if (size == -1) - size == Type::static_size; unsigned int padding = (alignment - (this->head - this->start) % alignment) % alignment; /* TODO speedup */ if (unlikely (this->ran_out_of_room || this->end - this->head > padding + size)) { this->ran_out_of_room = true; return NULL; } this->head += padding; - const char *ret = this->head; + char *ret = this->head; this->head += size; return reinterpret_cast (ret); } + template + inline Type *allocate_min (unsigned int alignment = 2) + { + return this->allocate (Type::min_size, alignment); + } + template inline Type *embed (const Type &obj, unsigned int alignment = 2) { - return allocate (obj.size (), alignment); + return this->allocate (obj.get_size (), alignment); + } + + template + inline Type *extend (Type &obj, unsigned int size, unsigned int alignment = 2) + { + assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); + this->allocate (((char *) &obj) + size - this->head, alignment); + return reinterpret_cast (&obj); + } + + template + inline Type *extend (Type &obj) + { + return this->extend (obj, obj.get_size ()); } inline void truncate (void *head) @@ -630,6 +648,10 @@ struct GenericArrayOf if (unlikely (i >= len)) return Null(Type); return array[i]; } + inline Type& operator [] (unsigned int i) + { + return array[i]; + } inline unsigned int get_size (void) const { return len.static_size + len * Type::static_size; } diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 48c7e0cf3..91d5a1982 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -355,6 +355,21 @@ struct CoverageFormat1 return i; } + inline static bool serialize (hb_serialize_context_t *c, + const USHORT *glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + CoverageFormat1 *t = c->allocate_min (); + if (unlikely (!t)) return TRACE_RETURN (false); + t->coverageFormat.set (1); + t->glyphArray.len.set (num_glyphs); + if (unlikely (!c->extend (t->glyphArray))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_glyphs; i++) + t->glyphArray[i].set (glyphs[i]); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (glyphArray.sanitize (c)); @@ -406,6 +421,35 @@ struct CoverageFormat2 return NOT_COVERED; } + inline static bool serialize (hb_serialize_context_t *c, + const USHORT *glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + CoverageFormat2 *t = c->allocate_min (); + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) + num_ranges++; + if (unlikely (!t)) return TRACE_RETURN (false); + t->coverageFormat.set (2); + t->rangeRecord.len.set (num_ranges); + if (unlikely (!c->extend (t->rangeRecord))) return TRACE_RETURN (false); + if (unlikely (!num_glyphs)) return TRACE_RETURN (true); + unsigned int range = 0; + t->rangeRecord[range].start.set (glyphs[0]); + t->rangeRecord[range].value.set (0); + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) { + t->rangeRecord[range].start.set (glyphs[i]); + t->rangeRecord[range].value.set (i); + range++; + } else { + t->rangeRecord[range].end = glyphs[i]; + } + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (rangeRecord.sanitize (c)); @@ -482,6 +526,24 @@ struct Coverage } } + inline static bool serialize (hb_serialize_context_t *c, + const USHORT *glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + unsigned int format; + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) + num_ranges++; + format = num_glyphs * 2 < num_ranges * 3 ? 1 : 2; + switch (format) { + case 1: return TRACE_RETURN (CoverageFormat1::serialize (c, glyphs, num_glyphs)); + case 2: return TRACE_RETURN (CoverageFormat2::serialize (c, glyphs, num_glyphs)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false);