Example #1
0
static void
fribidi_shape_arabic_ligature (
  /* input */
  const PairMap *table,
  int size,
  const FriBidiLevel *embedding_levels,
  const FriBidiStrIndex len,
  /* input and output */
  FriBidiArabicProp *ar_props,
  FriBidiChar *str
)
{
  /* TODO: This doesn't form ligatures for even-level Arabic text.
   * no big problem though. */
  register FriBidiStrIndex i;

  for (i = 0; i < len - 1; i++) {
    register FriBidiChar c;
    if (FRIBIDI_LEVEL_IS_RTL(embedding_levels[i]) &&
	embedding_levels[i] == embedding_levels[i+1] &&
	(c = PAIR_MATCH(table, size, str[i], str[i+1])))
      {
	str[i] = FRIBIDI_CHAR_FILL;
	FRIBIDI_SET_BITS(ar_props[i], FRIBIDI_MASK_LIGATURED);
	str[i+1] = c;
      }
  }
}
FRIBIDI_ENTRY void
fribidi_join_arabic (
  /* input */
  const FriBidiCharType *bidi_types,
  const FriBidiStrIndex len,
  const FriBidiLevel *embedding_levels,
  /* input and output */
  FriBidiArabicProp *ar_props
)
{
  if UNLIKELY
    (len == 0) return;

  DBG ("in fribidi_join_arabic");

  fribidi_assert (bidi_types);
  fribidi_assert (embedding_levels);
  fribidi_assert (ar_props);

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_joining_types (embedding_levels, len, ar_props);
    }
# endif	/* DEBUG */

  /* The joining algorithm turned out very very dirty :(.  That's what happens
   * when you follow the standard which has never been implemented closely
   * before.
   */

  /* 8.2 Arabic - Cursive Joining */
  DBG ("Arabic cursive joining");
  {
    /* The following do not need to be initialized as long as joins is
     * initialized to false.  We just do to turn off compiler warnings. */
    register FriBidiStrIndex saved = 0;
    register FriBidiLevel saved_level = FRIBIDI_SENTINEL;
    register fribidi_boolean saved_shapes = false;
    register FriBidiArabicProp saved_joins_following_mask = 0;

    register fribidi_boolean joins = false;
    register FriBidiStrIndex i;

    for (i = 0; i < len; i++)
      if (!FRIBIDI_IS_JOINING_TYPE_G (ar_props[i]))
	{
	  register fribidi_boolean disjoin = false;
	  register fribidi_boolean shapes = FRIBIDI_ARAB_SHAPES (ar_props[i]);
	  register FriBidiLevel level = FRIBIDI_CONSISTENT_LEVEL (i);

	  if (joins && !FRIBIDI_LEVELS_MATCH (saved_level, level))
	    {
	      disjoin = true;
	      joins = false;
	    }

	  if (!FRIBIDI_IS_JOIN_SKIPPED (ar_props[i]))
	    {
	      register const FriBidiArabicProp joins_preceding_mask =
		FRIBIDI_JOINS_PRECEDING_MASK (level);

	      if (!joins)
		{
		  if (shapes)
		    FRIBIDI_UNSET_BITS (ar_props[i], joins_preceding_mask);
		}
	      else if (!FRIBIDI_TEST_BITS (ar_props[i], joins_preceding_mask))
	        {
		  disjoin = true;
		}
	      else
	        {
		  register FriBidiStrIndex j;
		  /* This is a FriBidi extension:  we set joining properties
		   * for skipped characters in between, so we can put NSMs on tatweel
		   * later if we want.  Useful on console for example.
		   */
		  for (j = saved + 1; j < i; j++)
		    FRIBIDI_SET_BITS (ar_props[j], joins_preceding_mask | saved_joins_following_mask);
		}
	    }

	  if (disjoin && saved_shapes)
	    FRIBIDI_UNSET_BITS (ar_props[saved], saved_joins_following_mask);

	  if (!FRIBIDI_IS_JOIN_SKIPPED (ar_props[i]))
	    {
	      saved = i;
	      saved_level = level;
	      saved_shapes = shapes;
	      saved_joins_following_mask =
		FRIBIDI_JOINS_FOLLOWING_MASK (level);
	      joins =
		FRIBIDI_TEST_BITS (ar_props[i], saved_joins_following_mask);
	    }
	}
    if ((joins) && saved_shapes)
      FRIBIDI_UNSET_BITS (ar_props[saved], saved_joins_following_mask);

  }

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_joining_types (embedding_levels, len, ar_props);
    }
# endif	/* DEBUG */

  DBG ("leaving fribidi_join_arabic");
}