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.c967
1 files changed, 0 insertions, 967 deletions
diff --git a/pango/mini-fribidi/fribidi.c b/pango/mini-fribidi/fribidi.c
deleted file mode 100644
index cef814ca..00000000
--- a/pango/mini-fribidi/fribidi.c
+++ /dev/null
@@ -1,967 +0,0 @@
-/* FriBidi - Library of BiDi algorithm
- * Copyright (C) 1999,2000 Dov Grobgeld, and
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * 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; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA
- *
- * For licensing issues, contact <dov@imagic.weizmann.ac.il> and
- * <fwpg@sharif.edu>.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-
-#include "fribidi.h"
-
-/* Redefine FRIBIDI_CHUNK_SIZE in config.h to override this. */
-#ifndef FRIBIDI_CHUNK_SIZE
-#ifdef MEM_OPTIMIZED
-#define FRIBIDI_CHUNK_SIZE 16
-#else
-#define FRIBIDI_CHUNK_SIZE 128
-#endif
-#endif
-
-#define DBG(s)
-#define DBG2(s, t)
-
-/*======================================================================
- * Typedef for the run-length list.
- *----------------------------------------------------------------------*/
-typedef struct _TypeLink TypeLink;
-
-struct _TypeLink
-{
- TypeLink *prev;
- TypeLink *next;
-
- FriBidiStrIndex pos, len;
- FriBidiCharType type;
- FriBidiLevel level;
-};
-
-#define FRIBIDI_LEVEL_START -1
-#define FRIBIDI_LEVEL_END -1
-#define FRIBIDI_LEVEL_REMOVED -2
-
-typedef struct
-{
- FriBidiCharType override; /* only L, R and N are valid */
- FriBidiLevel level;
-}
-LevelInfo;
-
-static TypeLink *
-new_type_link (void)
-{
- TypeLink *link;
-
- link = g_slice_new0 (TypeLink);
-
- return link;
-}
-
-static void
-free_type_link (TypeLink *link)
-{
- g_slice_free (TypeLink, link);
-}
-
-#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_utf8 (const char *s,
- int bytelen,
- FriBidiStrIndex *len,
- FriBidiCharType *pored_types,
- FriBidiCharType *panded_strongs)
-{
- TypeLink *list, *last, *link;
- FriBidiCharType char_type;
- FriBidiCharType ored_types = 0;
- FriBidiCharType anded_strongs = FRIBIDI_TYPE_RLE;
- FriBidiStrIndex i;
- const char *p;
-
- /* Add the starting link */
- list = new_type_link ();
- list->type = FRIBIDI_TYPE_SOT;
- list->level = FRIBIDI_LEVEL_START;
- last = list;
-
- /* 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));
- ored_types |= char_type;
- if (FRIBIDI_IS_STRONG (char_type))
- anded_strongs &= char_type;
- if (char_type != last->type)
- {
- 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 = i;
- FRIBIDI_ADD_TYPE_LINK (last, link);
-
- if (len)
- *len = i;
-
- if (pored_types)
- *pored_types = ored_types;
- if (panded_strongs)
- *panded_strongs = anded_strongs;
-
- return list;
-}
-
-/* explicits_list is a list like type_rl_list, that holds the explicit
- codes that are removed from rl_list, to reinsert them later by calling
- the override_list.
-*/
-static void
-init_list (TypeLink **start,
- TypeLink **end)
-{
- TypeLink *list;
- TypeLink *link;
-
- /* Add the starting link */
- list = new_type_link ();
- list->type = FRIBIDI_TYPE_SOT;
- list->level = FRIBIDI_LEVEL_START;
- list->len = 0;
- list->pos = 0;
-
- /* Add the ending link */
- link = new_type_link ();
- link->type = FRIBIDI_TYPE_EOT;
- link->level = FRIBIDI_LEVEL_END;
- link->len = 0;
- link->pos = 0;
- list->next = link;
- link->prev = list;
-
- *start = list;
- *end = link;
-}
-
-/* move an element before another element in a list, the list must have a
- previous element, used to update explicits_list.
- assuming that p have both prev and next or none of them, also update
- the list that p is currently in, if any.
-*/
-static void
-move_element_before (TypeLink *p,
- TypeLink *list)
-{
- if (p->prev)
- {
- p->prev->next = p->next;
- p->next->prev = p->prev;
- }
- p->prev = list->prev;
- list->prev->next = p;
- p->next = list;
- list->prev = p;
-}
-
-/* override the rl_list 'base', with the elements in the list 'over', to
- reinsert the previously-removed explicit codes (at X9) from
- 'explicits_list' back into 'type_rl_list'. This is used at the end of I2
- to restore the explicit marks, and also to reset the character types of
- characters at L1.
-
- it is assumed that the 'pos' of the first element in 'base' list is not
- more than the 'pos' of the first element of the 'over' list, and the
- 'pos' of the last element of the 'base' list is not less than the 'pos'
- of the last element of the 'over' list. these two conditions are always
- satisfied for the two usages mentioned above.
-
- TBD: use some explanatory names instead of p, q, ...
-*/
-static void
-override_list (TypeLink *base,
- TypeLink *over)
-{
- TypeLink *p = base, *q, *r, *s, *t;
- FriBidiStrIndex pos = 0, pos2;
-
- if (!over)
- return;
- 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;
- }
-}
-
-/* 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)
-
-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)
- 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
-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);
- }
- }
-}
-
-/*======================================================================
- * Frees up the rl_list, must be called after each call to
- * fribidi_analyse_string(), after the list is not needed anymore.
- *----------------------------------------------------------------------*/
-static void
-free_rl_list (TypeLink *type_rl_list)
-{
- DBG ("Entering free_rl_list()\n");
-
- if (!type_rl_list)
- {
- DBG ("Leaving free_rl_list()\n");
- return;
- }
-
- g_slice_free_chain (TypeLink, type_rl_list, next);
-
- DBG ("Leaving free_rl_list()\n");
- return;
-}
-
-/*=========================================================================
- * 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 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
- 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.
- Remember (push) the current embedding level and override status.
- Reset current level to this new level, and reset the override status to
- new_override.
- b. If the new level would not be valid, then this code is invalid. Don't
- change the current level or override status.
-*/
-#define PUSH_STATUS \
- do { \
- if (new_level <= UNI_MAX_BIDI_LEVEL) \
- { \
- if (level == UNI_MAX_BIDI_LEVEL - 1) \
- first_interval = over_pushed; \
- status_stack[stack_size].level = level; \
- status_stack[stack_size].override = override; \
- stack_size++; \
- level = new_level; \
- override = new_override; \
- } else \
- 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) \
- over_pushed--; \
- else \
- { \
- if (over_pushed == first_interval) \
- first_interval = 0; \
- stack_size--; \
- level = status_stack[stack_size].level; \
- override = status_stack[stack_size].override; \
- } \
- } \
- } while (0)
-
-/*==========================================================================
- * There was no support for sor and eor in the absence of Explicit Embedding
- * Levels, so define macros, to support them, with as less change as needed.
- *--------------------------------------------------------------------------*/
-
-/* 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_TYPE(pp->prev) : \
- FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \
- )
-
-/* 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 ? \
- FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(pp)) : \
- (RL_LEVEL(pp->next) == RL_LEVEL(pp) ? \
- RL_TYPE(pp->next) : \
- FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->next), RL_LEVEL(pp))) \
- ) \
- )
-
-
-/* Return the embedding direction of a link. */
-#define FRIBIDI_EMBEDDING_DIRECTION(list) \
- FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list))
-
-
-/*======================================================================
- * This function should follow the Unicode specification closely!
- *----------------------------------------------------------------------*/
-static fribidi_boolean
-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;
- TypeLink *type_rl_list, *explicits_list, *explicits_list_end, *pp;
-
- DBG ("Entering fribidi_analyse_string()\n");
-
- /* Determinate character types */
- DBG (" Determine character types\n");
- {
- FriBidiCharType ored_types;
- FriBidiCharType anded_strongs;
-
- /* Run length encode the character types */
- type_rl_list = run_length_encode_types_utf8 (str, bytelen, len,
- &ored_types, &anded_strongs);
-
- /* The case that all resolved levels will be ltr.
- * First, all strongs should be ltr, there should be no Arabic numbers
- * (or letters for that matter), and one of the following:
- *
- * o *pbase_dir doesn't have an rtl taste.
- * o there are letters, and *pbase_dir is weak.
- *
- * For details see:
- * https://bugzilla.gnome.org/show_bug.cgi?id=590183
- */
- if (!FRIBIDI_IS_RTL (ored_types) && !FRIBIDI_IS_ARABIC (ored_types) &&
- (!FRIBIDI_IS_RTL (*pbase_dir) ||
- (FRIBIDI_IS_WEAK (*pbase_dir) && FRIBIDI_IS_LETTER (ored_types))
- ))
- {
- /* all ltr */
- free_rl_list (type_rl_list);
-
- *ptype_rl_list = NULL;
- *pmax_level = 0;
- *pbase_dir = FRIBIDI_TYPE_LTR;
-
- return 0;
- }
- /* The case that all resolved levels will be rtl is much more complex.
- * First, there should be no numbers, all strongs be rtl, and one of
- * the following:
- *
- * o *pbase_dir has an rtl taste (may be weak).
- * o there are letters, and *pbase_dir is weak.
- */
- else if (!FRIBIDI_IS_NUMBER (ored_types) && FRIBIDI_IS_RTL (anded_strongs) &&
- (FRIBIDI_IS_RTL (*pbase_dir) ||
- (FRIBIDI_IS_WEAK (*pbase_dir) && FRIBIDI_IS_LETTER (ored_types))
- ))
- {
- free_rl_list (type_rl_list);
-
- *ptype_rl_list = NULL;
- *pmax_level = 1;
- *pbase_dir = FRIBIDI_TYPE_RTL;
-
- return 0;
- }
- }
- DBG (" Determine character types, Done\n");
-
- init_list (&explicits_list, &explicits_list_end);
-
- /* Find base level */
- DBG (" Finding the base level\n");
- if (FRIBIDI_IS_STRONG (*pbase_dir))
- base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
- /* P2. P3. Search for first strong character and use its direction as
- base direction */
- else
- {
- /* If no strong base_dir was found, resort to the weak direction
- that was passed on input. */
- base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
- 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));
- DBG2 (" Base dir : %c\n", fribidi_char_from_type (base_dir));
- DBG (" Finding the base level, Done\n");
-
- /* Explicit Levels and Directions */
- DBG ("Explicit Levels and Directions\n");
- {
- /* X1. Begin by setting the current embedding level to the paragraph
- 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. */
- FriBidiLevel level, new_level;
- FriBidiCharType override, new_override;
- FriBidiStrIndex i;
- int stack_size, over_pushed, first_interval;
- LevelInfo *status_stack;
- TypeLink temp_link;
-
- level = base_level;
- override = FRIBIDI_TYPE_ON;
- /* stack */
- stack_size = 0;
- over_pushed = 0;
- first_interval = 0;
- status_stack =
- (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 if (this_type == FRIBIDI_TYPE_BS)
- {
- /* X8. All explicit directional embeddings and overrides are
- completely terminated at the end of each paragraph. Paragraph
- separators are not included in the embedding. */
- break;
- }
- 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;
- }
- }
-
- /* Implementing X8. It has no effect on a single paragraph! */
- level = base_level;
- override = FRIBIDI_TYPE_ON;
- stack_size = 0;
- over_pushed = 0;
-
- 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
- end-of-level-run (eor) type, either L or R. This depends on the
- higher of the two levels on either side of the boundary (at the start
- or end of the paragraph, the level of the 'other' run is the base
- embedding level). If the higher level is odd, the type is R, otherwise
- it is L. */
- /* Resolving Implicit Levels can be done out of X10 loop, so only change
- of Resolving Weak Types and Resolving Neutral Types is needed. */
-
- compact_list (type_rl_list);
-
- /* 4. Resolving weak types */
- DBG ("Resolving weak types\n");
- {
- FriBidiCharType last_strong, prev_type_org;
- 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;
- if (prev_type == next_type && RL_LEVEL (pp) == RL_LEVEL (pp->next))
- {
- pp = merge_with_prev (pp->next);
- }
- 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;
- }
- }
-
-
- last_strong = base_dir;
- /* 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 = 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. */
- prev_type_org = FRIBIDI_TYPE_ON;
-
- 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 = 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);
-
- /* 5. Resolving Neutral Types */
- DBG ("Resolving neutral types\n");
- {
- /* N1. and N2.
- 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);
- }
- }
-
- compact_list (type_rl_list);
-
- /* 6. Resolving implicit levels */
- DBG ("Resolving implicit levels\n");
- {
- max_level = base_level;
-
- for (pp = type_rl_list->next; pp->next; pp = pp->next)
- {
- 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);
-
-/* Reinsert the explicit codes & bn's that already removed, from the
- explicits_list to type_rl_list. */
- DBG ("Reinserting explicit codes\n");
- {
- TypeLink *p;
-
- override_list (type_rl_list, explicits_list);
- p = type_rl_list->next;
- if (p->level < 0)
- p->level = base_level;
- for (; p->next; p = p->next)
- if (p->level < 0)
- p->level = p->prev->level;
- }
-
- 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--)
- {
- /* 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);
- }
-
- *ptype_rl_list = type_rl_list;
- *pmax_level = max_level;
- *pbase_dir = base_dir;
-
- DBG ("Leaving fribidi_analyse_string()\n");
- return 1;
-}
-
-/*======================================================================
- * fribidi_log2vis_get_embedding_levels() is used in order to just get
- * the embedding levels.
- *----------------------------------------------------------------------*/
-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, *embedding_level_list;
- FriBidiStrIndex len;
-
- DBG ("Entering fribidi_log2vis_get_embedding_levels()\n");
-
- if (bytelen == 0)
- {
- DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
- return NULL;
- }
-
- if (!fribidi_analyse_string_utf8 (str, bytelen, pbase_dir,
- /* output */
- &len, &type_rl_list, &max_level))
- {
- /* unidirectional. return all-zero or all-one embedding levels */
-
- if (max_level)
- {
- embedding_level_list = g_new (FriBidiLevel, len);
- /* assumes sizeof(FriBidiLevel) == 1, which is true! */
- memset (embedding_level_list, max_level, len);
- return embedding_level_list;
- }
- else
- {
- return g_new0 (FriBidiLevel, len);
- }
- }
-
- embedding_level_list = g_new (FriBidiLevel, len);
- for (pp = type_rl_list->next; pp->next; pp = pp->next)
- {
- 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;
- }
-
- free_rl_list (type_rl_list);
-
- DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
- return embedding_level_list;
-}
-