[OT] Add serialize() for Coverage

This commit is contained in:
Behdad Esfahbod 2012-08-29 21:08:59 -04:00
parent e901b954c6
commit 9f2348de58
2 changed files with 90 additions and 6 deletions

View File

@ -337,7 +337,7 @@ struct Sanitizer
#define TRACE_SERIALIZE() \ #define TRACE_SERIALIZE() \
hb_auto_trace_t<HB_DEBUG_SERIALIZE> trace (&c->debug_depth, "SERIALIZE", this, HB_FUNC, ""); hb_auto_trace_t<HB_DEBUG_SERIALIZE> trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, "");
struct hb_serialize_context_t struct hb_serialize_context_t
@ -371,25 +371,43 @@ struct hb_serialize_context_t
} }
template <typename Type> template <typename Type>
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 */ 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)) { if (unlikely (this->ran_out_of_room || this->end - this->head > padding + size)) {
this->ran_out_of_room = true; this->ran_out_of_room = true;
return NULL; return NULL;
} }
this->head += padding; this->head += padding;
const char *ret = this->head; char *ret = this->head;
this->head += size; this->head += size;
return reinterpret_cast<Type *> (ret); return reinterpret_cast<Type *> (ret);
} }
template <typename Type>
inline Type *allocate_min (unsigned int alignment = 2)
{
return this->allocate<Type> (Type::min_size, alignment);
}
template <typename Type> template <typename Type>
inline Type *embed (const Type &obj, unsigned int alignment = 2) inline Type *embed (const Type &obj, unsigned int alignment = 2)
{ {
return allocate (obj.size (), alignment); return this->allocate<Type> (obj.get_size (), alignment);
}
template <typename Type>
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<Type> (((char *) &obj) + size - this->head, alignment);
return reinterpret_cast<Type *> (&obj);
}
template <typename Type>
inline Type *extend (Type &obj)
{
return this->extend<Type> (obj, obj.get_size ());
} }
inline void truncate (void *head) inline void truncate (void *head)
@ -630,6 +648,10 @@ struct GenericArrayOf
if (unlikely (i >= len)) return Null(Type); if (unlikely (i >= len)) return Null(Type);
return array[i]; return array[i];
} }
inline Type& operator [] (unsigned int i)
{
return array[i];
}
inline unsigned int get_size (void) const inline unsigned int get_size (void) const
{ return len.static_size + len * Type::static_size; } { return len.static_size + len * Type::static_size; }

View File

@ -355,6 +355,21 @@ struct CoverageFormat1
return i; 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<CoverageFormat1> ();
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) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (); TRACE_SANITIZE ();
return TRACE_RETURN (glyphArray.sanitize (c)); return TRACE_RETURN (glyphArray.sanitize (c));
@ -406,6 +421,35 @@ struct CoverageFormat2
return NOT_COVERED; 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<CoverageFormat2> ();
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) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (); TRACE_SANITIZE ();
return TRACE_RETURN (rangeRecord.sanitize (c)); 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) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (); TRACE_SANITIZE ();
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);