2 * pango-gravity.c: Gravity routines
4 * Copyright (C) 2006, 2007 Red Hat Software
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.
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.
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.
24 #include "pango-gravity.h"
29 * pango_gravity_to_rotation:
30 * @gravity: gravity to query
32 * Converts a #PangoGravity value to its natural rotation in radians.
33 * @gravity should not be %PANGO_GRAVITY_AUTO.
35 * Note that pango_matrix_rotate() takes angle in degrees, not radians.
36 * So, to call pango_matrix_rotate() with the output of this function
37 * you should multiply it by (180. / G_PI).
39 * Return value: the rotation value corresponding to @gravity.
44 pango_gravity_to_rotation (PangoGravity gravity)
48 g_return_val_if_fail (gravity != PANGO_GRAVITY_AUTO, 0);
53 case PANGO_GRAVITY_AUTO: /* shut gcc up */
54 case PANGO_GRAVITY_SOUTH: rotation = 0; break;
55 case PANGO_GRAVITY_NORTH: rotation = G_PI; break;
56 case PANGO_GRAVITY_EAST: rotation = -G_PI_2; break;
57 case PANGO_GRAVITY_WEST: rotation = +G_PI_2; break;
64 * pango_gravity_get_for_matrix:
65 * @matrix: a #PangoMatrix
67 * Finds the gravity that best matches the rotation component
70 * Return value: the gravity of @matrix, which will never be
71 * %PANGO_GRAVITY_AUTO, or %PANGO_GRAVITY_SOUTH if @matrix is %NULL
76 pango_gravity_get_for_matrix (const PangoMatrix *matrix)
83 return PANGO_GRAVITY_SOUTH;
88 if (fabs (x) > fabs (y))
89 gravity = x > 0 ? PANGO_GRAVITY_WEST : PANGO_GRAVITY_EAST;
91 gravity = y < 0 ? PANGO_GRAVITY_NORTH : PANGO_GRAVITY_SOUTH;
100 PANGO_VERTICAL_DIRECTION_NONE,
101 PANGO_VERTICAL_DIRECTION_TTB,
102 PANGO_VERTICAL_DIRECTION_BTT
103 } PangoVerticalDirection;
107 guint8 horiz_dir; /* Orientation in horizontal context */
109 /* PangoVerticalDirection */
110 guint8 vert_dir; /* Orientation in vertical context */
113 guint8 preferred_gravity; /* Preferred context gravity */
116 guint8 wide; /* Whether script is mostly wide.
117 * Wide characters are upright (ie.
118 * not rotated) in foreign context */
119 } PangoScriptProperties;
121 #define NONE PANGO_VERTICAL_DIRECTION_NONE
122 #define TTB PANGO_VERTICAL_DIRECTION_TTB
123 #define BTT PANGO_VERTICAL_DIRECTION_BTT
125 #define LTR PANGO_DIRECTION_LTR
126 #define RTL PANGO_DIRECTION_RTL
127 #define WEAK PANGO_DIRECTION_WEAK_LTR
129 #define S PANGO_GRAVITY_SOUTH
130 #define E PANGO_GRAVITY_EAST
131 #define N PANGO_GRAVITY_NORTH
132 #define W PANGO_GRAVITY_WEST
134 const PangoScriptProperties script_properties[] =
135 { /* ISO 15924 code */
136 {LTR, NONE, S, FALSE}, /* Zyyy */
137 {LTR, NONE, S, FALSE}, /* Qaai */
138 {RTL, NONE, S, FALSE}, /* Arab */
139 {LTR, NONE, S, FALSE}, /* Armn */
140 {LTR, NONE, S, FALSE}, /* Beng */
141 {LTR, TTB, E, TRUE }, /* Bopo */
142 {LTR, NONE, S, FALSE}, /* Cher */
143 {LTR, NONE, S, FALSE}, /* Qaac */
144 {LTR, NONE, S, FALSE}, /* Cyrl (Cyrs) */
145 {LTR, NONE, S, FALSE}, /* Dsrt */
146 {LTR, NONE, S, FALSE}, /* Deva */
147 {LTR, NONE, S, FALSE}, /* Ethi */
148 {LTR, NONE, S, FALSE}, /* Geor (Geon, Geoa) */
149 {LTR, NONE, S, FALSE}, /* Goth */
150 {LTR, NONE, S, FALSE}, /* Grek */
151 {LTR, NONE, S, FALSE}, /* Gujr */
152 {LTR, NONE, S, FALSE}, /* Guru */
153 {LTR, TTB, E, TRUE }, /* Hani */
154 {LTR, TTB, E, TRUE }, /* Hang */
155 {RTL, NONE, S, FALSE}, /* Hebr */
156 {LTR, TTB, E, TRUE }, /* Hira */
157 {LTR, NONE, S, FALSE}, /* Knda */
158 {LTR, TTB, E, TRUE }, /* Kana */
159 {LTR, NONE, S, FALSE}, /* Khmr */
160 {LTR, NONE, S, FALSE}, /* Laoo */
161 {LTR, NONE, S, FALSE}, /* Latn (Latf, Latg) */
162 {LTR, NONE, S, FALSE}, /* Mlym */
163 {WEAK,TTB, W, FALSE}, /* Mong */
164 {LTR, NONE, S, FALSE}, /* Mymr */
165 {LTR, BTT, W, FALSE}, /* Ogam */
166 {LTR, NONE, S, FALSE}, /* Ital */
167 {LTR, NONE, S, FALSE}, /* Orya */
168 {LTR, NONE, S, FALSE}, /* Runr */
169 {LTR, NONE, S, FALSE}, /* Sinh */
170 {RTL, NONE, S, FALSE}, /* Syrc (Syrj, Syrn, Syre) */
171 {LTR, NONE, S, FALSE}, /* Taml */
172 {LTR, NONE, S, FALSE}, /* Telu */
173 {RTL, NONE, S, FALSE}, /* Thaa */
174 {LTR, NONE, S, FALSE}, /* Thai */
175 {LTR, NONE, S, FALSE}, /* Tibt */
176 {LTR, NONE, S, FALSE}, /* Cans */
177 {LTR, TTB, S, TRUE }, /* Yiii */
178 {LTR, NONE, S, FALSE}, /* Tglg */
179 {LTR, NONE, S, FALSE}, /* Hano */
180 {LTR, NONE, S, FALSE}, /* Buhd */
181 {LTR, NONE, S, FALSE}, /* Tagb */
183 /* Unicode-4.0 additions */
184 {LTR, NONE, S, FALSE}, /* Brai */
185 {LTR, NONE, S, FALSE}, /* Cprt */
186 {LTR, NONE, S, FALSE}, /* Limb */
187 {LTR, NONE, S, FALSE}, /* Osma */
188 {LTR, NONE, S, FALSE}, /* Shaw */
189 {LTR, NONE, S, FALSE}, /* Linb */
190 {LTR, NONE, S, FALSE}, /* Tale */
191 {LTR, NONE, S, FALSE}, /* Ugar */
193 /* Unicode-4.1 additions */
194 {LTR, NONE, S, FALSE}, /* Talu */
195 {LTR, NONE, S, FALSE}, /* Bugi */
196 {LTR, NONE, S, FALSE}, /* Glag */
197 {LTR, NONE, S, FALSE}, /* Tfng */
198 {LTR, NONE, S, FALSE}, /* Sylo */
199 {LTR, NONE, S, FALSE}, /* Xpeo */
200 {LTR, NONE, S, FALSE}, /* Khar */
202 /* Unicode-5.0 additions */
203 {LTR, NONE, S, FALSE}, /* Zzzz */
204 {LTR, NONE, S, FALSE}, /* Bali */
205 {LTR, NONE, S, FALSE}, /* Xsux */
206 {RTL, NONE, S, FALSE}, /* Phnx */
207 {LTR, NONE, S, FALSE}, /* Phag */
208 {RTL, NONE, S, FALSE} /* Nkoo */
224 static PangoScriptProperties
225 get_script_properties (PangoScript script)
227 g_return_val_if_fail (script >= 0, script_properties[0]);
229 if ((guint)script >= G_N_ELEMENTS (script_properties))
230 return script_properties[0];
232 return script_properties[script];
236 * pango_gravity_get_for_script:
237 * @script: #PangoScript to query
238 * @base_gravity: base gravity of the paragraph
239 * @hint: orientation hint
241 * Based on the script, base gravity, and hint, returns actual gravity
242 * to use in laying out a single #PangoItem.
244 * If @base_gravity is %PANGO_GRAVITY_AUTO, it is first replaced with the
245 * preferred gravity of @script. To get the preferred gravity of a script,
246 * pass %PANGO_GRAVITY_AUTO and %PANGO_GRAVITY_HINT_STRONG in.
248 * Return value: resolved gravity suitable to use for a run of text
254 pango_gravity_get_for_script (PangoScript script,
255 PangoGravity base_gravity,
256 PangoGravityHint hint)
258 PangoScriptProperties props = get_script_properties (script);
262 if (G_UNLIKELY (base_gravity == PANGO_GRAVITY_AUTO))
263 base_gravity = props.preferred_gravity;
265 vertical = PANGO_GRAVITY_IS_VERTICAL (base_gravity);
267 return pango_gravity_get_for_script_and_width (script, props.wide,
272 * pango_gravity_get_for_script_and_width:
273 * @script: #PangoScript to query
274 * @wide: %TRUE for wide characters as returned by g_unichar_iswide()
275 * @base_gravity: base gravity of the paragraph
276 * @hint: orientation hint
278 * Based on the script, East Asian width, base gravity, and hint,
279 * returns actual gravity to use in laying out a single character
282 * This function is similar to pango_gravity_get_for_script() except
283 * that this function makes a distinction between narrow/half-width and
284 * wide/full-width characters also. Wide/full-width characters always
285 * stand <emph>upright</emph>, that is, they always take the base gravity,
286 * whereas narrow/full-width characters are always rotated in vertical
289 * If @base_gravity is %PANGO_GRAVITY_AUTO, it is first replaced with the
290 * preferred gravity of @script.
292 * Return value: resolved gravity suitable to use for a run of text
293 * with @script and @wide.
298 pango_gravity_get_for_script_and_width (PangoScript script,
300 PangoGravity base_gravity,
301 PangoGravityHint hint)
303 PangoScriptProperties props = get_script_properties (script);
307 if (G_UNLIKELY (base_gravity == PANGO_GRAVITY_AUTO))
308 base_gravity = props.preferred_gravity;
310 vertical = PANGO_GRAVITY_IS_VERTICAL (base_gravity);
312 /* Everything is designed such that a system with no vertical support
313 * renders everything correctly horizontally. So, if not in a vertical
314 * gravity, base and resolved gravities are always the same.
316 * Wide characters are always upright.
318 if (G_LIKELY (!vertical || wide))
321 /* If here, we have a narrow character in a vertical gravity setting.
322 * Resolve depending on the hint.
327 case PANGO_GRAVITY_HINT_NATURAL:
328 if (props.vert_dir == PANGO_VERTICAL_DIRECTION_NONE)
329 return PANGO_GRAVITY_SOUTH;
330 if ((base_gravity == PANGO_GRAVITY_EAST) ^
331 (props.vert_dir == PANGO_VERTICAL_DIRECTION_BTT))
332 return PANGO_GRAVITY_SOUTH;
334 return PANGO_GRAVITY_NORTH;
336 case PANGO_GRAVITY_HINT_STRONG:
339 case PANGO_GRAVITY_HINT_LINE:
340 if ((base_gravity == PANGO_GRAVITY_EAST) ^
341 (props.horiz_dir == PANGO_DIRECTION_RTL))
342 return PANGO_GRAVITY_SOUTH;
344 return PANGO_GRAVITY_NORTH;