"Fossies" - the Fresh Open Source Software Archive

Member "pango-1.44.7/pango/pango-bidi-type.c" (25 Oct 2019, 10469 Bytes) of package /linux/misc/pango-1.44.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pango-bidi-type.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.43.0_vs_1.44.0.

    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 /**
   23  * SECTION:bidi
   24  * @short_description:Types and functions for bidirectional text
   25  * @title:Bidirectional Text
   26  * @see_also:
   27  * pango_context_get_base_dir(),
   28  * pango_context_set_base_dir(),
   29  * pango_itemize_with_base_dir()
   30  *
   31  * Pango supports bidirectional text (like Arabic and Hebrew) automatically.
   32  * Some applications however, need some help to correctly handle bidirectional text.
   33  *
   34  * The #PangoDirection type can be used with pango_context_set_base_dir() to
   35  * instruct Pango about direction of text, though in most cases Pango detects
   36  * that correctly and automatically.  The rest of the facilities in this section
   37  * are used internally by Pango already, and are provided to help applications
   38  * that need more direct control over bidirectional setting of text.
   39  */
   40 #include "config.h"
   41 
   42 #include <string.h>
   43 
   44 #include <fribidi.h>
   45 
   46 #undef PANGO_DISABLE_DEPRECATED
   47 
   48 #include "pango-bidi-type.h"
   49 #include "pango-utils.h"
   50 
   51 #if FRIBIDI_MAJOR_VERSION >= 1
   52 #define USE_FRIBIDI_EX_API
   53 #endif
   54 
   55 /**
   56  * pango_bidi_type_for_unichar:
   57  * @ch: a Unicode character
   58  *
   59  * Determines the normative bidirectional character type of a
   60  * character, as specified in the Unicode Character Database.
   61  *
   62  * A simplified version of this function is available as
   63  * pango_unichar_direction().
   64  *
   65  * Return value: the bidirectional character type, as used in the
   66  * Unicode bidirectional algorithm.
   67  *
   68  * Since: 1.22
   69  */
   70 PangoBidiType
   71 pango_bidi_type_for_unichar (gunichar ch)
   72 {
   73   FriBidiCharType fribidi_ch_type;
   74 
   75   G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar));
   76 
   77   fribidi_ch_type = fribidi_get_bidi_type (ch);
   78 
   79   switch (fribidi_ch_type)
   80     {
   81     case FRIBIDI_TYPE_LTR:  return PANGO_BIDI_TYPE_L;
   82     case FRIBIDI_TYPE_LRE:  return PANGO_BIDI_TYPE_LRE;
   83     case FRIBIDI_TYPE_LRO:  return PANGO_BIDI_TYPE_LRO;
   84     case FRIBIDI_TYPE_RTL:  return PANGO_BIDI_TYPE_R;
   85     case FRIBIDI_TYPE_AL:   return PANGO_BIDI_TYPE_AL;
   86     case FRIBIDI_TYPE_RLE:  return PANGO_BIDI_TYPE_RLE;
   87     case FRIBIDI_TYPE_RLO:  return PANGO_BIDI_TYPE_RLO;
   88     case FRIBIDI_TYPE_PDF:  return PANGO_BIDI_TYPE_PDF;
   89     case FRIBIDI_TYPE_EN:   return PANGO_BIDI_TYPE_EN;
   90     case FRIBIDI_TYPE_ES:   return PANGO_BIDI_TYPE_ES;
   91     case FRIBIDI_TYPE_ET:   return PANGO_BIDI_TYPE_ET;
   92     case FRIBIDI_TYPE_AN:   return PANGO_BIDI_TYPE_AN;
   93     case FRIBIDI_TYPE_CS:   return PANGO_BIDI_TYPE_CS;
   94     case FRIBIDI_TYPE_NSM:  return PANGO_BIDI_TYPE_NSM;
   95     case FRIBIDI_TYPE_BN:   return PANGO_BIDI_TYPE_BN;
   96     case FRIBIDI_TYPE_BS:   return PANGO_BIDI_TYPE_B;
   97     case FRIBIDI_TYPE_SS:   return PANGO_BIDI_TYPE_S;
   98     case FRIBIDI_TYPE_WS:   return PANGO_BIDI_TYPE_WS;
   99     case FRIBIDI_TYPE_ON:   return PANGO_BIDI_TYPE_ON;
  100     default:
  101       /* TODO
  102        * This function has not been updated for latest FriBidi.
  103        * Should add new types and / or deprecate this function. */
  104       return PANGO_BIDI_TYPE_ON;
  105     }
  106 }
  107 
  108 /* Some bidi-related functions */
  109 
  110 /**
  111  * pango_log2vis_get_embedding_levels:
  112  * @text:      the text to itemize.
  113  * @length:    the number of bytes (not characters) to process, or -1
  114  *             if @text is nul-terminated and the length should be calculated.
  115  * @pbase_dir: input base direction, and output resolved direction.
  116  *
  117  * This will return the bidirectional embedding levels of the input paragraph
  118  * as defined by the Unicode Bidirectional Algorithm available at:
  119  *
  120  *   http://www.unicode.org/reports/tr9/
  121  *
  122  * If the input base direction is a weak direction, the direction of the
  123  * characters in the text will determine the final resolved direction.
  124  *
  125  * Return value: a newly allocated array of embedding levels, one item per
  126  *               character (not byte), that should be freed using g_free.
  127  *
  128  * Since: 1.4
  129  */
  130 guint8 *
  131 pango_log2vis_get_embedding_levels (const gchar    *text,
  132                     int             length,
  133                     PangoDirection *pbase_dir)
  134 {
  135   glong n_chars, i;
  136   guint8 *embedding_levels_list;
  137   const gchar *p;
  138   FriBidiParType fribidi_base_dir;
  139   FriBidiCharType *bidi_types;
  140 #ifdef USE_FRIBIDI_EX_API
  141   FriBidiBracketType *bracket_types;
  142 #endif
  143   FriBidiLevel max_level;
  144   FriBidiCharType ored_types = 0;
  145   FriBidiCharType anded_strongs = FRIBIDI_TYPE_RLE;
  146 
  147   G_STATIC_ASSERT (sizeof (FriBidiLevel) == sizeof (guint8));
  148   G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar));
  149 
  150   switch (*pbase_dir)
  151     {
  152     case PANGO_DIRECTION_LTR:
  153     case PANGO_DIRECTION_TTB_RTL:
  154       fribidi_base_dir = FRIBIDI_PAR_LTR;
  155       break;
  156     case PANGO_DIRECTION_RTL:
  157     case PANGO_DIRECTION_TTB_LTR:
  158       fribidi_base_dir = FRIBIDI_PAR_RTL;
  159       break;
  160     case PANGO_DIRECTION_WEAK_RTL:
  161       fribidi_base_dir = FRIBIDI_PAR_WRTL;
  162       break;
  163     case PANGO_DIRECTION_WEAK_LTR:
  164     case PANGO_DIRECTION_NEUTRAL:
  165     default:
  166       fribidi_base_dir = FRIBIDI_PAR_WLTR;
  167       break;
  168     }
  169 
  170   if (length < 0)
  171     length = strlen (text);
  172 
  173   n_chars = g_utf8_strlen (text, length);
  174 
  175   bidi_types = g_new (FriBidiCharType, n_chars);
  176 #ifdef USE_FRIBIDI_EX_API
  177   bracket_types = g_new (FriBidiBracketType, n_chars);
  178 #endif
  179   embedding_levels_list = g_new (guint8, n_chars);
  180 
  181   for (i = 0, p = text; p < text + length; p = g_utf8_next_char(p), i++)
  182     {
  183       gunichar ch = g_utf8_get_char (p);
  184       FriBidiCharType char_type = fribidi_get_bidi_type (ch);
  185 
  186       if (i == n_chars)
  187         break;
  188 
  189       bidi_types[i] = char_type;
  190       ored_types |= char_type;
  191       if (FRIBIDI_IS_STRONG (char_type))
  192         anded_strongs &= char_type;
  193 #ifdef USE_FRIBIDI_EX_API
  194       if (G_UNLIKELY(bidi_types[i] == FRIBIDI_TYPE_ON))
  195         bracket_types[i] = fribidi_get_bracket (ch);
  196       else
  197         bracket_types[i] = FRIBIDI_NO_BRACKET;
  198 #endif
  199     }
  200 
  201     /* Short-circuit (malloc-expensive) FriBidi call for unidirectional
  202      * text.
  203      *
  204      * For details see:
  205      * https://bugzilla.gnome.org/show_bug.cgi?id=590183
  206      */
  207 
  208 #ifndef FRIBIDI_IS_ISOLATE
  209 #define FRIBIDI_IS_ISOLATE(x) 0
  210 #endif
  211     /* The case that all resolved levels will be ltr.
  212      * No isolates, all strongs be LTR, there should be no Arabic numbers
  213      * (or letters for that matter), and one of the following:
  214      *
  215      * o base_dir doesn't have an RTL taste.
  216      * o there are letters, and base_dir is weak.
  217      */
  218     if (!FRIBIDI_IS_ISOLATE (ored_types) &&
  219     !FRIBIDI_IS_RTL (ored_types) &&
  220     !FRIBIDI_IS_ARABIC (ored_types) &&
  221     (!FRIBIDI_IS_RTL (fribidi_base_dir) ||
  222       (FRIBIDI_IS_WEAK (fribidi_base_dir) &&
  223        FRIBIDI_IS_LETTER (ored_types))
  224     ))
  225       {
  226         /* all LTR */
  227     fribidi_base_dir = FRIBIDI_PAR_LTR;
  228     memset (embedding_levels_list, 0, n_chars);
  229     goto resolved;
  230       }
  231     /* The case that all resolved levels will be RTL is much more complex.
  232      * No isolates, no numbers, all strongs are RTL, and one of
  233      * the following:
  234      *
  235      * o base_dir has an RTL taste (may be weak).
  236      * o there are letters, and base_dir is weak.
  237      */
  238     else if (!FRIBIDI_IS_ISOLATE (ored_types) &&
  239          !FRIBIDI_IS_NUMBER (ored_types) &&
  240          FRIBIDI_IS_RTL (anded_strongs) &&
  241          (FRIBIDI_IS_RTL (fribidi_base_dir) ||
  242            (FRIBIDI_IS_WEAK (fribidi_base_dir) &&
  243         FRIBIDI_IS_LETTER (ored_types))
  244          ))
  245       {
  246         /* all RTL */
  247     fribidi_base_dir = FRIBIDI_PAR_RTL;
  248     memset (embedding_levels_list, 1, n_chars);
  249     goto resolved;
  250       }
  251 
  252 
  253 #ifdef USE_FRIBIDI_EX_API
  254   max_level = fribidi_get_par_embedding_levels_ex (bidi_types, bracket_types, n_chars,
  255                            &fribidi_base_dir,
  256                            (FriBidiLevel*)embedding_levels_list);
  257 #else
  258   max_level = fribidi_get_par_embedding_levels (bidi_types, n_chars,
  259                         &fribidi_base_dir,
  260                         (FriBidiLevel*)embedding_levels_list);
  261 #endif
  262 
  263   if (G_UNLIKELY(max_level == 0))
  264     {
  265       /* fribidi_get_par_embedding_levels() failed. */
  266       memset (embedding_levels_list, 0, length);
  267     }
  268 
  269 resolved:
  270   g_free (bidi_types);
  271 
  272 #ifdef USE_FRIBIDI_EX_API
  273   g_free (bracket_types);
  274 #endif
  275 
  276   *pbase_dir = (fribidi_base_dir == FRIBIDI_PAR_LTR) ?  PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
  277 
  278   return embedding_levels_list;
  279 }
  280 
  281 /**
  282  * pango_unichar_direction:
  283  * @ch: a Unicode character
  284  *
  285  * Determines the inherent direction of a character; either
  286  * %PANGO_DIRECTION_LTR, %PANGO_DIRECTION_RTL, or
  287  * %PANGO_DIRECTION_NEUTRAL.
  288  *
  289  * This function is useful to categorize characters into left-to-right
  290  * letters, right-to-left letters, and everything else.  If full
  291  * Unicode bidirectional type of a character is needed,
  292  * pango_bidi_type_for_unichar() can be used instead.
  293  *
  294  * Return value: the direction of the character.
  295  */
  296 PangoDirection
  297 pango_unichar_direction (gunichar ch)
  298 {
  299   FriBidiCharType fribidi_ch_type;
  300 
  301   G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar));
  302 
  303   fribidi_ch_type = fribidi_get_bidi_type (ch);
  304 
  305   if (!FRIBIDI_IS_STRONG (fribidi_ch_type))
  306     return PANGO_DIRECTION_NEUTRAL;
  307   else if (FRIBIDI_IS_RTL (fribidi_ch_type))
  308     return PANGO_DIRECTION_RTL;
  309   else
  310     return PANGO_DIRECTION_LTR;
  311 }
  312 
  313 
  314 /**
  315  * pango_get_mirror_char:
  316  * @ch: a Unicode character
  317  * @mirrored_ch: location to store the mirrored character
  318  *
  319  * If @ch has the Unicode mirrored property and there is another Unicode
  320  * character that typically has a glyph that is the mirror image of @ch's
  321  * glyph, puts that character in the address pointed to by @mirrored_ch.
  322  *
  323  * Use g_unichar_get_mirror_char() instead; the docs for that function
  324  * provide full details.
  325  *
  326  * Return value: %TRUE if @ch has a mirrored character and @mirrored_ch is
  327  * filled in, %FALSE otherwise
  328  **/
  329 gboolean
  330 pango_get_mirror_char (gunichar        ch,
  331                gunichar       *mirrored_ch)
  332 {
  333   return g_unichar_get_mirror_char (ch, mirrored_ch);
  334 }
  335