[FriBidi-commit] fribidi/lib Makefile.am, 1.11, 1.12 common.h, 1.13, 1.14 fribidi-bidi-types.c, 1.7, 1.8 fribidi-bidi-types.h, 1.9, 1.10 fribidi-bidi.c, 1.12, 1.13 fribidi-bidi.h, 1.9, 1.10 fribidi-joining-types-list.h, 1.1, 1.2 fribidi-joining-types.c, 1.2, 1.3 fribidi-joining-types.h, 1.2, 1.3 fribidi-joining.c, 1.1, 1.2 fribidi-joining.h, 1.1, 1.2 fribidi-mirroring.c, 1.12, 1.13 fribidi-mirroring.h, 1.8, 1.9 fribidi-types.h, 1.6, 1.7 fribidi.c, 1.10, 1.11 fribidi.def, 1.6, 1.7 fribidi.h, 1.6, 1.7 joining-types.h, 1.1, 1.2

Behdad Esfahbod behdad at pdx.freedesktop.org
Tue Jun 15 04:52:05 PDT 2004


Update of /cvs/fribidi/fribidi/lib
In directory pdx:/tmp/cvs-serv6754/lib

Modified Files:
	Makefile.am common.h fribidi-bidi-types.c fribidi-bidi-types.h 
	fribidi-bidi.c fribidi-bidi.h fribidi-joining-types-list.h 
	fribidi-joining-types.c fribidi-joining-types.h 
	fribidi-joining.c fribidi-joining.h fribidi-mirroring.c 
	fribidi-mirroring.h fribidi-types.h fribidi.c fribidi.def 
	fribidi.h joining-types.h 
Log Message:
Arabic joining is almost complete.  Going for Shaping.


Index: Makefile.am
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/Makefile.am,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- Makefile.am	14 Jun 2004 18:43:53 -0000	1.11
+++ Makefile.am	15 Jun 2004 11:52:02 -0000	1.12
@@ -33,6 +33,7 @@
 libfribidi_la_SOURCES =	\
 		bidi-type.tab.i \
 		bidi-types.h \
+		cf-bn-nsm.tab.i \
 		common.h \
 		debug.h \
 		env.h \
@@ -55,7 +56,8 @@
 		fribidi-unicode-version.h \
 		bidi-type.tab.i \
 		joining-type.tab.i \
-		mirroring.tab.i
+		mirroring.tab.i \
+		cf-bn-nsm.tab.i
 
 $(BUILT_SOURCES):
 	@(cd $(top_builddir)/gen.tab && \

Index: common.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/common.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- common.h	13 Jun 2004 20:11:42 -0000	1.13
+++ common.h	15 Jun 2004 11:52:02 -0000	1.14
@@ -162,7 +162,9 @@
 #endif /* !HAVE_STRINGIZE */
 
 /* As per recommendation of GNU Coding Standards. */
-#define _GNU_SOURCE
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif /* !_GNU_SOURCE */
 
 #include "debug.h"
 

Index: fribidi-bidi-types.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-bidi-types.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- fribidi-bidi-types.c	14 Jun 2004 18:43:53 -0000	1.7
+++ fribidi-bidi-types.c	15 Jun 2004 11:52:02 -0000	1.8
@@ -69,19 +69,19 @@
   const FriBidiChar *str,
   const FriBidiStrIndex len,
   /* output */
-  FriBidiCharType *type
+  FriBidiCharType *btypes
 )
 {
   register FriBidiStrIndex i = len;
   for (; i; i--)
     {
-      *type++ = linear_enum_to_char_type[FRIBIDI_GET_BIDI_TYPE (*str)];
+      *btypes++ = linear_enum_to_char_type[FRIBIDI_GET_BIDI_TYPE (*str)];
       str++;
     }
 }
 
 FRIBIDI_ENTRY const char *
-fribidi_bidi_type_name (
+fribidi_get_bidi_type_name (
   /* input */
   FriBidiCharType t
 )

Index: fribidi-bidi-types.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-bidi-types.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- fribidi-bidi-types.h	14 Jun 2004 18:43:53 -0000	1.9
+++ fribidi-bidi-types.h	15 Jun 2004 11:52:02 -0000	1.10
@@ -46,6 +46,7 @@
  * only one bit set.
  */
 
+/* RTL mask better be the least significant bit. */
 #define FRIBIDI_MASK_RTL	0x00000001L	/* Is right to left */
 #define FRIBIDI_MASK_ARABIC	0x00000002L	/* Is arabic */
 
@@ -90,6 +91,8 @@
  * Define values for FriBidiCharType
  */
 
+/* Strong types */
+
 /* Left-To-Right letter */
 #define FRIBIDI_TYPE_LTR_VAL	( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_LETTER )
 /* Right-To-Left letter */
@@ -110,6 +113,8 @@
 #define FRIBIDI_TYPE_RLO_VAL	( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_EXPLICIT \
 				| FRIBIDI_MASK_RTL | FRIBIDI_MASK_OVERRIDE )
 
+/* Weak types */
+
 /* Pop Directional Flag*/
 #define FRIBIDI_TYPE_PDF_VAL	( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_EXPLICIT )
 /* European Numeral */
@@ -132,6 +137,8 @@
 #define FRIBIDI_TYPE_BN_VAL	( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_SPACE \
 				| FRIBIDI_MASK_BN )
 
+/* Neutral types */
+
 /* Block Separator */
 #define FRIBIDI_TYPE_BS_VAL	( FRIBIDI_MASK_NEUTRAL | FRIBIDI_MASK_SPACE \
 				| FRIBIDI_MASK_SEPARATOR | FRIBIDI_MASK_BS )
@@ -238,17 +245,19 @@
 /* Is right-to-left level? */
 #define FRIBIDI_LEVEL_IS_RTL(lev) ((lev) & 1)
 
-/* Return the direction of the level number, FRIBIDI_TYPE_LTR for even and
-   FRIBIDI_TYPE_RTL for odds. */
-#define FRIBIDI_LEVEL_TO_DIR(lev) (FRIBIDI_TYPE_LTR | ((lev) & 1))
+/* Return the bidi type corresponding to the direction of the level number,
+   FRIBIDI_TYPE_LTR for evens and FRIBIDI_TYPE_RTL for odds. */
+#define FRIBIDI_LEVEL_TO_DIR(lev)	\
+	(FRIBIDI_LEVEL_IS_RTL (lev) ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR)
 
 /* Return the minimum level of the direction, 0 for FRIBIDI_TYPE_LTR and
    1 for FRIBIDI_TYPE_RTL and FRIBIDI_TYPE_AL. */
-#define FRIBIDI_DIR_TO_LEVEL(dir) ((FriBidiLevel)((dir) & 1))
+#define FRIBIDI_DIR_TO_LEVEL(dir)	\
+	((FriBidiLevel) (FRIBIDI_IS_RTL (dir) ? 1 : 0))
 
-/* Is right to left? */
+/* Is right to left: RTL, AL, RLE, RLO? */
 #define FRIBIDI_IS_RTL(p)      ((p) & FRIBIDI_MASK_RTL)
-/* Is arabic? */
+/* Is arabic: AL, AN? */
 #define FRIBIDI_IS_ARABIC(p)   ((p) & FRIBIDI_MASK_ARABIC)
 
 /* Is strong? */
@@ -312,7 +321,7 @@
 
 /* Define some conversions. */
 
-/* Change numbers: EN, AN to RTL. */
+/* Change numbers to RTL: EN,AN -> RTL. */
 #define FRIBIDI_CHANGE_NUMBER_TO_RTL(p) \
 	(FRIBIDI_IS_NUMBER(p) ? FRIBIDI_TYPE_RTL : (p))
 
@@ -324,7 +333,7 @@
 
 /* Weaken type for paragraph fallback purposes:
  * LTR->WLTR, RTL->WRTL. */
-#define FRIBIDI_WEAK_PARAGRAPH(p) (FRIBIDI_TYPE_WLTR | ((p) & 1))
+#define FRIBIDI_WEAK_PARAGRAPH(p) (FRIBIDI_PAR_WLTR | ((p) & FRIBIDI_MASK_RTL))
 
 
 /* Functions finally */
@@ -333,8 +342,15 @@
 #define fribidi_get_bidi_type FRIBIDI_NAMESPACE(get_bidi_type)
 /* fribidi_get_bidi_type - get character bidi type
  *
- * This function returns the bidi type of a character.  There are a few macros
- * defined in fribidi-bidi-types.h for querying a bidi type.
+ * This function returns the bidi type of a character as defined in Table 3.7
+ * Bidirectional Character Types of the Unicode Bidirectional Algorithm
+ * available at
+ * http://www.unicode.org/reports/tr9/#Bidirectional_Character_Types, using
+ * data provided in file UnicodeData.txt of the Unicode Character Database
+ * available at http://www.unicode.org/Public/UNIDATA/UnicodeData.txt.
+ *
+ * There are a few macros defined in fribidi-bidi-types.h for querying a bidi
+ * type.
  */
 FRIBIDI_ENTRY FriBidiCharType
 fribidi_get_bidi_type (
@@ -345,25 +361,41 @@
 /* fribidi_get_bidi_types - get bidi types for an string of characters
  *
  * This function finds the bidi types of an string of characters.  See
- * fribidi_get_bidi_type for more information about the bidi types returned
+ * fribidi_get_bidi_type() for more information about the bidi types returned
  * by this function.
  */
      FRIBIDI_ENTRY void fribidi_get_bidi_types (
   const FriBidiChar *str,	/* input string */
   const FriBidiStrIndex len,	/* input string length */
-  FriBidiCharType *type		/* output bidi types */
+  FriBidiCharType *btypes	/* output bidi types */
 );
 
-#define fribidi_bidi_type_name FRIBIDI_NAMESPACE(bidi_type_name)
-/* fribidi_bidi_type_name - get bidi type name
+#define fribidi_get_bidi_type_name FRIBIDI_NAMESPACE(get_bidi_type_name)
+/* fribidi_get_bidi_type_name - get bidi type name
  *
  * This function returns the bidi type name of a character type.  The
  * returned string is a static string and should not be freed.
+ *
+ * The type names are the same as ones defined in Table 3.7 Bidirectional
+ * Character Types of the Unicode Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/#Bidirectional_Character_Types, with a
+ * few modifications: L->LTR, R->RTL, B->BS, S->SS.
  */
-     FRIBIDI_ENTRY const char *fribidi_bidi_type_name (
+     FRIBIDI_ENTRY const char *fribidi_get_bidi_type_name (
   FriBidiCharType t		/* input bidi type */
 ) FRIBIDI_GNUC_CONST;
 
+#define fribidi_is_cf_minus_bn_and_nsm FRIBIDI_NAMESPACE(is_cf_minus_bn_and_nsm)
+/* fribidi_is_cf_minus_bn_and_nsm - is other format control character?
+ *
+ * This function finds the bidi types of an string of characters.  See
+ * fribidi_get_bidi_type() for more information about the bidi types returned
+ * by this function.
+ */
+     FRIBIDI_ENTRY fribidi_boolean fribidi_get_bidi_types (
+  const FriBidiChar ch		/* input character */
+);
+
 #include "fribidi-enddecls.h"
 
 #endif /* !_FRIBIDI_BIDI_TYPES_H */

Index: fribidi-bidi.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-bidi.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- fribidi-bidi.c	14 Jun 2004 18:43:53 -0000	1.12
+++ fribidi-bidi.c	15 Jun 2004 11:52:02 -0000	1.13
@@ -36,7 +36,6 @@
 #include "common.h"
 
 #include <fribidi-bidi.h>
-#include <fribidi-bidi-types.h>
 #include <fribidi-mirroring.h>
 #include <fribidi-unicode.h>
 #include <fribidi-env.h>
@@ -153,7 +152,7 @@
   for_run_list (pp, pp)
   {
     MSG5 ("%d:%d(%s)[%d] ",
-	  pp->pos, pp->len, fribidi_bidi_type_name (pp->type), pp->level);
+	  pp->pos, pp->len, fribidi_get_bidi_type_name (pp->type), pp->level);
   }
   MSG ("\n");
 }
@@ -205,9 +204,8 @@
   fribidi_assert (str || bidi_types);
 
   MSG ("  Org. types : ");
-  if (bidi_types)
-    for (i = 0; i < len; i++)
-      MSG2 ("%c", fribidi_char_from_bidi_type (BIDI_TYPE (i)));
+  for (i = 0; i < len; i++)
+    MSG2 ("%c", fribidi_char_from_bidi_type (BIDI_TYPE (i)));
   MSG ("\n");
 }
 #endif /* DEBUG */
@@ -299,10 +297,30 @@
 
 
 /* Return the embedding direction of a link. */
-#define FRIBIDI_EMBEDDING_DIRECTION(list) \
-    FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list))
+#define FRIBIDI_EMBEDDING_DIRECTION(link) \
+    FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(link))
 
 
+FRIBIDI_ENTRY FriBidiParType
+fribidi_get_par_direction (
+  /* input */
+  const FriBidiChar *str,
+  const FriBidiStrIndex len,
+  const FriBidiCharType *bidi_types
+)
+{
+  register FriBidiStrIndex i;
+
+  fribidi_assert (str || bidi_types);
+
+  for (i = 0; i < len; i++)
+    if (FRIBIDI_IS_LETTER (BIDI_TYPE (i)))
+      return FRIBIDI_IS_RTL (BIDI_TYPE (i)) ? FRIBIDI_PAR_RTL :
+	FRIBIDI_PAR_LTR;
+
+  return FRIBIDI_PAR_ON;
+}
+
 FRIBIDI_ENTRY FriBidiLevel
 fribidi_get_par_embedding_levels (
   /* input */
@@ -312,7 +330,7 @@
   /* input and output */
   FriBidiParType *pbase_dir,
   /* output */
-  FriBidiLevel *embedding_level_list
+  FriBidiLevel *embedding_levels
 )
 {
   FriBidiLevel base_level, max_level = 0;
@@ -320,12 +338,6 @@
   FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp;
   fribidi_boolean status = false;
 
-  DBG ("entering fribidi_get_par_embedding_levels");
-
-  fribidi_assert (str || bidi_types);
-  fribidi_assert (pbase_dir);
-  fribidi_assert (embedding_level_list);
-
   if UNLIKELY
     (!len)
     {
@@ -333,6 +345,12 @@
       goto out;
     }
 
+  DBG ("entering fribidi_get_par_embedding_levels");
+
+  fribidi_assert (str || bidi_types);
+  fribidi_assert (pbase_dir);
+  fribidi_assert (embedding_levels);
+
   /* Determinate character types */
   {
     /* Get run-length encoded character types */
@@ -369,7 +387,7 @@
 # endif	/* DEBUG */
 
   /* Explicit Levels and Directions */
-  DBG ("pxplicit Levels and Directions");
+  DBG ("explicit levels and directions");
   {
     FriBidiLevel level, new_level;
     FriBidiCharType override, new_override;
@@ -679,7 +697,8 @@
 	RL_LEVEL (pp) = (level + 2) & ~1;
       else
 	RL_LEVEL (pp) =
-	  level + ((level & 1) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
+	  level +
+	  (FRIBIDI_LEVEL_IS_RTL (level) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
 
       if (RL_LEVEL (pp) > max_level)
 	max_level = RL_LEVEL (pp);
@@ -792,7 +811,7 @@
       register FriBidiStrIndex l;
       register FriBidiLevel level = pp->level;
       for (l = pp->len; l; l--)
-	embedding_level_list[pos++] = level;
+	embedding_levels[pos++] = level;
     }
   }
 
@@ -850,24 +869,21 @@
 FRIBIDI_ENTRY FriBidiLevel
 fribidi_reorder_line (
   /* input */
-  const FriBidiLevel *embedding_level_list,
+  const FriBidiLevel *embedding_levels,
   const FriBidiStrIndex len,
   const FriBidiStrIndex off,
   const FriBidiCharType *bidi_types,
   /* input and output */
   FriBidiChar *str,
   /* output */
-  FriBidiStrIndex *position_L_to_V_list,
-  FriBidiStrIndex *position_V_to_L_list
+  FriBidiStrIndex *positions_L_to_V,
+  FriBidiStrIndex *positions_V_to_L
 )
 {
   fribidi_boolean private_V_to_L = false;
   fribidi_boolean status = false;
   FriBidiLevel max_level = 0;
 
-  fribidi_assert (embedding_level_list);
-  fribidi_assert (str || bidi_types);
-
   if UNLIKELY
     (len == 0)
     {
@@ -876,8 +892,8 @@
     }
 
   if UNLIKELY
-    (off + len > FRIBIDI_MAX_STRING_LENGTH && (position_V_to_L_list ||
-					       position_L_to_V_list))
+    (off + len > FRIBIDI_MAX_STRING_LENGTH && (positions_V_to_L ||
+					       positions_L_to_V))
     {
 #     if DEBUG
       MSG2 (FRIBIDI ": cannot handle strings > %lu characters\n",
@@ -886,14 +902,18 @@
       goto out;
     }
 
+  DBG ("in fribidi_reorder_line");
+
+  fribidi_assert (embedding_levels);
+  fribidi_assert (str || bidi_types);
+
   /* If l2v is to be calculated we must have v2l as well. If it is not
      given by the caller, we have to make a private instance of it. */
-  if (position_L_to_V_list && !position_V_to_L_list)
+  if (positions_L_to_V && !positions_V_to_L)
     {
-      position_V_to_L_list =
-	fribidi_malloc (sizeof (position_V_to_L_list[0]) * len);
+      positions_V_to_L = fribidi_malloc (sizeof (positions_V_to_L[0]) * len);
       if UNLIKELY
-	(!position_V_to_L_list) goto out;
+	(!positions_V_to_L) goto out;
       private_V_to_L = true;
     }
 
@@ -904,10 +924,10 @@
     register FriBidiStrIndex i;
 
     /* Set up the ordering array to identity order */
-    if (position_V_to_L_list)
+    if (positions_V_to_L)
       {
 	for (i = off + len - 1; i >= off; i--)
-	  position_V_to_L_list[i] = i;
+	  positions_V_to_L[i] = i;
       }
 
     /* Reorder both the outstring and the order array */
@@ -916,18 +936,18 @@
 	{
 	  /* L3. Reorder NSMs. */
 	  for (i = off + len - 1; i >= off; i--)
-	    if (FRIBIDI_LEVEL_IS_RTL (embedding_level_list[i])
+	    if (FRIBIDI_LEVEL_IS_RTL (embedding_levels[i])
 		&& BIDI_TYPE (i) == FRIBIDI_TYPE_NSM)
 	      {
 		register FriBidiStrIndex seq_end = i;
-		level = embedding_level_list[i];
+		level = embedding_levels[i];
 
 		for (i--; i >= off &&
 		     FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM (BIDI_TYPE (i))
-		     && embedding_level_list[i] == level; i--)
+		     && embedding_levels[i] == level; i--)
 		  ;
 
-		if (i < off || embedding_level_list[i] != level)
+		if (i < off || embedding_levels[i] != level)
 		  {
 		    i++;
 		    DBG ("warning: NSM(s) at the beggining of level run");
@@ -937,9 +957,9 @@
 		  {
 		    bidi_string_reverse (str + i, seq_end - i + 1);
 		  }
-		if (position_V_to_L_list)
+		if (positions_V_to_L)
 		  {
-		    index_array_reverse (position_V_to_L_list + i,
+		    index_array_reverse (positions_V_to_L + i,
 					 seq_end - i + 1);
 		  }
 	      }
@@ -949,32 +969,31 @@
        * max_level, both for a cleaner API, and that the line max_level
        * may be far less than paragraph max_level. */
       for (i = off + len - 1; i >= off; i--)
-	if (embedding_level_list[i] > max_level)
-	  max_level = embedding_level_list[i];
+	if (embedding_levels[i] > max_level)
+	  max_level = embedding_levels[i];
 
       /* L2. Reorder. */
       for (level = max_level; level > 0; level--)
 	for (i = off + len - 1; i >= off; i--)
-	  if (embedding_level_list[i] >= level)
+	  if (embedding_levels[i] >= level)
 	    {
 	      /* Find all stretches that are >= level_idx */
 	      register FriBidiStrIndex seq_end = i;
-	      for (i--; i >= off && embedding_level_list[i] >= level; i--)
+	      for (i--; i >= off && embedding_levels[i] >= level; i--)
 		;
 
 	      if (str)
 		bidi_string_reverse (str + i + 1, seq_end - i);
-	      if (position_V_to_L_list)
-		index_array_reverse (position_V_to_L_list + i + 1, seq_end
-				     - i);
+	      if (positions_V_to_L)
+		index_array_reverse (positions_V_to_L + i + 1, seq_end - i);
 	    }
     }
 
     /* Convert the v2l list to l2v */
-    if (position_L_to_V_list)
+    if (positions_L_to_V)
       {
 	for (i = off + len - 1; i >= off; i--)
-	  position_L_to_V_list[position_V_to_L_list[i]] = i;
+	  positions_L_to_V[positions_V_to_L[i]] = i;
       }
   }
 
@@ -983,7 +1002,7 @@
 out:
 
   if (private_V_to_L)
-    fribidi_free (position_V_to_L_list);
+    fribidi_free (positions_V_to_L);
 
   return status ? max_level + 1 : 0;
 }

Index: fribidi-bidi.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-bidi.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- fribidi-bidi.h	14 Jun 2004 18:43:53 -0000	1.9
+++ fribidi-bidi.h	15 Jun 2004 11:52:02 -0000	1.10
@@ -43,16 +43,54 @@
 #include "fribidi-begindecls.h"
 
 #define fribidi_get_par_embedding_levels FRIBIDI_NAMESPACE(get_par_embedding_levels)
+/* fribidi_get_par_direction - get base paragraph direction
+ *
+ * This function finds the base direction of a single paragraph,
+ * as defined by rule P2 of the Unicode Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/#P2.
+ *
+ * You can provide either the string, or the bidi types; or both.
+ * If bidi_types are provided, they are used as the bidi types of characters
+ * in the string, otherwise the types are computed from the characters in str.
+ * Providing bidi types if available at your side, saves you a few cycles.
+ * Bidi types can be obtained by calling fribidi_get_bidi_types().
+ *
+ * You typically do not need this function as
+ * fribidi_get_par_embedding_levels() knows how to compute base direction
+ * itself, but you may need this to implement a more sophisticated paragraph
+ * direction handling.  Note that you can pass more than a paragraph to this
+ * function and the direction of the first non-neutral paragraph is returned,
+ * which is a very good heuristic to set direction of the neutral paragraphs
+ * at the beginning of text.  For other neutral paragraphs, better you use the
+ * direction of the previous paragraph.  This is today known as the best
+ * auto-paragraph-direction-detection scheme!
+ *
+ * Returns: Base pargraph direction.  No weak paragraph direction is returned,
+ * only LTR, RTL, or ON.
+ */
+FRIBIDI_ENTRY FriBidiParType fribidi_get_par_direction (
+  const FriBidiChar *str,	/* input paragraph string */
+  const FriBidiStrIndex len,	/* input string length */
+  const FriBidiCharType *bidi_types	/* input bidi types */
+);
+
+#define fribidi_get_par_embedding_levels FRIBIDI_NAMESPACE(get_par_embedding_levels)
 /* fribidi_get_par_embedding_levels - get bidi embedding levels of a paragraph
  *
  * This function finds the bidi embedding levels of a single paragraph,
- * as defined by the Unicode Bidirectional Algorithm.
+ * as defined by the Unicode Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/.  This function implements rules P2 to
+ * L1 inclusive, except for rule X9 which is implemented in
+ * fribidi_remove_bidi_marks().
  *
- * You can provide either the string, or the bidi types; or both.  If bidi_types are
- * provided, they are used as the bidi types of characters in the string, otherwise
- * the types are computed from the characters in str.  Providing bidi types if
- * available at your side, saves you a few cycles.  Bidi types can be obtained
- * by calling fribidi_get_bidi_types.
+ * You can provide either the string, or the bidi types; or both.
+ * If bidi_types are provided, they are used as the bidi types of characters
+ * in the string, otherwise the types are computed from the characters in str.
+ * Providing bidi types if available at your side, saves you a few cycles.
+ * Bidi types can be obtained by calling fribidi_get_bidi_types().
+ *
+ * There are a few macros defined in fribidi-bidi-types.h to work with this
+ * embedding levels.
  *
  * Returns: Maximum level found plus one, or zero if any error occured
  * (memory allocation failure most probably).
@@ -64,43 +102,47 @@
   const FriBidiCharType *bidi_types,	/* input bidi types */
   FriBidiParType *pbase_dir,	/* requested and resolved paragraph
 				 * base direction */
-  FriBidiLevel *embedding_level_list	/* output list of embedding levels */
+  FriBidiLevel *embedding_levels	/* output list of embedding levels */
 ) FRIBIDI_GNUC_WARN_UNUSED;
 
 #define fribidi_reorder_line FRIBIDI_NAMESPACE(reorder_line)
 /* fribidi_reorder_line - reorder a line of logical string to visual
  *
- * This function reorders the characters in a line of text from logical
- * to final visual order.  Also sets position maps if not NULL.
+ * This function reorders the characters in a line of text from logical to
+ * final visual order.  This function implements rules L2 and L3 of the
+ * Unicode Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels.
  *
- * You can provide either the string, or the bidi types; or both.  If bidi_types are
- * provided, they are used as the bidi types of characters in the string, otherwise
- * the types are computed from the characters in str.  If you have obtained
- * the embedding levels using custom bidi types, you should provide the same
- * types to this function for valid resutls.  Providing bidi types if
- * available at your side, saves you a few cycles.
+ * As a side effect it also sets position maps if not NULL.
+ *
+ * You can provide either the string, or the bidi types; or both.  If
+ * bidi_types are provided, they are used as the bidi types of characters in
+ * the string, otherwise the types are computed from the characters in str.
+ * If you have obtained the embedding levels using custom bidi types, you
+ * should provide the same types to this function for valid resutls.
+ * Providing bidi types if available at your side, saves you a few cycles.
  *
  * Note that the bidi types and embedding levels are not reordered.  You can
  * reorder these (or any other) arrays using the position_L_to_V_map later.
  *
- * Some features of this function can be turned on/off using environmental settings
- * functions fribidi_env_*.
+ * Some features of this function can be turned on/off using environmental
+ * settings functions fribidi_env_*().
  *
  * Returns: Maximum level found in this line plus one, or zero if any error
  * occured (memory allocation failure most probably).
  */
      FRIBIDI_ENTRY FriBidiLevel fribidi_reorder_line (
-  const FriBidiLevel *embedding_level_list,	/* input list of embedding levels,
-						   as returned by
-						   fribidi_get_par_embedding_levels */
+  const FriBidiLevel *embedding_levels,	/* input list of embedding levels,
+					   as returned by
+					   fribidi_get_par_embedding_levels */
   const FriBidiStrIndex len,	/* input length of the line */
   const FriBidiStrIndex off,	/* input offset of the beginning of the line
 				   in the paragraph */
   const FriBidiCharType *bidi_types,	/* input bidi types */
   FriBidiChar *str,		/* string to shape */
-  FriBidiStrIndex *position_L_to_V_list,	/* output mapping from logical to
-						   visual string positions */
-  FriBidiStrIndex *position_V_to_L_list	/* output mapping from visual string
+  FriBidiStrIndex *positions_L_to_V,	/* output mapping from logical to
+					   visual string positions */
+  FriBidiStrIndex *positions_V_to_L	/* output mapping from visual string
 					   back to logical string positions */
 ) FRIBIDI_GNUC_WARN_UNUSED;
 

Index: fribidi-joining-types-list.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-joining-types-list.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- fribidi-joining-types-list.h	13 Jun 2004 20:11:42 -0000	1.1
+++ fribidi-joining-types-list.h	15 Jun 2004 11:52:02 -0000	1.2
@@ -38,11 +38,11 @@
 #endif
 
 _FRIBIDI_ADD_TYPE (U, '|')	/* nUn-joining, e.g. Full Stop */
-_FRIBIDI_ADD_TYPE (R, '>')	/* Right-joining, e.g. Arabic Letter Dal */
+_FRIBIDI_ADD_TYPE (R, '<')	/* Right-joining, e.g. Arabic Letter Dal */
 _FRIBIDI_ADD_TYPE (D, '+')	/* Dual-joining, e.g. Arabic Letter Ain */
 _FRIBIDI_ADD_TYPE (C, '-')	/* join-Causing, e.g. Tatweel, ZWJ */
 _FRIBIDI_ADD_TYPE (T, '^')	/* Transparent, e.g. Arabic Fatha */
-_FRIBIDI_ADD_TYPE (L, '<')	/* Left-joining, i.e. fictional */
+_FRIBIDI_ADD_TYPE (L, '>')	/* Left-joining, i.e. fictional */
 _FRIBIDI_ADD_TYPE (G, '~')	/* iGnored, e.g. LRE, RLE, ZWNBSP */
 
 #ifndef __FRIBIDI_DOC

Index: fribidi-joining-types.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-joining-types.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- fribidi-joining-types.c	14 Jun 2004 18:43:53 -0000	1.2
+++ fribidi-joining-types.c	15 Jun 2004 11:52:02 -0000	1.3
@@ -64,19 +64,19 @@
   const FriBidiChar *str,
   const FriBidiStrIndex len,
   /* output */
-  FriBidiJoiningType *type
+  FriBidiJoiningType *jtypes
 )
 {
   register FriBidiStrIndex i = len;
   for (; i; i--)
     {
-      *type++ = FRIBIDI_GET_JOINING_TYPE (*str);
+      *jtypes++ = FRIBIDI_GET_JOINING_TYPE (*str);
       str++;
     }
 }
 
 FRIBIDI_ENTRY const char *
-fribidi_joining_type_name (
+fribidi_get_joining_type_name (
   /* input */
   FriBidiJoiningType j
 )
@@ -96,17 +96,21 @@
 char
 fribidi_char_from_joining_type (
   /* input */
-  FriBidiJoiningType j
+  FriBidiJoiningType j,
+  fribidi_boolean visual
 )
 {
-  switch (j)
-    {
-#   define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) case FRIBIDI_JOINING_TYPE_##TYPE: return SYMBOL;
+  /* switch left and right if on visual run */
+  if (visual & ((FRIBIDI_JOINS_RIGHT (j) && !FRIBIDI_JOINS_LEFT (j)) |
+		(!FRIBIDI_JOINS_RIGHT (j) && FRIBIDI_JOINS_LEFT (j))))
+    j ^= FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT;
+
+#   define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL)	\
+	if (FRIBIDI_IS_JOINING_TYPE_##TYPE(j)) return SYMBOL;
 #   include "fribidi-joining-types-list.h"
 #   undef _FRIBIDI_ADD_TYPE
-    default:
-      return '?';
-    }
+
+  return '?';
 }
 
 #endif /* DEBUG */

Index: fribidi-joining-types.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-joining-types.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- fribidi-joining-types.h	14 Jun 2004 18:43:53 -0000	1.2
+++ fribidi-joining-types.h	15 Jun 2004 11:52:02 -0000	1.3
@@ -47,9 +47,9 @@
 #define FRIBIDI_MASK_JOINS_RIGHT	0x01	/* May join to right */
 #define FRIBIDI_MASK_JOINS_LEFT		0x02	/* May join to right */
 #define FRIBIDI_MASK_ARAB_SHAPES	0x04	/* May Arabic shape */
-#define FRIBIDI_MASK_TRANSPARENT	0x10	/* Is transparent */
-#define FRIBIDI_MASK_IGNORED		0x20	/* Is ignored */
-#define FRIBIDI_MASK_LIGATURED		0x40	/* Is ligatured */
+#define FRIBIDI_MASK_TRANSPARENT	0x08	/* Is transparent */
+#define FRIBIDI_MASK_IGNORED		0x10	/* Is ignored */
+#define FRIBIDI_MASK_LIGATURED		0x20	/* Is ligatured */
 
 /*
  * Define values for FriBidiJoiningType
@@ -98,31 +98,99 @@
 typedef fribidi_uint8 FriBidiJoiningType;
 #endif /* !__FRIBIDI_DOC */
 
+/* FriBidiArabicProps is essentially the same type as FriBidiJoiningType, but
+ * not limited to the few values returned by fribidi_get_joining_type. */
+typedef fribidi_uint8 FriBidiArabicProps;
+
+/*
+ * The equivalent of JoiningType values for ArabicProps
+ */
+
+/* Primary Arabic Joining Classes (Table 8-2) */
+
+/* nUn-joining */
+#define FRIBIDI_IS_JOINING_TYPE_U(p)	\
+	( 0 == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT ) ) )
+
+/* Right-joining */
+#define FRIBIDI_IS_JOINING_TYPE_R(p)	\
+	( FRIBIDI_MASK_JOINS_RIGHT == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT ) ) )
+
+/* Dual-joining */
+#define FRIBIDI_IS_JOINING_TYPE_D(p)	\
+	( ( FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT	\
+	  | FRIBIDI_MASK_ARAB_SHAPES ) == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT	\
+		| FRIBIDI_MASK_ARAB_SHAPES ) ) )
+
+/* join-Causing */
+#define FRIBIDI_IS_JOINING_TYPE_C(p)	\
+	( ( FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT ) == ( (p) & \
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT	\
+		| FRIBIDI_MASK_ARAB_SHAPES ) ) )
+
+/* Left-joining */
+#define FRIBIDI_IS_JOINING_TYPE_L(p)	\
+	( FRIBIDI_MASK_JOINS_LEFT == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_RIGHT | FRIBIDI_MASK_JOINS_LEFT ) ) )
+
+/* Transparent */
+#define FRIBIDI_IS_JOINING_TYPE_T(p)	\
+	( FRIBIDI_MASK_TRANSPARENT == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED ) ) )
+
+/* iGnored */
+#define FRIBIDI_IS_JOINING_TYPE_G(p)	\
+	( FRIBIDI_MASK_IGNORED == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED ) ) )
+
+/* and for Derived Arabic Joining Classes (Table 8-3) */
+
+/* Right join-Causing */
+#define FRIBIDI_IS_JOINING_TYPE_RC(p)	\
+	( FRIBIDI_MASK_JOINS_RIGHT == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_RIGHT ) ) )
+
+/* Left join-Causing */
+#define FRIBIDI_IS_JOINING_TYPE_LC(p)	\
+	( FRIBIDI_MASK_JOINS_LEFT == ( (p) &	\
+		( FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED	\
+		| FRIBIDI_MASK_JOINS_LEFT ) ) )
+
 
 /*
  * Defining macros for needed queries, It is fully dependent on the 
  * implementation of FriBidiJoiningType.
  */
 
-/* Joins to right? */
+/* Joins to right: R, D, C? */
 #define FRIBIDI_JOINS_RIGHT(p)	((p) & FRIBIDI_MASK_JOINS_RIGHT)
 
-/* Joins to left? */
+/* Joins to left: L, D, C? */
 #define FRIBIDI_JOINS_LEFT(p)	((p) & FRIBIDI_MASK_JOINS_LEFT)
 
-/* Joins to left? */
+/* May shape: R, D, L, T? */
 #define FRIBIDI_ARAB_SHAPES(p)	((p) & FRIBIDI_MASK_ARAB_SHAPES)
 
-/* Is transparent in joining? */
-#define FRIBIDI_IS_JOIN_TRANSPARENT(p)	((p) & FRIBIDI_MASK_TRANSPARENT)
-
-/* Is ignored in joining? */
-#define FRIBIDI_IS_JOIN_IGNORED(p)	((p) & FRIBIDI_MASK_IGNORED)
-
-/* Is skipped in joining? */
+/* Is skipped in joining: T, G? */
 #define FRIBIDI_IS_JOIN_SKIPPED(p)	\
 	((p) & (FRIBIDI_MASK_TRANSPARENT | FRIBIDI_MASK_IGNORED))
 
+#define FRIBIDI_JOINS_PRECEDING_MASK(level)	\
+	(FRIBIDI_LEVEL_IS_RTL (level) ? FRIBIDI_MASK_JOINS_RIGHT	\
+				      : FRIBIDI_MASK_JOINS_LEFT)
+
+#define FRIBIDI_JOINS_FOLLOWING_MASK(level)	\
+	(FRIBIDI_LEVEL_IS_RTL (level) ? FRIBIDI_MASK_JOINS_LEFT	\
+				      : FRIBIDI_MASK_JOINS_RIGHT)
 
 /* Functions finally */
 
@@ -130,8 +198,16 @@
 #define fribidi_get_joining_type FRIBIDI_NAMESPACE(get_joining_type)
 /* fribidi_get_joining_type - get character joining type
  *
- * This function returns the joining type of a character.  There are a few
- * macros defined in fribidi-joining-types.h for querying a joining type.
+ * This function returns the joining type of a character as defined in Table
+ * 8-2 Primary Arabic Joining Classes of the Unicode standard available at
+ * http://www.unicode.org/versions/Unicode4.0.0/ch08.pdf#G7462, using data
+ * provided in file ArabicShaping.txt and UnicodeData.txt of the Unicode
+ * Character Database available at
+ * http://www.unicode.org/Public/UNIDATA/ArabicShaping.txt and
+ * http://www.unicode.org/Public/UNIDATA/UnicodeData.txt. 
+ *
+ * There are a few macros defined in fribidi-joining-types.h for querying a
+ * joining type.
  */
 FRIBIDI_ENTRY FriBidiJoiningType
 fribidi_get_joining_type (
@@ -148,16 +224,20 @@
      FRIBIDI_ENTRY void fribidi_get_joining_types (
   const FriBidiChar *str,	/* input string */
   const FriBidiStrIndex len,	/* input string length */
-  FriBidiJoiningType *type	/* output bidi types */
+  FriBidiJoiningType *jtypes	/* output joining types */
 );
 
-#define fribidi_joining_type_name FRIBIDI_NAMESPACE(joining_type_name)
-/* fribidi_joining_type_name - get joining type name
+#define fribidi_get_joining_type_name FRIBIDI_NAMESPACE(get_joining_type_name)
+/* fribidi_get_joining_type_name - get joining type name
  *
  * This function returns the joining type name of a joining type.  The
  * returned string is a static string and should not be freed.
+ *
+ * The type names are the same as ones defined in Table 8-2  Primary Arabic
+ * Joining Classes of the Unicode standard available at
+ * http://www.unicode.org/versions/Unicode4.0.0/ch08.pdf#G7462.
  */
-     FRIBIDI_ENTRY const char *fribidi_joining_type_name (
+     FRIBIDI_ENTRY const char *fribidi_get_joining_type_name (
   FriBidiJoiningType j		/* input joining type */
 ) FRIBIDI_GNUC_CONST;
 

Index: fribidi-joining.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-joining.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- fribidi-joining.c	13 Jun 2004 20:11:42 -0000	1.1
+++ fribidi-joining.c	15 Jun 2004 11:52:02 -0000	1.2
@@ -0,0 +1,161 @@
+/* FriBidi
+ * fribidi-joining.h - Arabic joining algorithm
+ *
+ * $Id$
+ * $Author$
+ * $Date$
+ * $Revision$
+ * $Source$
+ *
+ * Authors:
+ *   Behdad Esfahbod, 2004
+ *
+ * Copyright (C) 2004 Sharif FarsiWeb, Inc
+ * Copyright (C) 2004 Behdad Esfahbod
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library, in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA
+ * 
+ * For licensing issues, contact <license at farsiweb.info>.
+ */
+
+#include "common.h"
+
+#if !FRIBIDI_NO_ARABIC
+
+#include <fribidi-joining.h>
+#include <fribidi-env.h>
+
+#include "mem.h"
+#include "env.h"
+#include "joining-types.h"
+
+#if DEBUG
+/*======================================================================
+ *  For debugging, define some functions for printing joining types and
+ *  properties.
+ *----------------------------------------------------------------------*/
+
+static void
+print_joining_types (
+  /* input */
+  const FriBidiLevel *embedding_levels,
+  const FriBidiStrIndex len,
+  const FriBidiJoiningType *jtypes
+)
+{
+  register FriBidiStrIndex i;
+
+  fribidi_assert (jtypes);
+
+  MSG ("  Join. types: ");
+  for (i = 0; i < len; i++)
+    MSG2 ("%c", fribidi_char_from_joining_type (jtypes[i],
+						!FRIBIDI_LEVEL_IS_RTL
+						(embedding_levels[i])));
+  MSG ("\n");
+}
+#endif /* DEBUG */
+
+
+FRIBIDI_ENTRY void
+fribidi_join_arabic (
+  /* input */
+  const FriBidiLevel *embedding_levels,
+  const FriBidiStrIndex len,
+  /* input and output */
+  FriBidiArabicProps *ar_props
+)
+{
+  if UNLIKELY
+    (len == 0) return;
+
+  DBG ("entering fribidi_join_arabic");
+
+  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 */
+
+  /* 8.2 Arabic - Cursive Joining */
+  DBG ("Arabic cursive joining");
+  {
+    register FriBidiStrIndex i = 0;
+
+    for (i = 0; i < len; i++)
+      {
+	register FriBidiStrIndex saved = i;
+	register const FriBidiLevel direction =
+	  FRIBIDI_LEVEL_IS_RTL (embedding_levels[i]);
+	register const FriBidiArabicProps joins_preceding_mask =
+	  FRIBIDI_JOINS_PRECEDING_MASK (direction);
+	register const FriBidiArabicProps joins_following_mask =
+	  FRIBIDI_JOINS_FOLLOWING_MASK (direction);
+	register fribidi_boolean joins = false;
+
+	/* Sweep over directional runs */
+	for (;
+	     i < len
+	     && FRIBIDI_LEVEL_IS_RTL (embedding_levels[i]) == direction; i++)
+	  {
+	    /* R1. Transparent chars are skipped (and so do iGnored chars) */
+	    if (FRIBIDI_IS_JOIN_SKIPPED (ar_props[i]))
+	      continue;
+
+	    /* R2..R7. */
+	    if (!joins)
+	      FRIBIDI_UNSET_BITS (ar_props[i], joins_preceding_mask);
+	    else if (!FRIBIDI_TEST_BITS (ar_props[i], joins_preceding_mask))
+	      FRIBIDI_UNSET_BITS (ar_props[saved], joins_following_mask);
+	    else
+	      {
+		/* This is a FriBidi extension:  we set joining properties
+		 * for skipped characters in between. */
+		for (saved++; saved < i; saved++)
+		  FRIBIDI_SET_BITS (ar_props[saved],
+				    joins_preceding_mask |
+				    joins_following_mask);
+	      }
+
+	    joins = FRIBIDI_TEST_BITS (ar_props[i], joins_following_mask);
+	    saved = i;
+	  }
+	FRIBIDI_UNSET_BITS (ar_props[saved], joins_following_mask);
+	i--;
+      }
+  }
+
+# if DEBUG
+  if UNLIKELY
+    (fribidi_debug_status ())
+    {
+      print_joining_types (embedding_levels, len, ar_props);
+    }
+# endif	/* DEBUG */
+
+  DBG ("leaving fribidi_join_arabic");
+}
+
+#endif /* !FRIBIDI_NO_ARABIC */
+
+/* Editor directions:
+ * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
+ */

Index: fribidi-joining.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-joining.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- fribidi-joining.h	13 Jun 2004 20:11:42 -0000	1.1
+++ fribidi-joining.h	15 Jun 2004 11:52:02 -0000	1.2
@@ -36,11 +36,39 @@
 #include "fribidi-common.h"
 
 #include "fribidi-types.h"
+#include "fribidi-bidi-types.h"
 #include "fribidi-joining-types.h"
 
 #include "fribidi-begindecls.h"
 
-
+#define fribidi_join_arabic FRIBIDI_NAMESPACE(join_arabic)
+/* fribidi_join_arabic - do Arabic joining
+ *
+ * This function does the Arabic joining algorithm.  Means, given Arabic
+ * joining types of the characters in ar_props (don't worry,
+ * FriBidiJoiningType can be casted to FriBidiArabicProps automagically), this
+ * function modifies this properties to grasp the effect of neighboring
+ * characters.  You probably need this information later to do Arabic shaping.
+ *
+ * This function implements rules R1 to R7 inclusive (all rules) of the Arabic
+ * Cursive Joining algorithm of the Unicode standard as available at 
+ * http://www.unicode.org/versions/Unicode4.0.0/ch08.pdf#G7462.  It also
+ * interacts correctly with the bidirection algorithm as defined in Section
+ * 3.5 Shaping of the Unicode Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/#Shaping.
+ *
+ * There are a few macros defined in fribidi-joining-types.h for querying the
+ * Arabic properties computed by this function.
+ */
+FRIBIDI_ENTRY void fribidi_join_arabic (
+  const FriBidiLevel *embedding_levels,	/* input list of embedding
+					   levels, as returned by
+					   fribidi_get_par_embedding_levels */
+  const FriBidiStrIndex len,	/* input string length */
+  FriBidiArabicProps *ar_props	/* Arabic properties to analyze, initilized by
+				   joining types, as returned by
+				   fribidi_get_joining_types */
+);
 
 #include "fribidi-enddecls.h"
 

Index: fribidi-mirroring.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-mirroring.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- fribidi-mirroring.c	14 Jun 2004 18:43:53 -0000	1.12
+++ fribidi-mirroring.c	15 Jun 2004 11:52:02 -0000	1.13
@@ -59,7 +59,7 @@
 FRIBIDI_ENTRY void
 fribidi_shape_mirroring (
   /* input */
-  const FriBidiLevel *embedding_level_list,
+  const FriBidiLevel *embedding_levels,
   const FriBidiStrIndex len,
   /* input and output */
   FriBidiChar *str
@@ -67,14 +67,16 @@
 {
   register FriBidiStrIndex i;
 
-  fribidi_assert (embedding_level_list);
+  DBG ("in fribidi_shape_mirroring");
+
+  fribidi_assert (embedding_levels);
 
   if UNLIKELY
     (len == 0 || !str) return;
 
   /* L4. Mirror all characters that are in odd levels and have mirrors. */
   for (i = len - 1; i >= 0; i--)
-    if (FRIBIDI_LEVEL_IS_RTL (embedding_level_list[i]))
+    if (FRIBIDI_LEVEL_IS_RTL (embedding_levels[i]))
       {
 	FriBidiChar mirrored_ch;
 

Index: fribidi-mirroring.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-mirroring.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- fribidi-mirroring.h	14 Jun 2004 18:43:53 -0000	1.8
+++ fribidi-mirroring.h	15 Jun 2004 11:52:02 -0000	1.9
@@ -46,10 +46,14 @@
 #define fribidi_get_mirror_char FRIBIDI_NAMESPACE(get_mirror_char)
 /* fribidi_get_mirror_char - get mirrored character
  *
- * This function finds the mirrored equivalent of a character.  If  the input
- * character is a declared as a mirroring character in the Unicode standard
- * and has a mirrored equivalent.  The matching mirrored character is put in
- * the output, otherwise the input character itself is put.
+ * This function finds the mirrored equivalent of a character as defined in
+ * the file BidiMirroring.txt of the Unicode Character Database available at
+ * http://www.unicode.org/Public/UNIDATA/BidiMirroring.txt.
+ *
+ * If  the input character is a declared as a mirroring character in the
+ * Unicode standard and has a mirrored equivalent.  The matching mirrored
+ * character is put in the output, otherwise the input character itself is
+ * put.
  *
  * Returns: if the character has a mirroring equivalent or not.
  */
@@ -64,11 +68,14 @@
  * This functions replaces mirroring characters on right-to-left embeddings in
  * string with their mirrored equivalent as returned by
  * fribidi_get_mirror_char().
+ *
+ * This function implements rule L4 of the Unicode Bidirectional Algorithm
+ * available at http://www.unicode.org/reports/tr9/#L4.
  */
 FRIBIDI_ENTRY void fribidi_shape_mirroring (
-  const FriBidiLevel *embedding_level_list,	/* input list of embedding
-						   levels, as returned by
-						   fribidi_get_par_embedding_levels */
+  const FriBidiLevel *embedding_levels,	/* input list of embedding
+					   levels, as returned by
+					   fribidi_get_par_embedding_levels */
   const FriBidiStrIndex len,	/* input string length */
   FriBidiChar *str		/* string to shape */
 );

Index: fribidi-types.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-types.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- fribidi-types.h	9 Jun 2004 20:01:00 -0000	1.6
+++ fribidi-types.h	15 Jun 2004 11:52:02 -0000	1.7
@@ -143,6 +143,24 @@
 		0x7E : 0x8FFFFFFEL))
 #endif
 
+/* A few macros for working with bits */
+
+#define FRIBIDI_TEST_BITS(x, mask) ((x) & (mask))
+
+#define FRIBIDI_INCLUDE_BITS(x, mask) ((x) | (mask))
+
+#define FRIBIDI_EXCLUDE_BITS(x, mask) ((x) & ~(mask))
+
+#define FRIBIDI_SET_BITS(x, mask)	\
+	FRIBIDI_BEGIN_STMT	\
+	(x) |= (mask);	\
+	FRIBIDI_END_STMT
+
+#define FRIBIDI_UNSET_BITS(x, mask)	\
+	FRIBIDI_BEGIN_STMT	\
+	(x) &= ~(mask);	\
+	FRIBIDI_END_STMT
+
 #include "fribidi-enddecls.h"
 
 #endif /* !_FRIBIDI_TYPES_H */

Index: fribidi.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- fribidi.c	14 Jun 2004 18:43:53 -0000	1.10
+++ fribidi.c	15 Jun 2004 11:52:02 -0000	1.11
@@ -40,18 +40,20 @@
 FRIBIDI_ENTRY void
 fribidi_shape (
   /* input */
-  const FriBidiLevel *embedding_level_list,
+  const FriBidiLevel *embedding_levels,
   const FriBidiStrIndex len,
   /* input and output */
   FriBidiChar *str
 )
 {
-  fribidi_assert (embedding_level_list);
-
   if UNLIKELY
     (len == 0 || !str) return;
 
-  fribidi_shape_mirroring (embedding_level_list, len, str);
+  DBG ("in fribidi_shape");
+
+  fribidi_assert (embedding_levels);
+
+  fribidi_shape_mirroring (embedding_levels, len, str);
 }
 
 
@@ -59,17 +61,15 @@
 fribidi_remove_bidi_marks (
   FriBidiChar *str,
   const FriBidiStrIndex len,
-  FriBidiStrIndex *position_to_this_list,
+  FriBidiStrIndex *positions_to_this,
   FriBidiStrIndex *position_from_this_list,
-  FriBidiLevel *embedding_level_list
+  FriBidiLevel *embedding_levels
 )
 {
   register FriBidiStrIndex i, j = 0;
   fribidi_boolean private_from_this = false;
   fribidi_boolean status = false;
 
-  fribidi_assert (str);
-
   if UNLIKELY
     (len == 0)
     {
@@ -77,9 +77,13 @@
       goto out;
     }
 
+  DBG ("in fribidi_remove_bidi_marks");
+
+  fribidi_assert (str);
+
   /* If to_this is to not NULL, we must have from_this as well. If it is
      not given by the caller, we have to make a private instance of it. */
-  if (position_to_this_list && !position_from_this_list)
+  if (positions_to_this && !position_from_this_list)
     {
       position_from_this_list = fribidi_malloc (sizeof
 						(position_from_this_list[0]) *
@@ -88,7 +92,7 @@
 	(!position_from_this_list) goto out;
       private_from_this = true;
       for (i = len - 1; i >= 0; i--)
-	position_from_this_list[position_to_this_list[i]] = i;
+	position_from_this_list[positions_to_this[i]] = i;
     }
 
   for (i = 0; i < len; i++)
@@ -96,20 +100,20 @@
 	&& str[i] != FRIBIDI_CHAR_LRM && str[i] != FRIBIDI_CHAR_RLM)
       {
 	str[j] = str[i];
-	if (embedding_level_list)
-	  embedding_level_list[j] = embedding_level_list[i];
+	if (embedding_levels)
+	  embedding_levels[j] = embedding_levels[i];
 	if (position_from_this_list)
 	  position_from_this_list[j] = position_from_this_list[i];
 	j++;
       }
 
   /* Convert the from_this list to to_this */
-  if (position_to_this_list)
+  if (positions_to_this)
     {
       for (i = 0; i < len; i++)
-	position_to_this_list[i] = -1;
+	positions_to_this[i] = -1;
       for (i = 0; i < len; i++)
-	position_to_this_list[position_from_this_list[i]] = i;
+	positions_to_this[position_from_this_list[i]] = i;
     }
 
   status = true;
@@ -132,18 +136,16 @@
   FriBidiParType *pbase_dir,
   /* output */
   FriBidiChar *visual_str,
-  FriBidiStrIndex *position_L_to_V_list,
-  FriBidiStrIndex *position_V_to_L_list,
-  FriBidiLevel *embedding_level_list
+  FriBidiStrIndex *positions_L_to_V,
+  FriBidiStrIndex *positions_V_to_L,
+  FriBidiLevel *embedding_levels
 )
 {
   FriBidiLevel max_level = 0;
   fribidi_boolean private_V_to_L = false;
-  fribidi_boolean private_embedding_level_list = false;
+  fribidi_boolean private_embedding_levels = false;
   fribidi_boolean status = false;
-
-  fribidi_assert (str);
-  fribidi_assert (pbase_dir);
+  FriBidiArabicProps *ar_props = NULL;
 
   if UNLIKELY
     (len == 0)
@@ -152,26 +154,40 @@
       goto out;
     }
 
-  if (!embedding_level_list)
+  DBG ("in fribidi_log2vis");
+
+  fribidi_assert (str);
+  fribidi_assert (pbase_dir);
+
+  if (!embedding_levels)
     {
-      embedding_level_list = fribidi_malloc (len);
-      if (!embedding_level_list)
+      embedding_levels = fribidi_malloc (len * sizeof embedding_levels[0]);
+      if (!embedding_levels)
 	goto out;
-      private_embedding_level_list = true;
+      private_embedding_levels = true;
     }
 
   max_level = fribidi_get_par_embedding_levels (str, len, NULL, pbase_dir,
-						embedding_level_list) - 1;
+						embedding_levels) - 1;
   if UNLIKELY
     (max_level < 0) goto out;
 
+#if !FRIBIDI_NO_ARABIC
+  /* Arabic joining */
+  {
+    ar_props = fribidi_malloc (len * sizeof ar_props[0]);
+    fribidi_get_joining_types (str, len, ar_props);
+    fribidi_join_arabic (embedding_levels, len, ar_props);
+  }
+#endif /* !FRIBIDI_NO_ARABIC */
+
   /* If l2v is to be calculated we must have v2l as well. If it is not
      given by the caller, we have to make a private instance of it. */
-  if (position_L_to_V_list && !position_V_to_L_list)
+  if (positions_L_to_V && !positions_V_to_L)
     {
-      position_V_to_L_list =
+      positions_V_to_L =
 	(FriBidiStrIndex *) fribidi_malloc (sizeof (FriBidiStrIndex) * len);
-      if (!position_V_to_L_list)
+      if (!positions_V_to_L)
 	goto out;
       private_V_to_L = true;
     }
@@ -184,19 +200,22 @@
 	visual_str[i] = str[i];
     }
 
-  fribidi_shape (embedding_level_list, len, visual_str);
+  fribidi_shape (embedding_levels, len, visual_str);
 
   status =
-    fribidi_reorder_line (embedding_level_list, len, 0, NULL, visual_str,
-			  position_L_to_V_list, position_V_to_L_list);
+    fribidi_reorder_line (embedding_levels, len, 0, NULL, visual_str,
+			  positions_L_to_V, positions_V_to_L);
 
 out:
 
   if (private_V_to_L)
-    fribidi_free (position_V_to_L_list);
+    fribidi_free (positions_V_to_L);
 
-  if (private_embedding_level_list)
-    fribidi_free (embedding_level_list);
+  if (private_embedding_levels)
+    fribidi_free (embedding_levels);
+
+  if (ar_props)
+    fribidi_free (ar_props);
 
   return status ? max_level + 1 : 0;
 }

Index: fribidi.def
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi.def,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- fribidi.def	14 Jun 2004 18:43:53 -0000	1.6
+++ fribidi.def	15 Jun 2004 11:52:02 -0000	1.7
@@ -1,17 +1,19 @@
+fribidi_get_par_direction
 fribidi_get_par_embedding_levels
 fribidi_reorder_line
 fribidi_get_bidi_type
 fribidi_get_bidi_types
-fribidi_bidi_type_name
+fribidi_get_bidi_type_name
 fribidi_debug_status
 fribidi_set_debug
 fribidi_mirroring_status
 fribidi_set_mirroring
 fribidi_reorder_nsm_status
 fribidi_set_reorder_nsm
+fribidi_join_arabic
 fribidi_get_joining_type
 fribidi_get_joining_types
-fribidi_joining_type_name
+fribidi_get_joining_type_name
 fribidi_get_mirror_char
 fribidi_shape_mirroring
 fribidi_shape

Index: fribidi.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- fribidi.h	14 Jun 2004 18:43:53 -0000	1.6
+++ fribidi.h	15 Jun 2004 11:52:02 -0000	1.7
@@ -41,33 +41,34 @@
 #if !FRIBIDI_NO_ARABIC
 #include "fribidi-joining-types.h"
 #include "fribidi-joining.h"
-#endif /* !FRIBIDI_NO_ARABIC */
+#else
+typedef void FriBidiJoiningType typedef void FriBidiArabicProps
+#endif				/* !FRIBIDI_NO_ARABIC */
 #if FRIBIDI_CHARSETS
 # include "fribidi-char-sets.h"
-#endif /* FRIBIDI_CHARSETS */
-
+#endif				/* FRIBIDI_CHARSETS */
 #include "fribidi-begindecls.h"
-
-/* See fribidi-bidi.h for the core functions fribidi_get_par_embedding_levels
- * and fribidi_reorder_line which are probably the main calls you need.  See
- * README for a better understanding of what calls you need.
+/* See fribidi-bidi.h for the core functions
+ * fribidi_get_par_embedding_levels() and fribidi_reorder_line() which are
+ * probably the main calls you need.  See README for a better understanding of
+ * what calls you need.
  */
-
-
 #define fribidi_shape FRIBIDI_NAMESPACE(shape)
 /* fribidi_shape - do bidi-dependent shaping
  *
  * This function does all shaping work that depends on the resolved embedding
  * levels of the characters.  Currently it does mirroring and Arabic shaping,
- * but the list may grow later.  Individual shaping features can be turned
- * on/off using environmental setting functions fribidi_env_*.  Feel free to
- * do your own shaping before or after calling this function, but you should
- * take care of embedding levels yourself then.
+ * but the list may grow later.
+ *
+ * Individual shaping features can be turned on/off using environmental
+ * setting functions fribidi_env_*().  Feel free to do your own shaping before
+ * or after calling this function, but you should take care of embedding
+ * levels yourself then.
  */
 FRIBIDI_ENTRY void fribidi_shape (
-  const FriBidiLevel *embedding_level_list,	/* input list of embedding
-						   levels, as returned by
-						   fribidi_get_par_embedding_levels */
+  const FriBidiLevel *embedding_levels,	/* input list of embedding
+					   levels, as returned by
+					   fribidi_get_par_embedding_levels */
   const FriBidiStrIndex len,	/* input string length */
   FriBidiChar *str		/* string to shape */
 );
@@ -76,15 +77,22 @@
 /* fribidi_remove_bidi_marks - remove bidi marks out of an string
  *
  * This function removes the bidi and boundary-neutral marks out of an string
- * and the accompanying lists.  If any of the input lists are NULL, the list
- * is skipped.  If str is the visual string, then position_to_this_list is
- * position_L_to_V_list and position_from_this_list is position_V_to_L_list;
- * if str is the logical string, the other way.  Moreover, the position maps
- * should be filled with valid entries.  A position map pointing to a removed
- * character is filled with -1. By the way, you should not use
- * embedding_level_list if str is visual string.  For best results it should
- * be run on a whole paragraph, not lines; but feel free to do otherwise if
- * you know what you are doing.
+ * and the accompanying lists.  It implements rule X9 of the Unicode
+ * Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/#X9, with the exception that it removes
+ * U+200E LEFT-TO-RIGHT MARK and U+200F RIGHT-TO-LEFT MARK too.
+ *
+ * If any of the input lists are NULL, the list is skipped.  If str is the
+ * visual string, then positions_to_this is  positions_L_to_V and
+ * position_from_this_list is positions_V_to_L;  if str is the logical
+ * string, the other way.Moreover, the position maps should be filled with
+ * valid entries.
+ * 
+ * A position map pointing to a removed character is filled with -1. By the
+ * way, you should not use embedding_levels if str is visual string.
+ * 
+ * For best results this function should be run on a whole paragraph, not
+ * lines; but feel free to do otherwise if you know what you are doing.
  *
  * Returns: New length of the string, or -1 if an error occured (memory
  * allocation failure most probably).
@@ -93,11 +101,11 @@
 fribidi_remove_bidi_marks (
   FriBidiChar *str,		/* input string to clean */
   const FriBidiStrIndex len,	/* input string length */
-  FriBidiStrIndex *position_to_this_list,	/* list mapping positions to the
-						   order used in str */
+  FriBidiStrIndex *positions_to_this,	/* list mapping positions to the
+					   order used in str */
   FriBidiStrIndex *position_from_this_list,	/* list mapping positions from the
 						   order used in str */
-  FriBidiLevel *embedding_level_list	/* list of embedding levels */
+  FriBidiLevel *embedding_levels	/* list of embedding levels */
 ) FRIBIDI_GNUC_WARN_UNUSED;
 
 
@@ -109,10 +117,13 @@
  * This function converts the logical input string to the visual output
  * strings as specified by the Unicode Bidirectional Algorithm.  As a side
  * effect it also generates mapping lists between the two strings, and the
- * list of embedding levels as defined by the algorithm.  If any of the the
- * lists are passed as NULL, the list is ignored and not filled.  This
- * function is obsolete because it only handles one-line paragraphs. 
- * Please consider using other functions instead. Deprecated.
+ * list of embedding levels as defined by the algorithm.
+ *
+ * If NULL is passed as any of the the lists, the list is ignored and not
+ * filled.
+ *
+ * This function is obsolete because it only handles one-line paragraphs. 
+ * Please consider using other functions instead.  Deprecated.
  *
  * Returns: Maximum level found plus one, or zero if any error occured
  * (memory allocation failure most probably).
@@ -123,12 +134,12 @@
   FriBidiParType *pbase_dir,	/* requested and resolved paragraph
 				 * base direction */
   FriBidiChar *visual_str,	/* output visual string */
-  FriBidiStrIndex *position_L_to_V_list,	/* output mapping from logical to 
-						 * visual string positions */
-  FriBidiStrIndex *position_V_to_L_list,	/* output mapping from visual string
-						 * back to the logical string
-						 * positions */
-  FriBidiLevel *embedding_level_list	/* output list of embedding levels */
+  FriBidiStrIndex *positions_L_to_V,	/* output mapping from logical to 
+					 * visual string positions */
+  FriBidiStrIndex *positions_V_to_L,	/* output mapping from visual string
+					 * back to the logical string
+					 * positions */
+  FriBidiLevel *embedding_levels	/* output list of embedding levels */
 )
      FRIBIDI_GNUC_WARN_UNUSED FRIBIDI_GNUC_DEPRECATED;
 

Index: joining-types.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/joining-types.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- joining-types.h	13 Jun 2004 20:11:42 -0000	1.1
+++ joining-types.h	15 Jun 2004 11:52:02 -0000	1.2
@@ -45,7 +45,8 @@
 #define fribidi_char_from_joining_type FRIBIDI_PRIVATESPACE(char_from_joining_type)
 char
 fribidi_char_from_joining_type (
-  FriBidiJoiningType j		/* input joining type */
+  FriBidiJoiningType j,		/* input joining type */
+  fribidi_boolean visual	/* in visual context or logincal? */
 ) FRIBIDI_GNUC_HIDDEN;
 
 #endif /* DEBUG */




More information about the FriBidi-Commit mailing list