"Fossies" - the Fresh Open Source Software Archive

Member "pango-1.44.7/pango/pango-utils.c" (25 Oct 2019, 26933 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-utils.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-utils.c: Utilities for internal functions and modules
    3  *
    4  * Copyright (C) 2000 Red Hat Software
    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:pango-version
   24  * @short_description:Tools for checking Pango version at compile- and run-time.
   25  * @title:Version Checking
   26  *
   27  * The capital-letter macros defined here can be used to check the version of Pango
   28  * at compile-time, and to <firstterm>encode</firstterm> Pango versions into integers.
   29  *
   30  * The functions can be used to check the version of the linked Pango library at run-time.
   31  */
   32 /**
   33  * SECTION:utils
   34  * @short_description:Various convenience and utility functions
   35  * @title: Miscellaneous Utilities
   36  *
   37  * The functions and utilities in this section are mostly used from Pango
   38  * backends and modules, but may be useful for other purposes too.
   39  */
   40 #include "config.h"
   41 #include <errno.h>
   42 #include <string.h>
   43 #include <stdlib.h>
   44 #include <math.h>
   45 #include <locale.h>
   46 
   47 #include "pango-font.h"
   48 #include "pango-features.h"
   49 #include "pango-impl-utils.h"
   50 #include "pango-utils-internal.h"
   51 #include "pango-utils-private.h"
   52 
   53 #include <glib/gstdio.h>
   54 
   55 #ifndef HAVE_FLOCKFILE
   56 #  define flockfile(f) (void)1
   57 #  define funlockfile(f) (void)1
   58 #  define getc_unlocked(f) getc(f)
   59 #endif /* !HAVE_FLOCKFILE */
   60 
   61 #ifdef G_OS_WIN32
   62 
   63 #include <sys/types.h>
   64 
   65 #define STRICT
   66 #include <windows.h>
   67 
   68 #endif
   69 
   70 /**
   71  * pango_version:
   72  *
   73  * This is similar to the macro %PANGO_VERSION except that
   74  * it returns the encoded version of Pango available at run-time,
   75  * as opposed to the version available at compile-time.
   76  *
   77  * A version number can be encoded into an integer using
   78  * PANGO_VERSION_ENCODE().
   79  *
   80  * Returns: The encoded version of Pango library
   81  *   available at run time.
   82  *
   83  * Since: 1.16
   84  **/
   85 int
   86 pango_version (void)
   87 {
   88   return PANGO_VERSION;
   89 }
   90 
   91 /**
   92  * pango_version_string:
   93  *
   94  * This is similar to the macro %PANGO_VERSION_STRING except that
   95  * it returns the version of Pango available at run-time, as opposed to
   96  * the version available at compile-time.
   97  *
   98  * Returns: A string containing the version of Pango library
   99  *   available at run time.
  100  *   The returned string is owned by Pango and should not be modified
  101  *   or freed.
  102  *
  103  * Since: 1.16
  104  **/
  105 const char *
  106 pango_version_string (void)
  107 {
  108   return PANGO_VERSION_STRING;
  109 }
  110 
  111 /**
  112  * pango_version_check:
  113  * @required_major: the required major version.
  114  * @required_minor: the required minor version.
  115  * @required_micro: the required major version.
  116  *
  117  * Checks that the Pango library in use is compatible with the
  118  * given version. Generally you would pass in the constants
  119  * %PANGO_VERSION_MAJOR, %PANGO_VERSION_MINOR, %PANGO_VERSION_MICRO
  120  * as the three arguments to this function; that produces
  121  * a check that the library in use at run-time is compatible with
  122  * the version of Pango the application or module was compiled against.
  123  *
  124  * Compatibility is defined by two things: first the version
  125  * of the running library is newer than the version
  126  * @required_major.required_minor.@required_micro. Second
  127  * the running library must be binary compatible with the
  128  * version @required_major.required_minor.@required_micro
  129  * (same major version.)
  130  *
  131  * For compile-time version checking use PANGO_VERSION_CHECK().
  132  *
  133  * Return value: (nullable): %NULL if the Pango library is compatible
  134  *   with the given version, or a string describing the version
  135  *   mismatch.  The returned string is owned by Pango and should not
  136  *   be modified or freed.
  137  *
  138  * Since: 1.16
  139  **/
  140 const gchar*
  141 pango_version_check (int required_major,
  142              int required_minor,
  143              int required_micro)
  144 {
  145   gint pango_effective_micro = 100 * PANGO_VERSION_MINOR + PANGO_VERSION_MICRO;
  146   gint required_effective_micro = 100 * required_minor + required_micro;
  147 
  148   if (required_major < PANGO_VERSION_MAJOR)
  149     return "Pango version too new (major mismatch)";
  150   if (required_effective_micro < pango_effective_micro - PANGO_BINARY_AGE)
  151     return "Pango version too new (micro mismatch)";
  152   if (required_effective_micro > pango_effective_micro)
  153     return "Pango version too old (micro mismatch)";
  154   return NULL;
  155 }
  156 
  157 /**
  158  * pango_trim_string:
  159  * @str: a string
  160  *
  161  * Trims leading and trailing whitespace from a string.
  162  *
  163  * Return value: A newly-allocated string that must be freed with g_free()
  164  *
  165  * Deprecated: 1.38
  166  **/
  167 char *
  168 pango_trim_string (const char *str)
  169 {
  170   return _pango_trim_string (str);
  171 }
  172 
  173 char *
  174 _pango_trim_string (const char *str)
  175 {
  176   int len;
  177 
  178   g_return_val_if_fail (str != NULL, NULL);
  179 
  180   while (*str && g_ascii_isspace (*str))
  181     str++;
  182 
  183   len = strlen (str);
  184   while (len > 0 && g_ascii_isspace (str[len-1]))
  185     len--;
  186 
  187   return g_strndup (str, len);
  188 }
  189 
  190 /**
  191  * pango_split_file_list:
  192  * @str: a %G_SEARCHPATH_SEPARATOR separated list of filenames
  193  *
  194  * Splits a %G_SEARCHPATH_SEPARATOR-separated list of files, stripping
  195  * white space and substituting ~/ with $HOME/.
  196  *
  197  * Return value: (transfer full) (array zero-terminated=1): a list of
  198  * strings to be freed with g_strfreev()
  199  *
  200  * Deprecated: 1.38
  201  **/
  202 char **
  203 pango_split_file_list (const char *str)
  204 {
  205   int i = 0;
  206   int j;
  207   char **files;
  208 
  209   files = g_strsplit (str, G_SEARCHPATH_SEPARATOR_S, -1);
  210 
  211   while (files[i])
  212     {
  213       char *file = _pango_trim_string (files[i]);
  214 
  215       /* If the resulting file is empty, skip it */
  216       if (file[0] == '\0')
  217     {
  218       g_free(file);
  219       g_free (files[i]);
  220 
  221       for (j = i + 1; files[j]; j++)
  222         files[j - 1] = files[j];
  223 
  224       files[j - 1] = NULL;
  225 
  226       continue;
  227     }
  228 #ifndef G_OS_WIN32
  229       /* '~' is a quite normal and common character in file names on
  230        * Windows, especially in the 8.3 versions of long file names, which
  231        * still occur now and then. Also, few Windows user are aware of the
  232        * Unix shell convention that '~' stands for the home directory,
  233        * even if they happen to have a home directory.
  234        */
  235       if (file[0] == '~' && file[1] == G_DIR_SEPARATOR)
  236     {
  237       char *tmp = g_strconcat (g_get_home_dir(), file + 1, NULL);
  238       g_free (file);
  239       file = tmp;
  240     }
  241       else if (file[0] == '~' && file[1] == '\0')
  242     {
  243       g_free (file);
  244       file = g_strdup (g_get_home_dir());
  245     }
  246 #endif
  247       g_free (files[i]);
  248       files[i] = file;
  249 
  250       i++;
  251     }
  252 
  253   return files;
  254 }
  255 
  256 /**
  257  * pango_read_line:
  258  * @stream: a stdio stream
  259  * @str: #GString buffer into which to write the result
  260  *
  261  * Reads an entire line from a file into a buffer. Lines may
  262  * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
  263  * is not written into the buffer. Text after a '#' character is treated as
  264  * a comment and skipped. '\' can be used to escape a # character.
  265  * '\' proceeding a line delimiter combines adjacent lines. A '\' proceeding
  266  * any other character is ignored and written into the output buffer
  267  * unmodified.
  268  *
  269  * Return value: 0 if the stream was already at an %EOF character, otherwise
  270  *               the number of lines read (this is useful for maintaining
  271  *               a line number counter which doesn't combine lines with '\')
  272  *
  273  * Deprecated: 1.38
  274  **/
  275 gint
  276 pango_read_line (FILE *stream, GString *str)
  277 {
  278   gboolean quoted = FALSE;
  279   gboolean comment = FALSE;
  280   int n_read = 0;
  281   int lines = 1;
  282 
  283   flockfile (stream);
  284 
  285   g_string_truncate (str, 0);
  286 
  287   while (1)
  288     {
  289       int c;
  290 
  291       c = getc_unlocked (stream);
  292 
  293       if (c == EOF)
  294     {
  295       if (quoted)
  296         g_string_append_c (str, '\\');
  297 
  298       goto done;
  299     }
  300       else
  301     n_read++;
  302 
  303       if (quoted)
  304     {
  305       quoted = FALSE;
  306 
  307       switch (c)
  308         {
  309         case '#':
  310           g_string_append_c (str, '#');
  311           break;
  312         case '\r':
  313         case '\n':
  314           {
  315         int next_c = getc_unlocked (stream);
  316 
  317         if (!(next_c == EOF ||
  318               (c == '\r' && next_c == '\n') ||
  319               (c == '\n' && next_c == '\r')))
  320           ungetc (next_c, stream);
  321 
  322         lines++;
  323 
  324         break;
  325           }
  326         default:
  327           g_string_append_c (str, '\\');
  328           g_string_append_c (str, c);
  329         }
  330     }
  331       else
  332     {
  333       switch (c)
  334         {
  335         case '#':
  336           comment = TRUE;
  337           break;
  338         case '\\':
  339           if (!comment)
  340         quoted = TRUE;
  341           break;
  342         case '\r':
  343         case '\n':
  344           {
  345         int next_c = getc_unlocked (stream);
  346 
  347         if (!(next_c == EOF ||
  348               (c == '\r' && next_c == '\n') ||
  349               (c == '\n' && next_c == '\r')))
  350           ungetc (next_c, stream);
  351 
  352         goto done;
  353           }
  354         default:
  355           if (!comment)
  356         g_string_append_c (str, c);
  357         }
  358     }
  359     }
  360 
  361  done:
  362 
  363   funlockfile (stream);
  364 
  365   return (n_read > 0) ? lines : 0;
  366 }
  367 
  368 /**
  369  * pango_skip_space:
  370  * @pos: (inout): in/out string position
  371  *
  372  * Skips 0 or more characters of white space.
  373  *
  374  * Return value: %FALSE if skipping the white space leaves
  375  * the position at a '\0' character.
  376  *
  377  * Deprecated: 1.38
  378  **/
  379 gboolean
  380 pango_skip_space (const char **pos)
  381 {
  382   const char *p = *pos;
  383 
  384   while (g_ascii_isspace (*p))
  385     p++;
  386 
  387   *pos = p;
  388 
  389   return !(*p == '\0');
  390 }
  391 
  392 /**
  393  * pango_scan_word:
  394  * @pos: (inout): in/out string position
  395  * @out: a #GString into which to write the result
  396  *
  397  * Scans a word into a #GString buffer. A word consists
  398  * of [A-Za-z_] followed by zero or more [A-Za-z_0-9]
  399  * Leading white space is skipped.
  400  *
  401  * Return value: %FALSE if a parse error occurred.
  402  *
  403  * Deprecated: 1.38
  404  **/
  405 gboolean
  406 pango_scan_word (const char **pos, GString *out)
  407 {
  408   const char *p = *pos;
  409 
  410   while (g_ascii_isspace (*p))
  411     p++;
  412 
  413   if (!((*p >= 'A' && *p <= 'Z') ||
  414     (*p >= 'a' && *p <= 'z') ||
  415     *p == '_'))
  416     return FALSE;
  417 
  418   g_string_truncate (out, 0);
  419   g_string_append_c (out, *p);
  420   p++;
  421 
  422   while ((*p >= 'A' && *p <= 'Z') ||
  423      (*p >= 'a' && *p <= 'z') ||
  424      (*p >= '0' && *p <= '9') ||
  425      *p == '_')
  426     {
  427       g_string_append_c (out, *p);
  428       p++;
  429     }
  430 
  431   *pos = p;
  432 
  433   return TRUE;
  434 }
  435 
  436 /**
  437  * pango_scan_string:
  438  * @pos: (inout): in/out string position
  439  * @out: a #GString into which to write the result
  440  *
  441  * Scans a string into a #GString buffer. The string may either
  442  * be a sequence of non-white-space characters, or a quoted
  443  * string with '"'. Instead a quoted string, '\"' represents
  444  * a literal quote. Leading white space outside of quotes is skipped.
  445  *
  446  * Return value: %FALSE if a parse error occurred.
  447  *
  448  * Deprecated: 1.38
  449  **/
  450 gboolean
  451 pango_scan_string (const char **pos, GString *out)
  452 {
  453   const char *p = *pos;
  454 
  455   while (g_ascii_isspace (*p))
  456     p++;
  457 
  458   if (G_UNLIKELY (!*p))
  459     return FALSE;
  460   else if (*p == '"')
  461     {
  462       gboolean quoted = FALSE;
  463       g_string_truncate (out, 0);
  464 
  465       p++;
  466 
  467       while (TRUE)
  468     {
  469       if (quoted)
  470         {
  471           int c = *p;
  472 
  473           switch (c)
  474         {
  475         case '\0':
  476           return FALSE;
  477         case 'n':
  478           c = '\n';
  479           break;
  480         case 't':
  481           c = '\t';
  482           break;
  483         default:
  484           break;
  485         }
  486 
  487           quoted = FALSE;
  488           g_string_append_c (out, c);
  489         }
  490       else
  491         {
  492           switch (*p)
  493         {
  494         case '\0':
  495           return FALSE;
  496         case '\\':
  497           quoted = TRUE;
  498           break;
  499         case '"':
  500           p++;
  501           goto done;
  502         default:
  503           g_string_append_c (out, *p);
  504           break;
  505         }
  506         }
  507       p++;
  508     }
  509     done:
  510       ;
  511     }
  512   else
  513     {
  514       g_string_truncate (out, 0);
  515 
  516       while (*p && !g_ascii_isspace (*p))
  517     {
  518       g_string_append_c (out, *p);
  519       p++;
  520     }
  521     }
  522 
  523   *pos = p;
  524 
  525   return TRUE;
  526 }
  527 
  528 /**
  529  * pango_scan_int:
  530  * @pos: (inout): in/out string position
  531  * @out: (out): an int into which to write the result
  532  *
  533  * Scans an integer.
  534  * Leading white space is skipped.
  535  *
  536  * Return value: %FALSE if a parse error occurred.
  537  *
  538  * Deprecated: 1.38
  539  **/
  540 gboolean
  541 pango_scan_int (const char **pos, int *out)
  542 {
  543   return _pango_scan_int (pos, out);
  544 }
  545 
  546 gboolean
  547 _pango_scan_int (const char **pos, int *out)
  548 {
  549   char *end;
  550   long temp;
  551 
  552   errno = 0;
  553   temp = strtol (*pos, &end, 10);
  554   if (errno == ERANGE)
  555     {
  556       errno = 0;
  557       return FALSE;
  558     }
  559 
  560   *out = (int)temp;
  561   if ((long)(*out) != temp)
  562     {
  563       return FALSE;
  564     }
  565 
  566   *pos = end;
  567 
  568   return TRUE;
  569 }
  570 
  571 /**
  572  * pango_config_key_get_system:
  573  * @key: Key to look up, in the form "SECTION/KEY".
  574  *
  575  * Do not use.  Does not do anything.
  576  *
  577  * Return value: %NULL
  578  *
  579  * Deprecated: 1.38
  580  **/
  581 char *
  582 pango_config_key_get_system (const char *key)
  583 {
  584   return NULL;
  585 }
  586 
  587 /**
  588  * pango_config_key_get:
  589  * @key: Key to look up, in the form "SECTION/KEY".
  590  *
  591  * Do not use.  Does not do anything.
  592  *
  593  * Return value: %NULL
  594  *
  595  * Deprecated: 1.38
  596  **/
  597 char *
  598 pango_config_key_get (const char *key)
  599 {
  600   return NULL;
  601 }
  602 
  603 /**
  604  * pango_get_sysconf_subdirectory:
  605  *
  606  * Returns the name of the "pango" subdirectory of SYSCONFDIR
  607  * (which is set at compile time).
  608  *
  609  * Return value: the Pango sysconf directory. The returned string should
  610  * not be freed.
  611  *
  612  * Deprecated: 1.38
  613  */
  614 const char *
  615 pango_get_sysconf_subdirectory (void)
  616 {
  617   static const gchar *result = NULL; /* MT-safe */
  618 
  619   if (g_once_init_enter (&result))
  620     {
  621       const char *tmp_result = NULL;
  622       const char *sysconfdir = g_getenv ("PANGO_SYSCONFDIR");
  623       if (sysconfdir != NULL)
  624     tmp_result = g_build_filename (sysconfdir, "pango", NULL);
  625       else
  626     tmp_result = SYSCONFDIR "/pango";
  627       g_once_init_leave(&result, tmp_result);
  628     }
  629   return result;
  630 }
  631 
  632 /**
  633  * pango_get_lib_subdirectory:
  634  *
  635  * Returns the name of the "pango" subdirectory of LIBDIR
  636  * (which is set at compile time).
  637  *
  638  * Return value: the Pango lib directory. The returned string should
  639  * not be freed.
  640  *
  641  * Deprecated: 1.38
  642  */
  643 const char *
  644 pango_get_lib_subdirectory (void)
  645 {
  646   static const gchar *result = NULL; /* MT-safe */
  647 
  648   if (g_once_init_enter (&result))
  649     {
  650       const gchar *tmp_result = NULL;
  651       const char *libdir = g_getenv ("PANGO_LIBDIR");
  652       if (libdir != NULL)
  653     tmp_result = g_build_filename (libdir, "pango", NULL);
  654       else
  655     tmp_result = LIBDIR "/pango";
  656       g_once_init_leave(&result, tmp_result);
  657     }
  658   return result;
  659 }
  660 
  661 
  662 static gboolean
  663 parse_int (const char *word,
  664        int        *out)
  665 {
  666   char *end;
  667   long val;
  668   int i;
  669 
  670   if (word == NULL)
  671     return FALSE;
  672 
  673   val = strtol (word, &end, 10);
  674   i = val;
  675 
  676   if (end != word && *end == '\0' && val >= 0 && val == i)
  677     {
  678       if (out)
  679         *out = i;
  680 
  681       return TRUE;
  682     }
  683 
  684   return FALSE;
  685 }
  686 
  687 /**
  688  * pango_parse_enum:
  689  * @type: enum type to parse, eg. %PANGO_TYPE_ELLIPSIZE_MODE.
  690  * @str: (allow-none): string to parse.  May be %NULL.
  691  * @value: (out) (allow-none): integer to store the result in, or %NULL.
  692  * @warn: if %TRUE, issue a g_warning() on bad input.
  693  * @possible_values: (out) (allow-none): place to store list of possible values on failure, or %NULL.
  694  *
  695  * Parses an enum type and stores the result in @value.
  696  *
  697  * If @str does not match the nick name of any of the possible values for the
  698  * enum and is not an integer, %FALSE is returned, a warning is issued
  699  * if @warn is %TRUE, and a
  700  * string representing the list of possible values is stored in
  701  * @possible_values.  The list is slash-separated, eg.
  702  * "none/start/middle/end".  If failed and @possible_values is not %NULL,
  703  * returned string should be freed using g_free().
  704  *
  705  * Return value: %TRUE if @str was successfully parsed.
  706  *
  707  * Deprecated: 1.38
  708  *
  709  * Since: 1.16
  710  **/
  711 gboolean
  712 pango_parse_enum (GType       type,
  713           const char *str,
  714           int        *value,
  715           gboolean    warn,
  716           char      **possible_values)
  717 {
  718   return _pango_parse_enum (type, str, value, warn, possible_values);
  719 }
  720 
  721 gboolean
  722 _pango_parse_enum (GType       type,
  723            const char *str,
  724            int        *value,
  725            gboolean    warn,
  726            char      **possible_values)
  727 {
  728   GEnumClass *class = NULL;
  729   gboolean ret = TRUE;
  730   GEnumValue *v = NULL;
  731 
  732   class = g_type_class_ref (type);
  733 
  734   if (G_LIKELY (str))
  735     v = g_enum_get_value_by_nick (class, str);
  736 
  737   if (v)
  738     {
  739       if (G_LIKELY (value))
  740     *value = v->value;
  741     }
  742   else if (!parse_int (str, value))
  743     {
  744       ret = FALSE;
  745       if (G_LIKELY (warn || possible_values))
  746     {
  747       int i;
  748       GString *s = g_string_new (NULL);
  749 
  750       for (i = 0, v = g_enum_get_value (class, i); v;
  751            i++  , v = g_enum_get_value (class, i))
  752         {
  753           if (i)
  754         g_string_append_c (s, '/');
  755           g_string_append (s, v->value_nick);
  756         }
  757 
  758       if (warn)
  759         g_warning ("%s must be one of %s",
  760                G_ENUM_CLASS_TYPE_NAME(class),
  761                s->str);
  762 
  763       if (possible_values)
  764         *possible_values = s->str;
  765 
  766       g_string_free (s, possible_values ? FALSE : TRUE);
  767     }
  768     }
  769 
  770   g_type_class_unref (class);
  771 
  772   return ret;
  773 }
  774 
  775 gboolean
  776 pango_parse_flags (GType        type,
  777                    const char  *str,
  778                    int         *value,
  779                    char       **possible_values)
  780 {
  781   GFlagsClass *class = NULL;
  782   gboolean ret = TRUE;
  783   GFlagsValue *v = NULL;
  784 
  785   class = g_type_class_ref (type);
  786 
  787   v = g_flags_get_value_by_nick (class, str);
  788 
  789   if (v)
  790     {
  791       *value = v->value;
  792     }
  793   else if (!parse_int (str, value))
  794     {
  795       char **strv = g_strsplit (str, "|", 0);
  796       int i;
  797 
  798       *value = 0;
  799 
  800       for (i = 0; strv[i]; i++)
  801         {
  802           strv[i] = g_strstrip (strv[i]);
  803           v = g_flags_get_value_by_nick (class, strv[i]);
  804           if (!v)
  805             {
  806               ret = FALSE;
  807               break;
  808             }
  809           *value |= v->value;
  810         }
  811       g_strfreev (strv);
  812 
  813       if (!ret && possible_values)
  814     {
  815       int i;
  816       GString *s = g_string_new (NULL);
  817 
  818           for (i = 0; i < class->n_values; i++)
  819             {
  820               v = &class->values[i];
  821               if (i)
  822                 g_string_append_c (s, '/');
  823               g_string_append (s, v->value_nick);
  824             }
  825 
  826           *possible_values = s->str;
  827 
  828           g_string_free (s, FALSE);
  829     }
  830     }
  831 
  832   g_type_class_unref (class);
  833 
  834   return ret;
  835 }
  836 
  837 /**
  838  * pango_lookup_aliases:
  839  * @fontname: an ascii string
  840  * @families: (out) (array length=n_families): will be set to an array of font family names.
  841  *    this array is owned by pango and should not be freed.
  842  * @n_families: (out): will be set to the length of the @families array.
  843  *
  844  * Look up all user defined aliases for the alias @fontname.
  845  * The resulting font family names will be stored in @families,
  846  * and the number of families in @n_families.
  847  *
  848  * Deprecated: 1.32: This function is not thread-safe.
  849  */
  850 void
  851 pango_lookup_aliases (const char   *fontname,
  852               char       ***families,
  853               int          *n_families)
  854 {
  855   *families = NULL;
  856   *n_families = 0;
  857 }
  858 
  859 #pragma GCC diagnostic push
  860 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  861 
  862 /**
  863  * pango_find_base_dir:
  864  * @text:   the text to process. Must be valid UTF-8
  865  * @length: length of @text in bytes (may be -1 if @text is nul-terminated)
  866  *
  867  * Searches a string the first character that has a strong
  868  * direction, according to the Unicode bidirectional algorithm.
  869  *
  870  * Return value: The direction corresponding to the first strong character.
  871  * If no such character is found, then %PANGO_DIRECTION_NEUTRAL is returned.
  872  *
  873  * Since: 1.4
  874  */
  875 PangoDirection
  876 pango_find_base_dir (const gchar *text,
  877              gint         length)
  878 {
  879   PangoDirection dir = PANGO_DIRECTION_NEUTRAL;
  880   const gchar *p;
  881 
  882   g_return_val_if_fail (text != NULL || length == 0, PANGO_DIRECTION_NEUTRAL);
  883 
  884   p = text;
  885   while ((length < 0 || p < text + length) && *p)
  886     {
  887       gunichar wc = g_utf8_get_char (p);
  888 
  889       dir = pango_unichar_direction (wc);
  890 
  891       if (dir != PANGO_DIRECTION_NEUTRAL)
  892     break;
  893 
  894       p = g_utf8_next_char (p);
  895     }
  896 
  897   return dir;
  898 }
  899 
  900 #pragma GCC diagnostic pop
  901 
  902 /**
  903  * pango_is_zero_width:
  904  * @ch: a Unicode character
  905  *
  906  * Checks @ch to see if it is a character that should not be
  907  * normally rendered on the screen.  This includes all Unicode characters
  908  * with "ZERO WIDTH" in their name, as well as <firstterm>bidi</firstterm> formatting characters, and
  909  * a few other ones.  This is totally different from g_unichar_iszerowidth()
  910  * and is at best misnamed.
  911  *
  912  * Return value: %TRUE if @ch is a zero-width character, %FALSE otherwise
  913  *
  914  * Since: 1.10
  915  */
  916 gboolean
  917 pango_is_zero_width (gunichar ch)
  918 {
  919 /* Zero Width characters:
  920  *
  921  *  00AD  SOFT HYPHEN
  922  *  034F  COMBINING GRAPHEME JOINER
  923  *
  924  *  200B  ZERO WIDTH SPACE
  925  *  200C  ZERO WIDTH NON-JOINER
  926  *  200D  ZERO WIDTH JOINER
  927  *  200E  LEFT-TO-RIGHT MARK
  928  *  200F  RIGHT-TO-LEFT MARK
  929  *
  930  *  2028  LINE SEPARATOR
  931  *
  932  *  202A  LEFT-TO-RIGHT EMBEDDING
  933  *  202B  RIGHT-TO-LEFT EMBEDDING
  934  *  202C  POP DIRECTIONAL FORMATTING
  935  *  202D  LEFT-TO-RIGHT OVERRIDE
  936  *  202E  RIGHT-TO-LEFT OVERRIDE
  937  *
  938  *  2060  WORD JOINER
  939  *  2061  FUNCTION APPLICATION
  940  *  2062  INVISIBLE TIMES
  941  *  2063  INVISIBLE SEPARATOR
  942  *
  943  *  FEFF  ZERO WIDTH NO-BREAK SPACE
  944  */
  945   return ((ch & ~(gunichar)0x007F) == 0x2000 && (
  946         (ch >= 0x200B && ch <= 0x200F) ||
  947         (ch >= 0x202A && ch <= 0x202E) ||
  948         (ch >= 0x2060 && ch <= 0x2063) ||
  949         (ch == 0x2028)
  950      )) || G_UNLIKELY (ch == 0x00AD
  951             || ch == 0x034F
  952             || ch == 0xFEFF);
  953 }
  954 
  955 /**
  956  * pango_quantize_line_geometry:
  957  * @thickness: (inout): pointer to the thickness of a line, in Pango units
  958  * @position: (inout): corresponding position
  959  *
  960  * Quantizes the thickness and position of a line, typically an
  961  * underline or strikethrough, to whole device pixels, that is integer
  962  * multiples of %PANGO_SCALE. The purpose of this function is to avoid
  963  * such lines looking blurry.
  964  *
  965  * Care is taken to make sure @thickness is at least one pixel when this
  966  * function returns, but returned @position may become zero as a result
  967  * of rounding.
  968  *
  969  * Since: 1.12
  970  */
  971 void
  972 pango_quantize_line_geometry (int *thickness,
  973                   int *position)
  974 {
  975   int thickness_pixels = (*thickness + PANGO_SCALE / 2) / PANGO_SCALE;
  976   if (thickness_pixels == 0)
  977     thickness_pixels = 1;
  978 
  979   if (thickness_pixels & 1)
  980     {
  981       int new_center = ((*position - *thickness / 2) & ~(PANGO_SCALE - 1)) + PANGO_SCALE / 2;
  982       *position = new_center + (PANGO_SCALE * thickness_pixels) / 2;
  983     }
  984   else
  985     {
  986       int new_center = ((*position - *thickness / 2 + PANGO_SCALE / 2) & ~(PANGO_SCALE - 1));
  987       *position = new_center + (PANGO_SCALE * thickness_pixels) / 2;
  988     }
  989 
  990   *thickness = thickness_pixels * PANGO_SCALE;
  991 }
  992 
  993 /**
  994  * pango_units_from_double:
  995  * @d: double floating-point value
  996  *
  997  * Converts a floating-point number to Pango units: multiplies
  998  * it by %PANGO_SCALE and rounds to nearest integer.
  999  *
 1000  * Return value: the value in Pango units.
 1001  *
 1002  * Since: 1.16
 1003  */
 1004 int
 1005 pango_units_from_double (double d)
 1006 {
 1007   return (int)floor (d * PANGO_SCALE + 0.5);
 1008 }
 1009 
 1010 /**
 1011  * pango_units_to_double:
 1012  * @i: value in Pango units
 1013  *
 1014  * Converts a number in Pango units to floating-point: divides
 1015  * it by %PANGO_SCALE.
 1016  *
 1017  * Return value: the double value.
 1018  *
 1019  * Since: 1.16
 1020  */
 1021 double
 1022 pango_units_to_double (int i)
 1023 {
 1024   return (double)i / PANGO_SCALE;
 1025 }
 1026 
 1027 /**
 1028  * pango_extents_to_pixels:
 1029  * @inclusive: (allow-none): rectangle to round to pixels inclusively, or %NULL.
 1030  * @nearest: (allow-none): rectangle to round to nearest pixels, or %NULL.
 1031  *
 1032  * Converts extents from Pango units to device units, dividing by the
 1033  * %PANGO_SCALE factor and performing rounding.
 1034  *
 1035  * The @inclusive rectangle is converted by flooring the x/y coordinates and extending
 1036  * width/height, such that the final rectangle completely includes the original
 1037  * rectangle.
 1038  *
 1039  * The @nearest rectangle is converted by rounding the coordinates
 1040  * of the rectangle to the nearest device unit (pixel).
 1041  *
 1042  * The rule to which argument to use is: if you want the resulting device-space
 1043  * rectangle to completely contain the original rectangle, pass it in as @inclusive.
 1044  * If you want two touching-but-not-overlapping rectangles stay
 1045  * touching-but-not-overlapping after rounding to device units, pass them in
 1046  * as @nearest.
 1047  *
 1048  * Since: 1.16
 1049  **/
 1050 void
 1051 pango_extents_to_pixels (PangoRectangle *inclusive,
 1052              PangoRectangle *nearest)
 1053 {
 1054   if (inclusive)
 1055     {
 1056       int orig_x = inclusive->x;
 1057       int orig_y = inclusive->y;
 1058 
 1059       inclusive->x = PANGO_PIXELS_FLOOR (inclusive->x);
 1060       inclusive->y = PANGO_PIXELS_FLOOR (inclusive->y);
 1061 
 1062       inclusive->width  = PANGO_PIXELS_CEIL (orig_x + inclusive->width ) - inclusive->x;
 1063       inclusive->height = PANGO_PIXELS_CEIL (orig_y + inclusive->height) - inclusive->y;
 1064     }
 1065 
 1066   if (nearest)
 1067     {
 1068       int orig_x = nearest->x;
 1069       int orig_y = nearest->y;
 1070 
 1071       nearest->x = PANGO_PIXELS (nearest->x);
 1072       nearest->y = PANGO_PIXELS (nearest->y);
 1073 
 1074       nearest->width  = PANGO_PIXELS (orig_x + nearest->width ) - nearest->x;
 1075       nearest->height = PANGO_PIXELS (orig_y + nearest->height) - nearest->y;
 1076     }
 1077 }
 1078 
 1079 
 1080 
 1081 
 1082 
 1083 /*********************************************************
 1084  * Some internal functions for handling PANGO_ATTR_SHAPE *
 1085  ********************************************************/
 1086 
 1087 void
 1088 _pango_shape_shape (const char       *text,
 1089             unsigned int      n_chars,
 1090             PangoRectangle   *shape_ink G_GNUC_UNUSED,
 1091             PangoRectangle   *shape_logical,
 1092             PangoGlyphString *glyphs)
 1093 {
 1094   unsigned int i;
 1095   const char *p;
 1096 
 1097   pango_glyph_string_set_size (glyphs, n_chars);
 1098 
 1099   for (i=0, p = text; i < n_chars; i++, p = g_utf8_next_char (p))
 1100     {
 1101       glyphs->glyphs[i].glyph = PANGO_GLYPH_EMPTY;
 1102       glyphs->glyphs[i].geometry.x_offset = 0;
 1103       glyphs->glyphs[i].geometry.y_offset = 0;
 1104       glyphs->glyphs[i].geometry.width = shape_logical->width;
 1105       glyphs->glyphs[i].attr.is_cluster_start = 1;
 1106 
 1107       glyphs->log_clusters[i] = p - text;
 1108     }
 1109 }
 1110 
 1111 void
 1112 _pango_shape_get_extents (gint              n_chars,
 1113               PangoRectangle   *shape_ink,
 1114               PangoRectangle   *shape_logical,
 1115               PangoRectangle   *ink_rect,
 1116               PangoRectangle   *logical_rect)
 1117 {
 1118   if (n_chars > 0)
 1119     {
 1120       if (ink_rect)
 1121     {
 1122       ink_rect->x = MIN (shape_ink->x, shape_ink->x + shape_logical->width * (n_chars - 1));
 1123       ink_rect->width = MAX (shape_ink->width, shape_ink->width + shape_logical->width * (n_chars - 1));
 1124       ink_rect->y = shape_ink->y;
 1125       ink_rect->height = shape_ink->height;
 1126     }
 1127       if (logical_rect)
 1128     {
 1129       logical_rect->x = MIN (shape_logical->x, shape_logical->x + shape_logical->width * (n_chars - 1));
 1130       logical_rect->width = MAX (shape_logical->width, shape_logical->width + shape_logical->width * (n_chars - 1));
 1131       logical_rect->y = shape_logical->y;
 1132       logical_rect->height = shape_logical->height;
 1133     }
 1134     }
 1135   else
 1136     {
 1137       if (ink_rect)
 1138     {
 1139       ink_rect->x = 0;
 1140       ink_rect->y = 0;
 1141       ink_rect->width = 0;
 1142       ink_rect->height = 0;
 1143     }
 1144 
 1145       if (logical_rect)
 1146     {
 1147       logical_rect->x = 0;
 1148       logical_rect->y = 0;
 1149       logical_rect->width = 0;
 1150       logical_rect->height = 0;
 1151     }
 1152     }
 1153 }
 1154