Behdad Esfahbod | 64aef3a | 2008-01-23 16:14:38 -0500 | [diff] [blame] | 1 | /* |
Behdad Esfahbod | 6c78683 | 2009-05-25 03:22:19 -0400 | [diff] [blame] | 2 | * Copyright (C) 2007,2008,2009 Red Hat, Inc. |
Behdad Esfahbod | 64aef3a | 2008-01-23 16:14:38 -0500 | [diff] [blame] | 3 | * |
Behdad Esfahbod | c755cb3 | 2010-04-22 00:11:43 -0400 | [diff] [blame] | 4 | * This is part of HarfBuzz, a text shaping library. |
Behdad Esfahbod | 64aef3a | 2008-01-23 16:14:38 -0500 | [diff] [blame] | 5 | * |
| 6 | * Permission is hereby granted, without written agreement and without |
| 7 | * license or royalty fees, to use, copy, modify, and distribute this |
| 8 | * software and its documentation for any purpose, provided that the |
| 9 | * above copyright notice and the following two paragraphs appear in |
| 10 | * all copies of this software. |
| 11 | * |
| 12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| 15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 16 | * DAMAGE. |
| 17 | * |
| 18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| 21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 23 | * |
| 24 | * Red Hat Author(s): Behdad Esfahbod |
| 25 | */ |
| 26 | |
Behdad Esfahbod | 8dd1c8b | 2008-01-23 05:00:30 -0500 | [diff] [blame] | 27 | #ifndef HB_PRIVATE_H |
| 28 | #define HB_PRIVATE_H |
Behdad Esfahbod | 5b3f770 | 2006-12-28 06:42:37 -0500 | [diff] [blame] | 29 | |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 30 | #if HAVE_CONFIG_H |
| 31 | #include "config.h" |
| 32 | #endif |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 33 | |
Behdad Esfahbod | bc20045 | 2010-04-29 01:40:26 -0400 | [diff] [blame] | 34 | #include "hb-common.h" |
Behdad Esfahbod | b28815c | 2009-08-04 22:35:36 -0400 | [diff] [blame] | 35 | |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 36 | #include <stdlib.h> |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 37 | #include <string.h> |
| 38 | #include <assert.h> |
Behdad Esfahbod | 1d52151 | 2010-04-28 13:18:41 -0400 | [diff] [blame] | 39 | |
| 40 | /* We only use these two for debug output. However, the debug code is |
| 41 | * always seen by the compiler (and optimized out in non-debug builds. |
| 42 | * If including these becomes a problem, we can start thinking about |
| 43 | * someway around that. */ |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 44 | #include <stdio.h> |
| 45 | #include <errno.h> |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 46 | |
Behdad Esfahbod | bc20045 | 2010-04-29 01:40:26 -0400 | [diff] [blame] | 47 | |
| 48 | /* Essentials */ |
| 49 | |
| 50 | #ifndef NULL |
| 51 | # define NULL ((void *) 0) |
| 52 | #endif |
| 53 | |
| 54 | #undef FALSE |
| 55 | #define FALSE 0 |
| 56 | |
| 57 | #undef TRUE |
| 58 | #define TRUE 1 |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 59 | |
Behdad Esfahbod | a794ebf | 2009-08-06 12:32:35 -0400 | [diff] [blame] | 60 | |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 61 | /* Basics */ |
| 62 | |
| 63 | #undef MIN |
| 64 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) |
| 65 | |
Behdad Esfahbod | 8a3511a | 2009-11-04 19:45:39 -0500 | [diff] [blame] | 66 | #undef MAX |
| 67 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) |
| 68 | |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 69 | #ifndef HB_INTERNAL |
Behdad Esfahbod | 081819e | 2009-08-10 23:40:28 -0400 | [diff] [blame] | 70 | # define HB_INTERNAL extern |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 71 | #endif |
| 72 | |
Behdad Esfahbod | 4591753 | 2009-11-04 18:15:59 -0500 | [diff] [blame] | 73 | #undef ARRAY_LENGTH |
| 74 | #define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 75 | |
Behdad Esfahbod | 35a7383 | 2009-08-01 19:30:31 -0400 | [diff] [blame] | 76 | #define HB_STMT_START do |
| 77 | #define HB_STMT_END while (0) |
Behdad Esfahbod | 5b3f770 | 2006-12-28 06:42:37 -0500 | [diff] [blame] | 78 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 79 | #define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] |
| 80 | #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) |
| 81 | #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) |
| 82 | |
Behdad Esfahbod | bc20045 | 2010-04-29 01:40:26 -0400 | [diff] [blame] | 83 | |
| 84 | /* Misc */ |
| 85 | |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 86 | |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 87 | #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) |
Behdad Esfahbod | 7951279 | 2009-11-03 20:27:05 -0500 | [diff] [blame] | 88 | #define _HB_BOOLEAN_EXPR(expr) \ |
| 89 | __extension__ ({ \ |
| 90 | int _hb_boolean_var_; \ |
| 91 | if (expr) \ |
| 92 | _hb_boolean_var_ = 1; \ |
| 93 | else \ |
| 94 | _hb_boolean_var_ = 0; \ |
| 95 | _hb_boolean_var_; \ |
| 96 | }) |
Behdad Esfahbod | 64d3fc8 | 2010-05-03 22:51:19 -0400 | [diff] [blame] | 97 | #define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1)) |
| 98 | #define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0)) |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 99 | #else |
Behdad Esfahbod | 64d3fc8 | 2010-05-03 22:51:19 -0400 | [diff] [blame] | 100 | #define likely(expr) (expr) |
| 101 | #define unlikely(expr) (expr) |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 102 | #endif |
| 103 | |
| 104 | #ifndef __GNUC__ |
| 105 | #undef __attribute__ |
| 106 | #define __attribute__(x) |
| 107 | #endif |
| 108 | |
| 109 | #if __GNUC__ >= 3 |
Behdad Esfahbod | 33d13fd | 2010-04-29 13:56:44 -0400 | [diff] [blame] | 110 | #define HB_PURE_FUNC __attribute__((pure)) |
| 111 | #define HB_CONST_FUNC __attribute__((const)) |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 112 | #else |
Behdad Esfahbod | 33d13fd | 2010-04-29 13:56:44 -0400 | [diff] [blame] | 113 | #define HB_PURE_FUNC |
| 114 | #define HB_CONST_FUNC |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 115 | #endif |
Behdad Esfahbod | bc7830e | 2010-02-17 15:14:57 -0500 | [diff] [blame] | 116 | #if __GNUC__ >= 4 |
Behdad Esfahbod | 33d13fd | 2010-04-29 13:56:44 -0400 | [diff] [blame] | 117 | #define HB_UNUSED __attribute__((unused)) |
Behdad Esfahbod | bc7830e | 2010-02-17 15:14:57 -0500 | [diff] [blame] | 118 | #else |
Behdad Esfahbod | 33d13fd | 2010-04-29 13:56:44 -0400 | [diff] [blame] | 119 | #define HB_UNUSED |
Behdad Esfahbod | bc7830e | 2010-02-17 15:14:57 -0500 | [diff] [blame] | 120 | #endif |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 121 | |
| 122 | |
| 123 | #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) |
| 124 | #define snprintf _snprintf |
| 125 | #endif |
| 126 | |
| 127 | #ifdef _MSC_VER |
| 128 | #undef inline |
| 129 | #define inline __inline |
| 130 | #endif |
| 131 | |
| 132 | #ifdef __STRICT_ANSI__ |
| 133 | #undef inline |
| 134 | #define inline __inline__ |
| 135 | #endif |
| 136 | |
| 137 | |
Behdad Esfahbod | 7d3a126 | 2010-04-29 13:54:01 -0400 | [diff] [blame] | 138 | #if __GNUC__ >= 3 |
| 139 | #define HB_FUNC __PRETTY_FUNCTION__ |
| 140 | #elif defined(_MSC_VER) |
| 141 | #define HB_FUNC __FUNCSIG__ |
| 142 | #else |
| 143 | #define HB_FUNC __func__ |
| 144 | #endif |
| 145 | |
| 146 | |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 147 | /* Return the number of 1 bits in mask. |
| 148 | * |
| 149 | * GCC 3.4 supports a "population count" builtin, which on many targets is |
| 150 | * implemented with a single instruction. There is a fallback definition |
| 151 | * in libgcc in case a target does not have one, which should be just as |
| 152 | * good as the open-coded solution below, (which is "HACKMEM 169"). |
| 153 | */ |
Jeff Muizelaar | eaf29ed | 2010-05-03 22:27:56 -0400 | [diff] [blame] | 154 | static inline unsigned int |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 155 | _hb_popcount32 (uint32_t mask) |
| 156 | { |
| 157 | #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) |
| 158 | return __builtin_popcount (mask); |
| 159 | #else |
Behdad Esfahbod | 9faee63 | 2009-08-06 10:24:49 -0400 | [diff] [blame] | 160 | register uint32_t y; |
Behdad Esfahbod | c7d457a | 2009-05-21 12:46:29 -0400 | [diff] [blame] | 161 | |
| 162 | y = (mask >> 1) &033333333333; |
| 163 | y = mask - y - ((y >>1) & 033333333333); |
| 164 | return (((y + (y >> 3)) & 030707070707) % 077); |
| 165 | #endif |
| 166 | } |
| 167 | |
Behdad Esfahbod | df66028 | 2009-08-01 20:46:02 -0400 | [diff] [blame] | 168 | |
Behdad Esfahbod | 3c69bd4 | 2009-08-17 16:48:13 -0400 | [diff] [blame] | 169 | /* Multiplies a 16dot16 value by another value, then truncates the result */ |
Behdad Esfahbod | 06558d2 | 2010-04-19 02:34:10 -0400 | [diff] [blame] | 170 | #define _hb_16dot16_mul_round(A,B) (((int64_t) (A) * (B) + 0x8000) / 0x10000) |
Behdad Esfahbod | 3c69bd4 | 2009-08-17 16:48:13 -0400 | [diff] [blame] | 171 | |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 172 | |
| 173 | /* We need external help for these */ |
| 174 | |
| 175 | #ifdef HAVE_GLIB |
| 176 | |
| 177 | #include <glib.h> |
| 178 | |
| 179 | typedef int hb_atomic_int_t; |
| 180 | #define hb_atomic_int_fetch_and_add(AI, V) g_atomic_int_exchange_and_add (&(AI), V) |
| 181 | #define hb_atomic_int_get(AI) g_atomic_int_get (&(AI)) |
| 182 | #define hb_atomic_int_set(AI, V) g_atomic_int_set (&(AI), V) |
| 183 | |
| 184 | typedef GStaticMutex hb_mutex_t; |
| 185 | #define HB_MUTEX_INIT G_STATIC_MUTEX_INIT |
| 186 | #define hb_mutex_init(M) g_static_mutex_init (&M) |
| 187 | #define hb_mutex_lock(M) g_static_mutex_lock (&M) |
| 188 | #define hb_mutex_trylock(M) g_static_mutex_trylock (&M) |
| 189 | #define hb_mutex_unlock(M) g_static_mutex_unlock (&M) |
| 190 | |
| 191 | #else |
| 192 | |
| 193 | #ifdef _MSC_VER |
| 194 | #pragma message(__LOC__"Could not find any system to define platform macros, library will NOT be thread-safe") |
| 195 | #else |
| 196 | #warning "Could not find any system to define platform macros, library will NOT be thread-safe" |
| 197 | #endif |
| 198 | |
| 199 | typedef int hb_atomic_int_t; |
| 200 | #define hb_atomic_int_fetch_and_add(AI, V) ((AI) += (V), (AI) - (V)) |
| 201 | #define hb_atomic_int_get(AI) (AI) |
Behdad Esfahbod | ffff7dc | 2010-04-21 02:13:55 -0400 | [diff] [blame] | 202 | #define hb_atomic_int_set(AI, V) HB_STMT_START { (AI) = (V); } HB_STMT_END |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 203 | |
| 204 | typedef int hb_mutex_t; |
Behdad Esfahbod | ffff7dc | 2010-04-21 02:13:55 -0400 | [diff] [blame] | 205 | #define HB_MUTEX_INIT 0 |
| 206 | #define hb_mutex_init(M) HB_STMT_START { (M) = 0; } HB_STMT_END |
| 207 | #define hb_mutex_lock(M) HB_STMT_START { (M) = 1; } HB_STMT_END |
| 208 | #define hb_mutex_trylock(M) ((M) = 1, 1) |
| 209 | #define hb_mutex_unlock(M) HB_STMT_START { (M) = 0; } HB_STMT_END |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 210 | |
| 211 | #endif |
| 212 | |
| 213 | |
| 214 | /* Big-endian handling */ |
| 215 | |
Behdad Esfahbod | 7a52f28 | 2010-04-21 02:14:44 -0400 | [diff] [blame] | 216 | #define hb_be_uint16(v) ((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1]))) |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 217 | |
Behdad Esfahbod | e032ed9 | 2010-04-21 03:11:46 -0400 | [diff] [blame] | 218 | #define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END |
Behdad Esfahbod | 7a52f28 | 2010-04-21 02:14:44 -0400 | [diff] [blame] | 219 | #define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1]) |
| 220 | #define hb_be_uint16_cmp(a,b) (a[0] == b[0] && a[1] == b[1]) |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 221 | |
Behdad Esfahbod | e032ed9 | 2010-04-21 03:11:46 -0400 | [diff] [blame] | 222 | #define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END |
Behdad Esfahbod | 7a52f28 | 2010-04-21 02:14:44 -0400 | [diff] [blame] | 223 | #define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3]) |
| 224 | #define hb_be_uint32_cmp(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]) |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 225 | |
| 226 | |
Behdad Esfahbod | bc20045 | 2010-04-29 01:40:26 -0400 | [diff] [blame] | 227 | /* Debug */ |
| 228 | |
| 229 | #ifndef HB_DEBUG |
| 230 | #define HB_DEBUG 0 |
| 231 | #endif |
| 232 | |
Jeff Muizelaar | eaf29ed | 2010-05-03 22:27:56 -0400 | [diff] [blame] | 233 | static inline hb_bool_t /* always returns TRUE */ |
Behdad Esfahbod | bc20045 | 2010-04-29 01:40:26 -0400 | [diff] [blame] | 234 | _hb_trace (const char *what, |
| 235 | const char *function, |
| 236 | const void *obj, |
| 237 | unsigned int depth, |
| 238 | unsigned int max_depth) |
| 239 | { |
| 240 | if (depth < max_depth) |
| 241 | fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, depth, depth, function); |
| 242 | return TRUE; |
| 243 | } |
| 244 | |
Behdad Esfahbod | f60f216 | 2010-04-21 02:12:45 -0400 | [diff] [blame] | 245 | |
Behdad Esfahbod | ba8d94c | 2009-08-01 20:29:22 -0400 | [diff] [blame] | 246 | #include "hb-object-private.h" |
| 247 | |
Behdad Esfahbod | 8dd1c8b | 2008-01-23 05:00:30 -0500 | [diff] [blame] | 248 | #endif /* HB_PRIVATE_H */ |