summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2015-12-10 11:05:51 +0100
committerBehdad Esfahbod <behdad@behdad.org>2015-12-10 11:05:51 +0100
commit9d8c69b4aea7302391b1cafb3c1fa5c3d8c95198 (patch)
tree1df16bd1072a7530fff649164bfeac2cd00e70a1
parent7fd7d2badedffce5a3328301ba86204a24eed0a3 (diff)
parent0a8f80debcffded53db34246881cc5d73ad0cfa5 (diff)
downloadfribidi-9d8c69b4aea7302391b1cafb3c1fa5c3d8c95198.tar.gz
Merge pull request #10 from HOST-Oman/master
Add fribidi_reorder_runs()
-rw-r--r--lib/fribidi-bidi.c112
-rw-r--r--lib/fribidi-bidi.h29
-rw-r--r--lib/fribidi-common.h14
-rw-r--r--lib/run.h11
4 files changed, 151 insertions, 15 deletions
diff --git a/lib/fribidi-bidi.c b/lib/fribidi-bidi.c
index 89d6546..1bea6e8 100644
--- a/lib/fribidi-bidi.c
+++ b/lib/fribidi-bidi.c
@@ -993,6 +993,118 @@ out:
return status ? max_level + 1 : 0;
}
+
+static void
+reverse_run (
+ FriBidiRun *arr,
+ const FriBidiStrIndex len
+)
+{
+ FriBidiStrIndex i;
+
+ fribidi_assert (arr);
+
+ for (i = 0; i < len/2; i++)
+ {
+ FriBidiRun temp = arr[i];
+ arr[i] = arr[len - 1 - i];
+ arr[len - 1 - i] = temp;
+ }
+}
+
+FRIBIDI_ENTRY FriBidiStrIndex
+fribidi_reorder_runs (
+ /* input */
+ const FriBidiCharType *bidi_types,
+ const FriBidiStrIndex len,
+ const FriBidiParType base_dir,
+ /* input and output */
+ FriBidiLevel *embedding_levels,
+ /* output */
+ FriBidiRun *runs
+)
+{
+ FriBidiStrIndex i;
+ FriBidiLevel level;
+ FriBidiLevel last_level = -1;
+ FriBidiLevel max_level = 0;
+ FriBidiStrIndex run_count = 0;
+ FriBidiStrIndex run_start = 0;
+ FriBidiStrIndex run_index = 0;
+
+ if UNLIKELY
+ (len == 0)
+ {
+ goto out;
+ }
+
+ DBG ("in fribidi_reorder_runs");
+
+ fribidi_assert (bidi_types);
+ fribidi_assert (embedding_levels);
+
+ DBG ("reset the embedding levels, 4. whitespace at the end of line");
+ {
+ FriBidiStrIndex i;
+
+ /* L1. Reset the embedding levels of some chars:
+ 4. any sequence of white space characters at the end of the line. */
+ for (i = len - 1; i >= 0 &&
+ FRIBIDI_IS_EXPLICIT_OR_BN_OR_WS (bidi_types[i]); i--)
+ embedding_levels[i] = FRIBIDI_DIR_TO_LEVEL (base_dir);
+ }
+ /* Find max_level of the line. We don't reuse the paragraph
+ * max_level, both for a cleaner API, and that the line max_level
+ * may be far less than paragraph max_level. */
+ for (i = len - 1; i >= 0; i--)
+ if (embedding_levels[i] > max_level)
+ max_level = embedding_levels[i];
+
+ for (i = 0; i < len; i++)
+ {
+ if (embedding_levels[i] != last_level)
+ run_count++;
+
+ last_level = embedding_levels[i];
+ }
+
+ if (runs == NULL)
+ goto out;
+
+ while (run_start < len)
+ {
+ int runLength = 0;
+ while ((run_start + runLength) < len && embedding_levels[run_start] == embedding_levels[run_start + runLength])
+ runLength++;
+
+ runs[run_index].pos = run_start;
+ runs[run_index].level = embedding_levels[run_start];
+ runs[run_index].len = runLength;
+ run_start += runLength;
+ run_index++;
+ }
+
+ /* L2. Reorder. */
+ for (level = max_level; level > 0; level--)
+ {
+ for (i = run_count - 1; i >= 0; i--)
+ {
+ if (runs[i].level >= level)
+ {
+ int end = i;
+ for (i--; (i >= 0 && runs[i].level >= level); i--)
+ ;
+ reverse_run (runs + i + 1, end - i);
+ }
+ }
+ }
+
+out:
+
+ return run_count;
+}
+
+
/* Editor directions:
* vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
*/
diff --git a/lib/fribidi-bidi.h b/lib/fribidi-bidi.h
index dd2de67..6faba16 100644
--- a/lib/fribidi-bidi.h
+++ b/lib/fribidi-bidi.h
@@ -141,6 +141,35 @@ fribidi_get_par_embedding_levels (
* to reflect where each glyph ends up. */
) FRIBIDI_GNUC_WARN_UNUSED;
+#define fribidi_reorder_runs FRIBIDI_NAMESPACE(reorder_runs)
+/* fribidi_reorder_runs - reorder runs of logical string to visual
+ *
+ * This function reorders all runs from logical to final visual order. This
+ * function implements part 4 of rule L1 and rule L2 of the Unicode
+ * Bidirectional Algorithm available at
+ * http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels.
+ *
+ * You should provide the bidi types as returned by fribidi_get_bidi_types()
+ * and the resolved embedding levels as set by
+ * fribidi_get_par_embedding_levels(). Also note that the embedding levels may
+ * change a bit. To be exact, the embedding level of any sequence of white
+ * space at the end of line is reset to the paragraph embedding level (That is
+ * part 4 of rule L1).
+ *
+ * The runs array can be NULL and in this case no reordring will happen, only
+ * the count of the runs will be returned.
+ *
+ * Returns: number of the runs.
+ */
+FRIBIDI_ENTRY FriBidiStrIndex
+fribidi_reorder_runs (
+ const FriBidiCharType *bidi_types, /* input list of bidi types as returned by fribidi_get_bidi_types() */
+ const FriBidiStrIndex len, /* input length of the line */
+ const FriBidiParType base_dir, /* resolved paragraph base direction */
+ FriBidiLevel *embedding_levels, /* input list of embedding levels, as returned by fribidi_get_par_embedding_levels */
+ FriBidiRun *runs /* Fribidi run information ( pos of run, the length of the run ,level of the run) */
+) FRIBIDI_GNUC_WARN_UNUSED;
+
#include "fribidi-enddecls.h"
#endif /* !_FRIBIDI_BIDI_H */
diff --git a/lib/fribidi-common.h b/lib/fribidi-common.h
index 6dede39..ffcb27a 100644
--- a/lib/fribidi-common.h
+++ b/lib/fribidi-common.h
@@ -99,6 +99,7 @@
+#include <fribidi-bidi-types.h>
#define fribidi_debug_status FRIBIDI_NAMESPACE(debug_status)
FRIBIDI_ENTRY int fribidi_debug_status (
@@ -112,11 +113,16 @@ fribidi_set_debug (
+typedef struct _FriBidiRunStruct FriBidiRun;
-
-
-
-
+struct _FriBidiRunStruct
+{
+ FriBidiRun *prev;
+ FriBidiRun *next;
+ FriBidiStrIndex pos, len;
+ FriBidiCharType type;
+ FriBidiLevel level;
+};
diff --git a/lib/run.h b/lib/run.h
index 6028845..0b56cab 100644
--- a/lib/run.h
+++ b/lib/run.h
@@ -44,17 +44,6 @@
#include <fribidi-begindecls.h>
-typedef struct _FriBidiRunStruct FriBidiRun;
-
-struct _FriBidiRunStruct
-{
- FriBidiRun *prev;
- FriBidiRun *next;
-
- FriBidiStrIndex pos, len;
- FriBidiCharType type;
- FriBidiLevel level;
-};
#define new_run FRIBIDI_PRIVATESPACE(new_run)