[FriBidi-commit] fribidi/lib fribidi-bidi.c, 1.8, 1.9 fribidi-bidi.h, 1.4, 1.5 fribidi-run.c, 1.2, 1.3 run.h, 1.3, 1.4

Behdad Esfahbod behdad at pdx.freedesktop.org
Fri Jun 4 09:43:53 PDT 2004


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

Modified Files:
	fribidi-bidi.c fribidi-bidi.h fribidi-run.c run.h 
Log Message:
Isolating bidi reordering call, take 1.


Index: fribidi-bidi.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-bidi.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- a/fribidi-bidi.c	4 Jun 2004 09:41:11 -0000	1.8
+++ b/fribidi-bidi.c	4 Jun 2004 16:43:51 -0000	1.9
@@ -305,58 +305,44 @@
     FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list))
 
 
-static fribidi_boolean
-fribidi_get_embedding_levels_internal (
-  const FriBidiChar *str,
-  FriBidiStrIndex len,
-  FriBidiCharType *pbase_dir,
-  FriBidiRun **pmain_run_list,
-  FriBidiLevel *pmax_level
-) FRIBIDI_GNUC_WARN_UNUSED;
-
-/*======================================================================
- *  This function should follow the Unicode specification closely!
- *----------------------------------------------------------------------*/
-     static fribidi_boolean fribidi_get_embedding_levels_internal (
+FRIBIDI_ENTRY FriBidiLevel
+fribidi_get_embedding_levels (
   /* input */
   const FriBidiChar *str,
   FriBidiStrIndex len,
   /* input and output */
   FriBidiCharType *pbase_dir,
   /* output */
-  FriBidiRun **pmain_run_list,
-  FriBidiLevel *pmax_level
+  FriBidiLevel *embedding_level_list
 )
 {
-  FriBidiLevel base_level, max_level;
+  FriBidiLevel base_level, max_level = 0;
   FriBidiCharType base_dir;
   FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp;
   fribidi_boolean status = false;
 
-  DBG ("entering fribidi_get_embedding_levels_internal");
+  DBG ("entering fribidi_get_embedding_levels");
 
   fribidi_assert (str);
   fribidi_assert (pbase_dir);
+  fribidi_assert (embedding_level_list);
 
-  /* Determinate character types */
-  DBG ("  determine character types");
-  {
-    FriBidiCharType *char_types =
-      (FriBidiCharType *) fribidi_malloc (len * sizeof (FriBidiCharType));
-    if (!char_types)
+  if UNLIKELY
+    (!len)
+    {
+      status = true;
       goto out;
-    fribidi_get_bidi_types (str, len, char_types);
+    }
 
-    /* Run length encode the character types */
-    main_run_list = run_list_encode_bidi_types (char_types, len);
-    fribidi_free (char_types);
-    if (!main_run_list)
-      goto out;
+  /* Determinate character types */
+  {
+    /* Get run-length encoded character types */
+    main_run_list = run_list_encode_bidi_types (str, len);
+    if UNLIKELY
+      (!main_run_list) goto out;
   }
-  DBG ("  determine character types, done");
 
   /* Find base level */
-  DBG ("  finding the base level");
   /* If no strong base_dir was found, resort to the weak direction
      that was passed on input. */
   base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
@@ -374,7 +360,6 @@
   base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
   DBG2 ("  base level : %c", fribidi_char_from_level (base_level));
   DBG2 ("  base dir   : %c", fribidi_char_from_bidi_type (base_dir));
-  DBG ("  finding the base level, done");
 
 # if DEBUG
   if UNLIKELY
@@ -740,7 +725,8 @@
 
   DBG ("reset the embedding levels");
   {
-    register int j, k, state, pos;
+    register int j, state, pos;
+    register FriBidiCharType char_type;
     register FriBidiRun *p, *q, *list;
 
     /* L1. Reset the embedding levels of some chars. */
@@ -754,15 +740,16 @@
       {
 	/* if state is on at the very first of the string, do this too. */
 	if (j >= 0)
-	  k = fribidi_get_bidi_type (str[j]);
+	  char_type = fribidi_get_bidi_type (str[j]);
 	else
-	  k = FRIBIDI_TYPE_ON;
-	if (!state && FRIBIDI_IS_SEPARATOR (k))
+	  char_type = FRIBIDI_TYPE_ON;
+	if (!state && FRIBIDI_IS_SEPARATOR (char_type))
 	  {
 	    state = 1;
 	    pos = j;
 	  }
-	else if (state && !FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS (k))
+	else if (state && !FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS
+		 (char_type))
 	  {
 	    state = 0;
 	    p = new_run ();
@@ -794,25 +781,28 @@
     }
 # endif	/* DEBUG */
 
-  status = true;
-  if (pmain_run_list)
-    *pmain_run_list = main_run_list;
-  else
+  {
+    FriBidiStrIndex pos = 0;
+    for_run_list (pp, main_run_list)
     {
-      free_run_list (main_run_list);
-      main_run_list = NULL;
+      register FriBidiStrIndex l;
+      register FriBidiLevel level = pp->level;
+      for (l = pp->len; l; l--)
+	embedding_level_list[pos++] = level;
     }
-  if (pmax_level)
-    *pmax_level = max_level;
+  }
+
+  status = true;
 
-  DBG ("leaving fribidi_get_embedding_levels_internal");
 out:
+  DBG ("leaving fribidi_get_embedding_levels");
+
+  if (main_run_list)
+    free_run_list (main_run_list);
   if UNLIKELY
     (explicits_list) free_run_list (explicits_list);
-  if UNLIKELY
-    (!status && main_run_list) free_run_list (main_run_list);
 
-  return status;
+  return status ? max_level + 1 : 0;
 }
 
 static void
@@ -908,7 +898,7 @@
 }
 
 
-FRIBIDI_ENTRY fribidi_boolean
+FRIBIDI_ENTRY FriBidiLevel
 fribidi_log2vis (
   /* input */
   const FriBidiChar *str,
@@ -922,18 +912,20 @@
   FriBidiLevel *embedding_level_list
 )
 {
-  FriBidiRun *main_run_list = NULL, *pp = NULL;
-  FriBidiLevel max_level;
+  FriBidiLevel max_level = 0;
   fribidi_boolean private_V_to_L = false;
-  fribidi_boolean status = true;
-
-  DBG ("entering fribidi_log2vis()");
+  fribidi_boolean private_embedding_level_list = false;
+  fribidi_boolean status = false;
 
   fribidi_assert (str);
   fribidi_assert (pbase_dir);
 
-  if (len == 0)
-    goto out;
+  if UNLIKELY
+    (len == 0)
+    {
+      status = true;
+      goto out;
+    }
 
   if UNLIKELY
     (len > FRIBIDI_MAX_STRING_LENGTH && (position_V_to_L_list ||
@@ -943,19 +935,23 @@
       MSG2 (FRIBIDI ": cannot handle strings > %ld characters\n",
 	    (long) FRIBIDI_MAX_STRING_LENGTH);
 #     endif /* DEBUG */
-      status = false;
       goto out;
     }
 
-  if UNLIKELY
-    (!fribidi_get_embedding_levels_internal (str, len, pbase_dir,
-					     /* output */
-					     &main_run_list, &max_level))
+  if (!embedding_level_list)
     {
-      status = false;
-      goto out;
+      embedding_level_list = fribidi_malloc (len);
+      if (!embedding_level_list)
+	goto out;
+      private_embedding_level_list = true;
     }
 
+  max_level = fribidi_get_embedding_levels (str, len, pbase_dir,
+					    /* output */
+					    embedding_level_list) - 1;
+  if UNLIKELY
+    (max_level < 0) goto out;
+
   /* 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)
@@ -963,70 +959,40 @@
       position_V_to_L_list =
 	(FriBidiStrIndex *) fribidi_malloc (sizeof (FriBidiStrIndex) * len);
       if (!position_V_to_L_list)
-	{
-	  status = false;
-	  goto out;
-	}
+	goto out;
       private_V_to_L = true;
     }
 
 
   /* 7. Reordering resolved levels */
-  DBG ("reordering resolved levels");
   {
-    FriBidiLevel level_idx;
-    FriBidiStrIndex i;
+    register FriBidiLevel level;
+    register FriBidiStrIndex i;
 
     /* Set up the ordering array to sorted order */
     if (position_V_to_L_list)
       {
-	DBG ("  initialize position_V_to_L_list");
-	for (i = 0; i < len; i++)
+	for (i = len - 1; i >= 0; i--)
 	  position_V_to_L_list[i] = i;
-	DBG ("  initialize position_V_to_L_list, done");
       }
     /* Copy the logical string to the visual */
     if (visual_str)
       {
-	DBG ("  initialize visual_str");
-	for (i = 0; i < len; i++)
+	for (i = len - 1; i >= 0; i--)
 	  visual_str[i] = str[i];
 	visual_str[len] = 0;
-	DBG ("  initialize visual_str, done");
-      }
-
-    /* Assign the embedding level array */
-    if (embedding_level_list)
-      {
-	DBG ("  fill the embedding levels array");
-	for_run_list (pp, main_run_list)
-	{
-	  register FriBidiStrIndex i, pos = pp->pos, len = pp->len;
-	  register FriBidiLevel level = pp->level;
-	  for (i = 0; i < len; i++)
-	    embedding_level_list[pos + i] = level;
-	}
-	DBG ("  fill the embedding levels array, done");
       }
 
     if (fribidi_mirroring_status () && visual_str)
       {
 	/* L4. Mirror all characters that are in odd levels and have mirrors. */
-	DBG ("  mirroring");
-	for_run_list (pp, main_run_list)
-	{
-	  if (pp->level & 1)
+	for (i = len - 1; i >= 0; i--)
+	  if (embedding_level_list[i] & 1)
 	    {
-	      FriBidiStrIndex i;
-	      for (i = RL_POS (pp); i < RL_POS (pp) + RL_LEN (pp); i++)
-		{
-		  FriBidiChar mirrored_ch;
-		  if (fribidi_get_mirror_char (visual_str[i], &mirrored_ch))
-		    visual_str[i] = mirrored_ch;
-		}
+	      FriBidiChar mirrored_ch;
+	      if (fribidi_get_mirror_char (visual_str[i], &mirrored_ch))
+		visual_str[i] = mirrored_ch;
 	    }
-	}
-	DBG ("  mirroring, done");
       }
 
     /* Reorder both the outstring and the order array */
@@ -1035,146 +1001,74 @@
 	if (fribidi_reorder_nsm_status ())
 	  {
 	    /* L3. Reorder NSMs. */
-	    DBG ("  reordering NSM sequences");
-	    /* We apply this rule before L2, so go backward in odd levels. */
-	    for_run_list (pp, main_run_list)
-	    {
-	      if (pp->level & 1)
+	    for (i = len - 1; i >= 0; i--)
+	      if ((embedding_level_list[i] & 1)
+		  && fribidi_get_bidi_type (str[i]) == FRIBIDI_TYPE_NSM)
 		{
-		  FriBidiStrIndex i, seq_end = 0;
-		  fribidi_boolean is_nsm_seq;
+		  register FriBidiStrIndex seq_end = i;
+		  level = embedding_level_list[i];
 
-		  is_nsm_seq = false;
-		  for (i = RL_POS (pp) + RL_LEN (pp) - 1; i >= RL_POS (pp);
-		       i--)
-		    {
-		      FriBidiCharType this_type;
+		  for (i--; i >= 0 &&
+		       FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM (fribidi_get_bidi_type
+							 (str[i]))
+		       && embedding_level_list[i] == level; i--)
+		    ;
 
-		      this_type = fribidi_get_bidi_type (str[i]);
-		      if (is_nsm_seq && this_type != FRIBIDI_TYPE_NSM)
-			{
-			  if (visual_str)
-			    {
-			      bidi_string_reverse (visual_str + i,
-						   seq_end - i + 1);
-			    }
-			  if (position_V_to_L_list)
-			    {
-			      index_array_reverse (position_V_to_L_list + i,
-						   seq_end - i + 1);
-			    }
-			  is_nsm_seq = 0;
-			}
-		      else if (!is_nsm_seq && this_type == FRIBIDI_TYPE_NSM)
-			{
-			  seq_end = i;
-			  is_nsm_seq = 1;
-			}
-		    }
-		  if (is_nsm_seq)
+		  if (i < 0 || embedding_level_list[i] != level)
 		    {
-		      DBG ("warning: NSMs at the beggining of level run.\n");
+		      i++;
+		      DBG ("warning: NSM(s) at the beggining of level run");
 		    }
-		}
-	    }
-	    DBG ("  reordering NSM sequences, done");
-	  }
 
-	/* L2. Reorder. */
-	DBG ("  reordering");
-	for (level_idx = max_level; level_idx > 0; level_idx--)
-	  {
-	    for_run_list (pp, main_run_list)
-	    {
-	      if (RL_LEVEL (pp) >= level_idx)
-		{
-		  /* Find all stretches that are >= level_idx */
-		  register FriBidiStrIndex len = pp->len, pos = pp->pos;
-		  register FriBidiRun *pp1 = pp->next;
-		  while (pp1->next && pp1->level >= level_idx)
+		  if (visual_str)
 		    {
-		      len += pp1->len;
-		      pp1 = pp1->next;
+		      bidi_string_reverse (visual_str + i, seq_end - i + 1);
 		    }
-		  pp = pp1->prev;
-		  if (visual_str)
-		    bidi_string_reverse (visual_str + pos, len);
 		  if (position_V_to_L_list)
-		    index_array_reverse (position_V_to_L_list + pos, len);
+		    {
+		      index_array_reverse (position_V_to_L_list + i,
+					   seq_end - i + 1);
+		    }
 		}
-	    }
 	  }
-	DBG ("  reordering, done");
+
+	/* L2. Reorder. */
+	for (level = max_level; level > 0; level--)
+	  for (i = len - 1; i >= 0; i--)
+	    if (embedding_level_list[i] >= level)
+	      {
+		/* Find all stretches that are >= level_idx */
+		register FriBidiStrIndex seq_end = i;
+		for (i--; i >= 0 && embedding_level_list[i] >= level; i--)
+		  ;
+
+		if (visual_str)
+		  bidi_string_reverse (visual_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);
+	      }
       }
 
     /* Convert the v2l list to l2v */
     if (position_L_to_V_list)
       {
-	DBG ("  converting v2l list to l2v");
 	for (i = 0; i < len; i++)
 	  position_L_to_V_list[position_V_to_L_list[i]] = i;
-	DBG ("  converting v2l list to l2v, done");
       }
   }
-  DBG ("reordering resolved levels, done");
 
-  DBG ("leaving fribidi_log2vis()");
+  status = true;
+
 out:
+
   if (private_V_to_L)
     fribidi_free (position_V_to_L_list);
 
-  free_run_list (main_run_list);
-
-  return status;
-
-}
-
-FRIBIDI_ENTRY fribidi_boolean
-fribidi_get_embedding_levels (
-  /* input */
-  const FriBidiChar *str,
-  FriBidiStrIndex len,
-  /* input and output */
-  FriBidiCharType *pbase_dir,
-  /* output */
-  FriBidiLevel *embedding_level_list
-)
-{
-  FriBidiRun *main_run_list, *pp;
-  fribidi_boolean status = true;
-  register FriBidiStrIndex pos;
-
-  DBG ("entering fribidi_get_embedding_levels()");
-
-  fribidi_assert (str);
-  fribidi_assert (pbase_dir);
-
-  if UNLIKELY
-    (len == 0) goto out;
-
-  if UNLIKELY
-    (!fribidi_get_embedding_levels_internal (str, len, pbase_dir,
-					     /* output */
-					     &main_run_list, NULL))
-    {
-      status = false;
-      goto out;
-    }
-
-  pos = 0;
-  for_run_list (pp, main_run_list)
-  {
-    register FriBidiStrIndex l;
-    register FriBidiLevel level = pp->level;
-    for (l = pp->len; l; l--)
-      embedding_level_list[pos++] = level;
-  }
-
-  DBG ("leaving fribidi_get_embedding_levels()");
-out:
-  free_run_list (main_run_list);
+  if (private_embedding_level_list)
+    fribidi_free (embedding_level_list);
 
-  return status;
+  return status ? max_level + 1 : 0;
 }
 
 /* Editor directions:

Index: fribidi-bidi.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-bidi.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- a/fribidi-bidi.h	4 Jun 2004 09:41:11 -0000	1.4
+++ b/fribidi-bidi.h	4 Jun 2004 16:43:51 -0000	1.5
@@ -51,10 +51,10 @@
  * 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.
  *
- * Returns: Non-zero if it was successful, or zero if any error occured
+ * Returns: Maximum level found plus one, or zero if any error occured
  * (memory allocation failure most probably).
  */
-FRIBIDI_ENTRY fribidi_boolean
+FRIBIDI_ENTRY FriBidiLevel
 fribidi_log2vis (
   const FriBidiChar *str,	/* input logical string */
   FriBidiStrIndex len,		/* input string length */
@@ -75,10 +75,10 @@
  * This function finds the bidi embedding levels of a single paragraph,
  * as defined by the Unicode Bidirectional Algorithm.
  *
- * Returns: Non-zero if it was successful, or zero if any error occured
+ * Returns: Maximum level found plus one, or zero if any error occured
  * (memory allocation failure most probably).
  */
-     FRIBIDI_ENTRY fribidi_boolean fribidi_get_embedding_levels (
+     FRIBIDI_ENTRY FriBidiLevel fribidi_get_embedding_levels (
   const FriBidiChar *str,	/* input logical string */
   FriBidiStrIndex len,		/* input string length */
   FriBidiCharType *pbase_dir,	/* requested and resolved paragraph

Index: fribidi-run.c
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/fribidi-run.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/fribidi-run.c	3 May 2004 22:05:19 -0000	1.2
+++ b/fribidi-run.c	4 Jun 2004 16:43:51 -0000	1.3
@@ -35,6 +35,8 @@
 
 #include "common.h"
 
+#include <fribidi-bidi-type.h>
+
 #include "run.h"
 #include "env.h"
 #include "bidi-types.h"
@@ -154,7 +156,7 @@
 FriBidiRun *
 run_list_encode_bidi_types (
   /* input */
-  FriBidiCharType *char_type,
+  const FriBidiChar *str,
   FriBidiStrIndex len
 )
 {
@@ -162,7 +164,7 @@
   register FriBidiRun *run = NULL;
   FriBidiStrIndex i;
 
-  fribidi_assert (char_type);
+  fribidi_assert (str);
 
   /* Create the list sentinel */
   list = new_run_list ();
@@ -172,18 +174,21 @@
 
   /* Scan over the character types */
   for (i = 0; i < len; i++)
-    if (char_type[i] != last->type)
-      {
-	run = new_run ();
-	if UNLIKELY
-	  (!run) break;
-	run->type = char_type[i];
-	run->pos = i;
-	last->len = run->pos - last->pos;
-	last->next = run;
-	run->prev = last;
-	last = run;
-      }
+    {
+      register FriBidiCharType char_type = fribidi_get_bidi_type (str[i]);
+      if (char_type != last->type)
+	{
+	  run = new_run ();
+	  if UNLIKELY
+	    (!run) break;
+	  run->type = char_type;
+	  run->pos = i;
+	  last->len = run->pos - last->pos;
+	  last->next = run;
+	  run->prev = last;
+	  last = run;
+	}
+    }
 
   /* Close the circle */
   last->len = len - last->pos;

Index: run.h
===================================================================
RCS file: /cvs/fribidi/fribidi/lib/run.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/run.h	31 May 2004 18:39:39 -0000	1.3
+++ b/run.h	4 Jun 2004 16:43:51 -0000	1.4
@@ -80,7 +80,7 @@
 
 #define run_list_encode_bidi_types FRIBIDI_PRIVATESPACE(run_list_encode_bidi_types)
      FriBidiRun *run_list_encode_bidi_types (
-  FriBidiCharType *char_type,
+  const FriBidiChar *str,
   FriBidiStrIndex len
 )
      FRIBIDI_GNUC_HIDDEN FRIBIDI_GNUC_WARN_UNUSED;




More information about the FriBidi-Commit mailing list