Revert "Imported Upstream version 1.2.7"
[platform/upstream/harfbuzz.git] / src / hb-ot-shape-complex-arabic.cc
index 4da8990..ae90864 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-arabic-private.hh"
+#include "hb-ot-shape-complex-private.hh"
 #include "hb-ot-shape-private.hh"
 
 
-#ifndef HB_DEBUG_ARABIC
-#define HB_DEBUG_ARABIC (HB_DEBUG+0)
-#endif
-
-
 /* buffer var allocations */
 #define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
 
-#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
-
-/* See:
- * https://github.com/behdad/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
-#define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \
-       (FLAG_SAFE (gen_cat) & \
-        (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \
-         /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \
-         /*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \
-         /*FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |*/ \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL)))
-
-
-/*
- * Joining types:
- */
 
 /*
  * Bits used in the joining tables
  */
-enum hb_arabic_joining_type_t {
+enum {
   JOINING_TYPE_U               = 0,
   JOINING_TYPE_L               = 1,
   JOINING_TYPE_R               = 2,
@@ -82,6 +49,10 @@ enum hb_arabic_joining_type_t {
   JOINING_TYPE_X = 8  /* means: use general-category to choose between U or T. */
 };
 
+/*
+ * Joining types:
+ */
+
 #include "hb-ot-shape-complex-arabic-table.hh"
 
 static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
@@ -90,7 +61,7 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ
   if (likely (j_type != JOINING_TYPE_X))
     return j_type;
 
-  return (FLAG_SAFE(gen_cat) &
+  return (FLAG(gen_cat) &
          (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
           FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
           FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
@@ -113,7 +84,7 @@ static const hb_tag_t arabic_features[] =
 
 
 /* Same order as the feature array */
-enum arabic_action_t {
+enum {
   ISOL,
   FINA,
   FIN2,
@@ -124,11 +95,7 @@ enum arabic_action_t {
 
   NONE,
 
-  ARABIC_NUM_FEATURES = NONE,
-
-  /* We abuse the same byte for other things... */
-  STCH_FIXED,
-  STCH_REPEATING,
+  ARABIC_NUM_FEATURES = NONE
 };
 
 static const struct arabic_state_table_entry {
@@ -173,11 +140,6 @@ arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                       hb_buffer_t *buffer);
 
 static void
-record_stch (const hb_ot_shape_plan_t *plan,
-            hb_font_t *font,
-            hb_buffer_t *buffer);
-
-static void
 collect_features_arabic (hb_ot_shape_planner_t *plan)
 {
   hb_ot_map_builder_t *map = &plan->map;
@@ -203,9 +165,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
 
   map->add_gsub_pause (nuke_joiners);
 
-  map->add_global_bool_feature (HB_TAG('s','t','c','h'));
-  map->add_gsub_pause (record_stch);
-
   map->add_global_bool_feature (HB_TAG('c','c','m','p'));
   map->add_global_bool_feature (HB_TAG('l','o','c','l'));
 
@@ -223,6 +182,7 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
     map->add_gsub_pause (arabic_fallback_shape);
 
   map->add_global_bool_feature (HB_TAG('c','a','l','t'));
+  map->add_gsub_pause (NULL);
 
   /* The spec includes 'cswh'.  Earlier versions of Windows
    * used to enable this by default, but testing suggests
@@ -232,7 +192,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
    * Note that IranNastaliq uses this feature extensively
    * to fixup broken glyph sequences.  Oh well...
    * Test case: U+0643,U+0640,U+0631. */
-  //map->add_gsub_pause (NULL);
   //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
   map->add_global_bool_feature (HB_TAG('m','s','e','t'));
 }
@@ -249,13 +208,11 @@ struct arabic_shape_plan_t
    * mask_array[NONE] == 0. */
   hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
 
+  bool do_fallback;
   arabic_fallback_plan_t *fallback_plan;
-
-  unsigned int do_fallback : 1;
-  unsigned int has_stch : 1;
 };
 
-void *
+static void *
 data_create_arabic (const hb_ot_shape_plan_t *plan)
 {
   arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
@@ -263,7 +220,6 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
     return NULL;
 
   arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
-  arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h'));
   for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
     arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
     arabic_plan->do_fallback = arabic_plan->do_fallback &&
@@ -274,7 +230,7 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
   return arabic_plan;
 }
 
-void
+static void
 data_destroy_arabic (void *data)
 {
   arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data;
@@ -349,30 +305,25 @@ mongolian_variation_selectors (hb_buffer_t *buffer)
       info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
 }
 
-void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
-                        hb_buffer_t               *buffer,
-                        hb_script_t                script)
+static void
+setup_masks_arabic (const hb_ot_shape_plan_t *plan,
+                   hb_buffer_t              *buffer,
+                   hb_font_t                *font HB_UNUSED)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
 
+  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
+
   arabic_joining (buffer);
-  if (script == HB_SCRIPT_MONGOLIAN)
+  if (plan->props.script == HB_SCRIPT_MONGOLIAN)
     mongolian_variation_selectors (buffer);
 
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
     info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
-}
 
-static void
-setup_masks_arabic (const hb_ot_shape_plan_t *plan,
-                   hb_buffer_t              *buffer,
-                   hb_font_t                *font HB_UNUSED)
-{
-  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
-  setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }
 
 
@@ -413,197 +364,6 @@ retry:
   arabic_fallback_plan_shape (fallback_plan, font, buffer);
 }
 
-/*
- * Stretch feature: "stch".
- * See example here:
- * https://www.microsoft.com/typography/OpenTypeDev/syriac/intro.htm
- * We implement this in a generic way, such that the Arabic subtending
- * marks can use it as well.
- */
-
-static void
-record_stch (const hb_ot_shape_plan_t *plan,
-            hb_font_t *font,
-            hb_buffer_t *buffer)
-{
-  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
-  if (!arabic_plan->has_stch)
-    return;
-
-  /* 'stch' feature was just applied.  Look for anything that multiplied,
-   * and record it for stch treatment later.  Note that rtlm, frac, etc
-   * are applied before stch, but we assume that they didn't result in
-   * anything multiplying into 5 pieces, so it's safe-ish... */
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (unlikely (_hb_glyph_info_multiplied (&info[i])))
-    {
-      unsigned int comp = _hb_glyph_info_get_lig_comp (&info[i]);
-      info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
-    }
-}
-
-static void
-apply_stch (const hb_ot_shape_plan_t *plan,
-           hb_buffer_t              *buffer,
-           hb_font_t                *font)
-{
-  if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
-    return;
-
-  /* The Arabic shaper currently always processes in RTL mode, so we should
-   * stretch / position the stretched pieces to the left / preceding glyphs. */
-
-  /* We do a two pass implementation:
-   * First pass calculates the exact number of extra glyphs we need,
-   * We then enlarge buffer to have that much room,
-   * Second pass applies the stretch, copying things to the end of buffer.
-   */
-
-  int sign = font->x_scale < 0 ? -1 : +1;
-  unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
-  typedef enum { MEASURE, CUT } step_t;
-
-  for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1))
-  {
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    hb_glyph_position_t *pos = buffer->pos;
-    unsigned int new_len = count + extra_glyphs_needed; // write head during CUT
-    unsigned int j = new_len;
-    for (unsigned int i = count; i; i--)
-    {
-      if (!hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
-      {
-        if (step == CUT)
-       {
-         --j;
-         info[j] = info[i - 1];
-         pos[j] = pos[i - 1];
-       }
-        continue;
-      }
-
-      /* Yay, justification! */
-
-      hb_position_t w_total = 0; // Total to be filled
-      hb_position_t w_fixed = 0; // Sum of fixed tiles
-      hb_position_t w_repeating = 0; // Sum of repeating tiles
-      int n_fixed = 0;
-      int n_repeating = 0;
-
-      unsigned int end = i;
-      while (i &&
-            hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
-      {
-       i--;
-       hb_position_t width = font->get_glyph_h_advance (info[i].codepoint);
-       if (info[i].arabic_shaping_action() == STCH_FIXED)
-       {
-         w_fixed += width;
-         n_fixed++;
-       }
-       else
-       {
-         w_repeating += width;
-         n_repeating++;
-       }
-      }
-      unsigned int start = i;
-      unsigned int context = i;
-      while (context &&
-            !hb_in_range<unsigned> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) &&
-            (_hb_glyph_info_is_default_ignorable (&info[context - 1]) ||
-             HB_ARABIC_GENERAL_CATEGORY_IS_WORD (_hb_glyph_info_get_general_category (&info[context - 1]))))
-      {
-       context--;
-       w_total += pos[context].x_advance;
-      }
-      i++; // Don't touch i again.
-
-      DEBUG_MSG (ARABIC, NULL, "%s stretch at (%d,%d,%d)",
-                step == MEASURE ? "measuring" : "cutting", context, start, end);
-      DEBUG_MSG (ARABIC, NULL, "rest of word:    count=%d width %d", start - context, w_total);
-      DEBUG_MSG (ARABIC, NULL, "fixed tiles:     count=%d width=%d", n_fixed, w_fixed);
-      DEBUG_MSG (ARABIC, NULL, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
-
-      /* Number of additional times to repeat each repeating tile. */
-      int n_copies = 0;
-
-      hb_position_t w_remaining = w_total - w_fixed;
-      if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
-       n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
-
-      /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
-      hb_position_t extra_repeat_overlap = 0;
-      hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
-      if (shortfall > 0)
-      {
-        ++n_copies;
-        hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
-        if (excess > 0)
-          extra_repeat_overlap = excess / (n_copies * n_repeating);
-      }
-
-      if (step == MEASURE)
-      {
-       extra_glyphs_needed += n_copies * n_repeating;
-       DEBUG_MSG (ARABIC, NULL, "will add extra %d copies of repeating tiles", n_copies);
-      }
-      else
-      {
-       hb_position_t x_offset = 0;
-       for (unsigned int k = end; k > start; k--)
-       {
-         hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
-
-         unsigned int repeat = 1;
-         if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
-           repeat += n_copies;
-
-         DEBUG_MSG (ARABIC, NULL, "appending %d copies of glyph %d; j=%d",
-                    repeat, info[k - 1].codepoint, j);
-         for (unsigned int n = 0; n < repeat; n++)
-         {
-           x_offset -= width;
-           if (n > 0)
-             x_offset += extra_repeat_overlap;
-           pos[k - 1].x_offset = x_offset;
-           /* Append copy. */
-           --j;
-           info[j] = info[k - 1];
-           pos[j] = pos[k - 1];
-         }
-       }
-      }
-    }
-
-    if (step == MEASURE)
-    {
-      if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
-        break;
-    }
-    else
-    {
-      assert (j == 0);
-      buffer->len = new_len;
-    }
-  }
-}
-
-
-static void
-postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
-                          hb_buffer_t              *buffer,
-                          hb_font_t                *font)
-{
-  apply_stch (plan, buffer, font);
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
-}
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
 {
@@ -612,8 +372,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
   NULL, /* override_features */
   data_create_arabic,
   data_destroy_arabic,
-  NULL, /* preprocess_text */
-  postprocess_glyphs_arabic,
+  NULL, /* preprocess_text_arabic */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   NULL, /* compose */