diff options
Diffstat (limited to 'pango/opentype/hb-ot-layout-gpos-private.hh')
-rw-r--r-- | pango/opentype/hb-ot-layout-gpos-private.hh | 183 |
1 files changed, 134 insertions, 49 deletions
diff --git a/pango/opentype/hb-ot-layout-gpos-private.hh b/pango/opentype/hb-ot-layout-gpos-private.hh index be7b5a5c..e68739ed 100644 --- a/pango/opentype/hb-ot-layout-gpos-private.hh +++ b/pango/opentype/hb-ot-layout-gpos-private.hh @@ -51,30 +51,13 @@ struct ValueFormat : USHORT xAdvDevice = 0x0040, /* Includes horizontal Device table for advance */ yAdvDevice = 0x0080, /* Includes vertical Device table for advance */ ignored = 0x0F00, /* Was used in TrueType Open for MM fonts */ - reserved = 0xF000 /* For future use */ - }; - - inline unsigned int get_len () const - { return _hb_popcount32 ((unsigned int) *this); } - inline unsigned int get_size () const - { return get_len () * Value::get_size (); } + reserved = 0xF000, /* For future use */ - void apply_value (hb_ot_layout_context_t *context, - const char *base, - const Value *values, - hb_internal_glyph_position_t *glyph_pos) const - { - unsigned int x_ppem, y_ppem; - hb_16dot16_t x_scale, y_scale; - unsigned int format = *this; - - if (!format) - return; + devices = 0x00F0 /* Mask for having any Device table */ + }; - /* All fields are options. Only those available advance the value - * pointer. */ +/* All fields are options. Only those available advance the value pointer. */ #if 0 -struct ValueRecord { SHORT xPlacement; /* Horizontal adjustment for * placement--in design units */ SHORT yPlacement; /* Vertical adjustment for @@ -97,20 +80,35 @@ struct ValueRecord { Offset yAdvDevice; /* Offset to Device table for vertical * advance--measured from beginning of * PosTable (may be NULL) */ -}; #endif + inline unsigned int get_len () const + { return _hb_popcount32 ((unsigned int) *this); } + inline unsigned int get_size () const + { return get_len () * Value::get_size (); } + + void apply_value (hb_ot_layout_context_t *context, + const char *base, + const Value *values, + hb_internal_glyph_position_t *glyph_pos) const + { + unsigned int x_ppem, y_ppem; + hb_16dot16_t x_scale, y_scale; + unsigned int format = *this; + + if (!format) return; + x_scale = context->font->x_scale; y_scale = context->font->y_scale; /* design units -> fractional pixel */ if (format & xPlacement) - glyph_pos->x_pos += _hb_16dot16_mul_trunc (x_scale, *(SHORT*)values++); + glyph_pos->x_pos += _hb_16dot16_mul_round (x_scale, *(SHORT*)values++); if (format & yPlacement) - glyph_pos->y_pos += _hb_16dot16_mul_trunc (y_scale, *(SHORT*)values++); + glyph_pos->y_pos += _hb_16dot16_mul_round (y_scale, *(SHORT*)values++); if (format & xAdvance) - glyph_pos->x_advance += _hb_16dot16_mul_trunc (x_scale, *(SHORT*)values++); + glyph_pos->x_advance += _hb_16dot16_mul_round (x_scale, *(SHORT*)values++); if (format & yAdvance) - glyph_pos->y_advance += _hb_16dot16_mul_trunc (y_scale, *(SHORT*)values++); + glyph_pos->y_advance += _hb_16dot16_mul_round (y_scale, *(SHORT*)values++); x_ppem = context->font->x_ppem; y_ppem = context->font->y_ppem; @@ -140,6 +138,68 @@ struct ValueRecord { values++; } } + + private: + inline bool sanitize_value_devices (SANITIZE_ARG_DEF, void *base, const Value *values) { + unsigned int format = *this; + + if (format & xPlacement) values++; + if (format & yPlacement) values++; + if (format & xAdvance) values++; + if (format & yAdvance) values++; + + if ((format & xPlaDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false; + if ((format & yPlaDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false; + if ((format & xAdvDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false; + if ((format & yAdvDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false; + + return true; + } + + public: + + inline bool has_device () { + unsigned int format = *this; + return (format & devices) != 0; + } + + inline bool sanitize_value (SANITIZE_ARG_DEF, void *base, const Value *values) { + TRACE_SANITIZE (); + + return SANITIZE_MEM (values, get_size ()) && + (!has_device () || sanitize_value_devices (SANITIZE_ARG, base, values)); + } + + inline bool sanitize_values (SANITIZE_ARG_DEF, void *base, const Value *values, unsigned int count) { + TRACE_SANITIZE (); + unsigned int len = get_len (); + + if (!SANITIZE_ARRAY (values, get_size (), count)) return false; + + if (!has_device ()) return true; + + for (unsigned int i = 0; i < count; i++) { + if (!sanitize_value_devices (SANITIZE_ARG, base, values)) + return false; + values += len; + } + + return true; + } + + inline bool sanitize_values_stride_unsafe (SANITIZE_ARG_DEF, void *base, const Value *values, unsigned int count, unsigned int stride) { + TRACE_SANITIZE (); + + if (!has_device ()) return true; + + for (unsigned int i = 0; i < count; i++) { + if (!sanitize_value_devices (SANITIZE_ARG, base, values)) + return false; + values += stride; + } + + return true; + } }; ASSERT_SIZE (ValueFormat, 2); @@ -149,11 +209,11 @@ struct AnchorFormat1 friend struct Anchor; private: - inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id, + inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate); - *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate); + *x = _hb_16dot16_mul_round (context->font->x_scale, xCoordinate); + *y = _hb_16dot16_mul_round (context->font->y_scale, yCoordinate); } inline bool sanitize (SANITIZE_ARG_DEF) { @@ -177,8 +237,8 @@ struct AnchorFormat2 hb_position_t *x, hb_position_t *y) const { /* TODO Contour */ - *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate); - *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate); + *x = _hb_16dot16_mul_round (context->font->x_scale, xCoordinate); + *y = _hb_16dot16_mul_round (context->font->y_scale, yCoordinate); } inline bool sanitize (SANITIZE_ARG_DEF) { @@ -199,11 +259,11 @@ struct AnchorFormat3 friend struct Anchor; private: - inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id, + inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate); - *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate); + *x = _hb_16dot16_mul_round (context->font->x_scale, xCoordinate); + *y = _hb_16dot16_mul_round (context->font->y_scale, yCoordinate); /* pixel -> fractional pixel */ if (context->font->x_ppem) @@ -377,7 +437,7 @@ struct SinglePosFormat1 inline bool sanitize (SANITIZE_ARG_DEF) { TRACE_SANITIZE (); return SANITIZE_SELF () && SANITIZE_THIS (coverage) && - SANITIZE_MEM (values, valueFormat.get_size ()); + valueFormat.sanitize_value (SANITIZE_ARG, CHARP(this), values); } private: @@ -419,7 +479,7 @@ struct SinglePosFormat2 inline bool sanitize (SANITIZE_ARG_DEF) { TRACE_SANITIZE (); return SANITIZE_SELF () && SANITIZE_THIS (coverage) && - SANITIZE_MEM (values, valueFormat.get_size () * valueCount); + valueFormat.sanitize_values (SANITIZE_ARG, CHARP(this), values, valueCount); } private: @@ -486,6 +546,7 @@ struct PairSet { friend struct PairPosFormat1; + /* Note: Doesn't sanitize the Device entries in the ValueRecord */ inline bool sanitize (SANITIZE_ARG_DEF, unsigned int format_len) { TRACE_SANITIZE (); if (!SANITIZE_SELF ()) return false; @@ -525,12 +586,11 @@ struct PairPosFormat1 j++; } - const PairSet &pair_set = this+pairSet[index]; - unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int record_size = USHORT::get_size () * (1 + len1 + len2); + const PairSet &pair_set = this+pairSet[index]; unsigned int count = pair_set.len; const PairValueRecord *record = pair_set.array; for (unsigned int i = 0; i < count; i++) @@ -552,9 +612,29 @@ struct PairPosFormat1 inline bool sanitize (SANITIZE_ARG_DEF) { TRACE_SANITIZE (); - return SANITIZE_SELF () && SANITIZE_THIS (coverage) && - pairSet.sanitize (SANITIZE_ARG, CONST_CHARP(this), - valueFormat1.get_len () + valueFormat2.get_len ()); + + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); + + if (!(SANITIZE_SELF () && SANITIZE_THIS (coverage) && + pairSet.sanitize (SANITIZE_ARG, CONST_CHARP(this), len1 + len2))) return false; + + if (!(valueFormat1.has_device () || valueFormat2.has_device ())) return true; + + unsigned int stride = 1 + len1 + len2; + unsigned int count1 = pairSet.len; + for (unsigned int i = 0; i < count1; i++) + { + const PairSet &pair_set = this+pairSet[i]; + + unsigned int count2 = pair_set.len; + const PairValueRecord *record = pair_set.array; + if (!(valueFormat1.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &record->values[0], count2, stride) && + valueFormat2.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &record->values[len1], count2, stride))) + return false; + } + + return true; } private: @@ -623,9 +703,14 @@ struct PairPosFormat2 if (!(SANITIZE_SELF () && SANITIZE_THIS (coverage) && SANITIZE_THIS2 (classDef1, classDef2))) return false; + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); + unsigned int stride = len1 + len2; unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); - unsigned int len = class1Count * class2Count; - return SANITIZE_ARRAY (values, record_size, len); + unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; + return SANITIZE_ARRAY (values, record_size, count) && + valueFormat1.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &values[0], count, stride) && + valueFormat2.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &values[len1], count, stride); } private: @@ -1334,10 +1419,10 @@ struct PosLookupSubTable } } - inline bool sanitize (SANITIZE_ARG_DEF) { + inline bool sanitize (SANITIZE_ARG_DEF, unsigned int lookup_type) { TRACE_SANITIZE (); - if (!SANITIZE (u.format)) return false; - switch (u.format) { + if (!SANITIZE (u.sub_format)) return false; + switch (lookup_type) { case Single: return u.single->sanitize (SANITIZE_ARG); case Pair: return u.pair->sanitize (SANITIZE_ARG); case Cursive: return u.cursive->sanitize (SANITIZE_ARG); @@ -1353,7 +1438,7 @@ struct PosLookupSubTable private: union { - USHORT format; + USHORT sub_format; SinglePos single[VAR]; PairPos pair[VAR]; CursivePos cursive[VAR]; @@ -1450,7 +1535,7 @@ struct PosLookup : Lookup TRACE_SANITIZE (); if (!Lookup::sanitize (SANITIZE_ARG)) return false; OffsetArrayOf<PosLookupSubTable> &list = (OffsetArrayOf<PosLookupSubTable> &) subTable; - return SANITIZE_THIS (list); + return list.sanitize (SANITIZE_ARG, this, get_type ()); } }; @@ -1506,7 +1591,7 @@ inline bool ExtensionPos::sanitize (SANITIZE_ARG_DEF) return Extension::sanitize (SANITIZE_ARG) && (&(Extension::get_subtable ()) == &Null(LookupSubTable) || get_type () == PosLookupSubTable::Extension || - DECONST_CAST (PosLookupSubTable, get_subtable (), 0).sanitize (SANITIZE_ARG)); + DECONST_CAST (PosLookupSubTable, get_subtable (), 0).sanitize (SANITIZE_ARG, get_type ())); } static inline bool position_lookup (APPLY_ARG_DEF, unsigned int lookup_index) |