Git init
[external/pango1.0.git] / pango / pango-bidi-type.c
1 /* Pango
2  * pango-bidi-type.c: Bidirectional Character Types
3  *
4  * Copyright (C) 2008 Jürg Billeter <j@bitron.ch>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include "pango-bidi-type.h"
27 #include "pango-utils.h"
28
29 #include "mini-fribidi/fribidi.h"
30
31
32
33 /**
34  * pango_bidi_type_for_unichar
35  * @ch: a Unicode character
36  *
37  * Determines the normative bidirectional character type of a
38  * character, as specified in the Unicode Character Database.
39  *
40  * A simplified version of this function is available as
41  * pango_unichar_get_direction().
42  *
43  * Return value: the bidirectional character type, as used in the
44  * Unicode bidirectional algorithm.
45  *
46  * Since: 1.22
47  */
48 PangoBidiType
49 pango_bidi_type_for_unichar (gunichar ch)
50 {
51   FriBidiCharType fribidi_ch_type = fribidi_get_type (ch);
52
53   switch (fribidi_ch_type)
54     {
55     case FRIBIDI_TYPE_LTR:  return PANGO_BIDI_TYPE_L;
56     case FRIBIDI_TYPE_LRE:  return PANGO_BIDI_TYPE_LRE;
57     case FRIBIDI_TYPE_LRO:  return PANGO_BIDI_TYPE_LRO;
58     case FRIBIDI_TYPE_RTL:  return PANGO_BIDI_TYPE_R;
59     case FRIBIDI_TYPE_AL:   return PANGO_BIDI_TYPE_AL;
60     case FRIBIDI_TYPE_RLE:  return PANGO_BIDI_TYPE_RLE;
61     case FRIBIDI_TYPE_RLO:  return PANGO_BIDI_TYPE_RLO;
62     case FRIBIDI_TYPE_PDF:  return PANGO_BIDI_TYPE_PDF;
63     case FRIBIDI_TYPE_EN:   return PANGO_BIDI_TYPE_EN;
64     case FRIBIDI_TYPE_ES:   return PANGO_BIDI_TYPE_ES;
65     case FRIBIDI_TYPE_ET:   return PANGO_BIDI_TYPE_ET;
66     case FRIBIDI_TYPE_AN:   return PANGO_BIDI_TYPE_AN;
67     case FRIBIDI_TYPE_CS:   return PANGO_BIDI_TYPE_CS;
68     case FRIBIDI_TYPE_NSM:  return PANGO_BIDI_TYPE_NSM;
69     case FRIBIDI_TYPE_BN:   return PANGO_BIDI_TYPE_BN;
70     case FRIBIDI_TYPE_BS:   return PANGO_BIDI_TYPE_B;
71     case FRIBIDI_TYPE_SS:   return PANGO_BIDI_TYPE_S;
72     case FRIBIDI_TYPE_WS:   return PANGO_BIDI_TYPE_WS;
73     case FRIBIDI_TYPE_ON:   return PANGO_BIDI_TYPE_ON;
74     default:
75       g_assert_not_reached ();
76       return PANGO_BIDI_TYPE_ON;
77     }
78 }
79
80 /* Some bidi-related functions */
81
82 /**
83  * pango_log2vis_get_embedding_levels:
84  * @text:      the text to itemize.
85  * @length:    the number of bytes (not characters) to process, or -1
86  *             if @text is nul-terminated and the length should be calculated.
87  * @pbase_dir: input base direction, and output resolved direction.
88  *
89  * This will return the bidirectional embedding levels of the input paragraph
90  * as defined by the Unicode Bidirectional Algorithm available at:
91  *
92  *   http://www.unicode.org/reports/tr9/
93  *
94  * If the input base direction is a weak direction, the direction of the
95  * characters in the text will determine the final resolved direction.
96  *
97  * Return value: a newly allocated array of embedding levels, one item per
98  *               character (not byte), that should be freed using g_free.
99  *
100  * Since: 1.4
101  */
102 guint8 *
103 pango_log2vis_get_embedding_levels (const gchar    *text,
104                                     int             length,
105                                     PangoDirection *pbase_dir)
106 {
107   FriBidiCharType fribidi_base_dir;
108   guint8 *embedding_levels_list;
109
110   switch (*pbase_dir)
111     {
112     case PANGO_DIRECTION_LTR:
113     case PANGO_DIRECTION_TTB_RTL:
114       fribidi_base_dir = FRIBIDI_TYPE_L;
115       break;
116     case PANGO_DIRECTION_RTL:
117     case PANGO_DIRECTION_TTB_LTR:
118       fribidi_base_dir = FRIBIDI_TYPE_R;
119       break;
120     case PANGO_DIRECTION_WEAK_RTL:
121       fribidi_base_dir = FRIBIDI_TYPE_WR;
122       break;
123     case PANGO_DIRECTION_WEAK_LTR:
124     case PANGO_DIRECTION_NEUTRAL:
125     default:
126       fribidi_base_dir = FRIBIDI_TYPE_WL;
127       break;
128     }
129
130 #ifdef FRIBIDI_HAVE_UTF8
131   {
132     if (length < 0)
133       length = strlen (text);
134     embedding_levels_list = (guint8 *) fribidi_log2vis_get_embedding_levels_new_utf8 (text, length, &fribidi_base_dir);
135   }
136 #else
137   {
138     gunichar *text_ucs4;
139     int n_chars;
140     text_ucs4 = g_utf8_to_ucs4_fast (text, length, &n_chars);
141     embedding_levels_list = g_new (guint8, n_chars);
142     fribidi_log2vis_get_embedding_levels ((FriBidiChar*)text_ucs4, n_chars,
143                                           &fribidi_base_dir,
144                                           (FriBidiLevel*)embedding_levels_list);
145     g_free (text_ucs4);
146   }
147 #endif
148
149   *pbase_dir = (fribidi_base_dir == FRIBIDI_TYPE_L) ?  PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
150
151   return embedding_levels_list;
152 }
153
154 /**
155  * pango_unichar_direction:
156  * @ch: a Unicode character
157  *
158  * Determines the inherent direction of a character; either
159  * %PANGO_DIRECTION_LTR, %PANGO_DIRECTION_RTL, or
160  * %PANGO_DIRECTION_NEUTRAL.
161  *
162  * This function is useful to categorize characters into left-to-right
163  * letters, right-to-left letters, and everything else.  If full
164  * Unicode bidirectional type of a character is needed,
165  * pango_bidi_type_for_gunichar() can be used instead.
166  *
167  * Return value: the direction of the character.
168  */
169 PangoDirection
170 pango_unichar_direction (gunichar ch)
171 {
172   FriBidiCharType fribidi_ch_type = fribidi_get_type (ch);
173
174   if (!FRIBIDI_IS_STRONG (fribidi_ch_type))
175     return PANGO_DIRECTION_NEUTRAL;
176   else if (FRIBIDI_IS_RTL (fribidi_ch_type))
177     return PANGO_DIRECTION_RTL;
178   else
179     return PANGO_DIRECTION_LTR;
180 }
181
182 /**
183  * pango_get_mirror_char:
184  * @ch: a Unicode character
185  * @mirrored_ch: location to store the mirrored character
186  *
187  * If @ch has the Unicode mirrored property and there is another Unicode
188  * character that typically has a glyph that is the mirror image of @ch's
189  * glyph, puts that character in the address pointed to by @mirrored_ch.
190  *
191  * Use g_unichar_get_mirror_char() instead; the docs for that function
192  * provide full details.
193  *
194  * Return value: %TRUE if @ch has a mirrored character and @mirrored_ch is
195  * filled in, %FALSE otherwise
196  **/
197 gboolean
198 pango_get_mirror_char (gunichar        ch,
199                        gunichar       *mirrored_ch)
200 {
201   return g_unichar_get_mirror_char (ch, mirrored_ch);
202 }
203