Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / src / hb-ot-var-hvar-table.hh
index e9d9035..ca1ea1c 100644 (file)
@@ -45,7 +45,8 @@ struct index_map_subset_plan_t
   void init (const DeltaSetIndexMap  &index_map,
             hb_inc_bimap_t          &outer_map,
             hb_vector_t<hb_set_t *> &inner_sets,
-            const hb_subset_plan_t  *plan)
+            const hb_subset_plan_t  *plan,
+            bool bypass_empty = true)
   {
     map_count = 0;
     outer_bit_count = 0;
@@ -53,55 +54,51 @@ struct index_map_subset_plan_t
     max_inners.init ();
     output_map.init ();
 
-    if (&index_map == &Null (DeltaSetIndexMap)) return;
+    if (bypass_empty && !index_map.get_map_count ()) return;
 
     unsigned int       last_val = (unsigned int)-1;
-    hb_codepoint_t     last_gid = (hb_codepoint_t)-1;
-    hb_codepoint_t     gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
+    hb_codepoint_t     last_gid = HB_CODEPOINT_INVALID;
 
     outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count ();
     max_inners.resize (inner_sets.length);
     for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0;
 
     /* Search backwards for a map value different from the last map value */
-    for (; gid > 0; gid--)
+    auto &new_to_old_gid_list = plan->new_to_old_gid_list;
+    unsigned count = new_to_old_gid_list.length;
+    for (unsigned j = count; j; j--)
     {
-      hb_codepoint_t   old_gid;
-      if (!plan->old_gid_for_new_gid (gid - 1, &old_gid))
-      {
-       if (last_gid == (hb_codepoint_t) -1)
-         continue;
-       else
-         break;
-      }
+      hb_codepoint_t gid = new_to_old_gid_list.arrayZ[j - 1].first;
+      hb_codepoint_t old_gid = new_to_old_gid_list.arrayZ[j - 1].second;
 
       unsigned int v = index_map.map (old_gid);
-      if (last_gid == (hb_codepoint_t) -1)
+      if (last_gid == HB_CODEPOINT_INVALID)
       {
        last_val = v;
        last_gid = gid;
        continue;
       }
-      if (v != last_val) break;
+      if (v != last_val)
+       break;
 
       last_gid = gid;
     }
 
     if (unlikely (last_gid == (hb_codepoint_t)-1)) return;
-    map_count = last_gid;
-    for (gid = 0; gid < map_count; gid++)
+    map_count = last_gid + 1;
+    for (auto _ : plan->new_to_old_gid_list)
     {
-      hb_codepoint_t   old_gid;
-      if (plan->old_gid_for_new_gid (gid, &old_gid))
-      {
-       unsigned int v = index_map.map (old_gid);
-       unsigned int outer = v >> 16;
-       unsigned int inner = v & 0xFFFF;
-       outer_map.add (outer);
-       if (inner > max_inners[outer]) max_inners[outer] = inner;
-       if (outer >= inner_sets.length) return;
-       inner_sets[outer]->add (inner);
-      }
+      hb_codepoint_t gid = _.first;
+      if (gid >= map_count) break;
+
+      hb_codepoint_t old_gid = _.second;
+      unsigned int v = index_map.map (old_gid);
+      unsigned int outer = v >> 16;
+      unsigned int inner = v & 0xFFFF;
+      outer_map.add (outer);
+      if (inner > max_inners[outer]) max_inners[outer] = inner;
+      if (outer >= inner_sets.length) return;
+      inner_sets[outer]->add (inner);
     }
   }
 
@@ -116,8 +113,6 @@ struct index_map_subset_plan_t
              const hb_vector_t<hb_inc_bimap_t> &inner_maps,
              const hb_subset_plan_t *plan)
   {
-    if (input_map == &Null (DeltaSetIndexMap)) return;
-
     for (unsigned int i = 0; i < max_inners.length; i++)
     {
       if (inner_maps[i].get_population () == 0) continue;
@@ -125,21 +120,50 @@ struct index_map_subset_plan_t
       if (bit_count > inner_bit_count) inner_bit_count = bit_count;
     }
 
-    output_map.resize (map_count);
-    for (hb_codepoint_t gid = 0; gid < output_map.length; gid++)
+    if (unlikely (!output_map.resize (map_count))) return;
+    for (const auto &_ : plan->new_to_old_gid_list)
     {
-      hb_codepoint_t   old_gid;
-      if (plan->old_gid_for_new_gid (gid, &old_gid))
-      {
-       uint32_t v = input_map->map (old_gid);
-       unsigned int outer = v >> 16;
-       output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
-      }
-      else
-       output_map[gid] = 0;    /* Map unused glyph to outer/inner=0/0 */
+      hb_codepoint_t new_gid = _.first;
+      hb_codepoint_t old_gid = _.second;
+
+      if (unlikely (new_gid >= map_count)) break;
+
+      uint32_t v = input_map->map (old_gid);
+      unsigned int outer = v >> 16;
+      output_map.arrayZ[new_gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
     }
   }
 
+  bool remap_after_instantiation (const hb_subset_plan_t *plan,
+                                  const hb_map_t& varidx_map)
+  {
+    /* recalculate bit_count after remapping */
+    outer_bit_count = 1;
+    inner_bit_count = 1;
+
+    for (const auto &_ : plan->new_to_old_gid_list)
+    {
+      hb_codepoint_t new_gid = _.first;
+      if (unlikely (new_gid >= map_count)) break;
+
+      uint32_t v = output_map.arrayZ[new_gid];
+      uint32_t *new_varidx;
+      if (!varidx_map.has (v, &new_varidx))
+        return false;
+
+      output_map.arrayZ[new_gid] = *new_varidx;
+
+      unsigned outer = (*new_varidx) >> 16;
+      unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer);
+      outer_bit_count = hb_max (bit_count, outer_bit_count);
+      
+      unsigned inner = (*new_varidx) & 0xFFFF;
+      bit_count = (inner == 0) ? 1 : hb_bit_storage (inner);
+      inner_bit_count = hb_max (bit_count, inner_bit_count);
+    }
+    return true;
+  }
+
   unsigned int get_inner_bit_count () const { return inner_bit_count; }
   unsigned int get_width ()           const { return ((outer_bit_count + inner_bit_count + 7) / 8); }
   unsigned int get_map_count ()       const { return map_count; }
@@ -180,17 +204,13 @@ struct hvarvvar_subset_plan_t
     if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return;
 
     bool retain_adv_map = false;
-    index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan);
+    index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan, false);
     if (index_maps[0] == &Null (DeltaSetIndexMap))
     {
       retain_adv_map = plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS;
       outer_map.add (0);
-      for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
-      {
-       hb_codepoint_t old_gid;
-       if (plan->old_gid_for_new_gid (gid, &old_gid))
-         inner_sets[0]->add (old_gid);
-      }
+      for (hb_codepoint_t old_gid : plan->glyphset()->iter())
+        inner_sets[0]->add (old_gid);
       hb_set_union (adv_set, inner_sets[0]);
     }
 
@@ -201,11 +221,11 @@ struct hvarvvar_subset_plan_t
 
     if (retain_adv_map)
     {
-      for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
-       if (inner_sets[0]->has (gid))
-         inner_maps[0].add (gid);
-       else
-         inner_maps[0].skip ();
+      for (const auto &_ : plan->new_to_old_gid_list)
+      {
+        hb_codepoint_t old_gid = _.second;
+       inner_maps[0].add (old_gid);
+      }
     }
     else
     {
@@ -221,6 +241,16 @@ struct hvarvvar_subset_plan_t
       index_map_plans[i].remap (index_maps[i], outer_map, inner_maps, plan);
   }
 
+  /* remap */
+  bool remap_index_map_plans (const hb_subset_plan_t *plan,
+                              const hb_map_t& varidx_map)
+  {
+    for (unsigned i = 0; i < index_map_plans.length; i++)
+      if (!index_map_plans[i].remap_after_instantiation (plan, varidx_map))
+        return false;
+    return true;
+  }
+
   void fini ()
   {
     for (unsigned int i = 0; i < inner_sets.length; i++)
@@ -265,6 +295,9 @@ struct HVARVVAR
                  rsbMap.sanitize (c, this));
   }
 
+  const VariationStore& get_var_store () const
+  { return this+varStore; }
+
   void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
   {
     index_maps.push (&(this+advMap));
@@ -296,6 +329,9 @@ struct HVARVVAR
   bool _subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
+    if (c->plan->all_axes_pinned)
+      return_trace (false);
+
     hvarvvar_subset_plan_t     hvar_plan;
     hb_vector_t<const DeltaSetIndexMap *>
                                index_maps;
@@ -309,33 +345,63 @@ struct HVARVVAR
     out->version.major = 1;
     out->version.minor = 0;
 
-    if (unlikely (!out->varStore
-                     .serialize_serialize (c->serializer,
-                                           hvar_plan.var_store,
-                                           hvar_plan.inner_maps.as_array ())))
+    if (c->plan->normalized_coords)
+    {
+      item_variations_t item_vars;
+      if (!item_vars.instantiate (this+varStore, c->plan,
+                                  advMap == 0 ? false : true,
+                                  false, /* use_no_variation_idx = false */
+                                  hvar_plan.inner_maps.as_array ()))
+        return_trace (false);
+
+      if (!out->varStore.serialize_serialize (c->serializer,
+                                              item_vars.has_long_word (),
+                                              c->plan->axis_tags,
+                                              item_vars.get_region_list (),
+                                              item_vars.get_vardata_encodings ()))
+        return_trace (false);
+
+      /* if varstore is optimized, remap output_map */
+      if (advMap)
+      {
+        if (!hvar_plan.remap_index_map_plans (c->plan, item_vars.get_varidx_map ()))
+          return_trace (false);
+      }
+    }
+    else
+    {
+      if (unlikely (!out->varStore
+                   .serialize_serialize (c->serializer,
+                                         hvar_plan.var_store,
+                                         hvar_plan.inner_maps.as_array ())))
       return_trace (false);
+    }
 
     return_trace (out->T::serialize_index_maps (c->serializer,
                                                hvar_plan.index_map_plans.as_array ()));
   }
 
-  float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
+  float get_advance_delta_unscaled (hb_codepoint_t  glyph,
+                                   const int *coords, unsigned int coord_count,
+                                   VariationStore::cache_t *store_cache = nullptr) const
   {
     uint32_t varidx = (this+advMap).map (glyph);
-    return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
+    return (this+varStore).get_delta (varidx,
+                                     coords, coord_count,
+                                     store_cache);
   }
 
-  float get_side_bearing_var (hb_codepoint_t glyph,
-                             const int *coords, unsigned int coord_count) const
+  bool get_lsb_delta_unscaled (hb_codepoint_t glyph,
+                              const int *coords, unsigned int coord_count,
+                              float *lsb) const
   {
-    if (!has_side_bearing_deltas ()) return 0.f;
+    if (!lsbMap) return false;
     uint32_t varidx = (this+lsbMap).map (glyph);
-    return (this+varStore).get_delta (varidx, coords, coord_count);
+    *lsb = (this+varStore).get_delta (varidx, coords, coord_count);
+    return true;
   }
 
-  bool has_side_bearing_deltas () const { return lsbMap && rsbMap; }
-
-  protected:
+  public:
   FixedVersion<>version;       /* Version of the metrics variation table
                                 * initially set to 0x00010000u */
   Offset32To<VariationStore>
@@ -387,6 +453,16 @@ struct VVAR : HVARVVAR {
 
   bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
 
+  bool get_vorg_delta_unscaled (hb_codepoint_t glyph,
+                               const int *coords, unsigned int coord_count,
+                               float *delta) const
+  {
+    if (!vorgMap) return false;
+    uint32_t varidx = (this+vorgMap).map (glyph);
+    *delta = (this+varStore).get_delta (varidx, coords, coord_count);
+    return true;
+  }
+
   protected:
   Offset32To<DeltaSetIndexMap>
                vorgMap;        /* Offset to vertical-origin var-idx mapping. */