| OLD | NEW |
| (Empty) |
| 1 #include <stdint.h> | |
| 2 #include <stdlib.h> | |
| 3 | |
| 4 #include <harfbuzz-external.h> | |
| 5 #include <harfbuzz-impl.h> | |
| 6 #include <harfbuzz-shaper.h> | |
| 7 #include "harfbuzz-unicode.h" | |
| 8 | |
| 9 #include "tables/grapheme-break-properties.h" | |
| 10 #include "tables/mirroring-properties.h" | |
| 11 #include "tables/script-properties.h" | |
| 12 | |
| 13 uint32_t | |
| 14 utf16_to_code_point(const uint16_t *chars, size_t len, ssize_t *iter) { | |
| 15 const uint16_t v = chars[(*iter)++]; | |
| 16 if (HB_IsHighSurrogate(v)) { | |
| 17 // surrogate pair | |
| 18 if (*iter >= len) { | |
| 19 // the surrogate is incomplete. | |
| 20 return HB_InvalidCodePoint; | |
| 21 } | |
| 22 const uint16_t v2 = chars[(*iter)++]; | |
| 23 if (!HB_IsLowSurrogate(v2)) { | |
| 24 // invalidate surrogate pair. | |
| 25 return HB_InvalidCodePoint; | |
| 26 } | |
| 27 | |
| 28 return HB_SurrogateToUcs4(v, v2); | |
| 29 } | |
| 30 | |
| 31 if (HB_IsLowSurrogate(v)) { | |
| 32 // this isn't a valid code point | |
| 33 return HB_InvalidCodePoint; | |
| 34 } | |
| 35 | |
| 36 return v; | |
| 37 } | |
| 38 | |
| 39 uint32_t | |
| 40 utf16_to_code_point_prev(const uint16_t *chars, size_t len, ssize_t *iter) { | |
| 41 const uint16_t v = chars[(*iter)--]; | |
| 42 if (HB_IsLowSurrogate(v)) { | |
| 43 // surrogate pair | |
| 44 if (*iter < 0) { | |
| 45 // the surrogate is incomplete. | |
| 46 return HB_InvalidCodePoint; | |
| 47 } | |
| 48 const uint16_t v2 = chars[(*iter)--]; | |
| 49 if (!HB_IsHighSurrogate(v2)) { | |
| 50 // invalidate surrogate pair. | |
| 51 return HB_InvalidCodePoint; | |
| 52 } | |
| 53 | |
| 54 return HB_SurrogateToUcs4(v2, v); | |
| 55 } | |
| 56 | |
| 57 if (HB_IsHighSurrogate(v)) { | |
| 58 // this isn't a valid code point | |
| 59 return HB_InvalidCodePoint; | |
| 60 } | |
| 61 | |
| 62 return v; | |
| 63 } | |
| 64 | |
| 65 static int | |
| 66 script_property_cmp(const void *vkey, const void *vcandidate) { | |
| 67 const uint32_t key = (uint32_t) (intptr_t) vkey; | |
| 68 const struct script_property *candidate = vcandidate; | |
| 69 | |
| 70 if (key < candidate->range_start) { | |
| 71 return -1; | |
| 72 } else if (key > candidate->range_end) { | |
| 73 return 1; | |
| 74 } else { | |
| 75 return 0; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 HB_Script | |
| 80 code_point_to_script(uint32_t cp) { | |
| 81 const void *vprop = bsearch((void *) (intptr_t) cp, script_properties, | |
| 82 script_properties_count, | |
| 83 sizeof(struct script_property), | |
| 84 script_property_cmp); | |
| 85 if (!vprop) | |
| 86 return HB_Script_Common; | |
| 87 | |
| 88 return ((const struct script_property *) vprop)->script; | |
| 89 } | |
| 90 | |
| 91 char | |
| 92 hb_utf16_script_run_next(unsigned *num_code_points, HB_ScriptItem *output, | |
| 93 const uint16_t *chars, size_t len, ssize_t *iter) { | |
| 94 if (*iter == len) | |
| 95 return 0; | |
| 96 | |
| 97 output->pos = *iter; | |
| 98 const uint32_t init_cp = utf16_to_code_point(chars, len, iter); | |
| 99 unsigned cps = 1; | |
| 100 if (init_cp == HB_InvalidCodePoint) | |
| 101 return 0; | |
| 102 const HB_Script init_script = code_point_to_script(init_cp); | |
| 103 HB_Script current_script = init_script; | |
| 104 output->script = init_script; | |
| 105 | |
| 106 for (;;) { | |
| 107 if (*iter == len) | |
| 108 break; | |
| 109 const ssize_t prev_iter = *iter; | |
| 110 const uint32_t cp = utf16_to_code_point(chars, len, iter); | |
| 111 if (cp == HB_InvalidCodePoint) | |
| 112 return 0; | |
| 113 cps++; | |
| 114 const HB_Script script = code_point_to_script(cp); | |
| 115 | |
| 116 if (script != current_script) { | |
| 117 if (current_script == HB_Script_Inherited && init_script == HB_Script_Inhe
rited) { | |
| 118 // If we started off as inherited, we take whatever we can find. | |
| 119 output->script = script; | |
| 120 current_script = script; | |
| 121 continue; | |
| 122 } else if (script == HB_Script_Inherited) { | |
| 123 continue; | |
| 124 } else { | |
| 125 *iter = prev_iter; | |
| 126 cps--; | |
| 127 break; | |
| 128 } | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 if (output->script == HB_Script_Inherited) | |
| 133 output->script = HB_Script_Common; | |
| 134 | |
| 135 output->length = *iter - output->pos; | |
| 136 if (num_code_points) | |
| 137 *num_code_points = cps; | |
| 138 return 1; | |
| 139 } | |
| 140 | |
| 141 char | |
| 142 hb_utf16_script_run_prev(unsigned *num_code_points, HB_ScriptItem *output, | |
| 143 const uint16_t *chars, size_t len, ssize_t *iter) { | |
| 144 if (*iter == (size_t) -1) | |
| 145 return 0; | |
| 146 | |
| 147 const size_t ending_index = *iter; | |
| 148 const uint32_t init_cp = utf16_to_code_point_prev(chars, len, iter); | |
| 149 unsigned cps = 1; | |
| 150 if (init_cp == HB_InvalidCodePoint) | |
| 151 return 0; | |
| 152 const HB_Script init_script = code_point_to_script(init_cp); | |
| 153 HB_Script current_script = init_script; | |
| 154 output->script = init_script; | |
| 155 | |
| 156 for (;;) { | |
| 157 if (*iter < 0) | |
| 158 break; | |
| 159 const ssize_t prev_iter = *iter; | |
| 160 const uint32_t cp = utf16_to_code_point_prev(chars, len, iter); | |
| 161 if (cp == HB_InvalidCodePoint) | |
| 162 return 0; | |
| 163 cps++; | |
| 164 const HB_Script script = code_point_to_script(cp); | |
| 165 | |
| 166 if (script != current_script) { | |
| 167 if (current_script == init_script == HB_Script_Inherited) { | |
| 168 // If we started off as inherited, we take whatever we can find. | |
| 169 output->script = script; | |
| 170 current_script = script; | |
| 171 continue; | |
| 172 } else if (script == HB_Script_Inherited) { | |
| 173 // Just assume that whatever follows this combining character is within | |
| 174 // the same script. This is incorrect if you had language1 + combining | |
| 175 // char + language 2, but that is rare and this code is suspicious | |
| 176 // anyway. | |
| 177 continue; | |
| 178 } else { | |
| 179 *iter = prev_iter; | |
| 180 cps--; | |
| 181 break; | |
| 182 } | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 if (output->script == HB_Script_Inherited) | |
| 187 output->script = HB_Script_Common; | |
| 188 | |
| 189 output->pos = *iter + 1; | |
| 190 output->length = ending_index - *iter; | |
| 191 if (num_code_points) | |
| 192 *num_code_points = cps; | |
| 193 return 1; | |
| 194 } | |
| 195 | |
| 196 static int | |
| 197 grapheme_break_property_cmp(const void *vkey, const void *vcandidate) { | |
| 198 const uint32_t key = (uint32_t) (intptr_t) vkey; | |
| 199 const struct grapheme_break_property *candidate = vcandidate; | |
| 200 | |
| 201 if (key < candidate->range_start) { | |
| 202 return -1; | |
| 203 } else if (key > candidate->range_end) { | |
| 204 return 1; | |
| 205 } else { | |
| 206 return 0; | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 HB_GraphemeClass | |
| 211 HB_GetGraphemeClass(HB_UChar32 ch) { | |
| 212 const void *vprop = bsearch((void *) (intptr_t) ch, grapheme_break_properties, | |
| 213 grapheme_break_properties_count, | |
| 214 sizeof(struct grapheme_break_property), | |
| 215 grapheme_break_property_cmp); | |
| 216 if (!vprop) | |
| 217 return HB_Grapheme_Other; | |
| 218 | |
| 219 return ((const struct grapheme_break_property *) vprop)->klass; | |
| 220 } | |
| 221 | |
| 222 HB_WordClass | |
| 223 HB_GetWordClass(HB_UChar32 ch) { | |
| 224 abort(); | |
| 225 return 0; | |
| 226 } | |
| 227 | |
| 228 HB_SentenceClass | |
| 229 HB_GetSentenceClass(HB_UChar32 ch) { | |
| 230 abort(); | |
| 231 return 0; | |
| 232 } | |
| 233 | |
| 234 void | |
| 235 HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *gclass, HB_Line
BreakClass *breakclass) { | |
| 236 *gclass = HB_GetGraphemeClass(ch); | |
| 237 *breakclass = HB_GetLineBreakClass(ch); | |
| 238 } | |
| 239 | |
| 240 static int | |
| 241 mirroring_property_cmp(const void *vkey, const void *vcandidate) { | |
| 242 const uint32_t key = (uint32_t) (intptr_t) vkey; | |
| 243 const struct mirroring_property *candidate = vcandidate; | |
| 244 | |
| 245 if (key < candidate->a) { | |
| 246 return -1; | |
| 247 } else if (key > candidate->a) { | |
| 248 return 1; | |
| 249 } else { | |
| 250 return 0; | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 HB_UChar16 | |
| 255 HB_GetMirroredChar(HB_UChar16 ch) { | |
| 256 const void *mprop = bsearch((void *) (intptr_t) ch, mirroring_properties, | |
| 257 mirroring_properties_count, | |
| 258 sizeof(struct mirroring_property), | |
| 259 mirroring_property_cmp); | |
| 260 if (!mprop) | |
| 261 return ch; | |
| 262 | |
| 263 return ((const struct mirroring_property *) mprop)->b; | |
| 264 } | |
| 265 | |
| 266 void * | |
| 267 HB_Library_Resolve(const char *library, int version, const char *symbol) { | |
| 268 abort(); | |
| 269 return NULL; | |
| 270 } | |
| OLD | NEW |