summaryrefslogtreecommitdiff
path: root/pango/opentype/hb-ot-layout-gpos-private.hh
diff options
context:
space:
mode:
Diffstat (limited to 'pango/opentype/hb-ot-layout-gpos-private.hh')
-rw-r--r--pango/opentype/hb-ot-layout-gpos-private.hh183
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)