WIP
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 21 Apr 2010 06:02:57 +0000 (02:02 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 21 Apr 2010 06:02:57 +0000 (02:02 -0400)
src/hb-ot-layout-gpos-private.hh

index bd72aae..60eb439 100644 (file)
@@ -52,29 +52,12 @@ struct ValueFormat : USHORT
     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 (); }
 
-  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,9 +80,24 @@ 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 */
@@ -124,6 +122,68 @@ struct ValueRecord {
       if (y_ppem) glyph_pos->y_advance += (base+*(OffsetTo<Device>*)values++).get_delta (y_ppem) << 16; else 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);