diff options
Diffstat (limited to 'pango/pango-gravity.c')
-rw-r--r-- | pango/pango-gravity.c | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/pango/pango-gravity.c b/pango/pango-gravity.c new file mode 100644 index 00000000..73103134 --- /dev/null +++ b/pango/pango-gravity.c @@ -0,0 +1,294 @@ +/* Pango + * pango-gravity.c: Gravity routines + * + * Copyright (C) 2006, 2007 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include "pango-gravity.h" + +#include <math.h> + +/** + * pango_gravity_to_rotation: + * @gravity: gravity to query + * + * Converts a #PangoGravity value to its rotation value. + * @gravity should not be %PANGO_GRAVITY_AUTO. + * + * Return value: the rotation value corresponding to @gravity. + * + * Since: 1.16 + */ +double +pango_gravity_to_rotation (PangoGravity gravity) +{ + double rotation; + + g_return_val_if_fail (gravity != PANGO_GRAVITY_AUTO, 0); + + switch (gravity) + { + default: + case PANGO_GRAVITY_AUTO: /* shut gcc up */ + case PANGO_GRAVITY_SOUTH: rotation = 0; break; + case PANGO_GRAVITY_NORTH: rotation = G_PI; break; + case PANGO_GRAVITY_EAST: rotation = -G_PI_2; break; + case PANGO_GRAVITY_WEST: rotation = +G_PI_2; break; + } + + return rotation; +} + +/** + * pango_gravity_get_for_matrix: + * @matrix: a #PangoMatrix + * + * Finds the gravity that best matches the rotation component + * in a #PangoMatrix. + * + * Return value: the gravity of @matrix, which will never be + * %PANGO_GRAVITY_AUTO, or %PANGO_GRAVITY_SOUTH if @matrix is %NULL + * + * Since: 1.16 + */ +PangoGravity +pango_gravity_get_for_matrix (const PangoMatrix *matrix) +{ + PangoGravity gravity; + double x; + double y; + + if (!matrix) + return PANGO_GRAVITY_SOUTH; + + x = matrix->xy; + y = matrix->yy; + + if (fabs (x) > fabs (y)) + gravity = x > 0 ? PANGO_GRAVITY_WEST : PANGO_GRAVITY_EAST; + else + gravity = y < 0 ? PANGO_GRAVITY_NORTH : PANGO_GRAVITY_SOUTH; + + return gravity; +} + + + +typedef enum +{ + PANGO_VERTICAL_DIRECTION_NONE, + PANGO_VERTICAL_DIRECTION_TTB, + PANGO_VERTICAL_DIRECTION_BTT +} PangoVerticalDirection; + +typedef struct { + /* PangoDirection */ + guint8 horiz_dir; /* Orientation in horizontal context */ + + /* PangoVerticalDirection */ + guint8 vert_dir; /* Orientation in vertical context */ + + /* PangoGravity */ + guint8 preferred_gravity; /* Preferred context gravity */ + + /* gboolean */ + guint8 upright; /* Whether glyphs are upright or + * rotated in foreign context */ +} PangoScriptProperties; + +#define NONE PANGO_VERTICAL_DIRECTION_NONE +#define TTB PANGO_VERTICAL_DIRECTION_TTB +#define BTT PANGO_VERTICAL_DIRECTION_BTT + +#define LTR PANGO_DIRECTION_LTR +#define RTL PANGO_DIRECTION_RTL +#define WEAK PANGO_DIRECTION_WEAK_LTR + +#define S PANGO_GRAVITY_SOUTH +#define E PANGO_GRAVITY_EAST +#define N PANGO_GRAVITY_NORTH +#define W PANGO_GRAVITY_WEST + +const PangoScriptProperties script_properties[] = + { /* ISO 15924 code */ + {LTR, NONE, S, FALSE}, /* Zyyy */ + {LTR, NONE, S, FALSE}, /* Qaai */ + {RTL, NONE, S, FALSE}, /* Arab */ + {LTR, NONE, S, FALSE}, /* Armn */ + {LTR, NONE, S, FALSE}, /* Beng */ + {LTR, TTB, E, TRUE }, /* Bopo */ + {LTR, NONE, S, FALSE}, /* Cher */ + {LTR, NONE, S, FALSE}, /* Qaac */ + {LTR, NONE, S, FALSE}, /* Cyrl (Cyrs) */ + {LTR, NONE, S, FALSE}, /* Dsrt */ + {LTR, NONE, S, FALSE}, /* Deva */ + {LTR, NONE, S, FALSE}, /* Ethi */ + {LTR, NONE, S, FALSE}, /* Geor (Geon, Geoa) */ + {LTR, NONE, S, FALSE}, /* Goth */ + {LTR, NONE, S, FALSE}, /* Grek */ + {LTR, NONE, S, FALSE}, /* Gujr */ + {LTR, NONE, S, FALSE}, /* Guru */ + {LTR, TTB, E, TRUE }, /* Hani */ + {LTR, TTB, E, TRUE }, /* Hang */ + {RTL, NONE, S, FALSE}, /* Hebr */ + {LTR, TTB, E, TRUE }, /* Hira */ + {LTR, NONE, S, FALSE}, /* Knda */ + {LTR, TTB, E, TRUE }, /* Kana */ + {LTR, NONE, S, FALSE}, /* Khmr */ + {LTR, NONE, S, FALSE}, /* Laoo */ + {LTR, NONE, S, FALSE}, /* Latn (Latf, Latg) */ + {LTR, NONE, S, FALSE}, /* Mlym */ + {WEAK,TTB, W, FALSE}, /* Mong */ + {LTR, NONE, S, FALSE}, /* Mymr */ + {LTR, BTT, W, FALSE}, /* Ogam */ + {LTR, NONE, S, FALSE}, /* Ital */ + {LTR, NONE, S, FALSE}, /* Orya */ + {LTR, NONE, S, FALSE}, /* Runr */ + {LTR, NONE, S, FALSE}, /* Sinh */ + {RTL, NONE, S, FALSE}, /* Syrc (Syrj, Syrn, Syre) */ + {LTR, NONE, S, FALSE}, /* Taml */ + {LTR, NONE, S, FALSE}, /* Telu */ + {RTL, NONE, S, FALSE}, /* Thaa */ + {LTR, NONE, S, FALSE}, /* Thai */ + {LTR, NONE, S, FALSE}, /* Tibt */ + {LTR, NONE, S, FALSE}, /* Cans */ + {LTR, TTB, S, TRUE }, /* Yiii */ + {LTR, NONE, S, FALSE}, /* Tglg */ + {LTR, NONE, S, FALSE}, /* Hano */ + {LTR, NONE, S, FALSE}, /* Buhd */ + {LTR, NONE, S, FALSE}, /* Tagb */ + + /* Unicode-4.0 additions */ + {LTR, NONE, S, FALSE}, /* Brai */ + {LTR, NONE, S, FALSE}, /* Cprt */ + {LTR, NONE, S, FALSE}, /* Limb */ + {LTR, NONE, S, FALSE}, /* Osma */ + {LTR, NONE, S, FALSE}, /* Shaw */ + {LTR, NONE, S, FALSE}, /* Linb */ + {LTR, NONE, S, FALSE}, /* Tale */ + {LTR, NONE, S, FALSE}, /* Ugar */ + + /* Unicode-4.1 additions */ + {LTR, NONE, S, FALSE}, /* Talu */ + {LTR, NONE, S, FALSE}, /* Bugi */ + {LTR, NONE, S, FALSE}, /* Glag */ + {LTR, NONE, S, FALSE}, /* Tfng */ + {LTR, NONE, S, FALSE}, /* Sylo */ + {LTR, NONE, S, FALSE}, /* Xpeo */ + {LTR, NONE, S, FALSE}, /* Khar */ + + /* Unicode-5.0 additions */ + {LTR, NONE, S, FALSE}, /* Zzzz */ + {LTR, NONE, S, FALSE}, /* Bali */ + {LTR, NONE, S, FALSE}, /* Xsux */ + {RTL, NONE, S, FALSE}, /* Phnx */ + {LTR, NONE, S, FALSE}, /* Phag */ + {RTL, NONE, S, FALSE} /* Nkoo */ +}; + +#undef NONE +#undef TTB +#undef BTT + +#undef LTR +#undef RTL +#undef WEAK + +#undef S +#undef E +#undef N +#undef W + +static PangoScriptProperties +get_script_properties (PangoScript script) +{ + if ((guint)script >= G_N_ELEMENTS (script_properties)) + script = 0; + + return script_properties[script]; +} + +/** + * pango_gravity_get_for_script: + * @script: #PangoScript to query + * @base_gravity: base gravity of the paragraph + * @hint: orientation hint + * + * Based on the script, base gravity, and hint, returns actual gravity + * to use in laying out a single #PangoItem. + * + * If @base_gravity is %PANGO_GRAVITY_AUTO, it is first replaced with the + * preferred gravity of @script. To get the preferred gravity of a script, + * pass %PANGO_GRAVITY_AUTO and %PANGO_GRAVITY_HINT_STRONG in. + * + * Return value: resolved gravity suitable to use for a run of text + * + * Since: 1.16 + */ +PangoGravity +pango_gravity_get_for_script (PangoScript script, + PangoGravity base_gravity, + PangoGravityHint hint) +{ + PangoScriptProperties props = get_script_properties (script); + gboolean vertical; + + + if (G_UNLIKELY (base_gravity == PANGO_GRAVITY_AUTO)) + base_gravity = props.preferred_gravity; + + vertical = PANGO_GRAVITY_IS_VERTICAL (base_gravity); + + /* Everything is designed such that a system with no vertical support + * renders everything correctly horizontally. So, if not in a vertical + * gravity, base and resolved gravities are always the same. + * + * If the script should be upright all the time, like Chinese and Japenese, + * any base gravity should resolve to itself. + */ + if (G_LIKELY (!vertical || props.upright)) + return base_gravity; + + /* If here, we have a non-upright script in a vertical gravity setting. + * Resolve depending on the hint. + */ + switch (hint) + { + default: + case PANGO_GRAVITY_HINT_NATURAL: + if (props.vert_dir == PANGO_VERTICAL_DIRECTION_NONE) + return PANGO_GRAVITY_SOUTH; + if ((base_gravity == PANGO_GRAVITY_EAST) ^ + (props.vert_dir == PANGO_VERTICAL_DIRECTION_BTT)) + return PANGO_GRAVITY_SOUTH; + else + return PANGO_GRAVITY_NORTH; + + case PANGO_GRAVITY_HINT_STRONG: + return base_gravity; + + case PANGO_GRAVITY_HINT_LINE: + if ((base_gravity == PANGO_GRAVITY_EAST) ^ + (props.horiz_dir == PANGO_DIRECTION_RTL)) + return PANGO_GRAVITY_SOUTH; + else + return PANGO_GRAVITY_NORTH; + } +} |