[OT] More serialize. Implements all basic GSUB subtables

This commit is contained in:
Behdad Esfahbod 2012-09-04 18:17:57 -04:00
parent 1b38b4e817
commit a930c68e9c
3 changed files with 156 additions and 30 deletions

View File

@ -428,6 +428,40 @@ struct hb_serialize_context_t
bool ran_out_of_room; bool ran_out_of_room;
}; };
template <typename Type>
struct Supplier
{
/* For automatic wrapping of bare arrays */
inline Supplier (const Type *array)
{
head = array;
len = (unsigned int) -1;
}
inline Supplier (const Type *array, unsigned int len_)
{
head = array;
len = len_;
}
inline const Type operator [] (unsigned int i) const
{
if (unlikely (i >= len)) return Type ();
return head[i];
}
inline void advance (unsigned int count) {
if (unlikely (count > len))
count = len;
len -= count;
head += count;
}
private:
unsigned int len;
const Type *head;
};
/* /*
@ -687,7 +721,7 @@ struct GenericArrayOf
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const Type *items, Supplier<Type> &items,
unsigned int items_len) unsigned int items_len)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
@ -697,6 +731,7 @@ struct GenericArrayOf
unsigned int count = items_len; unsigned int count = items_len;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
array[i].set (items[i]); array[i].set (items[i]);
items.advance (items_len);
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
@ -803,6 +838,22 @@ struct HeadlessArrayOf
inline unsigned int get_size (void) const inline unsigned int get_size (void) const
{ return len.static_size + (len ? len - 1 : 0) * Type::static_size; } { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
inline bool serialize (hb_serialize_context_t *c,
Supplier<Type> &items,
unsigned int items_len)
{
TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
len.set (items_len); /* TODO(serialize) Overflow? */
if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
if (unlikely (!items_len)) return TRACE_RETURN (true);
unsigned int count = items_len;
for (unsigned int i = 1; i < count; i++)
array[i-1].set (items[i]);
items.advance (items_len - 1);
return TRACE_RETURN (true);
}
inline bool sanitize_shallow (hb_sanitize_context_t *c) { inline bool sanitize_shallow (hb_sanitize_context_t *c) {
return c->check_struct (this) return c->check_struct (this)
&& c->check_array (this, Type::static_size, len); && c->check_array (this, Type::static_size, len);

View File

@ -356,7 +356,7 @@ struct CoverageFormat1
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int num_glyphs) unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
@ -365,6 +365,7 @@ struct CoverageFormat1
if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false); if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
for (unsigned int i = 0; i < num_glyphs; i++) for (unsigned int i = 0; i < num_glyphs; i++)
glyphArray[i].set (glyphs[i]); glyphArray[i].set (glyphs[i]);
glyphs.advance (num_glyphs);
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
@ -420,7 +421,7 @@ struct CoverageFormat2
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int num_glyphs) unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
@ -446,6 +447,7 @@ struct CoverageFormat2
} else { } else {
rangeRecord[range].end = glyphs[i]; rangeRecord[range].end = glyphs[i];
} }
glyphs.advance (num_glyphs);
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
@ -526,7 +528,7 @@ struct Coverage
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int num_glyphs) unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();

View File

@ -73,7 +73,7 @@ struct SingleSubstFormat1
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int num_glyphs, unsigned int num_glyphs,
int delta) int delta)
{ {
@ -137,8 +137,8 @@ struct SingleSubstFormat2
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
const USHORT *substitutes, Supplier<GlyphID> &substitutes,
unsigned int num_glyphs) unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
@ -201,8 +201,8 @@ struct SingleSubst
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
const USHORT *substitutes, Supplier<GlyphID> &substitutes,
unsigned int num_glyphs) unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
@ -277,7 +277,7 @@ struct Sequence
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int num_glyphs) unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
@ -331,19 +331,20 @@ struct MultipleSubstFormat1
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int *substitute_len_list, Supplier<unsigned int> &substitute_len_list,
unsigned int num_glyphs, unsigned int num_glyphs,
const USHORT *substitute_glyphs_list) Supplier<GlyphID> &substitute_glyphs_list)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false); if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false);
for (unsigned int i = 0; i < num_glyphs; i++) { for (unsigned int i = 0; i < num_glyphs; i++)
if (unlikely (!sequence[i].serialize (c, this).serialize (c, substitute_glyphs_list, substitute_len_list[i]))) return TRACE_RETURN (false); if (unlikely (!sequence[i].serialize (c, this).serialize (c,
substitute_glyphs_list += substitute_len_list[i]; substitute_glyphs_list,
} substitute_len_list[i]))) return TRACE_RETURN (false);
substitute_len_list.advance (num_glyphs);
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
@ -397,10 +398,10 @@ struct MultipleSubst
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int *substitute_len_list, Supplier<unsigned int> &substitute_len_list,
unsigned int num_glyphs, unsigned int num_glyphs,
const USHORT *substitute_glyphs_list) Supplier<GlyphID> &substitute_glyphs_list)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
@ -486,19 +487,20 @@ struct AlternateSubstFormat1
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int *alternate_len_list, Supplier<unsigned int> &alternate_len_list,
unsigned int num_glyphs, unsigned int num_glyphs,
const USHORT *alternate_glyphs_list) Supplier<GlyphID> &alternate_glyphs_list)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false); if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false);
for (unsigned int i = 0; i < num_glyphs; i++) { for (unsigned int i = 0; i < num_glyphs; i++)
if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, alternate_glyphs_list, alternate_len_list[i]))) return TRACE_RETURN (false); if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
alternate_glyphs_list += alternate_len_list[i]; alternate_glyphs_list,
} alternate_len_list[i]))) return TRACE_RETURN (false);
alternate_len_list.advance (num_glyphs);
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
@ -552,10 +554,10 @@ struct AlternateSubst
} }
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
const USHORT *glyphs, Supplier<GlyphID> &glyphs,
unsigned int *alternate_len_list, Supplier<unsigned int> &alternate_len_list,
unsigned int num_glyphs, unsigned int num_glyphs,
const USHORT *alternate_glyphs_list) Supplier<GlyphID> &alternate_glyphs_list)
{ {
TRACE_SERIALIZE (); TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
@ -646,6 +648,18 @@ struct Ligature
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool serialize (hb_serialize_context_t *c,
GlyphID ligature,
Supplier<GlyphID> &components, /* Starting from second */
unsigned int num_components /* Including first component */)
{
TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
ligGlyph.set (ligature);
if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false);
return TRACE_RETURN (true);
}
public: public:
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (); TRACE_SANITIZE ();
@ -701,6 +715,24 @@ struct LigatureSet
return TRACE_RETURN (false); return TRACE_RETURN (false);
} }
inline bool serialize (hb_serialize_context_t *c,
Supplier<GlyphID> &ligatures,
Supplier<unsigned int> &component_count_list,
unsigned int num_ligatures,
Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
{
TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (false);
for (unsigned int i = 0; i < num_ligatures; i++)
if (unlikely (!ligature[i].serialize (c, this).serialize (c,
ligatures[i],
component_list,
component_count_list[i]))) return TRACE_RETURN (false);
component_count_list.advance (num_ligatures);
return TRACE_RETURN (true);
}
public: public:
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (); TRACE_SANITIZE ();
@ -753,6 +785,28 @@ struct LigatureSubstFormat1
return TRACE_RETURN (lig_set.apply (c)); return TRACE_RETURN (lig_set.apply (c));
} }
inline bool serialize (hb_serialize_context_t *c,
Supplier<GlyphID> &first_glyphs,
Supplier<unsigned int> &ligature_per_first_glyph_count_list,
unsigned int num_first_glyphs,
Supplier<GlyphID> &ligatures_list,
Supplier<unsigned int> &component_count_list,
Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
{
TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false);
if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (false);
for (unsigned int i = 0; i < num_first_glyphs; i++)
if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
ligatures_list,
component_count_list,
ligature_per_first_glyph_count_list[i],
component_list))) return TRACE_RETURN (false);
ligature_per_first_glyph_count_list.advance (num_first_glyphs);
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 (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
@ -810,6 +864,25 @@ struct LigatureSubst
} }
} }
inline bool serialize (hb_serialize_context_t *c,
Supplier<GlyphID> &first_glyphs,
Supplier<unsigned int> &ligature_per_first_glyph_count_list,
unsigned int num_first_glyphs,
Supplier<GlyphID> &ligatures_list,
Supplier<unsigned int> &component_count_list,
Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
{
TRACE_SERIALIZE ();
if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
unsigned int format = 1;
u.format.set (format);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs,
ligatures_list, component_count_list, component_list));
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);