Imported Upstream version 1.7.6
[platform/upstream/harfbuzz.git] / src / hb-ot-shape-fallback.cc
index 53274b5..c7b4605 100644 (file)
@@ -200,8 +200,7 @@ position_mark (const hb_ot_shape_plan_t *plan,
               unsigned int combining_class)
 {
   hb_glyph_extents_t mark_extents;
-  if (!font->get_glyph_extents (buffer->info[i].codepoint,
-                               &mark_extents))
+  if (!font->get_glyph_extents (buffer->info[i].codepoint, &mark_extents))
     return;
 
   hb_position_t y_gap = font->y_scale / 16;
@@ -210,7 +209,7 @@ position_mark (const hb_ot_shape_plan_t *plan,
   pos.x_offset = pos.y_offset = 0;
 
 
-  /* We dont position LEFT and RIGHT marks. */
+  /* We don't position LEFT and RIGHT marks. */
 
   /* X positioning */
   switch (combining_class)
@@ -218,13 +217,13 @@ position_mark (const hb_ot_shape_plan_t *plan,
     case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
     case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
       if (buffer->props.direction == HB_DIRECTION_LTR) {
-       pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
+       pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
         break;
       } else if (buffer->props.direction == HB_DIRECTION_RTL) {
-       pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
+       pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
         break;
       }
-      /* Fall through */
+      HB_FALLTHROUGH;
 
     default:
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
@@ -259,6 +258,7 @@ position_mark (const hb_ot_shape_plan_t *plan,
     case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
       /* Add gap, fall-through. */
       base_extents.height -= y_gap;
+      HB_FALLTHROUGH;
 
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
@@ -279,6 +279,7 @@ position_mark (const hb_ot_shape_plan_t *plan,
       /* Add gap, fall-through. */
       base_extents.y_bearing += y_gap;
       base_extents.height -= y_gap;
+      HB_FALLTHROUGH;
 
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
@@ -305,6 +306,9 @@ position_around_base (const hb_ot_shape_plan_t *plan,
                      unsigned int end)
 {
   hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
+
+  buffer->unsafe_to_break (base, end);
+
   hb_glyph_extents_t base_extents;
   if (!font->get_glyph_extents (buffer->info[base].codepoint,
                                &base_extents))
@@ -317,7 +321,9 @@ position_around_base (const hb_ot_shape_plan_t *plan,
   base_extents.y_bearing += buffer->pos[base].y_offset;
 
   unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
-  unsigned int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
+  /* Use integer for num_lig_components such that it doesn't convert to unsigned
+   * when we divide or multiply by it. */
+  int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
 
   hb_position_t x_offset = 0, y_offset = 0;
   if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
@@ -326,7 +332,7 @@ position_around_base (const hb_ot_shape_plan_t *plan,
   }
 
   hb_glyph_extents_t component_extents = base_extents;
-  unsigned int last_lig_component = (unsigned int) -1;
+  int last_lig_component = -1;
   unsigned int last_combining_class = 255;
   hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
   hb_glyph_info_t *info = buffer->info;
@@ -335,7 +341,7 @@ position_around_base (const hb_ot_shape_plan_t *plan,
     {
       if (num_lig_components > 1) {
        unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
-       unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
+       int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
        /* Conditions for attaching to the last component. */
        if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
          this_lig_component = num_lig_components - 1;
@@ -418,13 +424,12 @@ _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
   _hb_buffer_assert_gsubgpos_vars (buffer);
 
   unsigned int start = 0;
-  unsigned int last_cluster = buffer->info[0].cluster;
   unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 1; i < count; i++)
-    if (buffer->info[i].cluster != last_cluster) {
+    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
       position_cluster (plan, font, buffer, start, i);
       start = i;
-      last_cluster = buffer->info[i].cluster;
     }
   position_cluster (plan, font, buffer, start, count);
 }
@@ -438,10 +443,10 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
 {
   if (!plan->has_kern) return;
 
-  OT::hb_apply_context_t c (1, font, buffer);
+  OT::hb_ot_apply_context_t c (1, font, buffer);
   c.set_lookup_mask (plan->kern_mask);
   c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
-  OT::hb_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
+  OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
   skippy_iter.init (&c);
 
   unsigned int count = buffer->len;
@@ -469,6 +474,7 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
       pos[idx].x_advance += kern1;
       pos[skippy_iter.idx].x_advance += kern2;
       pos[skippy_iter.idx].x_offset += kern2;
+      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
     }
 
     if (y_kern)
@@ -478,8 +484,76 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
       pos[idx].y_advance += kern1;
       pos[skippy_iter.idx].y_advance += kern2;
       pos[skippy_iter.idx].y_offset += kern2;
+      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
     }
 
     idx = skippy_iter.idx;
   }
 }
+
+
+/* Adjusts width of various spaces. */
+void
+_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+                             hb_font_t *font,
+                             hb_buffer_t  *buffer)
+{
+  if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+    return;
+
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
+    {
+      hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
+      hb_codepoint_t glyph;
+      typedef hb_unicode_funcs_t t;
+      switch (space_type)
+      {
+       case t::NOT_SPACE: /* Shouldn't happen. */
+       case t::SPACE:
+         break;
+
+       case t::SPACE_EM:
+       case t::SPACE_EM_2:
+       case t::SPACE_EM_3:
+       case t::SPACE_EM_4:
+       case t::SPACE_EM_5:
+       case t::SPACE_EM_6:
+       case t::SPACE_EM_16:
+         pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
+         break;
+
+       case t::SPACE_4_EM_18:
+         pos[i].x_advance = (int64_t) font->x_scale * 4 / 18;
+         break;
+
+       case t::SPACE_FIGURE:
+         for (char u = '0'; u <= '9'; u++)
+           if (font->get_nominal_glyph (u, &glyph))
+           {
+             pos[i].x_advance = font->get_glyph_h_advance (glyph);
+             break;
+           }
+         break;
+
+       case t::SPACE_PUNCTUATION:
+         if (font->get_nominal_glyph ('.', &glyph))
+           pos[i].x_advance = font->get_glyph_h_advance (glyph);
+         else if (font->get_nominal_glyph (',', &glyph))
+           pos[i].x_advance = font->get_glyph_h_advance (glyph);
+         break;
+
+       case t::SPACE_NARROW:
+         /* Half-space?
+          * Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
+          * However, in my testing, many fonts have their regular space being about that
+          * size.  To me, a percentage of the space width makes more sense.  Half is as
+          * good as any. */
+         pos[i].x_advance /= 2;
+         break;
+      }
+    }
+}