| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | |
| 3 * | |
| 4 * This is part of HarfBuzz, an OpenType Layout engine library. | |
| 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 | |
| 25 #include "harfbuzz-shaper.h" | |
| 26 #include "harfbuzz-shaper-private.h" | |
| 27 | |
| 28 #include <assert.h> | |
| 29 #include <stdio.h> | |
| 30 | |
| 31 #define FLAG(x) (1 << (x)) | |
| 32 | |
| 33 static HB_Bool isLetter(HB_UChar16 ucs) | |
| 34 { | |
| 35 const int test = FLAG(HB_Letter_Uppercase) | | |
| 36 FLAG(HB_Letter_Lowercase) | | |
| 37 FLAG(HB_Letter_Titlecase) | | |
| 38 FLAG(HB_Letter_Modifier) | | |
| 39 FLAG(HB_Letter_Other); | |
| 40 return !!(FLAG(HB_GetUnicodeCharCategory(ucs)) & test); | |
| 41 } | |
| 42 | |
| 43 static HB_Bool isMark(HB_UChar16 ucs) | |
| 44 { | |
| 45 const int test = FLAG(HB_Mark_NonSpacing) | | |
| 46 FLAG(HB_Mark_SpacingCombining) | | |
| 47 FLAG(HB_Mark_Enclosing); | |
| 48 return !!(FLAG(HB_GetUnicodeCharCategory(ucs)) & test); | |
| 49 } | |
| 50 | |
| 51 enum Form { | |
| 52 Invalid = 0x0, | |
| 53 UnknownForm = Invalid, | |
| 54 Consonant, | |
| 55 Nukta, | |
| 56 Halant, | |
| 57 Matra, | |
| 58 VowelMark, | |
| 59 StressMark, | |
| 60 IndependentVowel, | |
| 61 LengthMark, | |
| 62 Control, | |
| 63 Other | |
| 64 }; | |
| 65 | |
| 66 static const unsigned char indicForms[0xe00-0x900] = { | |
| 67 // Devangari | |
| 68 Invalid, VowelMark, VowelMark, VowelMark, | |
| 69 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 70 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 71 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 72 | |
| 73 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 74 IndependentVowel, Consonant, Consonant, Consonant, | |
| 75 Consonant, Consonant, Consonant, Consonant, | |
| 76 Consonant, Consonant, Consonant, Consonant, | |
| 77 | |
| 78 Consonant, Consonant, Consonant, Consonant, | |
| 79 Consonant, Consonant, Consonant, Consonant, | |
| 80 Consonant, Consonant, Consonant, Consonant, | |
| 81 Consonant, Consonant, Consonant, Consonant, | |
| 82 | |
| 83 Consonant, Consonant, Consonant, Consonant, | |
| 84 Consonant, Consonant, Consonant, Consonant, | |
| 85 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 86 Nukta, Other, Matra, Matra, | |
| 87 | |
| 88 Matra, Matra, Matra, Matra, | |
| 89 Matra, Matra, Matra, Matra, | |
| 90 Matra, Matra, Matra, Matra, | |
| 91 Matra, Halant, UnknownForm, UnknownForm, | |
| 92 | |
| 93 Other, StressMark, StressMark, StressMark, | |
| 94 StressMark, UnknownForm, UnknownForm, UnknownForm, | |
| 95 Consonant, Consonant, Consonant, Consonant, | |
| 96 Consonant, Consonant, Consonant, Consonant, | |
| 97 | |
| 98 IndependentVowel, IndependentVowel, VowelMark, VowelMark, | |
| 99 Other, Other, Other, Other, | |
| 100 Other, Other, Other, Other, | |
| 101 Other, Other, Other, Other, | |
| 102 | |
| 103 Other, Other, Other, Other, | |
| 104 Other, Other, Other, Other, | |
| 105 Other, Other, Other, Consonant, | |
| 106 Consonant, Consonant /* ??? */, Consonant, Consonant, | |
| 107 | |
| 108 // Bengali | |
| 109 Invalid, VowelMark, VowelMark, VowelMark, | |
| 110 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 111 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 112 IndependentVowel, Invalid, Invalid, IndependentVowel, | |
| 113 | |
| 114 IndependentVowel, Invalid, Invalid, IndependentVowel, | |
| 115 IndependentVowel, Consonant, Consonant, Consonant, | |
| 116 Consonant, Consonant, Consonant, Consonant, | |
| 117 Consonant, Consonant, Consonant, Consonant, | |
| 118 | |
| 119 Consonant, Consonant, Consonant, Consonant, | |
| 120 Consonant, Consonant, Consonant, Consonant, | |
| 121 Consonant, Invalid, Consonant, Consonant, | |
| 122 Consonant, Consonant, Consonant, Consonant, | |
| 123 | |
| 124 Consonant, Invalid, Consonant, Invalid, | |
| 125 Invalid, Invalid, Consonant, Consonant, | |
| 126 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 127 Nukta, Other, Matra, Matra, | |
| 128 | |
| 129 Matra, Matra, Matra, Matra, | |
| 130 Matra, Invalid, Invalid, Matra, | |
| 131 Matra, Invalid, Invalid, Matra, | |
| 132 Matra, Halant, Consonant, UnknownForm, | |
| 133 | |
| 134 Invalid, Invalid, Invalid, Invalid, | |
| 135 Invalid, Invalid, Invalid, VowelMark, | |
| 136 Invalid, Invalid, Invalid, Invalid, | |
| 137 Consonant, Consonant, Invalid, Consonant, | |
| 138 | |
| 139 IndependentVowel, IndependentVowel, VowelMark, VowelMark, | |
| 140 Other, Other, Other, Other, | |
| 141 Other, Other, Other, Other, | |
| 142 Other, Other, Other, Other, | |
| 143 | |
| 144 Consonant, Consonant, Other, Other, | |
| 145 Other, Other, Other, Other, | |
| 146 Other, Other, Other, Other, | |
| 147 Other, Other, Other, Other, | |
| 148 | |
| 149 // Gurmukhi | |
| 150 Invalid, VowelMark, VowelMark, VowelMark, | |
| 151 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 152 IndependentVowel, IndependentVowel, IndependentVowel, Invalid, | |
| 153 Invalid, Invalid, Invalid, IndependentVowel, | |
| 154 | |
| 155 IndependentVowel, Invalid, Invalid, IndependentVowel, | |
| 156 IndependentVowel, Consonant, Consonant, Consonant, | |
| 157 Consonant, Consonant, Consonant, Consonant, | |
| 158 Consonant, Consonant, Consonant, Consonant, | |
| 159 | |
| 160 Consonant, Consonant, Consonant, Consonant, | |
| 161 Consonant, Consonant, Consonant, Consonant, | |
| 162 Consonant, Invalid, Consonant, Consonant, | |
| 163 Consonant, Consonant, Consonant, Consonant, | |
| 164 | |
| 165 Consonant, Invalid, Consonant, Consonant, | |
| 166 Invalid, Consonant, Consonant, Invalid, | |
| 167 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 168 Nukta, Other, Matra, Matra, | |
| 169 | |
| 170 Matra, Matra, Matra, Invalid, | |
| 171 Invalid, Invalid, Invalid, Matra, | |
| 172 Matra, Invalid, Invalid, Matra, | |
| 173 Matra, Halant, UnknownForm, UnknownForm, | |
| 174 | |
| 175 Invalid, Invalid, Invalid, Invalid, | |
| 176 Invalid, UnknownForm, UnknownForm, UnknownForm, | |
| 177 Invalid, Consonant, Consonant, Consonant, | |
| 178 Consonant, Invalid, Consonant, Invalid, | |
| 179 | |
| 180 Other, Other, Invalid, Invalid, | |
| 181 Other, Other, Other, Other, | |
| 182 Other, Other, Other, Other, | |
| 183 Other, Other, Other, Other, | |
| 184 | |
| 185 StressMark, StressMark, Consonant, Consonant, | |
| 186 Other, Other, Other, Other, | |
| 187 Other, Other, Other, Other, | |
| 188 Other, Other, Other, Other, | |
| 189 | |
| 190 // Gujarati | |
| 191 Invalid, VowelMark, VowelMark, VowelMark, | |
| 192 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 193 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 194 IndependentVowel, IndependentVowel, Invalid, IndependentVowel, | |
| 195 | |
| 196 IndependentVowel, IndependentVowel, Invalid, IndependentVowel, | |
| 197 IndependentVowel, Consonant, Consonant, Consonant, | |
| 198 Consonant, Consonant, Consonant, Consonant, | |
| 199 Consonant, Consonant, Consonant, Consonant, | |
| 200 | |
| 201 Consonant, Consonant, Consonant, Consonant, | |
| 202 Consonant, Consonant, Consonant, Consonant, | |
| 203 Consonant, Invalid, Consonant, Consonant, | |
| 204 Consonant, Consonant, Consonant, Consonant, | |
| 205 | |
| 206 Consonant, Invalid, Consonant, Consonant, | |
| 207 Invalid, Consonant, Consonant, Consonant, | |
| 208 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 209 Nukta, Other, Matra, Matra, | |
| 210 | |
| 211 Matra, Matra, Matra, Matra, | |
| 212 Matra, Matra, Invalid, Matra, | |
| 213 Matra, Matra, Invalid, Matra, | |
| 214 Matra, Halant, UnknownForm, UnknownForm, | |
| 215 | |
| 216 Other, UnknownForm, UnknownForm, UnknownForm, | |
| 217 UnknownForm, UnknownForm, UnknownForm, UnknownForm, | |
| 218 UnknownForm, UnknownForm, UnknownForm, UnknownForm, | |
| 219 UnknownForm, UnknownForm, UnknownForm, UnknownForm, | |
| 220 | |
| 221 IndependentVowel, IndependentVowel, VowelMark, VowelMark, | |
| 222 Other, Other, Other, Other, | |
| 223 Other, Other, Other, Other, | |
| 224 Other, Other, Other, Other, | |
| 225 | |
| 226 Other, Other, Other, Other, | |
| 227 Other, Other, Other, Other, | |
| 228 Other, Other, Other, Other, | |
| 229 Other, Other, Other, Other, | |
| 230 | |
| 231 // Oriya | |
| 232 Invalid, VowelMark, VowelMark, VowelMark, | |
| 233 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 234 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 235 IndependentVowel, Invalid, Invalid, IndependentVowel, | |
| 236 | |
| 237 IndependentVowel, Invalid, Invalid, IndependentVowel, | |
| 238 IndependentVowel, Consonant, Consonant, Consonant, | |
| 239 Consonant, Consonant, Consonant, Consonant, | |
| 240 Consonant, Consonant, Consonant, Consonant, | |
| 241 | |
| 242 Consonant, Consonant, Consonant, Consonant, | |
| 243 Consonant, Consonant, Consonant, Consonant, | |
| 244 Consonant, Invalid, Consonant, Consonant, | |
| 245 Consonant, Consonant, Consonant, Consonant, | |
| 246 | |
| 247 Consonant, Invalid, Consonant, Consonant, | |
| 248 Invalid, Consonant, Consonant, Consonant, | |
| 249 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 250 Nukta, Other, Matra, Matra, | |
| 251 | |
| 252 Matra, Matra, Matra, Matra, | |
| 253 Invalid, Invalid, Invalid, Matra, | |
| 254 Matra, Invalid, Invalid, Matra, | |
| 255 Matra, Halant, UnknownForm, UnknownForm, | |
| 256 | |
| 257 Other, Invalid, Invalid, Invalid, | |
| 258 Invalid, UnknownForm, LengthMark, LengthMark, | |
| 259 Invalid, Invalid, Invalid, Invalid, | |
| 260 Consonant, Consonant, Invalid, Consonant, | |
| 261 | |
| 262 IndependentVowel, IndependentVowel, Invalid, Invalid, | |
| 263 Invalid, Invalid, Other, Other, | |
| 264 Other, Other, Other, Other, | |
| 265 Other, Other, Other, Other, | |
| 266 | |
| 267 Other, Consonant, Other, Other, | |
| 268 Other, Other, Other, Other, | |
| 269 Other, Other, Other, Other, | |
| 270 Other, Other, Other, Other, | |
| 271 | |
| 272 //Tamil | |
| 273 Invalid, Invalid, VowelMark, Other, | |
| 274 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 275 IndependentVowel, IndependentVowel, IndependentVowel, Invalid, | |
| 276 Invalid, Invalid, IndependentVowel, IndependentVowel, | |
| 277 | |
| 278 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 279 IndependentVowel, Consonant, Invalid, Invalid, | |
| 280 Invalid, Consonant, Consonant, Invalid, | |
| 281 Consonant, Invalid, Consonant, Consonant, | |
| 282 | |
| 283 Invalid, Invalid, Invalid, Consonant, | |
| 284 Consonant, Invalid, Invalid, Invalid, | |
| 285 Consonant, Consonant, Consonant, Invalid, | |
| 286 Invalid, Invalid, Consonant, Consonant, | |
| 287 | |
| 288 Consonant, Consonant, Consonant, Consonant, | |
| 289 Consonant, Consonant, Consonant, Consonant, | |
| 290 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 291 Invalid, Invalid, Matra, Matra, | |
| 292 | |
| 293 Matra, Matra, Matra, Invalid, | |
| 294 Invalid, Invalid, Matra, Matra, | |
| 295 Matra, Invalid, Matra, Matra, | |
| 296 Matra, Halant, Invalid, Invalid, | |
| 297 | |
| 298 Invalid, Invalid, Invalid, Invalid, | |
| 299 Invalid, Invalid, Invalid, LengthMark, | |
| 300 Invalid, Invalid, Invalid, Invalid, | |
| 301 Invalid, Invalid, Invalid, Invalid, | |
| 302 | |
| 303 Invalid, Invalid, Invalid, Invalid, | |
| 304 Invalid, Invalid, Other, Other, | |
| 305 Other, Other, Other, Other, | |
| 306 Other, Other, Other, Other, | |
| 307 | |
| 308 Other, Other, Other, Other, | |
| 309 Other, Other, Other, Other, | |
| 310 Other, Other, Other, Other, | |
| 311 Other, Other, Other, Other, | |
| 312 | |
| 313 // Telugu | |
| 314 Invalid, VowelMark, VowelMark, VowelMark, | |
| 315 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 316 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 317 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 318 | |
| 319 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 320 IndependentVowel, Consonant, Consonant, Consonant, | |
| 321 Consonant, Consonant, Consonant, Consonant, | |
| 322 Consonant, Consonant, Consonant, Consonant, | |
| 323 | |
| 324 Consonant, Consonant, Consonant, Consonant, | |
| 325 Consonant, Consonant, Consonant, Consonant, | |
| 326 Consonant, Invalid, Consonant, Consonant, | |
| 327 Consonant, Consonant, Consonant, Consonant, | |
| 328 | |
| 329 Consonant, Consonant, Consonant, Consonant, | |
| 330 Invalid, Consonant, Consonant, Consonant, | |
| 331 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 332 Invalid, Invalid, Matra, Matra, | |
| 333 | |
| 334 Matra, Matra, Matra, Matra, | |
| 335 Matra, Invalid, Matra, Matra, | |
| 336 Matra, Invalid, Matra, Matra, | |
| 337 Matra, Halant, Invalid, Invalid, | |
| 338 | |
| 339 Invalid, Invalid, Invalid, Invalid, | |
| 340 Invalid, LengthMark, Matra, Invalid, | |
| 341 Invalid, Invalid, Invalid, Invalid, | |
| 342 Invalid, Invalid, Invalid, Invalid, | |
| 343 | |
| 344 IndependentVowel, IndependentVowel, Invalid, Invalid, | |
| 345 Invalid, Invalid, Other, Other, | |
| 346 Other, Other, Other, Other, | |
| 347 Other, Other, Other, Other, | |
| 348 | |
| 349 Other, Other, Other, Other, | |
| 350 Other, Other, Other, Other, | |
| 351 Other, Other, Other, Other, | |
| 352 Other, Other, Other, Other, | |
| 353 | |
| 354 // Kannada | |
| 355 Invalid, Invalid, VowelMark, VowelMark, | |
| 356 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 357 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 358 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 359 | |
| 360 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 361 IndependentVowel, Consonant, Consonant, Consonant, | |
| 362 Consonant, Consonant, Consonant, Consonant, | |
| 363 Consonant, Consonant, Consonant, Consonant, | |
| 364 | |
| 365 Consonant, Consonant, Consonant, Consonant, | |
| 366 Consonant, Consonant, Consonant, Consonant, | |
| 367 Consonant, Invalid, Consonant, Consonant, | |
| 368 Consonant, Consonant, Consonant, Consonant, | |
| 369 | |
| 370 Consonant, Consonant, Consonant, Consonant, | |
| 371 Invalid, Consonant, Consonant, Consonant, | |
| 372 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 373 Nukta, Other, Matra, Matra, | |
| 374 | |
| 375 Matra, Matra, Matra, Matra, | |
| 376 Matra, Invalid, Matra, Matra, | |
| 377 Matra, Invalid, Matra, Matra, | |
| 378 Matra, Halant, Invalid, Invalid, | |
| 379 | |
| 380 Invalid, Invalid, Invalid, Invalid, | |
| 381 Invalid, LengthMark, LengthMark, Invalid, | |
| 382 Invalid, Invalid, Invalid, Invalid, | |
| 383 Invalid, Invalid, Consonant, Invalid, | |
| 384 | |
| 385 IndependentVowel, IndependentVowel, VowelMark, VowelMark, | |
| 386 Invalid, Invalid, Other, Other, | |
| 387 Other, Other, Other, Other, | |
| 388 Other, Other, Other, Other, | |
| 389 | |
| 390 Other, Other, Other, Other, | |
| 391 Other, Other, Other, Other, | |
| 392 Other, Other, Other, Other, | |
| 393 Other, Other, Other, Other, | |
| 394 | |
| 395 // Malayalam | |
| 396 Invalid, Invalid, VowelMark, VowelMark, | |
| 397 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 398 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 399 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 400 | |
| 401 IndependentVowel, Invalid, IndependentVowel, IndependentVowel, | |
| 402 IndependentVowel, Consonant, Consonant, Consonant, | |
| 403 Consonant, Consonant, Consonant, Consonant, | |
| 404 Consonant, Consonant, Consonant, Consonant, | |
| 405 | |
| 406 Consonant, Consonant, Consonant, Consonant, | |
| 407 Consonant, Consonant, Consonant, Consonant, | |
| 408 Consonant, Invalid, Consonant, Consonant, | |
| 409 Consonant, Consonant, Consonant, Consonant, | |
| 410 | |
| 411 Consonant, Consonant, Consonant, Consonant, | |
| 412 Consonant, Consonant, Consonant, Consonant, | |
| 413 Consonant, Consonant, UnknownForm, UnknownForm, | |
| 414 Invalid, Invalid, Matra, Matra, | |
| 415 | |
| 416 Matra, Matra, Matra, Matra, | |
| 417 Invalid, Invalid, Matra, Matra, | |
| 418 Matra, Invalid, Matra, Matra, | |
| 419 Matra, Halant, Invalid, Invalid, | |
| 420 | |
| 421 Invalid, Invalid, Invalid, Invalid, | |
| 422 Invalid, Invalid, Invalid, Matra, | |
| 423 Invalid, Invalid, Invalid, Invalid, | |
| 424 Invalid, Invalid, Invalid, Invalid, | |
| 425 | |
| 426 IndependentVowel, IndependentVowel, Invalid, Invalid, | |
| 427 Invalid, Invalid, Other, Other, | |
| 428 Other, Other, Other, Other, | |
| 429 Other, Other, Other, Other, | |
| 430 | |
| 431 Other, Other, Other, Other, | |
| 432 Other, Other, Other, Other, | |
| 433 Other, Other, Other, Other, | |
| 434 Other, Other, Other, Other, | |
| 435 | |
| 436 // Sinhala | |
| 437 Invalid, Invalid, VowelMark, VowelMark, | |
| 438 Invalid, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 439 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 440 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 441 | |
| 442 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, | |
| 443 IndependentVowel, IndependentVowel, IndependentVowel, Invalid, | |
| 444 Invalid, Invalid, Consonant, Consonant, | |
| 445 Consonant, Consonant, Consonant, Consonant, | |
| 446 | |
| 447 Consonant, Consonant, Consonant, Consonant, | |
| 448 Consonant, Consonant, Consonant, Consonant, | |
| 449 Consonant, Consonant, Consonant, Consonant, | |
| 450 Consonant, Consonant, Consonant, Consonant, | |
| 451 | |
| 452 Consonant, Consonant, Invalid, Consonant, | |
| 453 Consonant, Consonant, Consonant, Consonant, | |
| 454 Consonant, Consonant, Consonant, Consonant, | |
| 455 Invalid, Consonant, Invalid, Invalid, | |
| 456 | |
| 457 Consonant, Consonant, Consonant, Consonant, | |
| 458 Consonant, Consonant, Consonant, Invalid, | |
| 459 Invalid, Invalid, Halant, Invalid, | |
| 460 Invalid, Invalid, Invalid, Matra, | |
| 461 | |
| 462 Matra, Matra, Matra, Matra, | |
| 463 Matra, Invalid, Matra, Invalid, | |
| 464 Matra, Matra, Matra, Matra, | |
| 465 Matra, Matra, Matra, Matra, | |
| 466 | |
| 467 Invalid, Invalid, Invalid, Invalid, | |
| 468 Invalid, Invalid, Invalid, Invalid, | |
| 469 Invalid, Invalid, Invalid, Invalid, | |
| 470 Invalid, Invalid, Invalid, Invalid, | |
| 471 | |
| 472 Invalid, Invalid, Matra, Matra, | |
| 473 Other, Other, Other, Other, | |
| 474 Other, Other, Other, Other, | |
| 475 Other, Other, Other, Other, | |
| 476 }; | |
| 477 | |
| 478 enum Position { | |
| 479 None, | |
| 480 Pre, | |
| 481 Above, | |
| 482 Below, | |
| 483 Post, | |
| 484 Split, | |
| 485 Base, | |
| 486 Reph, | |
| 487 Vattu, | |
| 488 Inherit | |
| 489 }; | |
| 490 | |
| 491 static const unsigned char indicPosition[0xe00-0x900] = { | |
| 492 // Devanagari | |
| 493 None, Above, Above, Post, | |
| 494 None, None, None, None, | |
| 495 None, None, None, None, | |
| 496 None, None, None, None, | |
| 497 | |
| 498 None, None, None, None, | |
| 499 None, None, None, None, | |
| 500 None, None, None, None, | |
| 501 None, None, None, None, | |
| 502 | |
| 503 None, None, None, None, | |
| 504 None, None, None, None, | |
| 505 None, None, None, None, | |
| 506 None, None, None, None, | |
| 507 | |
| 508 Below, None, None, None, | |
| 509 None, None, None, None, | |
| 510 None, None, None, None, | |
| 511 None, None, Post, Pre, | |
| 512 | |
| 513 Post, Below, Below, Below, | |
| 514 Below, Above, Above, Above, | |
| 515 Above, Post, Post, Post, | |
| 516 Post, None, None, None, | |
| 517 | |
| 518 None, Above, Below, Above, | |
| 519 Above, None, None, None, | |
| 520 None, None, None, None, | |
| 521 None, None, None, None, | |
| 522 | |
| 523 None, None, Below, Below, | |
| 524 None, None, None, None, | |
| 525 None, None, None, None, | |
| 526 None, None, None, None, | |
| 527 | |
| 528 None, None, None, None, | |
| 529 None, None, None, None, | |
| 530 None, None, None, None, | |
| 531 None, None, None, None, | |
| 532 | |
| 533 // Bengali | |
| 534 None, Above, Post, Post, | |
| 535 None, None, None, None, | |
| 536 None, None, None, None, | |
| 537 None, None, None, None, | |
| 538 | |
| 539 None, None, None, None, | |
| 540 None, None, None, None, | |
| 541 None, None, None, None, | |
| 542 None, None, None, None, | |
| 543 | |
| 544 None, None, None, None, | |
| 545 None, None, None, None, | |
| 546 None, None, None, None, | |
| 547 Below, None, None, Post, | |
| 548 | |
| 549 Below, None, None, None, | |
| 550 None, None, None, None, | |
| 551 None, None, None, None, | |
| 552 Below, None, Post, Pre, | |
| 553 | |
| 554 Post, Below, Below, Below, | |
| 555 Below, None, None, Pre, | |
| 556 Pre, None, None, Split, | |
| 557 Split, Below, None, None, | |
| 558 | |
| 559 None, None, None, None, | |
| 560 None, None, None, Post, | |
| 561 None, None, None, None, | |
| 562 None, None, None, None, | |
| 563 | |
| 564 None, None, Below, Below, | |
| 565 None, None, None, None, | |
| 566 None, None, None, None, | |
| 567 None, None, None, None, | |
| 568 | |
| 569 Below, None, None, None, | |
| 570 None, None, None, None, | |
| 571 None, None, None, None, | |
| 572 None, None, None, None, | |
| 573 | |
| 574 // Gurmukhi | |
| 575 None, Above, Above, Post, | |
| 576 None, None, None, None, | |
| 577 None, None, None, None, | |
| 578 None, None, None, None, | |
| 579 | |
| 580 None, None, None, None, | |
| 581 None, None, None, None, | |
| 582 None, None, None, None, | |
| 583 None, None, None, None, | |
| 584 | |
| 585 None, None, None, None, | |
| 586 None, None, None, None, | |
| 587 None, None, None, None, | |
| 588 None, None, None, Post, | |
| 589 | |
| 590 Below, None, None, None, | |
| 591 None, Below, None, None, | |
| 592 None, Below, None, None, | |
| 593 Below, None, Post, Pre, | |
| 594 | |
| 595 Post, Below, Below, None, | |
| 596 None, None, None, Above, | |
| 597 Above, None, None, Above, | |
| 598 Above, None, None, None, | |
| 599 | |
| 600 None, None, None, None, | |
| 601 None, None, None, None, | |
| 602 None, None, None, None, | |
| 603 None, None, None, None, | |
| 604 | |
| 605 None, None, None, None, | |
| 606 None, None, None, None, | |
| 607 None, None, None, None, | |
| 608 None, None, None, None, | |
| 609 | |
| 610 Above, Above, None, None, | |
| 611 None, None, None, None, | |
| 612 None, None, None, None, | |
| 613 None, None, None, None, | |
| 614 | |
| 615 // Gujarati | |
| 616 None, Above, Above, Post, | |
| 617 None, None, None, None, | |
| 618 None, None, None, None, | |
| 619 None, None, None, None, | |
| 620 | |
| 621 None, None, None, None, | |
| 622 None, None, None, None, | |
| 623 None, None, None, None, | |
| 624 None, None, None, None, | |
| 625 | |
| 626 None, None, None, None, | |
| 627 None, None, None, None, | |
| 628 None, None, None, None, | |
| 629 None, None, None, None, | |
| 630 | |
| 631 Below, None, None, None, | |
| 632 None, None, None, None, | |
| 633 None, None, None, None, | |
| 634 None, None, Post, Pre, | |
| 635 | |
| 636 Post, Below, Below, Below, | |
| 637 Below, Above, None, Above, | |
| 638 Above, Post, None, Post, | |
| 639 Post, None, None, None, | |
| 640 | |
| 641 None, None, None, None, | |
| 642 None, None, None, None, | |
| 643 None, None, None, None, | |
| 644 None, None, None, None, | |
| 645 | |
| 646 None, None, Below, Below, | |
| 647 None, None, None, None, | |
| 648 None, None, None, None, | |
| 649 None, None, None, None, | |
| 650 | |
| 651 None, None, None, None, | |
| 652 None, None, None, None, | |
| 653 None, None, None, None, | |
| 654 None, None, None, None, | |
| 655 | |
| 656 // Oriya | |
| 657 None, Above, Post, Post, | |
| 658 None, None, None, None, | |
| 659 None, None, None, None, | |
| 660 None, None, None, None, | |
| 661 | |
| 662 None, None, None, None, | |
| 663 None, None, None, None, | |
| 664 None, None, None, None, | |
| 665 None, None, None, None, | |
| 666 | |
| 667 None, None, None, None, | |
| 668 Below, None, None, None, | |
| 669 Below, None, None, None, | |
| 670 Below, Below, Below, Post, | |
| 671 | |
| 672 Below, None, Below, Below, | |
| 673 None, None, None, None, | |
| 674 None, None, None, None, | |
| 675 None, None, Post, Above, | |
| 676 | |
| 677 Post, Below, Below, Below, | |
| 678 None, None, None, Pre, | |
| 679 Split, None, None, Split, | |
| 680 Split, None, None, None, | |
| 681 | |
| 682 None, None, None, None, | |
| 683 None, None, Above, Post, | |
| 684 None, None, None, None, | |
| 685 None, None, None, Post, | |
| 686 | |
| 687 None, None, None, None, | |
| 688 None, None, None, None, | |
| 689 None, None, None, None, | |
| 690 None, None, None, None, | |
| 691 | |
| 692 None, Below, None, None, | |
| 693 None, None, None, None, | |
| 694 None, None, None, None, | |
| 695 None, None, None, None, | |
| 696 | |
| 697 // Tamil | |
| 698 None, None, Above, None, | |
| 699 None, None, None, None, | |
| 700 None, None, None, None, | |
| 701 None, None, None, None, | |
| 702 | |
| 703 None, None, None, None, | |
| 704 None, None, None, None, | |
| 705 None, None, None, None, | |
| 706 None, None, None, None, | |
| 707 | |
| 708 None, None, None, None, | |
| 709 None, None, None, None, | |
| 710 None, None, None, None, | |
| 711 None, None, None, None, | |
| 712 | |
| 713 None, None, None, None, | |
| 714 None, None, None, None, | |
| 715 None, None, None, None, | |
| 716 None, None, Post, Post, | |
| 717 | |
| 718 Above, Below, Below, None, | |
| 719 None, None, Pre, Pre, | |
| 720 Pre, None, Split, Split, | |
| 721 Split, Halant, None, None, | |
| 722 | |
| 723 None, None, None, None, | |
| 724 None, None, None, Post, | |
| 725 None, None, None, None, | |
| 726 None, None, None, None, | |
| 727 | |
| 728 None, None, None, None, | |
| 729 None, None, None, None, | |
| 730 None, None, None, None, | |
| 731 None, None, None, None, | |
| 732 | |
| 733 None, None, None, None, | |
| 734 None, None, None, None, | |
| 735 None, None, None, None, | |
| 736 None, None, None, None, | |
| 737 | |
| 738 // Telugu | |
| 739 None, Post, Post, Post, | |
| 740 None, None, None, None, | |
| 741 None, None, None, None, | |
| 742 None, None, None, None, | |
| 743 | |
| 744 None, None, None, None, | |
| 745 None, Below, Below, Below, | |
| 746 Below, Below, Below, Below, | |
| 747 Below, Below, Below, Below, | |
| 748 | |
| 749 Below, Below, Below, Below, | |
| 750 Below, Below, Below, Below, | |
| 751 Below, None, Below, Below, | |
| 752 Below, Below, Below, Below, | |
| 753 | |
| 754 Below, None, Below, Below, | |
| 755 None, Below, Below, Below, | |
| 756 Below, Below, None, None, | |
| 757 None, None, Post, Above, | |
| 758 | |
| 759 Above, Post, Post, Post, | |
| 760 Post, None, Above, Above, | |
| 761 Split, None, Post, Above, | |
| 762 Above, Halant, None, None, | |
| 763 | |
| 764 None, None, None, None, | |
| 765 None, Above, Below, None, | |
| 766 None, None, None, None, | |
| 767 None, None, None, None, | |
| 768 | |
| 769 None, None, None, None, | |
| 770 None, None, None, None, | |
| 771 None, None, None, None, | |
| 772 None, None, None, None, | |
| 773 | |
| 774 None, None, None, None, | |
| 775 None, None, None, None, | |
| 776 None, None, None, None, | |
| 777 None, None, None, None, | |
| 778 | |
| 779 // Kannada | |
| 780 None, None, Post, Post, | |
| 781 None, None, None, None, | |
| 782 None, None, None, None, | |
| 783 None, None, None, None, | |
| 784 | |
| 785 None, None, None, None, | |
| 786 None, Below, Below, Below, | |
| 787 Below, Below, Below, Below, | |
| 788 Below, Below, Below, Below, | |
| 789 | |
| 790 Below, Below, Below, Below, | |
| 791 Below, Below, Below, Below, | |
| 792 Below, Below, Below, Below, | |
| 793 Below, Below, Below, Below, | |
| 794 | |
| 795 Below, None, Below, Below, | |
| 796 None, Below, Below, Below, | |
| 797 Below, Below, None, None, | |
| 798 None, None, Post, Above, | |
| 799 | |
| 800 Split, Post, Post, Post, | |
| 801 Post, None, Above, Split, | |
| 802 Split, None, Split, Split, | |
| 803 Above, Halant, None, None, | |
| 804 | |
| 805 None, None, None, None, | |
| 806 None, Post, Post, None, | |
| 807 None, None, None, None, | |
| 808 None, None, Below, None, | |
| 809 | |
| 810 None, None, Below, Below, | |
| 811 None, None, None, None, | |
| 812 None, None, None, None, | |
| 813 None, None, None, None, | |
| 814 | |
| 815 None, None, None, None, | |
| 816 None, None, None, None, | |
| 817 None, None, None, None, | |
| 818 None, None, None, None, | |
| 819 | |
| 820 // Malayalam | |
| 821 None, None, Post, Post, | |
| 822 None, None, None, None, | |
| 823 None, None, None, None, | |
| 824 None, None, None, None, | |
| 825 | |
| 826 None, None, None, None, | |
| 827 None, None, None, None, | |
| 828 None, None, None, None, | |
| 829 None, None, None, None, | |
| 830 | |
| 831 None, None, None, None, | |
| 832 None, None, None, None, | |
| 833 None, None, None, None, | |
| 834 None, None, None, Post, | |
| 835 | |
| 836 Post, None, Below, None, | |
| 837 None, Post, None, None, | |
| 838 None, None, None, None, | |
| 839 None, None, Post, Post, | |
| 840 | |
| 841 Post, Post, Post, Post, | |
| 842 None, None, Pre, Pre, | |
| 843 Pre, None, Split, Split, | |
| 844 Split, Halant, None, None, | |
| 845 | |
| 846 None, None, None, None, | |
| 847 None, None, None, Post, | |
| 848 None, None, None, None, | |
| 849 None, None, None, None, | |
| 850 | |
| 851 None, None, None, None, | |
| 852 None, None, None, None, | |
| 853 None, None, None, None, | |
| 854 None, None, None, None, | |
| 855 | |
| 856 None, None, None, None, | |
| 857 None, None, None, None, | |
| 858 None, None, None, None, | |
| 859 None, None, None, None, | |
| 860 | |
| 861 // Sinhala | |
| 862 None, None, Post, Post, | |
| 863 None, None, None, None, | |
| 864 None, None, None, None, | |
| 865 None, None, None, None, | |
| 866 | |
| 867 None, None, None, None, | |
| 868 None, None, None, None, | |
| 869 None, None, None, None, | |
| 870 None, None, None, None, | |
| 871 | |
| 872 None, None, None, None, | |
| 873 None, None, None, None, | |
| 874 None, None, None, None, | |
| 875 None, None, None, None, | |
| 876 | |
| 877 None, None, None, None, | |
| 878 None, None, None, None, | |
| 879 None, None, None, None, | |
| 880 None, None, None, None, | |
| 881 | |
| 882 None, None, None, None, | |
| 883 None, None, None, None, | |
| 884 None, None, None, None, | |
| 885 None, None, None, Post, | |
| 886 | |
| 887 Post, Post, Above, Above, | |
| 888 Below, None, Below, None, | |
| 889 Post, Pre, Split, Pre, | |
| 890 Split, Split, Split, Post, | |
| 891 | |
| 892 None, None, None, None, | |
| 893 None, None, None, None, | |
| 894 None, None, None, None, | |
| 895 None, None, None, None, | |
| 896 | |
| 897 None, None, Post, Post, | |
| 898 None, None, None, None, | |
| 899 None, None, None, None, | |
| 900 None, None, None, None | |
| 901 }; | |
| 902 | |
| 903 static inline Form form(unsigned short uc) { | |
| 904 if (uc < 0x900 || uc > 0xdff) { | |
| 905 if (uc == 0x25cc) | |
| 906 return Consonant; | |
| 907 if (uc == 0x200c || uc == 0x200d) | |
| 908 return Control; | |
| 909 return Other; | |
| 910 } | |
| 911 return (Form)indicForms[uc-0x900]; | |
| 912 } | |
| 913 | |
| 914 static inline Position indic_position(unsigned short uc) { | |
| 915 if (uc < 0x900 || uc > 0xdff) | |
| 916 return None; | |
| 917 return (Position) indicPosition[uc-0x900]; | |
| 918 } | |
| 919 | |
| 920 | |
| 921 enum IndicScriptProperties { | |
| 922 HasReph = 0x01, | |
| 923 HasSplit = 0x02 | |
| 924 }; | |
| 925 | |
| 926 const hb_uint8 scriptProperties[10] = { | |
| 927 // Devanagari, | |
| 928 HasReph, | |
| 929 // Bengali, | |
| 930 HasReph|HasSplit, | |
| 931 // Gurmukhi, | |
| 932 0, | |
| 933 // Gujarati, | |
| 934 HasReph, | |
| 935 // Oriya, | |
| 936 HasReph|HasSplit, | |
| 937 // Tamil, | |
| 938 HasSplit, | |
| 939 // Telugu, | |
| 940 HasSplit, | |
| 941 // Kannada, | |
| 942 HasSplit|HasReph, | |
| 943 // Malayalam, | |
| 944 HasSplit, | |
| 945 // Sinhala, | |
| 946 HasSplit | |
| 947 }; | |
| 948 | |
| 949 struct IndicOrdering { | |
| 950 Form form; | |
| 951 Position position; | |
| 952 }; | |
| 953 | |
| 954 static const IndicOrdering devanagari_order [] = { | |
| 955 { Consonant, Below }, | |
| 956 { Matra, Below }, | |
| 957 { VowelMark, Below }, | |
| 958 { StressMark, Below }, | |
| 959 { Matra, Above }, | |
| 960 { Matra, Post }, | |
| 961 { Consonant, Reph }, | |
| 962 { VowelMark, Above }, | |
| 963 { StressMark, Above }, | |
| 964 { VowelMark, Post }, | |
| 965 { (Form)0, None } | |
| 966 }; | |
| 967 | |
| 968 static const IndicOrdering bengali_order [] = { | |
| 969 { Consonant, Below }, | |
| 970 { Matra, Below }, | |
| 971 { Matra, Above }, | |
| 972 { Consonant, Reph }, | |
| 973 { VowelMark, Above }, | |
| 974 { Consonant, Post }, | |
| 975 { Matra, Post }, | |
| 976 { VowelMark, Post }, | |
| 977 { (Form)0, None } | |
| 978 }; | |
| 979 | |
| 980 static const IndicOrdering gurmukhi_order [] = { | |
| 981 { Consonant, Below }, | |
| 982 { Matra, Below }, | |
| 983 { Matra, Above }, | |
| 984 { Consonant, Post }, | |
| 985 { Matra, Post }, | |
| 986 { VowelMark, Above }, | |
| 987 { (Form)0, None } | |
| 988 }; | |
| 989 | |
| 990 static const IndicOrdering tamil_order [] = { | |
| 991 { Matra, Above }, | |
| 992 { Matra, Post }, | |
| 993 { VowelMark, Post }, | |
| 994 { (Form)0, None } | |
| 995 }; | |
| 996 | |
| 997 static const IndicOrdering telugu_order [] = { | |
| 998 { Matra, Above }, | |
| 999 { Matra, Below }, | |
| 1000 { Matra, Post }, | |
| 1001 { Consonant, Below }, | |
| 1002 { Consonant, Post }, | |
| 1003 { VowelMark, Post }, | |
| 1004 { (Form)0, None } | |
| 1005 }; | |
| 1006 | |
| 1007 static const IndicOrdering kannada_order [] = { | |
| 1008 { Matra, Above }, | |
| 1009 { Matra, Post }, | |
| 1010 { Consonant, Below }, | |
| 1011 { Consonant, Post }, | |
| 1012 { LengthMark, Post }, | |
| 1013 { Consonant, Reph }, | |
| 1014 { VowelMark, Post }, | |
| 1015 { (Form)0, None } | |
| 1016 }; | |
| 1017 | |
| 1018 static const IndicOrdering malayalam_order [] = { | |
| 1019 { Consonant, Below }, | |
| 1020 { Matra, Below }, | |
| 1021 { Consonant, Reph }, | |
| 1022 { Consonant, Post }, | |
| 1023 { Matra, Post }, | |
| 1024 { VowelMark, Post }, | |
| 1025 { (Form)0, None } | |
| 1026 }; | |
| 1027 | |
| 1028 static const IndicOrdering sinhala_order [] = { | |
| 1029 { Matra, Below }, | |
| 1030 { Matra, Above }, | |
| 1031 { Matra, Post }, | |
| 1032 { VowelMark, Post }, | |
| 1033 { (Form)0, None } | |
| 1034 }; | |
| 1035 | |
| 1036 static const IndicOrdering * const indic_order[] = { | |
| 1037 devanagari_order, // Devanagari | |
| 1038 bengali_order, // Bengali | |
| 1039 gurmukhi_order, // Gurmukhi | |
| 1040 devanagari_order, // Gujarati | |
| 1041 bengali_order, // Oriya | |
| 1042 tamil_order, // Tamil | |
| 1043 telugu_order, // Telugu | |
| 1044 kannada_order, // Kannada | |
| 1045 malayalam_order, // Malayalam | |
| 1046 sinhala_order // Sinhala | |
| 1047 }; | |
| 1048 | |
| 1049 | |
| 1050 | |
| 1051 // vowel matras that have to be split into two parts. | |
| 1052 static const unsigned short split_matras[] = { | |
| 1053 // matra, split1, split2, split3 | |
| 1054 | |
| 1055 // bengalis | |
| 1056 0x9cb, 0x9c7, 0x9be, 0x0, | |
| 1057 0x9cc, 0x9c7, 0x9d7, 0x0, | |
| 1058 // oriya | |
| 1059 0xb48, 0xb47, 0xb56, 0x0, | |
| 1060 0xb4b, 0xb47, 0xb3e, 0x0, | |
| 1061 0xb4c, 0xb47, 0xb57, 0x0, | |
| 1062 // tamil | |
| 1063 0xbca, 0xbc6, 0xbbe, 0x0, | |
| 1064 0xbcb, 0xbc7, 0xbbe, 0x0, | |
| 1065 0xbcc, 0xbc6, 0xbd7, 0x0, | |
| 1066 // telugu | |
| 1067 0xc48, 0xc46, 0xc56, 0x0, | |
| 1068 // kannada | |
| 1069 0xcc0, 0xcbf, 0xcd5, 0x0, | |
| 1070 0xcc7, 0xcc6, 0xcd5, 0x0, | |
| 1071 0xcc8, 0xcc6, 0xcd6, 0x0, | |
| 1072 0xcca, 0xcc6, 0xcc2, 0x0, | |
| 1073 0xccb, 0xcc6, 0xcc2, 0xcd5, | |
| 1074 // malayalam | |
| 1075 0xd4a, 0xd46, 0xd3e, 0x0, | |
| 1076 0xd4b, 0xd47, 0xd3e, 0x0, | |
| 1077 0xd4c, 0xd46, 0xd57, 0x0, | |
| 1078 // sinhala | |
| 1079 0xdda, 0xdd9, 0xdca, 0x0, | |
| 1080 0xddc, 0xdd9, 0xdcf, 0x0, | |
| 1081 0xddd, 0xdd9, 0xdcf, 0xdca, | |
| 1082 0xdde, 0xdd9, 0xddf, 0x0, | |
| 1083 0xffff | |
| 1084 }; | |
| 1085 | |
| 1086 static inline void splitMatra(unsigned short *reordered, int matra, int &len) | |
| 1087 { | |
| 1088 unsigned short matra_uc = reordered[matra]; | |
| 1089 //qDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]); | |
| 1090 | |
| 1091 const unsigned short *split = split_matras; | |
| 1092 while (split[0] < matra_uc) | |
| 1093 split += 4; | |
| 1094 | |
| 1095 assert(*split == matra_uc); | |
| 1096 ++split; | |
| 1097 | |
| 1098 int added_chars = split[2] == 0x0 ? 1 : 2; | |
| 1099 | |
| 1100 memmove(reordered + matra + added_chars, reordered + matra, (len-matra)*size
of(unsigned short)); | |
| 1101 reordered[matra] = split[0]; | |
| 1102 reordered[matra+1] = split[1]; | |
| 1103 if(added_chars == 2) | |
| 1104 reordered[matra+2] = split[2]; | |
| 1105 len += added_chars; | |
| 1106 } | |
| 1107 | |
| 1108 #ifndef NO_OPENTYPE | |
| 1109 static const HB_OpenTypeFeature indic_features[] = { | |
| 1110 { HB_MAKE_TAG('l', 'o', 'c', 'a'), LocaProperty }, | |
| 1111 { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, | |
| 1112 { HB_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, | |
| 1113 { HB_MAKE_TAG('n', 'u', 'k', 't'), NuktaProperty }, | |
| 1114 { HB_MAKE_TAG('a', 'k', 'h', 'n'), AkhantProperty }, | |
| 1115 { HB_MAKE_TAG('r', 'p', 'h', 'f'), RephProperty }, | |
| 1116 { HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty }, | |
| 1117 { HB_MAKE_TAG('h', 'a', 'l', 'f'), HalfFormProperty }, | |
| 1118 { HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty }, | |
| 1119 { HB_MAKE_TAG('c', 'j', 'c', 't'), ConjunctFormProperty }, | |
| 1120 { HB_MAKE_TAG('v', 'a', 't', 'u'), VattuProperty }, | |
| 1121 { HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty }, | |
| 1122 { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty }, | |
| 1123 { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty }, | |
| 1124 { HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty }, | |
| 1125 { HB_MAKE_TAG('h', 'a', 'l', 'n'), HalantProperty }, | |
| 1126 { HB_MAKE_TAG('c', 'a', 'l', 't'), IndicCaltProperty }, | |
| 1127 { 0, 0 } | |
| 1128 }; | |
| 1129 #endif | |
| 1130 | |
| 1131 // #define INDIC_DEBUG | |
| 1132 #ifdef INDIC_DEBUG | |
| 1133 #define IDEBUG hb_debug | |
| 1134 #include <stdarg.h> | |
| 1135 | |
| 1136 static void hb_debug(const char *msg, ...) | |
| 1137 { | |
| 1138 va_list ap; | |
| 1139 va_start(ap, msg); // use variable arg list | |
| 1140 vfprintf(stderr, msg, ap); | |
| 1141 va_end(ap); | |
| 1142 fprintf(stderr, "\n"); | |
| 1143 } | |
| 1144 | |
| 1145 #else | |
| 1146 #define IDEBUG if(0) printf | |
| 1147 #endif | |
| 1148 | |
| 1149 #if 0 //def INDIC_DEBUG | |
| 1150 static QString propertiesToString(int properties) | |
| 1151 { | |
| 1152 QString res; | |
| 1153 properties = ~properties; | |
| 1154 if (properties & LocaProperty) | |
| 1155 res += "Loca "; | |
| 1156 if (properties & CcmpProperty) | |
| 1157 res += "Ccmp "; | |
| 1158 if (properties & InitProperty) | |
| 1159 res += "Init "; | |
| 1160 if (properties & NuktaProperty) | |
| 1161 res += "Nukta "; | |
| 1162 if (properties & AkhantProperty) | |
| 1163 res += "Akhant "; | |
| 1164 if (properties & RephProperty) | |
| 1165 res += "Reph "; | |
| 1166 if (properties & PreFormProperty) | |
| 1167 res += "PreForm "; | |
| 1168 if (properties & BelowFormProperty) | |
| 1169 res += "BelowForm "; | |
| 1170 if (properties & AboveFormProperty) | |
| 1171 res += "AboveForm "; | |
| 1172 if (properties & HalfFormProperty) | |
| 1173 res += "HalfForm "; | |
| 1174 if (properties & PostFormProperty) | |
| 1175 res += "PostForm "; | |
| 1176 if (properties & ConjunctFormProperty) | |
| 1177 res += "PostForm "; | |
| 1178 if (properties & VattuProperty) | |
| 1179 res += "Vattu "; | |
| 1180 if (properties & PreSubstProperty) | |
| 1181 res += "PreSubst "; | |
| 1182 if (properties & BelowSubstProperty) | |
| 1183 res += "BelowSubst "; | |
| 1184 if (properties & AboveSubstProperty) | |
| 1185 res += "AboveSubst "; | |
| 1186 if (properties & PostSubstProperty) | |
| 1187 res += "PostSubst "; | |
| 1188 if (properties & HalantProperty) | |
| 1189 res += "Halant "; | |
| 1190 if (properties & CligProperty) | |
| 1191 res += "Clig "; | |
| 1192 if (properties & IndicCaltProperty) | |
| 1193 res += "Calt "; | |
| 1194 return res; | |
| 1195 } | |
| 1196 #endif | |
| 1197 | |
| 1198 static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv
alid) | |
| 1199 { | |
| 1200 HB_Script script = item->item.script; | |
| 1201 assert(script >= HB_Script_Devanagari && script <= HB_Script_Sinhala); | |
| 1202 const unsigned short script_base = 0x0900 + 0x80*(script-HB_Script_Devanagar
i); | |
| 1203 const unsigned short ra = script_base + 0x30; | |
| 1204 const unsigned short halant = script_base + 0x4d; | |
| 1205 const unsigned short nukta = script_base + 0x3c; | |
| 1206 bool control = false; | |
| 1207 | |
| 1208 int len = (int)item->item.length; | |
| 1209 IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->item.pos, item
->item.length, invalid); | |
| 1210 | |
| 1211 if ((int)item->num_glyphs < len+4) { | |
| 1212 item->num_glyphs = len+4; | |
| 1213 return false; | |
| 1214 } | |
| 1215 | |
| 1216 HB_STACKARRAY(HB_UChar16, reordered, len + 4); | |
| 1217 HB_STACKARRAY(hb_uint8, position, len + 4); | |
| 1218 | |
| 1219 unsigned char properties = scriptProperties[script-HB_Script_Devanagari]; | |
| 1220 | |
| 1221 if (invalid) { | |
| 1222 *reordered = 0x25cc; | |
| 1223 memcpy(reordered+1, item->string + item->item.pos, len*sizeof(HB_UChar16
)); | |
| 1224 len++; | |
| 1225 } else { | |
| 1226 memcpy(reordered, item->string + item->item.pos, len*sizeof(HB_UChar16))
; | |
| 1227 } | |
| 1228 if (reordered[len-1] == 0x200c) // zero width non joiner | |
| 1229 len--; | |
| 1230 | |
| 1231 int i; | |
| 1232 int base = 0; | |
| 1233 int reph = -1; | |
| 1234 | |
| 1235 #ifdef INDIC_DEBUG | |
| 1236 IDEBUG("original:"); | |
| 1237 for (i = 0; i < len; i++) { | |
| 1238 IDEBUG(" %d: %4x", i, reordered[i]); | |
| 1239 } | |
| 1240 #endif | |
| 1241 | |
| 1242 if (len != 1) { | |
| 1243 HB_UChar16 *uc = reordered; | |
| 1244 bool beginsWithRa = false; | |
| 1245 | |
| 1246 // Rule 1: find base consonant | |
| 1247 // | |
| 1248 // The shaping engine finds the base consonant of the | |
| 1249 // syllable, using the following algorithm: starting from the | |
| 1250 // end of the syllable, move backwards until a consonant is | |
| 1251 // found that does not have a below-base or post-base form | |
| 1252 // (post-base forms have to follow below-base forms), or | |
| 1253 // arrive at the first consonant. The consonant stopped at | |
| 1254 // will be the base. | |
| 1255 // | |
| 1256 // * If the syllable starts with Ra + H (in a script that has | |
| 1257 // 'Reph'), Ra is excluded from candidates for base | |
| 1258 // consonants. | |
| 1259 // | |
| 1260 // * In Kannada and Telugu, the base consonant cannot be | |
| 1261 // farther than 3 consonants from the end of the syllable. | |
| 1262 // #### replace the HasReph property by testing if the feature exists in
the font! | |
| 1263 if (form(*uc) == Consonant || (script == HB_Script_Bengali && form(*uc)
== IndependentVowel)) { | |
| 1264 if ((properties & HasReph) && (len > 2) && | |
| 1265 (*uc == ra || *uc == 0x9f0) && *(uc+1) == halant) | |
| 1266 beginsWithRa = true; | |
| 1267 | |
| 1268 if (beginsWithRa && form(*(uc+2)) == Control) | |
| 1269 beginsWithRa = false; | |
| 1270 | |
| 1271 base = (beginsWithRa ? 2 : 0); | |
| 1272 IDEBUG(" length = %d, beginsWithRa = %d, base=%d", len, beginsWit
hRa, base); | |
| 1273 | |
| 1274 int lastConsonant = 0; | |
| 1275 int matra = -1; | |
| 1276 // we remember: | |
| 1277 // * the last consonant since we need it for rule 2 | |
| 1278 // * the matras position for rule 3 and 4 | |
| 1279 | |
| 1280 // figure out possible base glyphs | |
| 1281 memset(position, 0, len); | |
| 1282 if (script == HB_Script_Devanagari || script == HB_Script_Gujarati)
{ | |
| 1283 bool vattu = false; | |
| 1284 for (i = base; i < len; ++i) { | |
| 1285 position[i] = form(uc[i]); | |
| 1286 if (position[i] == Consonant) { | |
| 1287 lastConsonant = i; | |
| 1288 vattu = (!vattu && uc[i] == ra); | |
| 1289 if (vattu) { | |
| 1290 IDEBUG("excluding vattu glyph at %d from base candid
ates", i); | |
| 1291 position[i] = Vattu; | |
| 1292 } | |
| 1293 } else if (position[i] == Matra) { | |
| 1294 matra = i; | |
| 1295 } | |
| 1296 } | |
| 1297 } else { | |
| 1298 for (i = base; i < len; ++i) { | |
| 1299 position[i] = form(uc[i]); | |
| 1300 if (position[i] == Consonant) | |
| 1301 lastConsonant = i; | |
| 1302 else if (matra < 0 && position[i] == Matra) | |
| 1303 matra = i; | |
| 1304 } | |
| 1305 } | |
| 1306 int skipped = 0; | |
| 1307 Position pos = Post; | |
| 1308 for (i = len-1; i >= base; i--) { | |
| 1309 if (position[i] != Consonant && (position[i] != Control || scrip
t == HB_Script_Kannada)) | |
| 1310 continue; | |
| 1311 | |
| 1312 if (i < len-1 && position[i] == Control && position[i+1] == Cons
onant) { | |
| 1313 base = i+1; | |
| 1314 break; | |
| 1315 } | |
| 1316 | |
| 1317 Position charPosition = indic_position(uc[i]); | |
| 1318 if (pos == Post && charPosition == Post) { | |
| 1319 pos = Post; | |
| 1320 } else if ((pos == Post || pos == Below) && charPosition == Belo
w) { | |
| 1321 if (script == HB_Script_Devanagari || script == HB_Script_Gu
jarati) | |
| 1322 base = i; | |
| 1323 pos = Below; | |
| 1324 } else { | |
| 1325 base = i; | |
| 1326 break; | |
| 1327 } | |
| 1328 if (skipped == 2 && (script == HB_Script_Kannada || script == HB
_Script_Telugu)) { | |
| 1329 base = i; | |
| 1330 break; | |
| 1331 } | |
| 1332 ++skipped; | |
| 1333 } | |
| 1334 | |
| 1335 IDEBUG(" base consonant at %d skipped=%d, lastConsonant=%d", base
, skipped, lastConsonant); | |
| 1336 | |
| 1337 // Rule 2: | |
| 1338 // | |
| 1339 // If the base consonant is not the last one, Uniscribe | |
| 1340 // moves the halant from the base consonant to the last | |
| 1341 // one. | |
| 1342 if (lastConsonant > base) { | |
| 1343 int halantPos = 0; | |
| 1344 if (uc[base+1] == halant) | |
| 1345 halantPos = base + 1; | |
| 1346 else if (uc[base+1] == nukta && uc[base+2] == halant) | |
| 1347 halantPos = base + 2; | |
| 1348 if (halantPos > 0) { | |
| 1349 IDEBUG(" moving halant from %d to %d!", base+1, lastConso
nant); | |
| 1350 for (i = halantPos; i < lastConsonant; i++) | |
| 1351 uc[i] = uc[i+1]; | |
| 1352 uc[lastConsonant] = halant; | |
| 1353 } | |
| 1354 } | |
| 1355 | |
| 1356 // Rule 3: | |
| 1357 // | |
| 1358 // If the syllable starts with Ra + H, Uniscribe moves | |
| 1359 // this combination so that it follows either: | |
| 1360 | |
| 1361 // * the post-base 'matra' (if any) or the base consonant | |
| 1362 // (in scripts that show similarity to Devanagari, i.e., | |
| 1363 // Devanagari, Gujarati, Bengali) | |
| 1364 // * the base consonant (other scripts) | |
| 1365 // * the end of the syllable (Kannada) | |
| 1366 | |
| 1367 Position matra_position = None; | |
| 1368 if (matra > 0) | |
| 1369 matra_position = indic_position(uc[matra]); | |
| 1370 IDEBUG(" matra at %d with form %d, base=%d", matra, matra_positio
n, base); | |
| 1371 | |
| 1372 if (beginsWithRa && base != 0) { | |
| 1373 int toPos = base+1; | |
| 1374 if (toPos < len && uc[toPos] == nukta) | |
| 1375 toPos++; | |
| 1376 if (toPos < len && uc[toPos] == halant) | |
| 1377 toPos++; | |
| 1378 if (toPos < len && uc[toPos] == 0x200d) | |
| 1379 toPos++; | |
| 1380 if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant) | |
| 1381 toPos += 2; | |
| 1382 if (script == HB_Script_Devanagari || script == HB_Script_Gujara
ti || script == HB_Script_Bengali) { | |
| 1383 if (matra_position == Post || matra_position == Split) { | |
| 1384 toPos = matra+1; | |
| 1385 matra -= 2; | |
| 1386 } | |
| 1387 } else if (script == HB_Script_Kannada) { | |
| 1388 toPos = len; | |
| 1389 matra -= 2; | |
| 1390 } | |
| 1391 | |
| 1392 IDEBUG("moving leading ra+halant to position %d", toPos); | |
| 1393 for (i = 2; i < toPos; i++) | |
| 1394 uc[i-2] = uc[i]; | |
| 1395 uc[toPos-2] = ra; | |
| 1396 uc[toPos-1] = halant; | |
| 1397 base -= 2; | |
| 1398 if (properties & HasReph) | |
| 1399 reph = toPos-2; | |
| 1400 } | |
| 1401 | |
| 1402 // Rule 4: | |
| 1403 | |
| 1404 // Uniscribe splits two- or three-part matras into their | |
| 1405 // parts. This splitting is a character-to-character | |
| 1406 // operation). | |
| 1407 // | |
| 1408 // Uniscribe describes some moving operations for these | |
| 1409 // matras here. For shaping however all pre matras need | |
| 1410 // to be at the beginning of the syllable, so we just move | |
| 1411 // them there now. | |
| 1412 if (matra_position == Split) { | |
| 1413 splitMatra(uc, matra, len); | |
| 1414 // Handle three-part matras (0xccb in Kannada) | |
| 1415 matra_position = indic_position(uc[matra]); | |
| 1416 } | |
| 1417 | |
| 1418 if (matra_position == Pre) { | |
| 1419 unsigned short m = uc[matra]; | |
| 1420 while (matra--) | |
| 1421 uc[matra+1] = uc[matra]; | |
| 1422 uc[0] = m; | |
| 1423 base++; | |
| 1424 } | |
| 1425 } | |
| 1426 | |
| 1427 // Rule 5: | |
| 1428 // | |
| 1429 // Uniscribe classifies consonants and 'matra' parts as | |
| 1430 // pre-base, above-base (Reph), below-base or post-base. This | |
| 1431 // classification exists on the character code level and is | |
| 1432 // language-dependent, not font-dependent. | |
| 1433 for (i = 0; i < base; ++i) | |
| 1434 position[i] = Pre; | |
| 1435 position[base] = Base; | |
| 1436 for (i = base+1; i < len; ++i) { | |
| 1437 position[i] = indic_position(uc[i]); | |
| 1438 // #### replace by adjusting table | |
| 1439 if (uc[i] == nukta || uc[i] == halant) | |
| 1440 position[i] = Inherit; | |
| 1441 } | |
| 1442 if (reph > 0) { | |
| 1443 // recalculate reph, it might have changed. | |
| 1444 for (i = base+1; i < len; ++i) | |
| 1445 if (uc[i] == ra) | |
| 1446 reph = i; | |
| 1447 position[reph] = Reph; | |
| 1448 position[reph+1] = Inherit; | |
| 1449 } | |
| 1450 | |
| 1451 // all reordering happens now to the chars after the base | |
| 1452 int fixed = base+1; | |
| 1453 if (fixed < len && uc[fixed] == nukta) | |
| 1454 fixed++; | |
| 1455 if (fixed < len && uc[fixed] == halant) | |
| 1456 fixed++; | |
| 1457 if (fixed < len && uc[fixed] == 0x200d) | |
| 1458 fixed++; | |
| 1459 | |
| 1460 #ifdef INDIC_DEBUG | |
| 1461 for (i = fixed; i < len; ++i) | |
| 1462 IDEBUG("position[%d] = %d, form=%d uc=%x", i, position[i], form(uc[i
]), uc[i]); | |
| 1463 #endif | |
| 1464 // we continuosly position the matras and vowel marks and increase the f
ixed | |
| 1465 // until we reached the end. | |
| 1466 const IndicOrdering *finalOrder = indic_order[script-HB_Script_Devanagar
i]; | |
| 1467 | |
| 1468 IDEBUG(" reordering pass:"); | |
| 1469 IDEBUG(" base=%d fixed=%d", base, fixed); | |
| 1470 int toMove = 0; | |
| 1471 while (finalOrder[toMove].form && fixed < len-1) { | |
| 1472 IDEBUG(" fixed = %d, toMove=%d, moving form %d with pos %d",
fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position); | |
| 1473 for (i = fixed; i < len; i++) { | |
| 1474 // IDEBUG() << " i=" << i << "uc=" << hex << uc[i] << "
form=" << form(uc[i]) | |
| 1475 // << "position=" << position[i]; | |
| 1476 if (form(uc[i]) == finalOrder[toMove].form && | |
| 1477 position[i] == finalOrder[toMove].position) { | |
| 1478 // need to move this glyph | |
| 1479 int to = fixed; | |
| 1480 if (i < len-1 && position[i+1] == Inherit) { | |
| 1481 IDEBUG(" moving two chars from %d to %d", i, to)
; | |
| 1482 unsigned short ch = uc[i]; | |
| 1483 unsigned short ch2 = uc[i+1]; | |
| 1484 unsigned char pos = position[i]; | |
| 1485 for (int j = i+1; j > to+1; j--) { | |
| 1486 uc[j] = uc[j-2]; | |
| 1487 position[j] = position[j-2]; | |
| 1488 } | |
| 1489 uc[to] = ch; | |
| 1490 uc[to+1] = ch2; | |
| 1491 position[to] = pos; | |
| 1492 position[to+1] = pos; | |
| 1493 fixed += 2; | |
| 1494 } else { | |
| 1495 IDEBUG(" moving one char from %d to %d", i, to); | |
| 1496 unsigned short ch = uc[i]; | |
| 1497 unsigned char pos = position[i]; | |
| 1498 for (int j = i; j > to; j--) { | |
| 1499 uc[j] = uc[j-1]; | |
| 1500 position[j] = position[j-1]; | |
| 1501 } | |
| 1502 uc[to] = ch; | |
| 1503 position[to] = pos; | |
| 1504 fixed++; | |
| 1505 } | |
| 1506 } | |
| 1507 } | |
| 1508 toMove++; | |
| 1509 } | |
| 1510 | |
| 1511 } | |
| 1512 | |
| 1513 if (reph > 0) { | |
| 1514 // recalculate reph, it might have changed. | |
| 1515 for (i = base+1; i < len; ++i) | |
| 1516 if (reordered[i] == ra) | |
| 1517 reph = i; | |
| 1518 } | |
| 1519 | |
| 1520 #ifndef NO_OPENTYPE | |
| 1521 const int availableGlyphs = item->num_glyphs; | |
| 1522 #endif | |
| 1523 if (!item->font->klass->convertStringToGlyphIndices(item->font, | |
| 1524 reordered, len, | |
| 1525 item->glyphs, &item->num
_glyphs, | |
| 1526 item->item.bidiLevel % 2
)) | |
| 1527 goto error; | |
| 1528 | |
| 1529 | |
| 1530 IDEBUG(" base=%d, reph=%d", base, reph); | |
| 1531 IDEBUG("reordered:"); | |
| 1532 for (i = 0; i < len; i++) { | |
| 1533 item->attributes[i].mark = false; | |
| 1534 item->attributes[i].clusterStart = false; | |
| 1535 item->attributes[i].justification = 0; | |
| 1536 item->attributes[i].zeroWidth = false; | |
| 1537 IDEBUG(" %d: %4x", i, reordered[i]); | |
| 1538 } | |
| 1539 | |
| 1540 // now we have the syllable in the right order, and can start running it thr
ough open type. | |
| 1541 | |
| 1542 for (i = 0; i < len; ++i) | |
| 1543 control |= (form(reordered[i]) == Control); | |
| 1544 | |
| 1545 #ifndef NO_OPENTYPE | |
| 1546 if (openType) { | |
| 1547 | |
| 1548 // we need to keep track of where the base glyph is for some | |
| 1549 // scripts and use the cluster feature for this. This | |
| 1550 // also means we have to correct the logCluster output from | |
| 1551 // the open type engine manually afterwards. for indic this | |
| 1552 // is rather simple, as all chars just point to the first | |
| 1553 // glyph in the syllable. | |
| 1554 HB_STACKARRAY(unsigned short, clusters, len); | |
| 1555 HB_STACKARRAY(unsigned int, properties, len); | |
| 1556 | |
| 1557 for (i = 0; i < len; ++i) | |
| 1558 clusters[i] = i; | |
| 1559 | |
| 1560 // features we should always apply | |
| 1561 for (i = 0; i < len; ++i) | |
| 1562 properties[i] = ~(LocaProperty | |
| 1563 | CcmpProperty | |
| 1564 | NuktaProperty | |
| 1565 | VattuProperty | |
| 1566 | ConjunctFormProperty | |
| 1567 | PreSubstProperty | |
| 1568 | BelowSubstProperty | |
| 1569 | AboveSubstProperty | |
| 1570 | PostSubstProperty | |
| 1571 | HalantProperty | |
| 1572 | IndicCaltProperty | |
| 1573 | PositioningProperties); | |
| 1574 | |
| 1575 // Loca always applies | |
| 1576 // Ccmp always applies | |
| 1577 // Init | |
| 1578 if (item->item.pos == 0 | |
| 1579 || !(isLetter(item->string[item->item.pos-1]) || isMark(item->string
[item->item.pos-1]))) | |
| 1580 properties[0] &= ~InitProperty; | |
| 1581 | |
| 1582 // Nukta always applies | |
| 1583 // Akhant | |
| 1584 for (i = 0; i <= base; ++i) | |
| 1585 properties[i] &= ~AkhantProperty; | |
| 1586 // Reph | |
| 1587 if (reph >= 0) { | |
| 1588 properties[reph] &= ~RephProperty; | |
| 1589 properties[reph+1] &= ~RephProperty; | |
| 1590 } | |
| 1591 // BelowForm | |
| 1592 for (i = base+1; i < len; ++i) | |
| 1593 properties[i] &= ~BelowFormProperty; | |
| 1594 | |
| 1595 if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) { | |
| 1596 // vattu glyphs need this aswell | |
| 1597 bool vattu = false; | |
| 1598 for (i = base-2; i > 1; --i) { | |
| 1599 if (form(reordered[i]) == Consonant) { | |
| 1600 vattu = (!vattu && reordered[i] == ra); | |
| 1601 if (vattu) { | |
| 1602 IDEBUG("forming vattu ligature at %d", i); | |
| 1603 properties[i] &= ~BelowFormProperty; | |
| 1604 properties[i+1] &= ~BelowFormProperty; | |
| 1605 } | |
| 1606 } | |
| 1607 } | |
| 1608 } | |
| 1609 // HalfFormProperty | |
| 1610 for (i = 0; i < base; ++i) | |
| 1611 properties[i] &= ~HalfFormProperty; | |
| 1612 if (control) { | |
| 1613 for (i = 2; i < len; ++i) { | |
| 1614 if (reordered[i] == 0x200d /* ZWJ */) { | |
| 1615 properties[i-1] &= ~HalfFormProperty; | |
| 1616 properties[i-2] &= ~HalfFormProperty; | |
| 1617 } else if (reordered[i] == 0x200c /* ZWNJ */) { | |
| 1618 properties[i-1] &= ~HalfFormProperty; | |
| 1619 properties[i-2] &= ~HalfFormProperty; | |
| 1620 } | |
| 1621 } | |
| 1622 } | |
| 1623 // PostFormProperty | |
| 1624 for (i = base+1; i < len; ++i) | |
| 1625 properties[i] &= ~PostFormProperty; | |
| 1626 // vattu always applies | |
| 1627 // pres always applies | |
| 1628 // blws always applies | |
| 1629 // abvs always applies | |
| 1630 // psts always applies | |
| 1631 // halant always applies | |
| 1632 // calt always applies | |
| 1633 | |
| 1634 #ifdef INDIC_DEBUG | |
| 1635 // { | |
| 1636 // IDEBUG("OT properties:"); | |
| 1637 // for (int i = 0; i < len; ++i) | |
| 1638 // qDebug(" i: %s", ::propertiesToString(properties[i]).toLati
n1().data()); | |
| 1639 // } | |
| 1640 #endif | |
| 1641 | |
| 1642 // initialize | |
| 1643 item->log_clusters = clusters; | |
| 1644 HB_OpenTypeShape(item, properties); | |
| 1645 | |
| 1646 int newLen = item->face->buffer->in_length; | |
| 1647 HB_GlyphItem otl_glyphs = item->face->buffer->in_string; | |
| 1648 | |
| 1649 // move the left matra back to its correct position in malayalam and tam
il | |
| 1650 if ((script == HB_Script_Malayalam || script == HB_Script_Tamil) && (for
m(reordered[0]) == Matra)) { | |
| 1651 // qDebug("reordering matra, len=%d", newLen); | |
| 1652 // need to find the base in the shaped string and move the matra the
re | |
| 1653 int basePos = 0; | |
| 1654 while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base) | |
| 1655 basePos++; | |
| 1656 --basePos; | |
| 1657 if (basePos < newLen && basePos > 1) { | |
| 1658 // qDebug("moving prebase matra to position %d in syllable newle
n=%d", basePos, newLen); | |
| 1659 HB_GlyphItemRec m = otl_glyphs[0]; | |
| 1660 --basePos; | |
| 1661 for (i = 0; i < basePos; ++i) | |
| 1662 otl_glyphs[i] = otl_glyphs[i+1]; | |
| 1663 otl_glyphs[basePos] = m; | |
| 1664 } | |
| 1665 } | |
| 1666 | |
| 1667 HB_Bool positioned = HB_OpenTypePosition(item, availableGlyphs, false); | |
| 1668 | |
| 1669 HB_FREE_STACKARRAY(clusters); | |
| 1670 HB_FREE_STACKARRAY(properties); | |
| 1671 | |
| 1672 if (!positioned) | |
| 1673 goto error; | |
| 1674 | |
| 1675 if (control) { | |
| 1676 IDEBUG("found a control char in the syllable"); | |
| 1677 hb_uint32 i = 0, j = 0; | |
| 1678 while (i < item->num_glyphs) { | |
| 1679 if (form(reordered[otl_glyphs[i].cluster]) == Control) { | |
| 1680 ++i; | |
| 1681 if (i >= item->num_glyphs) | |
| 1682 break; | |
| 1683 } | |
| 1684 item->glyphs[j] = item->glyphs[i]; | |
| 1685 item->attributes[j] = item->attributes[i]; | |
| 1686 ++i; | |
| 1687 ++j; | |
| 1688 } | |
| 1689 item->num_glyphs = j; | |
| 1690 } | |
| 1691 | |
| 1692 } else { | |
| 1693 HB_HeuristicPosition(item); | |
| 1694 } | |
| 1695 #endif // NO_OPENTYPE | |
| 1696 item->attributes[0].clusterStart = true; | |
| 1697 | |
| 1698 HB_FREE_STACKARRAY(reordered); | |
| 1699 HB_FREE_STACKARRAY(position); | |
| 1700 | |
| 1701 IDEBUG("<<<<<<"); | |
| 1702 return true; | |
| 1703 | |
| 1704 error: | |
| 1705 HB_FREE_STACKARRAY(reordered); | |
| 1706 HB_FREE_STACKARRAY(position); | |
| 1707 return false; | |
| 1708 } | |
| 1709 | |
| 1710 /* syllables are of the form: | |
| 1711 | |
| 1712 (Consonant Nukta? Halant)* Consonant Matra? VowelMark? StressMark? | |
| 1713 (Consonant Nukta? Halant)* Consonant Halant | |
| 1714 IndependentVowel VowelMark? StressMark? | |
| 1715 | |
| 1716 We return syllable boundaries on invalid combinations aswell | |
| 1717 */ | |
| 1718 static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int
start, int end, bool *invalid) | |
| 1719 { | |
| 1720 *invalid = false; | |
| 1721 IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end); | |
| 1722 const HB_UChar16 *uc = s+start; | |
| 1723 | |
| 1724 int pos = 0; | |
| 1725 Form state = form(uc[pos]); | |
| 1726 IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos]); | |
| 1727 pos++; | |
| 1728 | |
| 1729 if (state != Consonant && state != IndependentVowel) { | |
| 1730 if (state != Other) | |
| 1731 *invalid = true; | |
| 1732 goto finish; | |
| 1733 } | |
| 1734 | |
| 1735 while (pos < end - start) { | |
| 1736 Form newState = form(uc[pos]); | |
| 1737 IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos]); | |
| 1738 switch(newState) { | |
| 1739 case Control: | |
| 1740 newState = state; | |
| 1741 if (state == Halant && uc[pos] == 0x200d /* ZWJ */) | |
| 1742 break; | |
| 1743 // the control character should be the last char in the item | |
| 1744 ++pos; | |
| 1745 goto finish; | |
| 1746 case Consonant: | |
| 1747 if (state == Halant && (script != HB_Script_Sinhala || uc[pos-1] ==
0x200d /* ZWJ */)) | |
| 1748 break; | |
| 1749 goto finish; | |
| 1750 case Halant: | |
| 1751 if (state == Nukta || state == Consonant) | |
| 1752 break; | |
| 1753 // Bengali has a special exception allowing the combination Vowel_A/
E + Halant + Ya | |
| 1754 if (script == HB_Script_Bengali && pos == 1 && | |
| 1755 (uc[0] == 0x0985 || uc[0] == 0x098f)) | |
| 1756 break; | |
| 1757 // Sinhala uses the Halant as a component of certain matras. Allow t
hese, but keep the state on Matra. | |
| 1758 if (script == HB_Script_Sinhala && state == Matra) { | |
| 1759 ++pos; | |
| 1760 continue; | |
| 1761 } | |
| 1762 if (script == HB_Script_Malayalam && state == Matra && uc[pos-1] ==
0x0d41) { | |
| 1763 ++pos; | |
| 1764 continue; | |
| 1765 } | |
| 1766 goto finish; | |
| 1767 case Nukta: | |
| 1768 if (state == Consonant) | |
| 1769 break; | |
| 1770 goto finish; | |
| 1771 case StressMark: | |
| 1772 if (state == VowelMark) | |
| 1773 break; | |
| 1774 // fall through | |
| 1775 case VowelMark: | |
| 1776 if (state == Matra || state == LengthMark || state == IndependentVow
el) | |
| 1777 break; | |
| 1778 // fall through | |
| 1779 case Matra: | |
| 1780 if (state == Consonant || state == Nukta) | |
| 1781 break; | |
| 1782 if (state == Matra) { | |
| 1783 // ### needs proper testing for correct two/three part matras | |
| 1784 break; | |
| 1785 } | |
| 1786 // ### not sure if this is correct. If it is, does it apply only to
Bengali or should | |
| 1787 // it work for all Indic languages? | |
| 1788 // the combination Independent_A + Vowel Sign AA is allowed. | |
| 1789 if (script == HB_Script_Bengali && uc[pos] == 0x9be && uc[pos-1] ==
0x985) | |
| 1790 break; | |
| 1791 if (script == HB_Script_Tamil && state == Matra) { | |
| 1792 if (uc[pos-1] == 0x0bc6 && | |
| 1793 (uc[pos] == 0xbbe || uc[pos] == 0xbd7)) | |
| 1794 break; | |
| 1795 if (uc[pos-1] == 0x0bc7 && uc[pos] == 0xbbe) | |
| 1796 break; | |
| 1797 } | |
| 1798 goto finish; | |
| 1799 | |
| 1800 case LengthMark: | |
| 1801 if (state == Matra) { | |
| 1802 // ### needs proper testing for correct two/three part matras | |
| 1803 break; | |
| 1804 } | |
| 1805 case IndependentVowel: | |
| 1806 case Invalid: | |
| 1807 case Other: | |
| 1808 goto finish; | |
| 1809 } | |
| 1810 state = newState; | |
| 1811 pos++; | |
| 1812 } | |
| 1813 finish: | |
| 1814 return pos+start; | |
| 1815 } | |
| 1816 | |
| 1817 HB_Bool HB_IndicShape(HB_ShaperItem *item) | |
| 1818 { | |
| 1819 assert(item->item.script >= HB_Script_Devanagari && item->item.script <= HB_
Script_Sinhala); | |
| 1820 | |
| 1821 HB_Bool openType = false; | |
| 1822 #ifndef NO_OPENTYPE | |
| 1823 openType = HB_SelectScript(item, indic_features); | |
| 1824 #endif | |
| 1825 unsigned short *logClusters = item->log_clusters; | |
| 1826 | |
| 1827 HB_ShaperItem syllable = *item; | |
| 1828 int first_glyph = 0; | |
| 1829 | |
| 1830 int sstart = item->item.pos; | |
| 1831 int end = sstart + item->item.length; | |
| 1832 IDEBUG("indic_shape: from %d length %d", item->item.pos, item->item.length); | |
| 1833 while (sstart < end) { | |
| 1834 bool invalid; | |
| 1835 int send = indic_nextSyllableBoundary(item->item.script, item->string, s
start, end, &invalid); | |
| 1836 IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, | |
| 1837 invalid ? "true" : "false"); | |
| 1838 syllable.item.pos = sstart; | |
| 1839 syllable.item.length = send-sstart; | |
| 1840 syllable.glyphs = item->glyphs + first_glyph; | |
| 1841 syllable.attributes = item->attributes + first_glyph; | |
| 1842 syllable.offsets = item->offsets + first_glyph; | |
| 1843 syllable.advances = item->advances + first_glyph; | |
| 1844 syllable.num_glyphs = item->num_glyphs - first_glyph; | |
| 1845 if (!indic_shape_syllable(openType, &syllable, invalid)) { | |
| 1846 IDEBUG("syllable shaping failed, syllable requests %d glyphs", sylla
ble.num_glyphs); | |
| 1847 item->num_glyphs += syllable.num_glyphs; | |
| 1848 return false; | |
| 1849 } | |
| 1850 // fix logcluster array | |
| 1851 IDEBUG("syllable:"); | |
| 1852 hb_uint32 g; | |
| 1853 for (g = first_glyph; g < first_glyph + syllable.num_glyphs; ++g) | |
| 1854 IDEBUG(" %d -> glyph %x", g, item->glyphs[g]); | |
| 1855 IDEBUG(" logclusters:"); | |
| 1856 int i; | |
| 1857 for (i = sstart; i < send; ++i) { | |
| 1858 IDEBUG(" %d -> glyph %d", i, first_glyph); | |
| 1859 logClusters[i-item->item.pos] = first_glyph; | |
| 1860 } | |
| 1861 sstart = send; | |
| 1862 first_glyph += syllable.num_glyphs; | |
| 1863 } | |
| 1864 item->num_glyphs = first_glyph; | |
| 1865 return true; | |
| 1866 } | |
| 1867 | |
| 1868 void HB_IndicAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from
, hb_uint32 len, HB_CharAttributes *attributes) | |
| 1869 { | |
| 1870 int end = from + len; | |
| 1871 const HB_UChar16 *uc = text + from; | |
| 1872 attributes += from; | |
| 1873 hb_uint32 i = 0; | |
| 1874 while (i < len) { | |
| 1875 bool invalid; | |
| 1876 hb_uint32 boundary = indic_nextSyllableBoundary(script, text, from+i, en
d, &invalid) - from; | |
| 1877 attributes[i].charStop = true; | |
| 1878 | |
| 1879 if (boundary > len-1) boundary = len; | |
| 1880 i++; | |
| 1881 while (i < boundary) { | |
| 1882 attributes[i].charStop = false; | |
| 1883 ++uc; | |
| 1884 ++i; | |
| 1885 } | |
| 1886 assert(i == boundary); | |
| 1887 } | |
| 1888 | |
| 1889 | |
| 1890 } | |
| 1891 | |
| 1892 | |
| OLD | NEW |