diff options
author | Noah Levitt <nlevitt@columbia.edu> | 2003-11-20 05:34:45 +0000 |
---|---|---|
committer | Noah Levitt <nlevitt@src.gnome.org> | 2003-11-20 05:34:45 +0000 |
commit | f4186548325987e5213ae3d25764f1b9fbe97274 (patch) | |
tree | dc5d3726e96523d35c01ab5cc0b0d7c30fbff1ea /pango/mini-fribidi/fribidi.c | |
parent | 6c5c213849d9e1f97238870d0cc25ab4056ecf26 (diff) | |
download | pango-f4186548325987e5213ae3d25764f1b9fbe97274.tar.gz |
Update to latest fribidi. (#68435)
2003-11-20 Noah Levitt <nlevitt@columbia.edu>
* pango/pango-utils.c:
* pango/mini-fribidi/Makefile.am:
* pango/mini-fribidi/README:
* pango/mini-fribidi/fribidi.c:
* pango/mini-fribidi/fribidi.patch:
* pango/mini-fribidi/fribidi_char_type.c:
* pango/mini-fribidi/fribidi_tab_char_type_2.i:
* pango/mini-fribidi/fribidi_types.c:
* pango/mini-fribidi/fribidi_types.h:
* pango/mini-fribidi/fribidi_types.i: Update to latest fribidi.
(#68435)
Diffstat (limited to 'pango/mini-fribidi/fribidi.c')
-rw-r--r-- | pango/mini-fribidi/fribidi.c | 917 |
1 files changed, 422 insertions, 495 deletions
diff --git a/pango/mini-fribidi/fribidi.c b/pango/mini-fribidi/fribidi.c index 27b5d9f8..e298f404 100644 --- a/pango/mini-fribidi/fribidi.c +++ b/pango/mini-fribidi/fribidi.c @@ -1,6 +1,6 @@ /* FriBidi - Library of BiDi algorithm * Copyright (C) 1999,2000 Dov Grobgeld, and - * Copyright (C) 2001 Behdad Esfahbod. + * Copyright (C) 2001,2002 Behdad Esfahbod. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -13,7 +13,7 @@ * 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.LIB; if not, write to the + * 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 * @@ -26,29 +26,23 @@ #include "fribidi_types.h" #ifdef DEBUG -#include <stdio.h> -#endif - -#ifndef FRIBIDI_CHUNK_SIZE -#define FRIBIDI_CHUNK_SIZE 128 +static gboolean fribidi_debug = FALSE; #endif #ifdef DEBUG -#define DBG(s) if (fribidi_debug) { fprintf(stderr, s); } -#define DBG2(s, t) if (fribidi_debug) { fprintf(stderr, s, t); } +#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) #else #define DBG(s) #define DBG2(s, t) #endif #ifdef DEBUG -/* for easier test with the reference code only */ -#define MAX_LEVEL 15 -#else -/* default value */ -#define MAX_LEVEL 61 +char fribidi_char_from_type (FriBidiCharType c); #endif +#define UNI_MAX_BIDI_LEVEL 61 + /*====================================================================== * Typedef for the run-length list. *----------------------------------------------------------------------*/ @@ -60,9 +54,8 @@ struct _TypeLink TypeLink *next; FriBidiCharType type; - gint pos; - gint len; - gint level; + FriBidiStrIndex pos, len; + FriBidiLevel level; }; #define FRIBIDI_LEVEL_START -1 @@ -71,43 +64,17 @@ struct _TypeLink typedef struct { - FriBidiCharType override; /* only L, R and N are valid */ - gint level; + FriBidiCharType override; /* only L, R and N are valid */ + FriBidiLevel level; } LevelInfo; -#ifdef DEBUG -static gboolean fribidi_debug = FALSE; -#endif - -#ifndef USE_SIMPLE_MALLOC -static TypeLink *free_type_links = NULL; -#endif - static TypeLink * -new_type_link (void) +new_type_link () { TypeLink *link; -#ifdef USE_SIMPLE_MALLOC - link = g_malloc (sizeof (TypeLink)); -#else /* !USE_SIMPLE_MALLOC */ - if (free_type_links) - { - link = free_type_links; - free_type_links = free_type_links->next; - } - else - { - static GMemChunk *mem_chunk = NULL; - - if (!mem_chunk) - mem_chunk = - g_mem_chunk_create (TypeLink, FRIBIDI_CHUNK_SIZE, G_ALLOC_ONLY); - - link = g_chunk_new (TypeLink, mem_chunk); - } -#endif /* !USE_SIMPLE_MALLOC */ + link = (TypeLink *) g_malloc (sizeof (TypeLink)); link->len = 0; link->pos = 0; @@ -120,65 +87,47 @@ new_type_link (void) static void free_type_link (TypeLink *link) { -#ifdef USE_SIMPLE_MALLOC g_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) + static TypeLink * -run_length_encode_types (FriBidiCharType *char_type, gint type_len) +run_length_encode_types (FriBidiCharType *char_type, + FriBidiStrIndex type_len) { TypeLink *list, *last, *link; - TypeLink current; - gint i; + FriBidiStrIndex i; /* Add the starting link */ list = new_type_link (); list->type = FRIBIDI_TYPE_SOT; list->level = FRIBIDI_LEVEL_START; - list->len = 0; - list->pos = 0; last = list; - /* Sweep over the string_types */ - current.type = FRIBIDI_LEVEL_START; - current.len = 0; - current.pos = -1; - for (i = 0; i <= type_len; i++) - { - if (i == type_len || char_type[i] != current.type) - { - if (current.pos >= 0) - { - link = new_type_link (); - link->type = current.type; - link->pos = current.pos; - link->len = current.len; - last->next = link; - link->prev = last; - last = last->next; - } - if (i == type_len) - break; - current.len = 0; - current.pos = i; - } - current.type = char_type[i]; - current.len++; - } + /* Sweep over the string_type s */ + for (i = 0; i < type_len; i++) + if (char_type[i] != last->type) + { + link = new_type_link (); + link->type = char_type[i]; + link->pos = i; + FRIBIDI_ADD_TYPE_LINK (last, link); + } /* Add the ending link */ link = new_type_link (); link->type = FRIBIDI_TYPE_EOT; link->level = FRIBIDI_LEVEL_END; - link->len = 0; link->pos = type_len; - last->next = link; - link->prev = last; + FRIBIDI_ADD_TYPE_LINK (last, link); return list; } @@ -188,7 +137,8 @@ run_length_encode_types (FriBidiCharType *char_type, gint type_len) the override_list. */ static void -init_list (TypeLink **start, TypeLink **end) +init_list (TypeLink **start, + TypeLink **end) { TypeLink *list; TypeLink *link; @@ -219,7 +169,8 @@ init_list (TypeLink **start, TypeLink **end) the list that p is currently in, if any. */ static void -move_element_before (TypeLink *p, TypeLink *list) +move_element_before (TypeLink *p, + TypeLink *list) { if (p->prev) { @@ -247,129 +198,124 @@ move_element_before (TypeLink *p, TypeLink *list) TBD: use some explanatory names instead of p, q, ... */ static void -override_list (TypeLink *base, TypeLink *over) +override_list (TypeLink *base, + TypeLink *over) { TypeLink *p = base, *q, *r, *s, *t; - gint pos = 0, pos2; + FriBidiStrIndex pos = 0, pos2; - if (!base) - base = over; - else if (over) + if (!over) + return; + q = over; + while (q) { - q = over; - while (q) - { - if (!q->len || q->pos < pos) - { - t = q; - q = q->next; - free_type_link (t); - continue; - } - pos = q->pos; - while (p->next && p->next->pos <= pos) - 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; - /* 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; - } - 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); - } - } - /* 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. - */ - t = q; - q = q->next; - p->next = t; - t->prev = p; - t->next = r; - r->prev = t; - } + if (!q->len || q->pos < pos) + { + t = q; + q = q->next; + free_type_link (t); + continue; + } + pos = q->pos; + while (p->next && p->next->pos <= pos) + 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; + /* 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; + } + 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); + } + } + /* 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. + */ + t = q; + q = q->next; + p->next = t; + t->prev = p; + t->next = r; + r->prev = t; } } /* Some convenience macros */ -#define RL_TYPE(list) (list)->type -#define RL_LEN(list) (list)->len -#define RL_POS(list) (list)->pos -#define RL_LEVEL(list) (list)->level +#define RL_TYPE(list) ((list)->type) +#define RL_LEN(list) ((list)->len) +#define RL_POS(list) ((list)->pos) +#define RL_LEVEL(list) ((list)->level) + +static TypeLink * +merge_with_prev (TypeLink *second) +{ + TypeLink *first = second->prev; + first->next = second->next; + first->next->prev = first; + RL_LEN (first) += RL_LEN (second); + free_type_link (second); + return first; +} static void compact_list (TypeLink *list) { if (list->next) - { - list = list->next; - while (list) - { - if (RL_TYPE (list->prev) == RL_TYPE (list) - && RL_LEVEL (list->prev) == RL_LEVEL (list)) - { - TypeLink *next = list->next; - list->prev->next = list->next; - list->next->prev = list->prev; - RL_LEN (list->prev) += RL_LEN (list); - free_type_link (list); - list = next; - } - else - list = 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); } static void @@ -377,48 +323,38 @@ compact_neutrals (TypeLink *list) { if (list->next) { - list = list->next; - while (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)))))) - { - TypeLink *next = list->next; - list->prev->next = list->next; - list->next->prev = list->prev; - RL_LEN (list->prev) += RL_LEN (list); - free_type_link (list); - list = next; - } - else - list = 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); + } } } -/*======================================================= +/*========================================================================= * define macros for push and pop the status in to / out of the stack - *-------------------------------------------------------*/ + *-------------------------------------------------------------------------*/ /* There's some little points in pushing and poping into the status stack: - 1. when the embedding level is not valid (more than MAX_LEVEL=61), + 1. when the embedding level is not valid (more than UNI_MAX_BIDI_LEVEL=61), you must reject it, and not to push into the stack, but when you see a PDF, you must find the matching code, and if it was pushed in the stack, pop it, it means you must pop if and only if you have pushed the matching code, the over_pushed var counts the number of rejected codes yet. 2. there's a more confusing point too, when the embedding level is exactly - MAX_LEVEL-1=60, an LRO or LRE must be rejected because the new level would - be MAX_LEVEL+1=62, that is invalid, but an RLO or RLE must be accepted - because the new level is MAX_LEVEL=61, that is valid, so the rejected - codes may be not continuous in the logical order, in fact there is at - most two continuous intervals of codes, with a RLO or RLE between them. - to support the case, the first_interval var counts the number of rejected - codes in the first interval, when it is 0, means that there is only one - interval yet. + UNI_MAX_BIDI_LEVEL-1=60, an LRO or LRE must be rejected because the new + level would be UNI_MAX_BIDI_LEVEL+1=62, that is invalid, but an RLO or RLE + must be accepted because the new level is UNI_MAX_BIDI_LEVEL=61, that is + valid, so the rejected codes may be not continuous in the logical order, + in fact there is at most two continuous intervals of codes, with a RLO or + RLE between them. To support this case, the first_interval var counts the + number of rejected codes in the first interval, when it is 0, means that + there is only one interval yet. */ /* a. If this new level would be valid, then this embedding code is valid. @@ -429,10 +365,10 @@ compact_neutrals (TypeLink *list) change the current level or override status. */ #define PUSH_STATUS \ - { \ - if (new_level <= MAX_LEVEL) \ + do { \ + if (new_level <= UNI_MAX_BIDI_LEVEL) \ { \ - if (level == MAX_LEVEL - 1) \ + if (level == UNI_MAX_BIDI_LEVEL - 1) \ first_interval = over_pushed; \ status_stack[stack_size].level = level; \ status_stack[stack_size].override = override; \ @@ -440,14 +376,14 @@ 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 (pushed) embedding level and directional override. */ #define POP_STATUS \ - { \ + do { \ if (over_pushed || stack_size) \ { \ if (over_pushed > first_interval) \ @@ -461,7 +397,7 @@ compact_neutrals (TypeLink *list) override = status_stack[stack_size].override; \ } \ } \ - } + } while (0) /*========================================================================== * There was no support for sor and eor in the absence of Explicit Embedding @@ -471,7 +407,8 @@ compact_neutrals (TypeLink *list) /* Return the type of previous char or the sor, if already at the start of a run level. */ #define PREV_TYPE_OR_SOR(pp) \ - (RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \ + ( \ + RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \ RL_TYPE(pp->prev) : \ FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \ ) @@ -479,7 +416,8 @@ compact_neutrals (TypeLink *list) /* Return the type of next char or the eor, if already at the end of a run level. */ #define NEXT_TYPE_OR_EOR(pp) \ - (!pp->next ? \ + ( \ + !pp->next ? \ FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(pp)) : \ (RL_LEVEL(pp->next) == RL_LEVEL(pp) ? \ RL_TYPE(pp->next) : \ @@ -487,7 +425,6 @@ compact_neutrals (TypeLink *list) ) \ ) - /* Return the embedding direction of a link. */ #define FRIBIDI_EMBEDDING_DIRECTION(list) \ FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list)) @@ -498,7 +435,7 @@ compact_neutrals (TypeLink *list) * levels. *----------------------------------------------------------------------*/ -static gchar char_from_level_array[] = { +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 @@ -530,7 +467,7 @@ print_resolved_levels (TypeLink *pp) fprintf (stderr, " Res. levels: "); while (pp) { - gint i; + FriBidiStrIndex i; for (i = 0; i < RL_LEN (pp); i++) fprintf (stderr, "%c", fribidi_char_from_level (RL_LEVEL (pp))); pp = pp->next; @@ -544,7 +481,7 @@ print_resolved_types (TypeLink *pp) fprintf (stderr, " Res. types : "); while (pp) { - gint i; + FriBidiStrIndex i; for (i = 0; i < RL_LEN (pp); i++) fprintf (stderr, "%c", fribidi_char_from_type (pp->type)); pp = pp->next; @@ -557,7 +494,7 @@ print_resolved_types (TypeLink *pp) static void print_bidi_string (FriBidiChar *str) { - gint i; + FriBidiStrIndex i; fprintf (stderr, " Org. types : "); for (i = 0; str[i]; i++) fprintf (stderr, "%c", @@ -565,20 +502,21 @@ print_bidi_string (FriBidiChar *str) fprintf (stderr, "\n"); } #endif - /*====================================================================== * This function should follow the Unicode specification closely! *----------------------------------------------------------------------*/ static void -fribidi_analyse_string ( /* input */ - FriBidiChar *str, - gint len, FriBidiCharType *pbase_dir, - /* output */ - TypeLink **ptype_rl_list, gint *pmax_level) +fribidi_analyse_string (/* input */ + const FriBidiChar *str, + FriBidiStrIndex len, + FriBidiCharType *pbase_dir, + /* output */ + TypeLink **ptype_rl_list, + FriBidiLevel *pmax_level) { - gint base_level, base_dir; - gint max_level; - gint i; + 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"); @@ -586,21 +524,14 @@ fribidi_analyse_string ( /* input */ /* Determinate character types */ DBG (" Determine character types\n"); { - FriBidiCharType* char_type; - - if (len < 512) - char_type = g_alloca (len*sizeof(FriBidiCharType)); - else - char_type = g_malloc (len*sizeof(FriBidiCharType)); - + 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); - - if (len >= 512) - g_free (char_type); + g_free (char_type); } DBG (" Determine character types, Done\n"); @@ -614,20 +545,17 @@ fribidi_analyse_string ( /* input */ base direction */ else { - base_level = 0; /* Default */ - 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 no strong base_dir was found, resort to the weak direction that was passed on input. */ - if (FRIBIDI_IS_NEUTRAL (base_dir)) - base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir); + 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; + } } base_dir = FRIBIDI_LEVEL_TO_DIR (base_level); DBG2 (" Base level : %c\n", fribidi_char_from_level (base_level)); @@ -648,8 +576,10 @@ fribidi_analyse_string ( /* input */ embedding level. Set the directional override status to neutral. Process each character iteratively, applying rules X2 through X9. Only embedding levels from 0 to 61 are valid in this phase. */ - gint level, override, new_level, new_override, i; - gint stack_size, over_pushed, first_interval; + FriBidiLevel level, new_level; + FriBidiCharType override, new_override; + FriBidiStrIndex i; + int stack_size, over_pushed, first_interval; LevelInfo *status_stack; TypeLink temp_link; @@ -659,62 +589,63 @@ fribidi_analyse_string ( /* input */ stack_size = 0; over_pushed = 0; first_interval = 0; - status_stack = g_new(LevelInfo, MAX_LEVEL + 2); + status_stack = + (LevelInfo *) g_malloc (sizeof (LevelInfo) * (UNI_MAX_BIDI_LEVEL + 2)); for (pp = type_rl_list->next; pp->next; pp = pp->next) { - gint 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! */ @@ -723,7 +654,7 @@ fribidi_analyse_string ( /* input */ stack_size = 0; over_pushed = 0; - g_free(status_stack); + g_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 @@ -750,41 +681,49 @@ fribidi_analyse_string ( /* input */ /* 4. Resolving weak types */ DBG ("Resolving weak types\n"); { - gint last_strong, prev_type_org, w4; + FriBidiCharType last_strong, prev_type_org; + gboolean w4; last_strong = base_dir; for (pp = type_rl_list->next; pp->next; pp = pp->next) { - gint 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. */ - if (this_type == FRIBIDI_TYPE_NSM) - { - RL_TYPE (pp) = prev_type; - continue; - } - - /* 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; + } } @@ -792,7 +731,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 = 1; + w4 = 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. */ @@ -800,62 +739,62 @@ fribidi_analyse_string ( /* input */ for (pp = type_rl_list->next; pp->next; pp = pp->next) { - gint 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 = 1; - 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 = 1; - - /* 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 = 0; - 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 = 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); } } @@ -876,18 +815,18 @@ fribidi_analyse_string ( /* input */ For each neutral, resolve it. */ for (pp = type_rl_list->next; pp->next; pp = pp->next) { - gint 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); } } @@ -908,21 +847,22 @@ fribidi_analyse_string ( /* input */ for (pp = type_rl_list->next; pp->next; pp = pp->next) { - gint this_type, level; - - this_type = RL_TYPE (pp); - level = RL_LEVEL (pp); - - /* I1. Even */ - /* I2. Odd */ - if (FRIBIDI_IS_NUMBER (this_type)) - RL_LEVEL (pp) = (RL_LEVEL (pp) + 2) & ~1; - else - RL_LEVEL (pp) = (RL_LEVEL (pp) ^ FRIBIDI_DIR_TO_LEVEL (this_type)) + - (RL_LEVEL (pp) & 1); - - if (RL_LEVEL (pp) > max_level) - max_level = RL_LEVEL (pp); + 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); } } @@ -949,7 +889,7 @@ 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 @@ -963,7 +903,7 @@ fribidi_analyse_string ( /* input */ DBG ("Reset the embedding levels\n"); { - gint j, k, state, pos; + int j, k, state, pos; TypeLink *p, *q, *list, *list_end; /* L1. Reset the embedding levels of some chars. */ @@ -973,28 +913,28 @@ fribidi_analyse_string ( /* input */ 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 = 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 = _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; + } } override_list (type_rl_list, list); } @@ -1034,7 +974,6 @@ free_rl_list (TypeLink *type_rl_list) return; } -#ifdef USE_SIMPLE_MALLOC pp = type_rl_list; while (pp) { @@ -1044,40 +983,30 @@ 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; } /*====================================================================== - * Here starts the exposed front end functions. - *----------------------------------------------------------------------*/ - -/*====================================================================== * fribidi_log2vis_get_embedding_levels() is used in order to just get * the embedding levels. *----------------------------------------------------------------------*/ gboolean -pango_log2vis_get_embedding_levels ( /* input */ - gunichar *str, - int len, PangoDirection *pbase_dir, - /* output */ - guint8 *embedding_level_list) +pango_log2vis_get_embedding_levels (/* input */ + gunichar *str, + gint len, + PangoDirection *pbase_dir, + /* output */ + guint8 *embedding_level_list) { TypeLink *type_rl_list, *pp; - gint max_level; + FriBidiLevel max_level; FriBidiCharType fribidi_base_dir; DBG ("Entering fribidi_log2vis_get_embedding_levels()\n"); - fribidi_base_dir = (*pbase_dir == PANGO_DIRECTION_LTR) ? FRIBIDI_TYPE_L : FRIBIDI_TYPE_R; + fribidi_base_dir = (*pbase_dir == PANGO_DIRECTION_LTR) ? FRIBIDI_TYPE_LTR : FRIBIDI_TYPE_RTL; if (len == 0) { @@ -1086,23 +1015,21 @@ pango_log2vis_get_embedding_levels ( /* input */ } fribidi_analyse_string (str, len, &fribidi_base_dir, - /* output */ - &type_rl_list, &max_level); + /* output */ + &type_rl_list, &max_level); for (pp = type_rl_list->next; pp->next; pp = pp->next) { - gint i; - gint pos = RL_POS (pp); - gint len = RL_LEN (pp); + gint i, pos = RL_POS (pp), + len = RL_LEN (pp); gint 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); - - *pbase_dir = (fribidi_base_dir == FRIBIDI_TYPE_L) ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL; DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n"); return TRUE; } + |