LCOV - app.info - gfx/harfbuzz/src/hb-common.cc

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