Fix array query API
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 4 Nov 2009 21:36:14 +0000 (16:36 -0500)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 4 Nov 2009 21:36:14 +0000 (16:36 -0500)
The array query APIs now all do:

  - Return the total number of items
  - Take a start_offset, such that individual items can be fetched
  - The _count IN/OUT variable always has number of items written
    into the array upon return of the function

TODO
src/hb-ot-layout-common-private.hh
src/hb-ot-layout-gdef-private.hh
src/hb-ot-layout-gsubgpos-private.hh
src/hb-ot-layout.cc
src/hb-ot-layout.h

diff --git a/TODO b/TODO
index 5df48a3..a12d0ca 100644 (file)
--- a/TODO
+++ b/TODO
@@ -5,7 +5,6 @@
 - Future-proof metrics struct
 
 hb-ot:
-- Fix ot query APIs
 - Rename hb_internal_glyph_info_t to hb_ot_glyph_info_t
 - Add query API for aalt-like features
 - HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH vs LookupType::... mess
index 3d1bc34..704ab19 100644 (file)
@@ -69,16 +69,19 @@ struct RecordArrayOf : ArrayOf<Record<Type> > {
     if (HB_UNLIKELY (i >= this->len)) return Null(Tag);
     return (*this)[i].tag;
   }
-  inline bool get_tags (unsigned int *record_count /* IN/OUT */,
-                       hb_tag_t     *record_tags /* OUT */) const
+  inline unsigned int get_tags (unsigned int start_offset,
+                               unsigned int *record_count /* IN/OUT */,
+                               hb_tag_t     *record_tags /* OUT */) const
   {
-    const Record<Type> *a = this->const_array();
-    unsigned int count = MIN (this->len, *record_count);
-    for (unsigned int i = 0; i < count; i++)
-      record_tags[i] = a[i].tag;
+    if (record_count) {
+      unsigned int count = MIN (MIN (0, (unsigned int) this->len - start_offset), *record_count);
+      const Record<Type> *array = this->const_array() + start_offset;
+      for (unsigned int i = 0; i < count; i++)
+       record_tags[i] = array[i].tag;
 
-    *record_count = this->len;
-    return !!this->len;
+      *record_count = this->len;
+    }
+    return this->len;
   }
   inline bool find_index (hb_tag_t tag, unsigned int *index) const
   {
@@ -120,16 +123,19 @@ struct IndexArray : ArrayOf<USHORT>
       return NO_INDEX;
     return this->const_array()[i];
   }
-  inline bool get_indexes (unsigned int *_count /* IN/OUT */,
-                          unsigned int *_indexes /* OUT */) const
+  inline unsigned int get_indexes (unsigned int start_offset,
+                                  unsigned int *_count /* IN/OUT */,
+                                  unsigned int *_indexes /* OUT */) const
   {
-    unsigned int count = MIN (this->len, *_count);
-    const USHORT *a = this->const_array();
-    for (unsigned int i = 0; i < count; i++)
-      _indexes[i] = a[i];
+    if (_count) {
+      unsigned int count = MIN (MIN (0, (unsigned int) this->len - start_offset), *_count);
+      const USHORT *array = this->const_array() + start_offset;
+      for (unsigned int i = 0; i < count; i++)
+       _indexes[i] = array[i];
 
-    *_count = this->len;
-    return !!this->len;
+      *_count = this->len;
+    }
+    return this->len;
   }
 };
 
@@ -145,9 +151,10 @@ struct LangSys
   { return featureIndex.len; }
   inline hb_tag_t get_feature_index (unsigned int i) const
   { return featureIndex[i]; }
-  inline bool get_feature_indexes (unsigned int *feature_count /* IN/OUT */,
-                                  unsigned int *feature_indexes /* OUT */) const
-  { return featureIndex.get_indexes (feature_count, feature_indexes); }
+  inline unsigned int get_feature_indexes (unsigned int start_offset,
+                                          unsigned int *feature_count /* IN/OUT */,
+                                          unsigned int *feature_indexes /* OUT */) const
+  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
 
   inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
   inline int get_required_feature_index (void) const
@@ -178,9 +185,10 @@ struct Script
   { return langSys.len; }
   inline const Tag& get_lang_sys_tag (unsigned int i) const
   { return langSys.get_tag (i); }
-  inline bool get_lang_sys_tags (unsigned int *lang_sys_count /* IN/OUT */,
-                                hb_tag_t     *lang_sys_tags /* OUT */) const
-  { return langSys.get_tags (lang_sys_count, lang_sys_tags); }
+  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                        unsigned int *lang_sys_count /* IN/OUT */,
+                                        hb_tag_t     *lang_sys_tags /* OUT */) const
+  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
   inline const LangSys& get_lang_sys (unsigned int i) const
   {
     if (i == NO_INDEX) return get_default_lang_sys ();
@@ -217,9 +225,10 @@ struct Feature
   { return lookupIndex.len; }
   inline hb_tag_t get_lookup_index (unsigned int i) const
   { return lookupIndex[i]; }
-  inline bool get_lookup_indexes (unsigned int *lookup_count /* IN/OUT */,
-                                 unsigned int *lookup_tags /* OUT */) const
-  { return lookupIndex.get_indexes (lookup_count, lookup_tags); }
+  inline unsigned int get_lookup_indexes (unsigned int start_index,
+                                         unsigned int *lookup_count /* IN/OUT */,
+                                         unsigned int *lookup_tags /* OUT */) const
+  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
index 69f90fe..d96bb16 100644 (file)
@@ -42,25 +42,31 @@ ASSERT_SIZE (AttachPoint, 2);
 
 struct AttachList
 {
-  inline bool get_attach_points (hb_codepoint_t glyph_id,
-                                unsigned int *point_count /* IN/OUT */,
-                                unsigned int *point_array /* OUT */) const
+  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                        unsigned int start_offset,
+                                        unsigned int *point_count /* IN/OUT */,
+                                        unsigned int *point_array /* OUT */) const
   {
     unsigned int index = (this+coverage) (glyph_id);
     if (index == NOT_COVERED)
     {
-      *point_count = 0;
-      return false;
+      if (point_count)
+       *point_count = 0;
+      return 0;
     }
+
     const AttachPoint &points = this+attachPoint[index];
 
-    unsigned int count = MIN (points.len, *point_count);
-    for (unsigned int i = 0; i < count; i++)
-      point_array[i] = points[i];
+    if (point_count) {
+      const USHORT *array = points.const_array () + start_offset;
+      unsigned int count = MIN (MIN (0, (unsigned int) points.len - start_offset), *point_count);
+      for (unsigned int i = 0; i < count; i++)
+       point_array[i] = array[i];
 
-    *point_count = points.len;
+      *point_count = points.len;
+    }
 
-    return true;
+    return points.len;
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
@@ -185,17 +191,22 @@ struct CaretValue
 
 struct LigGlyph
 {
-  inline void get_lig_carets (hb_ot_layout_context_t *context,
-                             hb_codepoint_t glyph_id,
-                             unsigned int *caret_count /* IN/OUT */,
-                             int *caret_array /* OUT */) const
+  inline unsigned int get_lig_carets (hb_ot_layout_context_t *context,
+                                     hb_codepoint_t glyph_id,
+                                     unsigned int start_offset,
+                                     unsigned int *caret_count /* IN/OUT */,
+                                     int *caret_array /* OUT */) const
   {
+    if (caret_count) {
+      const OffsetTo<CaretValue> *array = carets.const_array () + start_offset;
+      unsigned int count = MIN (MIN (0, (unsigned int) carets.len - start_offset), *caret_count);
+      for (unsigned int i = 0; i < count; i++)
+       caret_array[i] = (this+array[i]).get_caret_value (context, glyph_id);
 
-    unsigned int count = MIN (carets.len, *caret_count);
-    for (unsigned int i = 0; i < count; i++)
-      caret_array[i] = (this+carets[i]).get_caret_value (context, glyph_id);
+      *caret_count = carets.len;
+    }
 
-    *caret_count = carets.len;
+    return carets.len;
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
@@ -213,20 +224,21 @@ ASSERT_SIZE (LigGlyph, 2);
 
 struct LigCaretList
 {
-  inline bool get_lig_carets (hb_ot_layout_context_t *context,
-                             hb_codepoint_t glyph_id,
-                             unsigned int *caret_count /* IN/OUT */,
-                             int *caret_array /* OUT */) const
+  inline unsigned int get_lig_carets (hb_ot_layout_context_t *context,
+                                     hb_codepoint_t glyph_id,
+                                     unsigned int start_offset,
+                                     unsigned int *caret_count /* IN/OUT */,
+                                     int *caret_array /* OUT */) const
   {
     unsigned int index = (this+coverage) (glyph_id);
     if (index == NOT_COVERED)
     {
-      *caret_count = 0;
-      return false;
+      if (caret_count)
+       *caret_count = 0;
+      return 0;
     }
     const LigGlyph &lig_glyph = this+ligGlyph[index];
-    lig_glyph.get_lig_carets (context, glyph_id, caret_count, caret_array);
-    return true;
+    return lig_glyph.get_lig_carets (context, glyph_id, start_offset, caret_count, caret_array);
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
@@ -317,17 +329,19 @@ struct GDEF
   { return (this+markAttachClassDef).get_class (glyph); }
 
   inline bool has_attach_points () const { return attachList != 0; }
-  inline bool get_attach_points (hb_codepoint_t glyph_id,
-                                unsigned int *point_count /* IN/OUT */,
-                                unsigned int *point_array /* OUT */) const
-  { return (this+attachList).get_attach_points (glyph_id, point_count, point_array); }
+  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                        unsigned int start_offset,
+                                        unsigned int *point_count /* IN/OUT */,
+                                        unsigned int *point_array /* OUT */) const
+  { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
 
   inline bool has_lig_carets () const { return ligCaretList != 0; }
-  inline bool get_lig_carets (hb_ot_layout_context_t *context,
-                             hb_codepoint_t glyph_id,
-                             unsigned int *caret_count /* IN/OUT */,
-                             int *caret_array /* OUT */) const
-  { return (this+ligCaretList).get_lig_carets (context, glyph_id, caret_count, caret_array); }
+  inline unsigned int get_lig_carets (hb_ot_layout_context_t *context,
+                                     hb_codepoint_t glyph_id,
+                                     unsigned int start_offset,
+                                     unsigned int *caret_count /* IN/OUT */,
+                                     int *caret_array /* OUT */) const
+  { return (this+ligCaretList).get_lig_carets (context, glyph_id, start_offset, caret_count, caret_array); }
 
   inline bool has_mark_sets () const { return version >= 0x00010002 && markGlyphSetsDef[0] != 0; }
   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
index 91703da..4a5b8b2 100644 (file)
@@ -907,9 +907,10 @@ struct GSUBGPOS
   { return (this+scriptList).len; }
   inline const Tag& get_script_tag (unsigned int i) const
   { return (this+scriptList).get_tag (i); }
-  inline bool get_script_tags (unsigned int *script_count /* IN/OUT */,
-                              hb_tag_t     *script_tags /* OUT */) const
-  { return (this+scriptList).get_tags (script_count, script_tags); }
+  inline unsigned int get_script_tags (unsigned int start_offset,
+                                      unsigned int *script_count /* IN/OUT */,
+                                      hb_tag_t     *script_tags /* OUT */) const
+  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
   inline const Script& get_script (unsigned int i) const
   { return (this+scriptList)[i]; }
   inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
@@ -919,9 +920,10 @@ struct GSUBGPOS
   { return (this+featureList).len; }
   inline const Tag& get_feature_tag (unsigned int i) const
   { return (this+featureList).get_tag (i); }
-  inline bool get_feature_tags (unsigned int *feature_count /* IN/OUT */,
-                               hb_tag_t     *feature_tags /* OUT */) const
-  { return (this+featureList).get_tags (feature_count, feature_tags); }
+  inline unsigned int get_feature_tags (unsigned int start_offset,
+                                       unsigned int *feature_count /* IN/OUT */,
+                                       hb_tag_t     *feature_tags /* OUT */) const
+  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
   inline const Feature& get_feature (unsigned int i) const
   { return (this+featureList)[i]; }
   inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
index 67b2b9a..89c7374 100644 (file)
@@ -301,26 +301,28 @@ hb_ot_layout_build_glyph_classes (hb_face_t      *face,
     _hb_ot_layout_set_glyph_class (face, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]);
 }
 
-hb_bool_t
+unsigned int
 hb_ot_layout_get_attach_points (hb_face_t      *face,
                                hb_codepoint_t  glyph,
+                               unsigned int    start_offset,
                                unsigned int   *point_count /* IN/OUT */,
                                unsigned int   *point_array /* OUT */)
 {
-  return _get_gdef (face).get_attach_points (glyph, point_count, point_array);
+  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
 }
 
-hb_bool_t
+unsigned int
 hb_ot_layout_get_lig_carets (hb_face_t      *face,
                             hb_font_t      *font,
                             hb_codepoint_t  glyph,
+                            unsigned int    start_offset,
                             unsigned int   *caret_count /* IN/OUT */,
                             int            *caret_array /* OUT */)
 {
   hb_ot_layout_context_t context;
   context.font = font;
   context.face = face;
-  return _get_gdef (face).get_lig_carets (&context, glyph, caret_count, caret_array);
+  return _get_gdef (face).get_lig_carets (&context, glyph, start_offset, caret_count, caret_array);
 }
 
 /*
@@ -339,15 +341,16 @@ get_gsubgpos_table (hb_face_t *face,
 }
 
 
-hb_bool_t
+unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
                                    hb_tag_t      table_tag,
+                                   unsigned int  start_offset,
                                    unsigned int *script_count /* IN/OUT */,
                                    hb_tag_t     *script_tags /* OUT */)
 {
   const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
-  return g.get_script_tags (script_count, script_tags);
+  return g.get_script_tags (start_offset, script_count, script_tags);
 }
 
 hb_bool_t
@@ -374,28 +377,30 @@ hb_ot_layout_table_find_script (hb_face_t    *face,
   return FALSE;
 }
 
-hb_bool_t
+unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
                                     hb_tag_t      table_tag,
+                                    unsigned int  start_offset,
                                     unsigned int *feature_count /* IN/OUT */,
                                     hb_tag_t     *feature_tags /* OUT */)
 {
   const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
-  return g.get_feature_tags (feature_count, feature_tags);
+  return g.get_feature_tags (start_offset, feature_count, feature_tags);
 }
 
 
-hb_bool_t
+unsigned int
 hb_ot_layout_script_get_language_tags (hb_face_t    *face,
                                       hb_tag_t      table_tag,
                                       unsigned int  script_index,
+                                      unsigned int  start_offset,
                                       unsigned int *language_count /* IN/OUT */,
                                       hb_tag_t     *language_tags /* OUT */)
 {
   const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
 
-  return s.get_lang_sys_tags (language_count, language_tags);
+  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
 }
 
 hb_bool_t
@@ -433,25 +438,27 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
   return l.has_required_feature ();
 }
 
-hb_bool_t
+unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
                                           hb_tag_t      table_tag,
                                           unsigned int  script_index,
                                           unsigned int  language_index,
+                                          unsigned int  start_offset,
                                           unsigned int *feature_count /* IN/OUT */,
                                           unsigned int *feature_indexes /* OUT */)
 {
   const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
   const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
 
-  return l.get_feature_indexes (feature_count, feature_indexes);
+  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
 }
 
-hb_bool_t
+unsigned int
 hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
                                        hb_tag_t      table_tag,
                                        unsigned int  script_index,
                                        unsigned int  language_index,
+                                       unsigned int  start_offset,
                                        unsigned int *feature_count /* IN/OUT */,
                                        hb_tag_t     *feature_tags /* OUT */)
 {
@@ -459,7 +466,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
   const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
 
   ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
-  hb_bool_t ret = l.get_feature_indexes (feature_count, (unsigned int *) feature_tags);
+  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
 
   if (feature_tags) {
     unsigned int count = *feature_count;
@@ -497,17 +504,18 @@ hb_ot_layout_language_find_feature (hb_face_t    *face,
   return FALSE;
 }
 
-hb_bool_t
+unsigned int
 hb_ot_layout_feature_get_lookup_indexes (hb_face_t    *face,
                                         hb_tag_t      table_tag,
                                         unsigned int  feature_index,
+                                        unsigned int  start_offset,
                                         unsigned int *lookup_count /* IN/OUT */,
                                         unsigned int *lookup_indexes /* OUT */)
 {
   const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
   const Feature &f = g.get_feature (feature_index);
 
-  return f.get_lookup_indexes (lookup_count, lookup_indexes);
+  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
 }
 
 
index 54f785f..312482a 100644 (file)
@@ -73,17 +73,19 @@ hb_ot_layout_build_glyph_classes (hb_face_t      *face,
 
 /* Not that useful.  Provides list of attach points for a glyph that a
  * client may want to cache */
-hb_bool_t
+unsigned int
 hb_ot_layout_get_attach_points (hb_face_t      *face,
                                hb_codepoint_t  glyph,
+                               unsigned int    start_offset,
                                unsigned int   *point_count /* IN/OUT */,
                                unsigned int   *point_array /* OUT */);
 
 /* Ligature caret positions */
-hb_bool_t
+unsigned int
 hb_ot_layout_get_lig_carets (hb_face_t      *face,
                             hb_font_t      *font,
                             hb_codepoint_t  glyph,
+                            unsigned int    start_offset,
                             unsigned int   *caret_count /* IN/OUT */,
                             int            *caret_array /* OUT */);
 
@@ -98,9 +100,10 @@ hb_ot_layout_get_lig_carets (hb_face_t      *face,
 #define HB_OT_LAYOUT_TAG_DEFAULT_SCRIPT                HB_TAG ('D', 'F', 'L', 'T')
 #define HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE      HB_TAG ('d', 'f', 'l', 't')
 
-hb_bool_t
+unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
                                    hb_tag_t      table_tag,
+                                   unsigned int  start_offset,
                                    unsigned int *script_count /* IN/OUT */,
                                    hb_tag_t     *script_tags /* OUT */);
 
@@ -110,16 +113,18 @@ hb_ot_layout_table_find_script (hb_face_t    *face,
                                hb_tag_t      script_tag,
                                unsigned int *script_index);
 
-hb_bool_t
+unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
                                     hb_tag_t      table_tag,
+                                    unsigned int  start_offset,
                                     unsigned int *feature_count /* IN/OUT */,
                                     hb_tag_t     *feature_tags /* OUT */);
 
-hb_bool_t
+unsigned int
 hb_ot_layout_script_get_language_tags (hb_face_t    *face,
                                       hb_tag_t      table_tag,
                                       unsigned int  script_index,
+                                      unsigned int  start_offset,
                                       unsigned int *language_count /* IN/OUT */,
                                       hb_tag_t     *language_tags /* OUT */);
 
@@ -137,19 +142,21 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
                                                  unsigned int  language_index,
                                                  unsigned int *feature_index);
 
-hb_bool_t
+unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
                                           hb_tag_t      table_tag,
                                           unsigned int  script_index,
                                           unsigned int  language_index,
+                                          unsigned int  start_offset,
                                           unsigned int *feature_count /* IN/OUT */,
                                           unsigned int *feature_indexes /* OUT */);
 
-hb_bool_t
+unsigned int
 hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
                                        hb_tag_t      table_tag,
                                        unsigned int  script_index,
                                        unsigned int  language_index,
+                                       unsigned int  start_offset,
                                        unsigned int *feature_count /* IN/OUT */,
                                        hb_tag_t     *feature_tags /* OUT */);
 
@@ -161,10 +168,11 @@ hb_ot_layout_language_find_feature (hb_face_t    *face,
                                    hb_tag_t      feature_tag,
                                    unsigned int *feature_index);
 
-hb_bool_t
+unsigned int
 hb_ot_layout_feature_get_lookup_indexes (hb_face_t    *face,
                                         hb_tag_t      table_tag,
                                         unsigned int  feature_index,
+                                        unsigned int  start_offset,
                                         unsigned int *lookup_count /* IN/OUT */,
                                         unsigned int *lookup_indexes /* OUT */);