summaryrefslogtreecommitdiff
path: root/pango/mini-fribidi/fribidi.c
diff options
context:
space:
mode:
Diffstat (limited to 'pango/mini-fribidi/fribidi.c')
-rw-r--r--pango/mini-fribidi/fribidi.c902
1 files changed, 388 insertions, 514 deletions
diff --git a/pango/mini-fribidi/fribidi.c b/pango/mini-fribidi/fribidi.c
index 75366665..59ee6c7b 100644
--- a/pango/mini-fribidi/fribidi.c
+++ b/pango/mini-fribidi/fribidi.c
@@ -21,27 +21,24 @@
* <fwpg@sharif.edu>.
*/
-#include <glib.h>
-#include "pango/pango-utils.h"
-#include "fribidi_types.h"
+#include <stdlib.h>
-#ifdef DEBUG
-static gboolean fribidi_debug = FALSE;
+#ifdef HAVE_CONFIG_H
+#include <config.h>
#endif
+#include "fribidi.h"
-#ifdef DEBUG
-#define DBG(s) do { if (fribidi_debug) { fprintf(stderr, s); } } while (0)
-#define DBG2(s, t) do { if (fribidi_debug) { fprintf(stderr, s, t); } } while (0)
+/* Redefine FRIBIDI_CHUNK_SIZE in config.h to override this. */
+#ifndef FRIBIDI_CHUNK_SIZE
+#ifdef MEM_OPTIMIZED
+#define FRIBIDI_CHUNK_SIZE 16
#else
-#define DBG(s)
-#define DBG2(s, t)
+#define FRIBIDI_CHUNK_SIZE 128
#endif
-
-#ifdef DEBUG
-char fribidi_char_from_type (FriBidiCharType c);
#endif
-#define UNI_MAX_BIDI_LEVEL 61
+#define DBG(s)
+#define DBG2(s, t)
/*======================================================================
* Typedef for the run-length list.
@@ -64,17 +61,41 @@ struct _TypeLink
typedef struct
{
- FriBidiCharType override; /* only L, R and N are valid */
+ FriBidiCharType override; /* only L, R and N are valid */
FriBidiLevel level;
}
LevelInfo;
+#ifndef USE_SIMPLE_MALLOC
+static TypeLink *free_type_links = NULL;
+#endif
+
static TypeLink *
-new_type_link ()
+new_type_link (void)
{
TypeLink *link;
- link = (TypeLink *) g_malloc (sizeof (TypeLink));
+#ifdef USE_SIMPLE_MALLOC
+ link = malloc (sizeof (TypeLink));
+#else /* !USE_SIMPLE_MALLOC */
+ if (free_type_links)
+ {
+ link = free_type_links;
+ free_type_links = free_type_links->next;
+ }
+ else
+ {
+ static FriBidiMemChunk *mem_chunk = NULL;
+
+ if (!mem_chunk)
+ mem_chunk = fribidi_mem_chunk_create (TypeLink,
+ FRIBIDI_CHUNK_SIZE,
+ FRIBIDI_ALLOC_ONLY);
+
+ link = fribidi_chunk_new (TypeLink,
+ mem_chunk);
+ }
+#endif /* !USE_SIMPLE_MALLOC */
link->len = 0;
link->pos = 0;
@@ -87,24 +108,30 @@ new_type_link ()
static void
free_type_link (TypeLink *link)
{
- g_free (link);
+#ifdef USE_SIMPLE_MALLOC
+ free (link);
+#else
+ link->next = free_type_links;
+ free_type_links = link;
+#endif
}
#define FRIBIDI_ADD_TYPE_LINK(p,q) \
- do { \
- (p)->len = (q)->pos - (p)->pos; \
- (p)->next = (q); \
- (q)->prev = (p); \
- (p) = (q); \
- } while (0)
+ do { \
+ (p)->len = (q)->pos - (p)->pos; \
+ (p)->next = (q); \
+ (q)->prev = (p); \
+ (p) = (q); \
+ } while (0)
static TypeLink *
-run_length_encode_types (FriBidiCharType *char_type,
- FriBidiStrIndex type_len)
+run_length_encode_types_utf8 (const char *s,
+ int bytelen, FriBidiStrIndex *len)
{
TypeLink *list, *last, *link;
-
+ FriBidiCharType char_type;
FriBidiStrIndex i;
+ const char *p;
/* Add the starting link */
list = new_type_link ();
@@ -112,23 +139,30 @@ run_length_encode_types (FriBidiCharType *char_type,
list->level = FRIBIDI_LEVEL_START;
last = list;
- /* Sweep over the string_type s */
- for (i = 0; i < type_len; i++)
- if (char_type[i] != last->type)
+ /* Sweep over the string s */
+ i = 0;
+ for (p = s; p < s + bytelen; p = g_utf8_next_char(p)) {
+ char_type = fribidi_get_type (g_utf8_get_char (p));
+ if (char_type != last->type)
{
- link = new_type_link ();
- link->type = char_type[i];
- link->pos = i;
- FRIBIDI_ADD_TYPE_LINK (last, link);
+ link = new_type_link ();
+ link->type = char_type;
+ link->pos = i;
+ FRIBIDI_ADD_TYPE_LINK (last, link);
}
+ i++;
+ }
/* Add the ending link */
link = new_type_link ();
link->type = FRIBIDI_TYPE_EOT;
link->level = FRIBIDI_LEVEL_END;
- link->pos = type_len;
+ link->pos = i;
FRIBIDI_ADD_TYPE_LINK (last, link);
+ if (len)
+ *len = i;
+
return list;
}
@@ -138,7 +172,7 @@ run_length_encode_types (FriBidiCharType *char_type,
*/
static void
init_list (TypeLink **start,
- TypeLink **end)
+ TypeLink **end)
{
TypeLink *list;
TypeLink *link;
@@ -170,7 +204,7 @@ init_list (TypeLink **start,
*/
static void
move_element_before (TypeLink *p,
- TypeLink *list)
+ TypeLink *list)
{
if (p->prev)
{
@@ -199,7 +233,7 @@ move_element_before (TypeLink *p,
*/
static void
override_list (TypeLink *base,
- TypeLink *over)
+ TypeLink *over)
{
TypeLink *p = base, *q, *r, *s, *t;
FriBidiStrIndex pos = 0, pos2;
@@ -210,75 +244,75 @@ override_list (TypeLink *base,
while (q)
{
if (!q->len || q->pos < pos)
- {
- t = q;
- q = q->next;
- free_type_link (t);
- continue;
- }
+ {
+ t = q;
+ q = q->next;
+ free_type_link (t);
+ continue;
+ }
pos = q->pos;
while (p->next && p->next->pos <= pos)
- p = p->next;
+ p = p->next;
/* now p is the element that q must be inserted 'in'. */
pos2 = pos + q->len;
r = p;
while (r->next && r->next->pos < pos2)
- r = r->next;
+ r = r->next;
/* now r is the last element that q affects. */
if (p == r)
- {
- /* split p into at most 3 interval, and insert q in the place of
- the second interval, set r to be the third part. */
- /* third part needed? */
- if (p->next && p->next->pos == pos2)
- r = r->next;
- else
- {
- r = new_type_link ();
- *r = *p;
- if (r->next)
- {
- r->next->prev = r;
- r->len = r->next->pos - pos2;
- }
- else
- r->len -= pos - p->pos;
- r->pos = pos2;
- }
- /* first part needed? */
- if (p->prev && p->pos == pos)
- {
- t = p;
- p = p->prev;
- free_type_link (t);
- }
- else
- p->len = pos - p->pos;
- }
+ {
+ /* split p into at most 3 interval, and insert q in the place of
+ the second interval, set r to be the third part. */
+ /* third part needed? */
+ if (p->next && p->next->pos == pos2)
+ r = r->next;
+ else
+ {
+ r = new_type_link ();
+ *r = *p;
+ if (r->next)
+ {
+ r->next->prev = r;
+ r->len = r->next->pos - pos2;
+ }
+ else
+ r->len -= pos - p->pos;
+ r->pos = pos2;
+ }
+ /* first part needed? */
+ if (p->prev && p->pos == pos)
+ {
+ t = p;
+ p = p->prev;
+ free_type_link (t);
+ }
+ else
+ p->len = pos - p->pos;
+ }
else
- {
- /* cut the end of p. */
- p->len = pos - p->pos;
- /* if all of p is cut, remove it. */
- if (!p->len && p->prev)
- p = p->prev;
-
- /* cut the begining of r. */
- r->pos = pos2;
- if (r->next)
- r->len = r->next->pos - pos2;
- /* if all of r is cut, remove it. */
- if (!r->len && r->next)
- r = r->next;
-
- /* remove the elements between p and r. */
- for (s = p->next; s != r;)
- {
- t = s;
- s = s->next;
- free_type_link (t);
- }
- }
+ {
+ /* cut the end of p. */
+ p->len = pos - p->pos;
+ /* if all of p is cut, remove it. */
+ if (!p->len && p->prev)
+ p = p->prev;
+
+ /* cut the begining of r. */
+ r->pos = pos2;
+ if (r->next)
+ r->len = r->next->pos - pos2;
+ /* if all of r is cut, remove it. */
+ if (!r->len && r->next)
+ r = r->next;
+
+ /* remove the elements between p and r. */
+ for (s = p->next; s != r;)
+ {
+ t = s;
+ s = s->next;
+ free_type_link (t);
+ }
+ }
/* before updating the next and prev links to point to the inserted q,
we must remember the next element of q in the 'over' list.
*/
@@ -314,8 +348,8 @@ compact_list (TypeLink *list)
if (list->next)
for (list = list->next; list; list = list->next)
if (RL_TYPE (list->prev) == RL_TYPE (list)
- && RL_LEVEL (list->prev) == RL_LEVEL (list))
- list = merge_with_prev (list);
+ && RL_LEVEL (list->prev) == RL_LEVEL (list))
+ list = merge_with_prev (list);
}
static void
@@ -324,15 +358,15 @@ compact_neutrals (TypeLink *list)
if (list->next)
{
for (list = list->next; list; list = list->next)
- {
- if (RL_LEVEL (list->prev) == RL_LEVEL (list)
- &&
- ((RL_TYPE
- (list->prev) == RL_TYPE (list)
- || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev))
- && FRIBIDI_IS_NEUTRAL (RL_TYPE (list))))))
- list = merge_with_prev (list);
- }
+ {
+ if (RL_LEVEL (list->prev) == RL_LEVEL (list)
+ &&
+ ((RL_TYPE
+ (list->prev) == RL_TYPE (list)
+ || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev))
+ && FRIBIDI_IS_NEUTRAL (RL_TYPE (list))))))
+ list = merge_with_prev (list);
+ }
}
}
@@ -376,7 +410,7 @@ compact_neutrals (TypeLink *list)
level = new_level; \
override = new_override; \
} else \
- over_pushed++; \
+ over_pushed++; \
} while (0)
/* If there was a valid matching code, restore (pop) the last remembered
@@ -425,98 +459,27 @@ compact_neutrals (TypeLink *list)
) \
)
+
/* Return the embedding direction of a link. */
#define FRIBIDI_EMBEDDING_DIRECTION(list) \
FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list))
-#ifdef DEBUG
-/*======================================================================
- * For debugging, define some functions for printing the types and the
- * levels.
- *----------------------------------------------------------------------*/
-
-static char char_from_level_array[] = {
- 'e', /* FRIBIDI_LEVEL_REMOVED, internal error, this level shouldn't be viewed. */
- '_', /* FRIBIDI_LEVEL_START or _END, indicating start of string and end of string. */
- /* 0-9,A-F are the only valid levels in debug mode and before resolving
- implicits. after that the levels X, Y, Z may be appear too. */
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F',
- 'X', 'Y', 'Z', /* only must appear after resolving implicits. */
- 'o', 'o', 'o' /* overflows, this levels and higher levels show a bug!. */
-};
-
-#define fribidi_char_from_level(level) char_from_level_array[(level) + 2]
-
-static void
-print_types_re (TypeLink *pp)
-{
- fprintf (stderr, " Run types : ");
- while (pp)
- {
- fprintf (stderr, "%d:l%d(%s)[%d] ",
- pp->pos, pp->len, fribidi_type_name (pp->type), pp->level);
- pp = pp->next;
- }
- fprintf (stderr, "\n");
-}
-
-static void
-print_resolved_levels (TypeLink *pp)
-{
- fprintf (stderr, " Res. levels: ");
- while (pp)
- {
- FriBidiStrIndex i;
- for (i = 0; i < RL_LEN (pp); i++)
- fprintf (stderr, "%c", fribidi_char_from_level (RL_LEVEL (pp)));
- pp = pp->next;
- }
- fprintf (stderr, "\n");
-}
-
-static void
-print_resolved_types (TypeLink *pp)
-{
- fprintf (stderr, " Res. types : ");
- while (pp)
- {
- FriBidiStrIndex i;
- for (i = 0; i < RL_LEN (pp); i++)
- fprintf (stderr, "%c", fribidi_char_from_type (pp->type));
- pp = pp->next;
- }
- fprintf (stderr, "\n");
-}
-/* Here, only for test porpuses, we have assumed that a fribidi_string
- ends with a 0 character */
-static void
-print_bidi_string (FriBidiChar *str)
-{
- FriBidiStrIndex i;
- fprintf (stderr, " Org. types : ");
- for (i = 0; str[i]; i++)
- fprintf (stderr, "%c",
- fribidi_char_from_type (_pango_fribidi_get_type (str[i])));
- fprintf (stderr, "\n");
-}
-#endif
/*======================================================================
* This function should follow the Unicode specification closely!
*----------------------------------------------------------------------*/
static void
-fribidi_analyse_string (/* input */
- const FriBidiChar *str,
- FriBidiStrIndex len,
- FriBidiCharType *pbase_dir,
- /* output */
- TypeLink **ptype_rl_list,
- FriBidiLevel *pmax_level)
+fribidi_analyse_string_utf8 ( /* input */
+ const char *str,
+ int bytelen,
+ FriBidiCharType *pbase_dir,
+ /* output */
+ FriBidiStrIndex *len,
+ TypeLink **ptype_rl_list,
+ FriBidiLevel *pmax_level)
{
FriBidiLevel base_level, max_level;
FriBidiCharType base_dir;
- FriBidiStrIndex i;
TypeLink *type_rl_list, *explicits_list, *explicits_list_end, *pp;
DBG ("Entering fribidi_analyse_string()\n");
@@ -524,14 +487,8 @@ fribidi_analyse_string (/* input */
/* Determinate character types */
DBG (" Determine character types\n");
{
- FriBidiCharType *char_type =
- (FriBidiCharType *) g_malloc (len * sizeof (FriBidiCharType));
- for (i = 0; i < len; i++)
- char_type[i] = _pango_fribidi_get_type (str[i]);
-
/* Run length encode the character types */
- type_rl_list = run_length_encode_types (char_type, len);
- g_free (char_type);
+ type_rl_list = run_length_encode_types_utf8 (str, bytelen, len);
}
DBG (" Determine character types, Done\n");
@@ -550,25 +507,18 @@ fribidi_analyse_string (/* input */
base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
base_dir = FRIBIDI_TYPE_ON;
for (pp = type_rl_list; pp; pp = pp->next)
- if (FRIBIDI_IS_LETTER (RL_TYPE (pp)))
- {
- base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp));
- base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
- break;
- }
+ if (FRIBIDI_IS_LETTER (RL_TYPE (pp)))
+ {
+ base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp));
+ base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
+ break;
+ }
}
base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
DBG2 (" Base level : %c\n", fribidi_char_from_level (base_level));
DBG2 (" Base dir : %c\n", fribidi_char_from_type (base_dir));
DBG (" Finding the base level, Done\n");
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_types_re (type_rl_list);
- }
-#endif
-
/* Explicit Levels and Directions */
DBG ("Explicit Levels and Directions\n");
{
@@ -590,62 +540,62 @@ fribidi_analyse_string (/* input */
over_pushed = 0;
first_interval = 0;
status_stack =
- (LevelInfo *) g_malloc (sizeof (LevelInfo) * (UNI_MAX_BIDI_LEVEL + 2));
+ (LevelInfo *) malloc (sizeof (LevelInfo) * (UNI_MAX_BIDI_LEVEL + 2));
for (pp = type_rl_list->next; pp->next; pp = pp->next)
{
- FriBidiCharType this_type = RL_TYPE (pp);
- if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type))
- {
- if (FRIBIDI_IS_STRONG (this_type))
- { /* LRE, RLE, LRO, RLO */
- /* 1. Explicit Embeddings */
- /* X2. With each RLE, compute the least greater odd embedding level. */
- /* X3. With each LRE, compute the least greater even embedding level. */
- /* 2. Explicit Overrides */
- /* X4. With each RLO, compute the least greater odd embedding level. */
- /* X5. With each LRO, compute the least greater even embedding level. */
- new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type);
- for (i = 0; i < RL_LEN (pp); i++)
- {
- new_level =
- ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) -
- FRIBIDI_DIR_TO_LEVEL (this_type);
- PUSH_STATUS;
- }
- }
- else if (this_type == FRIBIDI_TYPE_PDF)
- {
- /* 3. Terminating Embeddings and overrides */
- /* X7. With each PDF, determine the matching embedding or
- override code. */
- for (i = 0; i < RL_LEN (pp); i++)
- POP_STATUS;
- }
- /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */
- /* Remove element and add it to explicits_list */
- temp_link.next = pp->next;
- pp->level = FRIBIDI_LEVEL_REMOVED;
- move_element_before (pp, explicits_list_end);
- pp = &temp_link;
- }
- else
- {
- /* X6. For all typed besides RLE, LRE, RLO, LRO, and PDF:
- a. Set the level of the current character to the current
- embedding level.
- b. Whenever the directional override status is not neutral,
- reset the current character type to the directional override
- status. */
- RL_LEVEL (pp) = level;
- if (!FRIBIDI_IS_NEUTRAL (override))
- RL_TYPE (pp) = override;
- }
- /* X8. All explicit directional embeddings and overrides are
- completely terminated at the end of each paragraph. Paragraph
- separators are not included in the embedding. */
- /* This function is running on a single paragraph, so we can do
- X8 after all the input is processed. */
+ FriBidiCharType this_type = RL_TYPE (pp);
+ if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type))
+ {
+ if (FRIBIDI_IS_STRONG (this_type))
+ { /* LRE, RLE, LRO, RLO */
+ /* 1. Explicit Embeddings */
+ /* X2. With each RLE, compute the least greater odd embedding level. */
+ /* X3. With each LRE, compute the least greater even embedding level. */
+ /* 2. Explicit Overrides */
+ /* X4. With each RLO, compute the least greater odd embedding level. */
+ /* X5. With each LRO, compute the least greater even embedding level. */
+ new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type);
+ for (i = 0; i < RL_LEN (pp); i++)
+ {
+ new_level =
+ ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) -
+ FRIBIDI_DIR_TO_LEVEL (this_type);
+ PUSH_STATUS;
+ }
+ }
+ else if (this_type == FRIBIDI_TYPE_PDF)
+ {
+ /* 3. Terminating Embeddings and overrides */
+ /* X7. With each PDF, determine the matching embedding or
+ override code. */
+ for (i = 0; i < RL_LEN (pp); i++)
+ POP_STATUS;
+ }
+ /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */
+ /* Remove element and add it to explicits_list */
+ temp_link.next = pp->next;
+ pp->level = FRIBIDI_LEVEL_REMOVED;
+ move_element_before (pp, explicits_list_end);
+ pp = &temp_link;
+ }
+ else
+ {
+ /* X6. For all typed besides RLE, LRE, RLO, LRO, and PDF:
+ a. Set the level of the current character to the current
+ embedding level.
+ b. Whenever the directional override status is not neutral,
+ reset the current character type to the directional override
+ status. */
+ RL_LEVEL (pp) = level;
+ if (!FRIBIDI_IS_NEUTRAL (override))
+ RL_TYPE (pp) = override;
+ }
+ /* X8. All explicit directional embeddings and overrides are
+ completely terminated at the end of each paragraph. Paragraph
+ separators are not included in the embedding. */
+ /* This function is running on a single paragraph, so we can do
+ X8 after all the input is processed. */
}
/* Implementing X8. It has no effect on a single paragraph! */
@@ -654,7 +604,7 @@ fribidi_analyse_string (/* input */
stack_size = 0;
over_pushed = 0;
- g_free (status_stack);
+ free (status_stack);
}
/* X10. The remaining rules are applied to each run of characters at the
same level. For each run, determine the start-of-level-run (sor) and
@@ -668,62 +618,52 @@ fribidi_analyse_string (/* input */
compact_list (type_rl_list);
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_types_re (type_rl_list);
- print_bidi_string (str);
- print_resolved_levels (type_rl_list);
- print_resolved_types (type_rl_list);
- }
-#endif
-
/* 4. Resolving weak types */
DBG ("Resolving weak types\n");
{
FriBidiCharType last_strong, prev_type_org;
- gboolean w4;
+ fribidi_boolean w4;
last_strong = base_dir;
for (pp = type_rl_list->next; pp->next; pp = pp->next)
{
- FriBidiCharType prev_type, this_type, next_type;
-
- prev_type = PREV_TYPE_OR_SOR (pp);
- this_type = RL_TYPE (pp);
- next_type = NEXT_TYPE_OR_EOR (pp);
-
- if (FRIBIDI_IS_STRONG (prev_type))
- last_strong = prev_type;
-
- /* W1. NSM
- Examine each non-spacing mark (NSM) in the level run, and change the
- type of the NSM to the type of the previous character. If the NSM
- is at the start of the level run, it will get the type of sor. */
- /* Implementation note: it is important that if the previous character
- is not sor, then we should merge this run with the previous,
- because of rules like W5, that we assume all of a sequence of
- adjacent ETs are in one TypeLink. */
- if (this_type == FRIBIDI_TYPE_NSM)
- {
- if (RL_LEVEL (pp->prev) == RL_LEVEL (pp))
- pp = merge_with_prev (pp);
- else
- RL_TYPE (pp) = prev_type;
- continue; /* As we know the next condition cannot be true. */
- }
-
- /* W2: European numbers. */
- if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_AL)
- {
- RL_TYPE (pp) = FRIBIDI_TYPE_AN;
-
- /* Resolving dependency of loops for rules W1 and W2, so we
- can merge them in one loop. */
- if (next_type == FRIBIDI_TYPE_NSM)
- RL_TYPE (pp->next) = FRIBIDI_TYPE_AN;
- }
+ FriBidiCharType prev_type, this_type, next_type;
+
+ prev_type = PREV_TYPE_OR_SOR (pp);
+ this_type = RL_TYPE (pp);
+ next_type = NEXT_TYPE_OR_EOR (pp);
+
+ if (FRIBIDI_IS_STRONG (prev_type))
+ last_strong = prev_type;
+
+ /* W1. NSM
+ Examine each non-spacing mark (NSM) in the level run, and change the
+ type of the NSM to the type of the previous character. If the NSM
+ is at the start of the level run, it will get the type of sor. */
+ /* Implementation note: it is important that if the previous character
+ is not sor, then we should merge this run with the previous,
+ because of rules like W5, that we assume all of a sequence of
+ adjacent ETs are in one TypeLink. */
+ if (this_type == FRIBIDI_TYPE_NSM)
+ {
+ if (RL_LEVEL (pp->prev) == RL_LEVEL (pp))
+ pp = merge_with_prev (pp);
+ else
+ RL_TYPE (pp) = prev_type;
+ continue; /* As we know the next condition cannot be true. */
+ }
+
+ /* W2: European numbers. */
+ if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_AL)
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_AN;
+
+ /* Resolving dependency of loops for rules W1 and W2, so we
+ can merge them in one loop. */
+ if (next_type == FRIBIDI_TYPE_NSM)
+ RL_TYPE (pp->next) = FRIBIDI_TYPE_AN;
+ }
}
@@ -731,7 +671,7 @@ fribidi_analyse_string (/* input */
/* Resolving dependency of loops for rules W4 and W5, W5 may
want to prevent W4 to take effect in the next turn, do this
through "w4". */
- w4 = TRUE;
+ w4 = FRIBIDI_TRUE;
/* Resolving dependency of loops for rules W4 and W5 with W7,
W7 may change an EN to L but it sets the prev_type_org if needed,
so W4 and W5 in next turn can still do their works. */
@@ -739,75 +679,67 @@ fribidi_analyse_string (/* input */
for (pp = type_rl_list->next; pp->next; pp = pp->next)
{
- FriBidiCharType prev_type, this_type, next_type;
-
- prev_type = PREV_TYPE_OR_SOR (pp);
- this_type = RL_TYPE (pp);
- next_type = NEXT_TYPE_OR_EOR (pp);
-
- if (FRIBIDI_IS_STRONG (prev_type))
- last_strong = prev_type;
-
- /* W3: Change ALs to R. */
- if (this_type == FRIBIDI_TYPE_AL)
- {
- RL_TYPE (pp) = FRIBIDI_TYPE_RTL;
- w4 = TRUE;
- prev_type_org = FRIBIDI_TYPE_ON;
- continue;
- }
-
- /* W4. A single european separator changes to a european number.
- A single common separator between two numbers of the same type
- changes to that type. */
- if (w4
- && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type)
- && FRIBIDI_IS_NUMBER (prev_type_org) && prev_type_org == next_type
- && (prev_type_org == FRIBIDI_TYPE_EN
- || this_type == FRIBIDI_TYPE_CS))
- {
- RL_TYPE (pp) = prev_type;
- this_type = RL_TYPE (pp);
- }
- w4 = TRUE;
-
- /* W5. A sequence of European terminators adjacent to European
- numbers changes to All European numbers. */
- if (this_type == FRIBIDI_TYPE_ET
- && (prev_type_org == FRIBIDI_TYPE_EN
- || next_type == FRIBIDI_TYPE_EN))
- {
- RL_TYPE (pp) = FRIBIDI_TYPE_EN;
- w4 = FALSE;
- this_type = RL_TYPE (pp);
- }
-
- /* W6. Otherwise change separators and terminators to other neutral. */
- if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type))
- RL_TYPE (pp) = FRIBIDI_TYPE_ON;
-
- /* W7. Change european numbers to L. */
- if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_LTR)
- {
- RL_TYPE (pp) = FRIBIDI_TYPE_LTR;
- prev_type_org = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ?
- FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON);
- }
- else
- prev_type_org = PREV_TYPE_OR_SOR (pp->next);
+ FriBidiCharType prev_type, this_type, next_type;
+
+ prev_type = PREV_TYPE_OR_SOR (pp);
+ this_type = RL_TYPE (pp);
+ next_type = NEXT_TYPE_OR_EOR (pp);
+
+ if (FRIBIDI_IS_STRONG (prev_type))
+ last_strong = prev_type;
+
+ /* W3: Change ALs to R. */
+ if (this_type == FRIBIDI_TYPE_AL)
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_RTL;
+ w4 = FRIBIDI_TRUE;
+ prev_type_org = FRIBIDI_TYPE_ON;
+ continue;
+ }
+
+ /* W4. A single european separator changes to a european number.
+ A single common separator between two numbers of the same type
+ changes to that type. */
+ if (w4
+ && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type)
+ && FRIBIDI_IS_NUMBER (prev_type_org) && prev_type_org == next_type
+ && (prev_type_org == FRIBIDI_TYPE_EN
+ || this_type == FRIBIDI_TYPE_CS))
+ {
+ RL_TYPE (pp) = prev_type;
+ this_type = RL_TYPE (pp);
+ }
+ w4 = FRIBIDI_TRUE;
+
+ /* W5. A sequence of European terminators adjacent to European
+ numbers changes to All European numbers. */
+ if (this_type == FRIBIDI_TYPE_ET
+ && (prev_type_org == FRIBIDI_TYPE_EN
+ || next_type == FRIBIDI_TYPE_EN))
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_EN;
+ w4 = FRIBIDI_FALSE;
+ this_type = RL_TYPE (pp);
+ }
+
+ /* W6. Otherwise change separators and terminators to other neutral. */
+ if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type))
+ RL_TYPE (pp) = FRIBIDI_TYPE_ON;
+
+ /* W7. Change european numbers to L. */
+ if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_LTR)
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_LTR;
+ prev_type_org = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ?
+ FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON);
+ }
+ else
+ prev_type_org = PREV_TYPE_OR_SOR (pp->next);
}
}
compact_neutrals (type_rl_list);
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_resolved_levels (type_rl_list);
- print_resolved_types (type_rl_list);
- }
-#endif
-
/* 5. Resolving Neutral Types */
DBG ("Resolving neutral types\n");
{
@@ -815,31 +747,23 @@ fribidi_analyse_string (/* input */
For each neutral, resolve it. */
for (pp = type_rl_list->next; pp->next; pp = pp->next)
{
- FriBidiCharType prev_type, this_type, next_type;
-
- /* "European and arabic numbers are treated as though they were R"
- FRIBIDI_CHANGE_NUMBER_TO_RTL does this. */
- this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp));
- prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (PREV_TYPE_OR_SOR (pp));
- next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (NEXT_TYPE_OR_EOR (pp));
-
- if (FRIBIDI_IS_NEUTRAL (this_type))
- RL_TYPE (pp) = (prev_type == next_type) ?
- /* N1. */ prev_type :
- /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp);
+ FriBidiCharType prev_type, this_type, next_type;
+
+ /* "European and arabic numbers are treated as though they were R"
+ FRIBIDI_CHANGE_NUMBER_TO_RTL does this. */
+ this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp));
+ prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (PREV_TYPE_OR_SOR (pp));
+ next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (NEXT_TYPE_OR_EOR (pp));
+
+ if (FRIBIDI_IS_NEUTRAL (this_type))
+ RL_TYPE (pp) = (prev_type == next_type) ?
+ /* N1. */ prev_type :
+ /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp);
}
}
compact_list (type_rl_list);
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_resolved_levels (type_rl_list);
- print_resolved_types (type_rl_list);
- }
-#endif
-
/* 6. Resolving implicit levels */
DBG ("Resolving implicit levels\n");
{
@@ -847,36 +771,27 @@ fribidi_analyse_string (/* input */
for (pp = type_rl_list->next; pp->next; pp = pp->next)
{
- FriBidiCharType this_type;
- FriBidiLevel level;
-
- this_type = RL_TYPE (pp);
- level = RL_LEVEL (pp);
-
- /* I1. Even */
- /* I2. Odd */
- if (FRIBIDI_IS_NUMBER (this_type))
- RL_LEVEL (pp) = (level + 2) & ~1;
- else
- RL_LEVEL (pp) = (level ^ FRIBIDI_DIR_TO_LEVEL (this_type)) +
- (level & 1);
-
- if (RL_LEVEL (pp) > max_level)
- max_level = RL_LEVEL (pp);
+ FriBidiCharType this_type;
+ int level;
+
+ this_type = RL_TYPE (pp);
+ level = RL_LEVEL (pp);
+
+ /* I1. Even */
+ /* I2. Odd */
+ if (FRIBIDI_IS_NUMBER (this_type))
+ RL_LEVEL (pp) = (level + 2) & ~1;
+ else
+ RL_LEVEL (pp) = (level ^ FRIBIDI_DIR_TO_LEVEL (this_type)) +
+ (level & 1);
+
+ if (RL_LEVEL (pp) > max_level)
+ max_level = RL_LEVEL (pp);
}
}
compact_list (type_rl_list);
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_bidi_string (str);
- print_resolved_levels (type_rl_list);
- print_resolved_types (type_rl_list);
- }
-#endif
-
/* Reinsert the explicit codes & bn's that already removed, from the
explicits_list to type_rl_list. */
DBG ("Reinserting explicit codes\n");
@@ -889,65 +804,49 @@ fribidi_analyse_string (/* input */
p->level = base_level;
for (; p->next; p = p->next)
if (p->level < 0)
- p->level = p->prev->level;
+ p->level = p->prev->level;
}
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_types_re (type_rl_list);
- print_resolved_levels (type_rl_list);
- print_resolved_types (type_rl_list);
- }
-#endif
-
DBG ("Reset the embedding levels\n");
{
int j, k, state, pos;
TypeLink *p, *q, *list, *list_end;
+ const char *strp = str + bytelen;
+
/* L1. Reset the embedding levels of some chars. */
init_list (&list, &list_end);
q = list_end;
state = 1;
- pos = len - 1;
- for (j = len - 1; j >= -1; j--)
+ pos = *len - 1;
+ for (j = *len - 1; j >= -1; j--)
{
- /* if state is on at the very first of string, do this too. */
- if (j >= 0)
- k = _pango_fribidi_get_type (str[j]);
- else
- k = FRIBIDI_TYPE_ON;
- if (!state && FRIBIDI_IS_SEPARATOR (k))
- {
- state = 1;
- pos = j;
- }
- else if (state && !FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS (k))
- {
- state = 0;
- p = new_type_link ();
- p->prev = p->next = (TypeLink *) NULL;
- p->pos = j + 1;
- p->len = pos - j;
- p->type = base_dir;
- p->level = base_level;
- move_element_before (p, q);
- q = p;
- }
+ /* if state is on at the very first of string, do this too. */
+ if (j >= 0)
+ k = fribidi_get_type (g_utf8_get_char (strp = g_utf8_prev_char (strp)));
+ else
+ k = FRIBIDI_TYPE_ON;
+ if (!state && FRIBIDI_IS_SEPARATOR (k))
+ {
+ state = 1;
+ pos = j;
+ }
+ else if (state && !FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS (k))
+ {
+ state = 0;
+ p = new_type_link ();
+ p->prev = p->next = NULL;
+ p->pos = j + 1;
+ p->len = pos - j;
+ p->type = base_dir;
+ p->level = base_level;
+ move_element_before (p, q);
+ q = p;
+ }
}
override_list (type_rl_list, list);
}
-#ifdef DEBUG
- if (fribidi_debug)
- {
- print_types_re (type_rl_list);
- print_resolved_levels (type_rl_list);
- print_resolved_types (type_rl_list);
- }
-#endif
-
*ptype_rl_list = type_rl_list;
*pmax_level = max_level;
*pbase_dir = base_dir;
@@ -974,6 +873,7 @@ free_rl_list (TypeLink *type_rl_list)
return;
}
+#ifdef USE_SIMPLE_MALLOC
pp = type_rl_list;
while (pp)
{
@@ -983,6 +883,13 @@ free_rl_list (TypeLink *type_rl_list)
pp = pp->next;
free_type_link (p);
};
+#else
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ /* Nothing */ ;
+ pp->next = free_type_links;
+ free_type_links = type_rl_list;
+ type_rl_list = NULL;
+#endif
DBG ("Leaving free_rl_list()\n");
return;
@@ -992,73 +899,40 @@ free_rl_list (TypeLink *type_rl_list)
* fribidi_log2vis_get_embedding_levels() is used in order to just get
* the embedding levels.
*----------------------------------------------------------------------*/
-gboolean
-pango_log2vis_get_embedding_levels (/* input */
- gunichar *str,
- gint len,
- PangoDirection *pbase_dir,
- /* output */
- guint8 *embedding_level_list)
+FRIBIDI_API FriBidiLevel *
+fribidi_log2vis_get_embedding_levels_new_utf8 ( /* input */
+ const char *str,
+ int bytelen,
+ FriBidiCharType *pbase_dir)
{
TypeLink *type_rl_list, *pp;
- FriBidiLevel max_level;
- FriBidiCharType fribidi_base_dir;
+ FriBidiLevel max_level, *embedding_level_list;
+ FriBidiStrIndex len;
DBG ("Entering fribidi_log2vis_get_embedding_levels()\n");
- switch (*pbase_dir)
- {
- case PANGO_DIRECTION_LTR:
- case PANGO_DIRECTION_TTB_RTL:
- fribidi_base_dir = FRIBIDI_TYPE_L;
- break;
- case PANGO_DIRECTION_RTL:
- case PANGO_DIRECTION_TTB_LTR:
- fribidi_base_dir = FRIBIDI_TYPE_R;
- break;
- case PANGO_DIRECTION_WEAK_LTR:
- case PANGO_DIRECTION_NEUTRAL:
- fribidi_base_dir = FRIBIDI_TYPE_WL;
- break;
- case PANGO_DIRECTION_WEAK_RTL:
- fribidi_base_dir = FRIBIDI_TYPE_WR;
- break;
- }
-
- if (len == 0)
+ if (bytelen == 0)
{
DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
- return TRUE;
+ return NULL;
}
- fribidi_analyse_string (str, len, &fribidi_base_dir,
- /* output */
- &type_rl_list, &max_level);
+ fribidi_analyse_string_utf8 (str, bytelen, pbase_dir,
+ /* output */
+ &len, &type_rl_list, &max_level);
+ embedding_level_list = g_new (FriBidiLevel, len);
for (pp = type_rl_list->next; pp->next; pp = pp->next)
{
- gint i, pos = RL_POS (pp),
- len = RL_LEN (pp);
- gint level = RL_LEVEL (pp);
+ FriBidiStrIndex i, pos = RL_POS (pp), len = RL_LEN (pp);
+ FriBidiLevel level = RL_LEVEL (pp);
for (i = 0; i < len; i++)
- embedding_level_list[pos + i] = level;
+ embedding_level_list[pos + i] = level;
}
free_rl_list (type_rl_list);
DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
- return TRUE;
+ return embedding_level_list;
}
-PangoDirection
-pango_unichar_direction (gunichar ch)
-{
- FriBidiCharType fribidi_ch_type = _pango_fribidi_get_type (ch);
-
- if (!FRIBIDI_IS_LETTER (fribidi_ch_type))
- return PANGO_DIRECTION_NEUTRAL;
- else if (FRIBIDI_IS_RTL (fribidi_ch_type))
- return PANGO_DIRECTION_RTL;
- else
- return PANGO_DIRECTION_LTR;
-}