LCOV - code coverage report
Current view: directory - gfx/harfbuzz/src - hb-common.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 105 5 4.8 %
Date: 2012-06-02 Functions: 25 4 16.0 %

       1                 : /*
       2                 :  * Copyright © 2009,2010  Red Hat, Inc.
       3                 :  * Copyright © 2011  Google, Inc.
       4                 :  *
       5                 :  *  This is part of HarfBuzz, a text shaping library.
       6                 :  *
       7                 :  * Permission is hereby granted, without written agreement and without
       8                 :  * license or royalty fees, to use, copy, modify, and distribute this
       9                 :  * software and its documentation for any purpose, provided that the
      10                 :  * above copyright notice and the following two paragraphs appear in
      11                 :  * all copies of this software.
      12                 :  *
      13                 :  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
      14                 :  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
      15                 :  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
      16                 :  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
      17                 :  * DAMAGE.
      18                 :  *
      19                 :  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
      20                 :  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      21                 :  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
      22                 :  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
      23                 :  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      24                 :  *
      25                 :  * Red Hat Author(s): Behdad Esfahbod
      26                 :  * Google Author(s): Behdad Esfahbod
      27                 :  */
      28                 : 
      29                 : #include "hb-private.hh"
      30                 : 
      31                 : #include "hb-version.h"
      32                 : 
      33                 : #include "hb-mutex-private.hh"
      34                 : #include "hb-object-private.hh"
      35                 : 
      36                 : #include <locale.h>
      37                 : 
      38                 : 
      39                 : 
      40                 : /* hb_tag_t */
      41                 : 
      42                 : hb_tag_t
      43               0 : hb_tag_from_string (const char *s, int len)
      44                 : {
      45                 :   char tag[4];
      46                 :   unsigned int i;
      47                 : 
      48               0 :   if (!s || !len || !*s)
      49               0 :     return HB_TAG_NONE;
      50                 : 
      51               0 :   if (len < 0 || len > 4)
      52               0 :     len = 4;
      53               0 :   for (i = 0; i < (unsigned) len && s[i]; i++)
      54               0 :     tag[i] = s[i];
      55               0 :   for (; i < 4; i++)
      56               0 :     tag[i] = ' ';
      57                 : 
      58               0 :   return HB_TAG_CHAR4 (tag);
      59                 : }
      60                 : 
      61                 : 
      62                 : /* hb_direction_t */
      63                 : 
      64                 : const char direction_strings[][4] = {
      65                 :   "ltr",
      66                 :   "rtl",
      67                 :   "ttb",
      68                 :   "btt"
      69                 : };
      70                 : 
      71                 : hb_direction_t
      72               0 : hb_direction_from_string (const char *str, int len)
      73                 : {
      74               0 :   if (unlikely (!str || !len || !*str))
      75               0 :     return HB_DIRECTION_INVALID;
      76                 : 
      77                 :   /* Lets match loosely: just match the first letter, such that
      78                 :    * all of "ltr", "left-to-right", etc work!
      79                 :    */
      80               0 :   char c = TOLOWER (str[0]);
      81               0 :   for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++)
      82               0 :     if (c == direction_strings[i][0])
      83               0 :       return (hb_direction_t) i;
      84                 : 
      85               0 :   return HB_DIRECTION_INVALID;
      86                 : }
      87                 : 
      88                 : const char *
      89               0 : hb_direction_to_string (hb_direction_t direction)
      90                 : {
      91               0 :   if (likely ((unsigned int) direction < ARRAY_LENGTH (direction_strings)))
      92               0 :     return direction_strings[direction];
      93                 : 
      94               0 :   return "invalid";
      95                 : }
      96                 : 
      97                 : 
      98                 : /* hb_language_t */
      99                 : 
     100                 : struct _hb_language_t {
     101                 :   const char s[1];
     102                 : };
     103                 : 
     104                 : static const char canon_map[256] = {
     105                 :    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
     106                 :    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
     107                 :    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
     108                 :   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
     109                 :   '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
     110                 :   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
     111                 :    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
     112                 :   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
     113                 : };
     114                 : 
     115                 : static hb_bool_t
     116               0 : lang_equal (const void *v1,
     117                 :             const void *v2)
     118                 : {
     119               0 :   const unsigned char *p1 = (const unsigned char *) v1;
     120               0 :   const unsigned char *p2 = (const unsigned char *) v2;
     121                 : 
     122               0 :   while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
     123                 :     {
     124               0 :       p1++, p2++;
     125                 :     }
     126                 : 
     127               0 :   return (canon_map[*p1] == canon_map[*p2]);
     128                 : }
     129                 : 
     130                 : #if 0
     131                 : static unsigned int
     132                 : lang_hash (const void *key)
     133                 : {
     134                 :   const unsigned char *p = key;
     135                 :   unsigned int h = 0;
     136                 :   while (canon_map[*p])
     137                 :     {
     138                 :       h = (h << 5) - h + canon_map[*p];
     139                 :       p++;
     140                 :     }
     141                 : 
     142                 :   return h;
     143                 : }
     144                 : #endif
     145                 : 
     146                 : 
     147                 : struct hb_language_item_t {
     148                 : 
     149                 :   hb_language_t lang;
     150                 : 
     151               0 :   inline bool operator == (const char *s) const {
     152               0 :     return lang_equal (lang, s);
     153                 :   }
     154                 : 
     155               0 :   inline hb_language_item_t & operator = (const char *s) {
     156               0 :     lang = (hb_language_t) strdup (s);
     157               0 :     for (unsigned char *p = (unsigned char *) lang; *p; p++)
     158               0 :       *p = canon_map[*p];
     159                 : 
     160               0 :     return *this;
     161                 :   }
     162                 : 
     163               0 :   void finish (void) { free (lang); }
     164                 : };
     165                 : 
     166            1464 : static struct hb_static_lang_set_t : hb_lockable_set_t<hb_language_item_t, hb_static_mutex_t> {
     167            1487 :   ~hb_static_lang_set_t (void) { this->finish (lock); }
     168                 :   hb_static_mutex_t lock;
     169            1464 : } langs;
     170                 : 
     171                 : hb_language_t
     172               0 : hb_language_from_string (const char *str, int len)
     173                 : {
     174               0 :   if (!str || !len || !*str)
     175               0 :     return HB_LANGUAGE_INVALID;
     176                 : 
     177                 :   char strbuf[32];
     178               0 :   if (len >= 0) {
     179               0 :     len = MIN (len, (int) sizeof (strbuf) - 1);
     180               0 :     str = (char *) memcpy (strbuf, str, len);
     181               0 :     strbuf[len] = '\0';
     182                 :   }
     183                 : 
     184               0 :   hb_language_item_t *item = langs.find_or_insert (str, langs.lock);
     185                 : 
     186               0 :   return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
     187                 : }
     188                 : 
     189                 : const char *
     190               0 : hb_language_to_string (hb_language_t language)
     191                 : {
     192                 :   /* This is actually NULL-safe! */
     193               0 :   return language->s;
     194                 : }
     195                 : 
     196                 : hb_language_t
     197               0 : hb_language_get_default (void)
     198                 : {
     199                 :   static hb_language_t default_language;
     200                 : 
     201               0 :   if (!default_language) {
     202                 :     /* This block is not quite threadsafe, but is not as bad as
     203                 :      * it looks since it's idempotent.  As long as pointer ops
     204                 :      * are atomic, we are safe. */
     205                 : 
     206                 :     /* I hear that setlocale() doesn't honor env vars on Windows,
     207                 :      * but for now we ignore that. */
     208                 : 
     209               0 :     default_language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
     210                 :   }
     211                 : 
     212               0 :   return default_language;
     213                 : }
     214                 : 
     215                 : 
     216                 : /* hb_script_t */
     217                 : 
     218                 : hb_script_t
     219               0 : hb_script_from_iso15924_tag (hb_tag_t tag)
     220                 : {
     221               0 :   if (unlikely (tag == HB_TAG_NONE))
     222               0 :     return HB_SCRIPT_INVALID;
     223                 : 
     224                 :   /* Be lenient, adjust case (one capital letter followed by three small letters) */
     225               0 :   tag = (tag & 0xDFDFDFDF) | 0x00202020;
     226                 : 
     227               0 :   switch (tag) {
     228                 : 
     229                 :     /* These graduated from the 'Q' private-area codes, but
     230                 :      * the old code is still aliased by Unicode, and the Qaai
     231                 :      * one in use by ICU. */
     232               0 :     case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
     233               0 :     case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
     234                 : 
     235                 :     /* Script variants from http://unicode.org/iso15924/ */
     236               0 :     case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC;
     237               0 :     case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
     238               0 :     case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
     239               0 :     case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC;
     240               0 :     case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC;
     241               0 :     case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC;
     242                 :   }
     243                 : 
     244                 :   /* If it looks right, just use the tag as a script */
     245               0 :   if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
     246               0 :     return (hb_script_t) tag;
     247                 : 
     248                 :   /* Otherwise, return unknown */
     249               0 :   return HB_SCRIPT_UNKNOWN;
     250                 : }
     251                 : 
     252                 : hb_script_t
     253               0 : hb_script_from_string (const char *s, int len)
     254                 : {
     255               0 :   return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
     256                 : }
     257                 : 
     258                 : hb_tag_t
     259               0 : hb_script_to_iso15924_tag (hb_script_t script)
     260                 : {
     261               0 :   return (hb_tag_t) script;
     262                 : }
     263                 : 
     264                 : hb_direction_t
     265               0 : hb_script_get_horizontal_direction (hb_script_t script)
     266                 : {
     267               0 :   switch ((hb_tag_t) script)
     268                 :   {
     269                 :     case HB_SCRIPT_ARABIC:
     270                 :     case HB_SCRIPT_HEBREW:
     271                 :     case HB_SCRIPT_SYRIAC:
     272                 :     case HB_SCRIPT_THAANA:
     273                 : 
     274                 :     /* Unicode-4.0 additions */
     275                 :     case HB_SCRIPT_CYPRIOT:
     276                 : 
     277                 :     /* Unicode-5.0 additions */
     278                 :     case HB_SCRIPT_PHOENICIAN:
     279                 :     case HB_SCRIPT_NKO:
     280                 : 
     281                 :     /* Unicode-5.2 additions */
     282                 :     case HB_SCRIPT_AVESTAN:
     283                 :     case HB_SCRIPT_IMPERIAL_ARAMAIC:
     284                 :     case HB_SCRIPT_INSCRIPTIONAL_PAHLAVI:
     285                 :     case HB_SCRIPT_INSCRIPTIONAL_PARTHIAN:
     286                 :     case HB_SCRIPT_OLD_SOUTH_ARABIAN:
     287                 :     case HB_SCRIPT_OLD_TURKIC:
     288                 :     case HB_SCRIPT_SAMARITAN:
     289                 : 
     290                 :     /* Unicode-6.0 additions */
     291                 :     case HB_SCRIPT_MANDAIC:
     292                 : 
     293               0 :       return HB_DIRECTION_RTL;
     294                 :   }
     295                 : 
     296               0 :   return HB_DIRECTION_LTR;
     297                 : }
     298                 : 
     299                 : 
     300                 : /* hb_user_data_array_t */
     301                 : 
     302                 : 
     303                 : /* NOTE: Currently we use a global lock for user_data access
     304                 :  * threadsafety.  If one day we add a mutex to any object, we
     305                 :  * should switch to using that insted for these too.
     306                 :  */
     307                 : 
     308            1464 : static hb_static_mutex_t user_data_lock;
     309                 : 
     310                 : bool
     311               0 : hb_user_data_array_t::set (hb_user_data_key_t *key,
     312                 :                            void *              data,
     313                 :                            hb_destroy_func_t   destroy,
     314                 :                            hb_bool_t           replace)
     315                 : {
     316               0 :   if (!key)
     317               0 :     return false;
     318                 : 
     319               0 :   if (replace) {
     320               0 :     if (!data && !destroy) {
     321               0 :       items.remove (key, user_data_lock);
     322               0 :       return true;
     323                 :     }
     324                 :   }
     325               0 :   hb_user_data_item_t item = {key, data, destroy};
     326               0 :   bool ret = !!items.replace_or_insert (item, user_data_lock, replace);
     327                 : 
     328               0 :   return ret;
     329                 : }
     330                 : 
     331                 : void *
     332               0 : hb_user_data_array_t::get (hb_user_data_key_t *key)
     333                 : {
     334               0 :   hb_user_data_item_t item = {NULL };
     335                 : 
     336               0 :   return items.find (key, &item, user_data_lock) ? item.data : NULL;
     337                 : }
     338                 : 
     339                 : void
     340               0 : hb_user_data_array_t::finish (void)
     341                 : {
     342               0 :   items.finish (user_data_lock);
     343               0 : }
     344                 : 
     345                 : 
     346                 : /* hb_version */
     347                 : 
     348                 : void
     349               0 : hb_version (unsigned int *major,
     350                 :             unsigned int *minor,
     351                 :             unsigned int *micro)
     352                 : {
     353               0 :   *major = HB_VERSION_MAJOR;
     354               0 :   *minor = HB_VERSION_MINOR;
     355               0 :   *micro = HB_VERSION_MICRO;
     356               0 : }
     357                 : 
     358                 : const char *
     359               0 : hb_version_string (void)
     360                 : {
     361               0 :   return HB_VERSION_STRING;
     362                 : }
     363                 : 
     364                 : hb_bool_t
     365               0 : hb_version_check (unsigned int major,
     366                 :                   unsigned int minor,
     367                 :                   unsigned int micro)
     368                 : {
     369               0 :   return HB_VERSION_CHECK (major, minor, micro);
     370            4392 : }
     371                 : 
     372                 : 

Generated by: LCOV version 1.7