diff options
Diffstat (limited to 'pango/mini-fribidi/fribidi.c')
-rw-r--r-- | pango/mini-fribidi/fribidi.c | 902 |
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; -} |