| 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 <QtTest/QtTest> | |
| 26 | |
| 27 #include <ft2build.h> | |
| 28 #include FT_FREETYPE_H | |
| 29 #include FT_TRUETYPE_TABLES_H | |
| 30 | |
| 31 #include <harfbuzz-shaper.h> | |
| 32 #include <harfbuzz-global.h> | |
| 33 #include <harfbuzz-gpos.h> | |
| 34 | |
| 35 static FT_Library freetype; | |
| 36 | |
| 37 static FT_Face loadFace(const char *name) | |
| 38 { | |
| 39 FT_Face face; | |
| 40 char path[256]; | |
| 41 | |
| 42 strcpy(path, SRCDIR); | |
| 43 strcat(path, "/fonts/"); | |
| 44 strcat(path, name); | |
| 45 | |
| 46 if (FT_New_Face(freetype, path, /*index*/0, &face)) | |
| 47 return 0; | |
| 48 return face; | |
| 49 } | |
| 50 | |
| 51 static HB_UChar32 getChar(const HB_UChar16 *string, hb_uint32 length, hb_uint32
&i) | |
| 52 { | |
| 53 HB_UChar32 ch; | |
| 54 if (HB_IsHighSurrogate(string[i]) | |
| 55 && i < length - 1 | |
| 56 && HB_IsLowSurrogate(string[i + 1])) { | |
| 57 ch = HB_SurrogateToUcs4(string[i], string[i + 1]); | |
| 58 ++i; | |
| 59 } else { | |
| 60 ch = string[i]; | |
| 61 } | |
| 62 return ch; | |
| 63 } | |
| 64 | |
| 65 static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint
32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool /*rightToLeft*/) | |
| 66 { | |
| 67 FT_Face face = (FT_Face)font->userData; | |
| 68 if (length > *numGlyphs) | |
| 69 return false; | |
| 70 | |
| 71 int glyph_pos = 0; | |
| 72 for (hb_uint32 i = 0; i < length; ++i) { | |
| 73 glyphs[glyph_pos] = FT_Get_Char_Index(face, getChar(string, length, i)); | |
| 74 ++glyph_pos; | |
| 75 } | |
| 76 | |
| 77 *numGlyphs = glyph_pos; | |
| 78 | |
| 79 return true; | |
| 80 } | |
| 81 | |
| 82 static void hb_getAdvances(HB_Font /*font*/, const HB_Glyph * /*glyphs*/, hb_uin
t32 numGlyphs, HB_Fixed *advances, int /*flags*/) | |
| 83 { | |
| 84 for (hb_uint32 i = 0; i < numGlyphs; ++i) | |
| 85 advances[i] = 0; // ### not tested right now | |
| 86 } | |
| 87 | |
| 88 static HB_Bool hb_canRender(HB_Font font, const HB_UChar16 *string, hb_uint32 le
ngth) | |
| 89 { | |
| 90 FT_Face face = (FT_Face)font->userData; | |
| 91 | |
| 92 for (hb_uint32 i = 0; i < length; ++i) | |
| 93 if (!FT_Get_Char_Index(face, getChar(string, length, i))) | |
| 94 return false; | |
| 95 | |
| 96 return true; | |
| 97 } | |
| 98 | |
| 99 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB
_UInt *length) | |
| 100 { | |
| 101 FT_Face face = (FT_Face)font; | |
| 102 FT_ULong ftlen = *length; | |
| 103 FT_Error error = 0; | |
| 104 | |
| 105 if (!FT_IS_SFNT(face)) | |
| 106 return HB_Err_Invalid_Argument; | |
| 107 | |
| 108 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen); | |
| 109 *length = ftlen; | |
| 110 return (HB_Error)error; | |
| 111 } | |
| 112 | |
| 113 HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32
point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints) | |
| 114 { | |
| 115 HB_Error error = HB_Err_Ok; | |
| 116 FT_Face face = (FT_Face)font->userData; | |
| 117 | |
| 118 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTI
NG : FT_LOAD_DEFAULT; | |
| 119 | |
| 120 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags))) | |
| 121 return error; | |
| 122 | |
| 123 if (face->glyph->format != ft_glyph_format_outline) | |
| 124 return (HB_Error)HB_Err_Invalid_SubTable; | |
| 125 | |
| 126 *nPoints = face->glyph->outline.n_points; | |
| 127 if (!(*nPoints)) | |
| 128 return HB_Err_Ok; | |
| 129 | |
| 130 if (point > *nPoints) | |
| 131 return (HB_Error)HB_Err_Invalid_SubTable; | |
| 132 | |
| 133 *xpos = face->glyph->outline.points[point].x; | |
| 134 *ypos = face->glyph->outline.points[point].y; | |
| 135 | |
| 136 return HB_Err_Ok; | |
| 137 } | |
| 138 | |
| 139 void hb_getGlyphMetrics(HB_Font, HB_Glyph, HB_GlyphMetrics *metrics) | |
| 140 { | |
| 141 // ### | |
| 142 metrics->x = metrics->y = metrics->width = metrics->height = metrics->xOffse
t = metrics->yOffset = 0; | |
| 143 } | |
| 144 | |
| 145 HB_Fixed hb_getFontMetric(HB_Font, HB_FontMetric ) | |
| 146 { | |
| 147 return 0; // #### | |
| 148 } | |
| 149 | |
| 150 const HB_FontClass hb_fontClass = { | |
| 151 hb_stringToGlyphs, hb_getAdvances, hb_canRender, | |
| 152 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric | |
| 153 }; | |
| 154 | |
| 155 | |
| 156 //TESTED_CLASS= | |
| 157 //TESTED_FILES= gui/text/qscriptengine.cpp | |
| 158 | |
| 159 class tst_QScriptEngine : public QObject | |
| 160 { | |
| 161 Q_OBJECT | |
| 162 | |
| 163 public: | |
| 164 tst_QScriptEngine(); | |
| 165 virtual ~tst_QScriptEngine(); | |
| 166 | |
| 167 | |
| 168 public slots: | |
| 169 void initTestCase(); | |
| 170 void cleanupTestCase(); | |
| 171 private slots: | |
| 172 void greek(); | |
| 173 | |
| 174 void devanagari(); | |
| 175 void bengali(); | |
| 176 void gurmukhi(); | |
| 177 // gujarati missing | |
| 178 void oriya(); | |
| 179 void tamil(); | |
| 180 void telugu(); | |
| 181 void kannada(); | |
| 182 void malayalam(); | |
| 183 void sinhala(); | |
| 184 | |
| 185 void khmer(); | |
| 186 void nko(); | |
| 187 void linearB(); | |
| 188 }; | |
| 189 | |
| 190 tst_QScriptEngine::tst_QScriptEngine() | |
| 191 { | |
| 192 } | |
| 193 | |
| 194 tst_QScriptEngine::~tst_QScriptEngine() | |
| 195 { | |
| 196 } | |
| 197 | |
| 198 void tst_QScriptEngine::initTestCase() | |
| 199 { | |
| 200 FT_Init_FreeType(&freetype); | |
| 201 } | |
| 202 | |
| 203 void tst_QScriptEngine::cleanupTestCase() | |
| 204 { | |
| 205 FT_Done_FreeType(freetype); | |
| 206 } | |
| 207 | |
| 208 class Shaper | |
| 209 { | |
| 210 public: | |
| 211 Shaper(FT_Face face, HB_Script script, const QString &str); | |
| 212 | |
| 213 HB_FontRec hbFont; | |
| 214 HB_ShaperItem shaper_item; | |
| 215 QVarLengthArray<HB_Glyph> hb_glyphs; | |
| 216 QVarLengthArray<HB_GlyphAttributes> hb_attributes; | |
| 217 QVarLengthArray<HB_Fixed> hb_advances; | |
| 218 QVarLengthArray<HB_FixedPoint> hb_offsets; | |
| 219 QVarLengthArray<unsigned short> hb_logClusters; | |
| 220 | |
| 221 }; | |
| 222 | |
| 223 Shaper::Shaper(FT_Face face, HB_Script script, const QString &str) | |
| 224 { | |
| 225 HB_Face hbFace = HB_NewFace(face, hb_getSFntTable); | |
| 226 | |
| 227 hbFont.klass = &hb_fontClass; | |
| 228 hbFont.userData = face; | |
| 229 hbFont.x_ppem = face->size->metrics.x_ppem; | |
| 230 hbFont.y_ppem = face->size->metrics.y_ppem; | |
| 231 hbFont.x_scale = face->size->metrics.x_scale; | |
| 232 hbFont.y_scale = face->size->metrics.y_scale; | |
| 233 | |
| 234 shaper_item.kerning_applied = false; | |
| 235 shaper_item.string = reinterpret_cast<const HB_UChar16 *>(str.constData()); | |
| 236 shaper_item.stringLength = str.length(); | |
| 237 shaper_item.item.script = script; | |
| 238 shaper_item.item.pos = 0; | |
| 239 shaper_item.item.length = shaper_item.stringLength; | |
| 240 shaper_item.item.bidiLevel = 0; // ### | |
| 241 shaper_item.shaperFlags = 0; | |
| 242 shaper_item.font = &hbFont; | |
| 243 shaper_item.face = hbFace; | |
| 244 shaper_item.num_glyphs = shaper_item.item.length; | |
| 245 shaper_item.glyphIndicesPresent = false; | |
| 246 shaper_item.initialGlyphCount = 0; | |
| 247 | |
| 248 | |
| 249 while (1) { | |
| 250 hb_glyphs.resize(shaper_item.num_glyphs); | |
| 251 hb_attributes.resize(shaper_item.num_glyphs); | |
| 252 hb_advances.resize(shaper_item.num_glyphs); | |
| 253 hb_offsets.resize(shaper_item.num_glyphs); | |
| 254 hb_logClusters.resize(shaper_item.num_glyphs); | |
| 255 | |
| 256 memset(hb_glyphs.data(), 0, hb_glyphs.size() * sizeof(HB_Glyph)); | |
| 257 memset(hb_attributes.data(), 0, hb_attributes.size() * sizeof(HB_GlyphAt
tributes)); | |
| 258 memset(hb_advances.data(), 0, hb_advances.size() * sizeof(HB_Fixed)); | |
| 259 memset(hb_offsets.data(), 0, hb_offsets.size() * sizeof(HB_FixedPoint)); | |
| 260 | |
| 261 shaper_item.glyphs = hb_glyphs.data(); | |
| 262 shaper_item.attributes = hb_attributes.data(); | |
| 263 shaper_item.advances = hb_advances.data(); | |
| 264 shaper_item.offsets = hb_offsets.data(); | |
| 265 shaper_item.log_clusters = hb_logClusters.data(); | |
| 266 | |
| 267 if (HB_ShapeItem(&shaper_item)) | |
| 268 break; | |
| 269 } | |
| 270 | |
| 271 HB_FreeFace(hbFace); | |
| 272 } | |
| 273 | |
| 274 | |
| 275 static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch) | |
| 276 { | |
| 277 QString uc = QString().append(ch); | |
| 278 Shaper shaper(face, script, uc); | |
| 279 | |
| 280 uc = uc.normalized(QString::NormalizationForm_D); | |
| 281 Shaper decomposed(face, script, uc); | |
| 282 | |
| 283 if( shaper.shaper_item.num_glyphs != decomposed.shaper_item.num_glyphs ) | |
| 284 goto error; | |
| 285 | |
| 286 for (unsigned int i = 0; i < shaper.shaper_item.num_glyphs; ++i) { | |
| 287 if ((shaper.shaper_item.glyphs[i]&0xffffff) != (decomposed.shaper_item.g
lyphs[i]&0xffffff)) | |
| 288 goto error; | |
| 289 } | |
| 290 return true; | |
| 291 error: | |
| 292 QString str = ""; | |
| 293 int i = 0; | |
| 294 while (i < uc.length()) { | |
| 295 str += QString("%1 ").arg(uc[i].unicode(), 4, 16); | |
| 296 ++i; | |
| 297 } | |
| 298 qDebug("%s: decomposedShaping of char %4x failed\n decomposedString: %s\n
nglyphs=%d, decomposed nglyphs %d", | |
| 299 face->family_name, | |
| 300 ch.unicode(), str.toLatin1().data(), | |
| 301 shaper.shaper_item.num_glyphs, | |
| 302 decomposed.shaper_item.num_glyphs); | |
| 303 | |
| 304 str = ""; | |
| 305 i = 0; | |
| 306 while (i < shaper.shaper_item.num_glyphs) { | |
| 307 str += QString("%1 ").arg(shaper.shaper_item.glyphs[i], 4, 16); | |
| 308 ++i; | |
| 309 } | |
| 310 qDebug(" composed glyph result = %s", str.toLatin1().constData()); | |
| 311 str = ""; | |
| 312 i = 0; | |
| 313 while (i < decomposed.shaper_item.num_glyphs) { | |
| 314 str += QString("%1 ").arg(decomposed.shaper_item.glyphs[i], 4, 16); | |
| 315 ++i; | |
| 316 } | |
| 317 qDebug(" decomposed glyph result = %s", str.toLatin1().constData()); | |
| 318 return false; | |
| 319 } | |
| 320 | |
| 321 struct ShapeTable { | |
| 322 unsigned short unicode[16]; | |
| 323 unsigned short glyphs[16]; | |
| 324 }; | |
| 325 | |
| 326 static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) | |
| 327 { | |
| 328 Shaper shaper(face, script, QString::fromUtf16( s->unicode )); | |
| 329 | |
| 330 hb_uint32 nglyphs = 0; | |
| 331 const unsigned short *g = s->glyphs; | |
| 332 while ( *g ) { | |
| 333 nglyphs++; | |
| 334 g++; | |
| 335 } | |
| 336 | |
| 337 if( nglyphs != shaper.shaper_item.num_glyphs ) | |
| 338 goto error; | |
| 339 | |
| 340 for (hb_uint32 i = 0; i < nglyphs; ++i) { | |
| 341 if ((shaper.shaper_item.glyphs[i]&0xffffff) != s->glyphs[i]) | |
| 342 goto error; | |
| 343 } | |
| 344 return true; | |
| 345 error: | |
| 346 QString str = ""; | |
| 347 const unsigned short *uc = s->unicode; | |
| 348 while (*uc) { | |
| 349 str += QString("%1 ").arg(*uc, 4, 16); | |
| 350 ++uc; | |
| 351 } | |
| 352 qDebug("%s: shaping of string %s failed, nglyphs=%d, expected %d", | |
| 353 face->family_name, | |
| 354 str.toLatin1().constData(), | |
| 355 shaper.shaper_item.num_glyphs, nglyphs); | |
| 356 | |
| 357 str = ""; | |
| 358 hb_uint32 i = 0; | |
| 359 while (i < shaper.shaper_item.num_glyphs) { | |
| 360 str += QString("%1 ").arg(shaper.shaper_item.glyphs[i], 4, 16); | |
| 361 ++i; | |
| 362 } | |
| 363 qDebug(" glyph result = %s", str.toLatin1().constData()); | |
| 364 return false; | |
| 365 } | |
| 366 | |
| 367 | |
| 368 void tst_QScriptEngine::greek() | |
| 369 { | |
| 370 FT_Face face = loadFace("DejaVuSans.ttf"); | |
| 371 if (face) { | |
| 372 for (int uc = 0x1f00; uc <= 0x1fff; ++uc) { | |
| 373 QString str; | |
| 374 str.append(uc); | |
| 375 if (str.normalized(QString::NormalizationForm_D).normalized(QString:
:NormalizationForm_C) != str) { | |
| 376 //qDebug() << "skipping" << hex << uc; | |
| 377 continue; | |
| 378 } | |
| 379 if (uc == 0x1fc1 || uc == 0x1fed) | |
| 380 continue; | |
| 381 QVERIFY( decomposedShaping(face, HB_Script_Greek, QChar(uc)) ); | |
| 382 } | |
| 383 FT_Done_Face(face); | |
| 384 } else { | |
| 385 QSKIP("couln't find DejaVu Sans", SkipAll); | |
| 386 } | |
| 387 | |
| 388 | |
| 389 face = loadFace("SBL_grk.ttf"); | |
| 390 if (face) { | |
| 391 for (int uc = 0x1f00; uc <= 0x1fff; ++uc) { | |
| 392 QString str; | |
| 393 str.append(uc); | |
| 394 if (str.normalized(QString::NormalizationForm_D).normalized(QString:
:NormalizationForm_C) != str) { | |
| 395 //qDebug() << "skipping" << hex << uc; | |
| 396 continue; | |
| 397 } | |
| 398 if (uc == 0x1fc1 || uc == 0x1fed) | |
| 399 continue; | |
| 400 QVERIFY( decomposedShaping(face, HB_Script_Greek, QChar(uc)) ); | |
| 401 | |
| 402 } | |
| 403 | |
| 404 const ShapeTable shape_table [] = { | |
| 405 { { 0x3b1, 0x300, 0x313, 0x0 }, | |
| 406 { 0xb8, 0x3d3, 0x3c7, 0x0 } }, | |
| 407 { { 0x3b1, 0x313, 0x300, 0x0 }, | |
| 408 { 0xd4, 0x0 } }, | |
| 409 | |
| 410 { {0}, {0} } | |
| 411 }; | |
| 412 | |
| 413 | |
| 414 const ShapeTable *s = shape_table; | |
| 415 while (s->unicode[0]) { | |
| 416 QVERIFY( shaping(face, s, HB_Script_Greek) ); | |
| 417 ++s; | |
| 418 } | |
| 419 | |
| 420 FT_Done_Face(face); | |
| 421 } else { | |
| 422 QSKIP("couln't find DejaVu Sans", SkipAll); | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 | |
| 427 void tst_QScriptEngine::devanagari() | |
| 428 { | |
| 429 { | |
| 430 FT_Face face = loadFace("raghu.ttf"); | |
| 431 if (face) { | |
| 432 const ShapeTable shape_table [] = { | |
| 433 // Ka | |
| 434 { { 0x0915, 0x0 }, | |
| 435 { 0x0080, 0x0 } }, | |
| 436 // Ka Halant | |
| 437 { { 0x0915, 0x094d, 0x0 }, | |
| 438 { 0x0080, 0x0051, 0x0 } }, | |
| 439 // Ka Halant Ka | |
| 440 { { 0x0915, 0x094d, 0x0915, 0x0 }, | |
| 441 { 0x00c8, 0x0080, 0x0 } }, | |
| 442 // Ka MatraI | |
| 443 { { 0x0915, 0x093f, 0x0 }, | |
| 444 { 0x01d1, 0x0080, 0x0 } }, | |
| 445 // Ra Halant Ka | |
| 446 { { 0x0930, 0x094d, 0x0915, 0x0 }, | |
| 447 { 0x0080, 0x005b, 0x0 } }, | |
| 448 // Ra Halant Ka MatraI | |
| 449 { { 0x0930, 0x094d, 0x0915, 0x093f, 0x0 }, | |
| 450 { 0x01d1, 0x0080, 0x005b, 0x0 } }, | |
| 451 // MatraI | |
| 452 { { 0x093f, 0x0 }, | |
| 453 { 0x01d4, 0x029c, 0x0 } }, | |
| 454 // Ka Nukta | |
| 455 { { 0x0915, 0x093c, 0x0 }, | |
| 456 { 0x00a4, 0x0 } }, | |
| 457 // Ka Halant Ra | |
| 458 { { 0x0915, 0x094d, 0x0930, 0x0 }, | |
| 459 { 0x0110, 0x0 } }, | |
| 460 // Ka Halant Ra Halant Ka | |
| 461 { { 0x0915, 0x094d, 0x0930, 0x094d, 0x0915, 0x0 }, | |
| 462 { 0x0158, 0x0080, 0x0 } }, | |
| 463 { { 0x0930, 0x094d, 0x200d, 0x0 }, | |
| 464 { 0x00e2, 0x0 } }, | |
| 465 { { 0x0915, 0x094d, 0x0930, 0x094d, 0x200d, 0x0 }, | |
| 466 { 0x0158, 0x0 } }, | |
| 467 | |
| 468 { {0}, {0} } | |
| 469 }; | |
| 470 | |
| 471 | |
| 472 const ShapeTable *s = shape_table; | |
| 473 while (s->unicode[0]) { | |
| 474 QVERIFY( shaping(face, s, HB_Script_Devanagari) ); | |
| 475 ++s; | |
| 476 } | |
| 477 | |
| 478 FT_Done_Face(face); | |
| 479 } else { | |
| 480 QSKIP("couln't find raghu.ttf", SkipAll); | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 { | |
| 485 FT_Face face = loadFace("mangal.ttf"); | |
| 486 if (face) { | |
| 487 const ShapeTable shape_table [] = { | |
| 488 // Ka | |
| 489 { { 0x0915, 0x0 }, | |
| 490 { 0x0080, 0x0 } }, | |
| 491 // Ka Halant | |
| 492 { { 0x0915, 0x094d, 0x0 }, | |
| 493 { 0x0080, 0x0051, 0x0 } }, | |
| 494 // Ka Halant Ka | |
| 495 { { 0x0915, 0x094d, 0x0915, 0x0 }, | |
| 496 { 0x00c8, 0x0080, 0x0 } }, | |
| 497 // Ka MatraI | |
| 498 { { 0x0915, 0x093f, 0x0 }, | |
| 499 { 0x01d1, 0x0080, 0x0 } }, | |
| 500 // Ra Halant Ka | |
| 501 { { 0x0930, 0x094d, 0x0915, 0x0 }, | |
| 502 { 0x0080, 0x005b, 0x0 } }, | |
| 503 // Ra Halant Ka MatraI | |
| 504 { { 0x0930, 0x094d, 0x0915, 0x093f, 0x0 }, | |
| 505 { 0x01d1, 0x0080, 0x005b, 0x0 } }, | |
| 506 // MatraI | |
| 507 { { 0x093f, 0x0 }, | |
| 508 { 0x01d4, 0x029c, 0x0 } }, | |
| 509 // Ka Nukta | |
| 510 { { 0x0915, 0x093c, 0x0 }, | |
| 511 { 0x00a4, 0x0 } }, | |
| 512 // Ka Halant Ra | |
| 513 { { 0x0915, 0x094d, 0x0930, 0x0 }, | |
| 514 { 0x0110, 0x0 } }, | |
| 515 // Ka Halant Ra Halant Ka | |
| 516 { { 0x0915, 0x094d, 0x0930, 0x094d, 0x0915, 0x0 }, | |
| 517 { 0x0158, 0x0080, 0x0 } }, | |
| 518 | |
| 519 { { 0x92b, 0x94d, 0x930, 0x0 }, | |
| 520 { 0x125, 0x0 } }, | |
| 521 { { 0x92b, 0x93c, 0x94d, 0x930, 0x0 }, | |
| 522 { 0x149, 0x0 } }, | |
| 523 { {0}, {0} } | |
| 524 }; | |
| 525 | |
| 526 const ShapeTable *s = shape_table; | |
| 527 while (s->unicode[0]) { | |
| 528 QVERIFY( shaping(face, s, HB_Script_Devanagari) ); | |
| 529 ++s; | |
| 530 } | |
| 531 | |
| 532 FT_Done_Face(face); | |
| 533 } else { | |
| 534 QSKIP("couldn't find mangal.ttf", SkipAll); | |
| 535 } | |
| 536 } | |
| 537 } | |
| 538 | |
| 539 void tst_QScriptEngine::bengali() | |
| 540 { | |
| 541 { | |
| 542 FT_Face face = loadFace("AkaashNormal.ttf"); | |
| 543 if (face) { | |
| 544 const ShapeTable shape_table [] = { | |
| 545 // Ka | |
| 546 { { 0x0995, 0x0 }, | |
| 547 { 0x0151, 0x0 } }, | |
| 548 // Ka Halant | |
| 549 { { 0x0995, 0x09cd, 0x0 }, | |
| 550 { 0x0151, 0x017d, 0x0 } }, | |
| 551 // Ka Halant Ka | |
| 552 { { 0x0995, 0x09cd, 0x0995, 0x0 }, | |
| 553 { 0x019b, 0x0 } }, | |
| 554 // Ka MatraI | |
| 555 { { 0x0995, 0x09bf, 0x0 }, | |
| 556 { 0x0173, 0x0151, 0x0 } }, | |
| 557 // Ra Halant Ka | |
| 558 { { 0x09b0, 0x09cd, 0x0995, 0x0 }, | |
| 559 { 0x0151, 0x0276, 0x0 } }, | |
| 560 // Ra Halant Ka MatraI | |
| 561 { { 0x09b0, 0x09cd, 0x0995, 0x09bf, 0x0 }, | |
| 562 { 0x0173, 0x0151, 0x0276, 0x0 } }, | |
| 563 // Ka Nukta | |
| 564 { { 0x0995, 0x09bc, 0x0 }, | |
| 565 { 0x0151, 0x0171, 0x0 } }, | |
| 566 // Ka Halant Ra | |
| 567 { { 0x0995, 0x09cd, 0x09b0, 0x0 }, | |
| 568 { 0x01f4, 0x0 } }, | |
| 569 // Ka Halant Ra Halant Ka | |
| 570 { { 0x0995, 0x09cd, 0x09b0, 0x09cd, 0x0995, 0x0 }, | |
| 571 { 0x025c, 0x0276, 0x0151, 0x0 } }, | |
| 572 // Ya + Halant | |
| 573 { { 0x09af, 0x09cd, 0x0 }, | |
| 574 { 0x016a, 0x017d, 0x0 } }, | |
| 575 // Da Halant Ya -> Da Ya-Phala | |
| 576 { { 0x09a6, 0x09cd, 0x09af, 0x0 }, | |
| 577 { 0x01e5, 0x0 } }, | |
| 578 // A Halant Ya -> A Ya-phala | |
| 579 { { 0x0985, 0x09cd, 0x09af, 0x0 }, | |
| 580 { 0x0145, 0x01cf, 0x0 } }, | |
| 581 // Na Halant Ka | |
| 582 { { 0x09a8, 0x09cd, 0x0995, 0x0 }, | |
| 583 { 0x026f, 0x0151, 0x0 } }, | |
| 584 // Na Halant ZWNJ Ka | |
| 585 { { 0x09a8, 0x09cd, 0x200c, 0x0995, 0x0 }, | |
| 586 { 0x0164, 0x017d, 0x0151, 0x0 } }, | |
| 587 // Na Halant ZWJ Ka | |
| 588 { { 0x09a8, 0x09cd, 0x200d, 0x0995, 0x0 }, | |
| 589 { 0x026f, 0x0151, 0x0 } }, | |
| 590 // Ka Halant ZWNJ Ka | |
| 591 { { 0x0995, 0x09cd, 0x200c, 0x0995, 0x0 }, | |
| 592 { 0x0151, 0x017d, 0x0151, 0x0 } }, | |
| 593 // Ka Halant ZWJ Ka | |
| 594 { { 0x0995, 0x09cd, 0x200d, 0x0995, 0x0 }, | |
| 595 { 0x025c, 0x0151, 0x0 } }, | |
| 596 // Na Halant Ra | |
| 597 { { 0x09a8, 0x09cd, 0x09b0, 0x0 }, | |
| 598 { 0x0207, 0x0 } }, | |
| 599 // Na Halant ZWNJ Ra | |
| 600 { { 0x09a8, 0x09cd, 0x200c, 0x09b0, 0x0 }, | |
| 601 { 0x0164, 0x017d, 0x016b, 0x0 } }, | |
| 602 // Na Halant ZWJ Ra | |
| 603 { { 0x09a8, 0x09cd, 0x200d, 0x09b0, 0x0 }, | |
| 604 { 0x026f, 0x016b, 0x0 } }, | |
| 605 // Na Halant Ba | |
| 606 { { 0x09a8, 0x09cd, 0x09ac, 0x0 }, | |
| 607 { 0x022f, 0x0 } }, | |
| 608 // Na Halant ZWNJ Ba | |
| 609 { { 0x09a8, 0x09cd, 0x200c, 0x09ac, 0x0 }, | |
| 610 { 0x0164, 0x017d, 0x0167, 0x0 } }, | |
| 611 // Na Halant ZWJ Ba | |
| 612 { { 0x09a8, 0x09cd, 0x200d, 0x09ac, 0x0 }, | |
| 613 { 0x026f, 0x0167, 0x0 } }, | |
| 614 // Na Halant Dha | |
| 615 { { 0x09a8, 0x09cd, 0x09a7, 0x0 }, | |
| 616 { 0x01d3, 0x0 } }, | |
| 617 // Na Halant ZWNJ Dha | |
| 618 { { 0x09a8, 0x09cd, 0x200c, 0x09a7, 0x0 }, | |
| 619 { 0x0164, 0x017d, 0x0163, 0x0 } }, | |
| 620 // Na Halant ZWJ Dha | |
| 621 { { 0x09a8, 0x09cd, 0x200d, 0x09a7, 0x0 }, | |
| 622 { 0x026f, 0x0163, 0x0 } }, | |
| 623 // Ra Halant Ka MatraAU | |
| 624 { { 0x09b0, 0x09cd, 0x0995, 0x09cc, 0x0 }, | |
| 625 { 0x0179, 0x0151, 0x0276, 0x017e, 0x0 } }, | |
| 626 // Ra Halant Ba Halant Ba | |
| 627 { { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 }, | |
| 628 { 0x0232, 0x0276, 0x0 } }, | |
| 629 { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x982, 0x0 }, | |
| 630 { 0x151, 0x276, 0x172, 0x143, 0x0 } }, | |
| 631 { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x983, 0x0 }, | |
| 632 { 0x151, 0x276, 0x172, 0x144, 0x0 } }, | |
| 633 // test decomposed two parts matras | |
| 634 { { 0x995, 0x9c7, 0x9be, 0x0 }, | |
| 635 { 0x179, 0x151, 0x172, 0x0 } }, | |
| 636 { { 0x995, 0x9c7, 0x9d7, 0x0 }, | |
| 637 { 0x179, 0x151, 0x17e, 0x0 } }, | |
| 638 { { 0x9b0, 0x9cd, 0x9ad, 0x0 }, | |
| 639 { 0x168, 0x276, 0x0 } }, | |
| 640 { { 0x9f0, 0x9cd, 0x9ad, 0x0 }, | |
| 641 { 0x168, 0x276, 0x0 } }, | |
| 642 { { 0x9f1, 0x9cd, 0x9ad, 0x0 }, | |
| 643 { 0x191, 0x17d, 0x168, 0x0 } }, | |
| 644 | |
| 645 { {0}, {0} } | |
| 646 }; | |
| 647 | |
| 648 | |
| 649 const ShapeTable *s = shape_table; | |
| 650 while (s->unicode[0]) { | |
| 651 QVERIFY( shaping(face, s, HB_Script_Bengali) ); | |
| 652 ++s; | |
| 653 } | |
| 654 | |
| 655 FT_Done_Face(face); | |
| 656 } else { | |
| 657 QSKIP("couln't find AkaashNormal.ttf", SkipAll); | |
| 658 } | |
| 659 } | |
| 660 { | |
| 661 FT_Face face = loadFace("MuktiNarrow.ttf"); | |
| 662 if (face) { | |
| 663 const ShapeTable shape_table [] = { | |
| 664 // Ka | |
| 665 { { 0x0995, 0x0 }, | |
| 666 { 0x0073, 0x0 } }, | |
| 667 // Ka Halant | |
| 668 { { 0x0995, 0x09cd, 0x0 }, | |
| 669 { 0x00b9, 0x0 } }, | |
| 670 // Ka Halant Ka | |
| 671 { { 0x0995, 0x09cd, 0x0995, 0x0 }, | |
| 672 { 0x0109, 0x0 } }, | |
| 673 // Ka MatraI | |
| 674 { { 0x0995, 0x09bf, 0x0 }, | |
| 675 { 0x0095, 0x0073, 0x0 } }, | |
| 676 // Ra Halant Ka | |
| 677 { { 0x09b0, 0x09cd, 0x0995, 0x0 }, | |
| 678 { 0x0073, 0x00e1, 0x0 } }, | |
| 679 // Ra Halant Ka MatraI | |
| 680 { { 0x09b0, 0x09cd, 0x0995, 0x09bf, 0x0 }, | |
| 681 { 0x0095, 0x0073, 0x00e1, 0x0 } }, | |
| 682 // MatraI | |
| 683 { { 0x09bf, 0x0 }, | |
| 684 { 0x0095, 0x01c8, 0x0 } }, | |
| 685 // Ka Nukta | |
| 686 { { 0x0995, 0x09bc, 0x0 }, | |
| 687 { 0x0073, 0x0093, 0x0 } }, | |
| 688 // Ka Halant Ra | |
| 689 { { 0x0995, 0x09cd, 0x09b0, 0x0 }, | |
| 690 { 0x00e5, 0x0 } }, | |
| 691 // Ka Halant Ra Halant Ka | |
| 692 { { 0x995, 0x9cd, 0x9b0, 0x9cd, 0x995, 0x0 }, | |
| 693 { 0x234, 0x24e, 0x73, 0x0 } }, | |
| 694 // Ya + Halant | |
| 695 { { 0x09af, 0x09cd, 0x0 }, | |
| 696 { 0x00d2, 0x0 } }, | |
| 697 // Da Halant Ya -> Da Ya-Phala | |
| 698 { { 0x09a6, 0x09cd, 0x09af, 0x0 }, | |
| 699 { 0x0084, 0x00e2, 0x0 } }, | |
| 700 // A Halant Ya -> A Ya-phala | |
| 701 { { 0x0985, 0x09cd, 0x09af, 0x0 }, | |
| 702 { 0x0067, 0x00e2, 0x0 } }, | |
| 703 // Na Halant Ka | |
| 704 { { 0x09a8, 0x09cd, 0x0995, 0x0 }, | |
| 705 { 0x0188, 0x0 } }, | |
| 706 // Na Halant ZWNJ Ka | |
| 707 { { 0x9a8, 0x9cd, 0x200c, 0x995, 0x0 }, | |
| 708 { 0xcc, 0x73, 0x0 } }, | |
| 709 // Na Halant ZWJ Ka | |
| 710 { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 }, | |
| 711 { 0x247, 0x73, 0x0 } }, | |
| 712 // Ka Halant ZWNJ Ka | |
| 713 { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 }, | |
| 714 { 0x247, 0x73, 0x0 } }, | |
| 715 // Ka Halant ZWJ Ka | |
| 716 { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 }, | |
| 717 { 0x247, 0x73, 0x0 } }, | |
| 718 // Na Halant Ra | |
| 719 { { 0x09a8, 0x09cd, 0x09b0, 0x0 }, | |
| 720 { 0x00f8, 0x0 } }, | |
| 721 // Na Halant ZWNJ Ra | |
| 722 { { 0x09a8, 0x09cd, 0x200c, 0x09b0, 0x0 }, | |
| 723 { 0xcc, 0x8d, 0x0 } }, | |
| 724 // Na Halant ZWJ Ra | |
| 725 { { 0x9a8, 0x9cd, 0x200d, 0x9b0, 0x0 }, | |
| 726 { 0x247, 0x8d, 0x0 } }, | |
| 727 // Na Halant Ba | |
| 728 { { 0x09a8, 0x09cd, 0x09ac, 0x0 }, | |
| 729 { 0x0139, 0x0 } }, | |
| 730 // Na Halant ZWNJ Ba | |
| 731 { { 0x9a8, 0x9cd, 0x200c, 0x9ac, 0x0 }, | |
| 732 { 0xcc, 0x89, 0x0 } }, | |
| 733 // Na Halant ZWJ Ba | |
| 734 { { 0x9a8, 0x9cd, 0x200d, 0x9ac, 0x0 }, | |
| 735 { 0x247, 0x89, 0x0 } }, | |
| 736 // Na Halant Dha | |
| 737 { { 0x09a8, 0x09cd, 0x09a7, 0x0 }, | |
| 738 { 0x0145, 0x0 } }, | |
| 739 // Na Halant ZWNJ Dha | |
| 740 { { 0x09a8, 0x09cd, 0x200c, 0x09a7, 0x0 }, | |
| 741 { 0xcc, 0x85, 0x0 } }, | |
| 742 // Na Halant ZWJ Dha | |
| 743 { { 0x09a8, 0x09cd, 0x200d, 0x09a7, 0x0 }, | |
| 744 { 0x247, 0x85, 0x0 } }, | |
| 745 // Ra Halant Ka MatraAU | |
| 746 { { 0x9b0, 0x9cd, 0x995, 0x9cc, 0x0 }, | |
| 747 { 0x232, 0x73, 0xe1, 0xa0, 0x0 } }, | |
| 748 // Ra Halant Ba Halant Ba | |
| 749 { { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 }, | |
| 750 { 0x013b, 0x00e1, 0x0 } }, | |
| 751 | |
| 752 { {0}, {0} } | |
| 753 }; | |
| 754 | |
| 755 | |
| 756 const ShapeTable *s = shape_table; | |
| 757 while (s->unicode[0]) { | |
| 758 QVERIFY( shaping(face, s, HB_Script_Bengali) ); | |
| 759 ++s; | |
| 760 } | |
| 761 | |
| 762 FT_Done_Face(face); | |
| 763 } else { | |
| 764 QSKIP("couln't find MuktiNarrow.ttf", SkipAll); | |
| 765 } | |
| 766 } | |
| 767 { | |
| 768 FT_Face face = loadFace("LikhanNormal.ttf"); | |
| 769 if (face) { | |
| 770 const ShapeTable shape_table [] = { | |
| 771 { { 0x09a8, 0x09cd, 0x09af, 0x0 }, | |
| 772 { 0x01ca, 0x0 } }, | |
| 773 { { 0x09b8, 0x09cd, 0x09af, 0x0 }, | |
| 774 { 0x020e, 0x0 } }, | |
| 775 { { 0x09b6, 0x09cd, 0x09af, 0x0 }, | |
| 776 { 0x01f4, 0x0 } }, | |
| 777 { { 0x09b7, 0x09cd, 0x09af, 0x0 }, | |
| 778 { 0x01fe, 0x0 } }, | |
| 779 { { 0x09b0, 0x09cd, 0x09a8, 0x09cd, 0x200d, 0x0 }, | |
| 780 { 0x10b, 0x167, 0x0 } }, | |
| 781 { { 0x9b0, 0x9cd, 0x9ad, 0x0 }, | |
| 782 { 0xa1, 0x167, 0x0 } }, | |
| 783 { { 0x9f0, 0x9cd, 0x9ad, 0x0 }, | |
| 784 { 0xa1, 0x167, 0x0 } }, | |
| 785 { { 0x9f1, 0x9cd, 0x9ad, 0x0 }, | |
| 786 { 0x11c, 0xa1, 0x0 } }, | |
| 787 | |
| 788 { {0}, {0} } | |
| 789 }; | |
| 790 | |
| 791 | |
| 792 const ShapeTable *s = shape_table; | |
| 793 while (s->unicode[0]) { | |
| 794 QVERIFY( shaping(face, s, HB_Script_Bengali) ); | |
| 795 ++s; | |
| 796 } | |
| 797 | |
| 798 FT_Done_Face(face); | |
| 799 } else { | |
| 800 QSKIP("couln't find LikhanNormal.ttf", SkipAll); | |
| 801 } | |
| 802 } | |
| 803 } | |
| 804 | |
| 805 void tst_QScriptEngine::gurmukhi() | |
| 806 { | |
| 807 { | |
| 808 FT_Face face = loadFace("lohit_pa.ttf"); | |
| 809 if (face) { | |
| 810 const ShapeTable shape_table [] = { | |
| 811 { { 0xA15, 0xA4D, 0xa39, 0x0 }, | |
| 812 { 0x3b, 0x8b, 0x0 } }, | |
| 813 { {0}, {0} } | |
| 814 }; | |
| 815 | |
| 816 | |
| 817 const ShapeTable *s = shape_table; | |
| 818 while (s->unicode[0]) { | |
| 819 QVERIFY( shaping(face, s, HB_Script_Gurmukhi) ); | |
| 820 ++s; | |
| 821 } | |
| 822 | |
| 823 FT_Done_Face(face); | |
| 824 } else { | |
| 825 QSKIP("couln't find lohit.punjabi.1.1.ttf", SkipAll); | |
| 826 } | |
| 827 } | |
| 828 } | |
| 829 | |
| 830 void tst_QScriptEngine::oriya() | |
| 831 { | |
| 832 { | |
| 833 FT_Face face = loadFace("utkalm.ttf"); | |
| 834 if (face) { | |
| 835 const ShapeTable shape_table [] = { | |
| 836 { { 0xb15, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 }, | |
| 837 { 0x150, 0x125, 0x0 } }, | |
| 838 { { 0xb24, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 }, | |
| 839 { 0x151, 0x120, 0x0 } }, | |
| 840 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 }, | |
| 841 { 0x152, 0x120, 0x0 } }, | |
| 842 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 }, | |
| 843 { 0x152, 0x120, 0x0 } }, | |
| 844 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 }, | |
| 845 { 0x176, 0x0 } }, | |
| 846 { { 0xb38, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 }, | |
| 847 { 0x177, 0x0 } }, | |
| 848 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0xb4d, 0xb2f, 0x0 }, | |
| 849 { 0x176, 0x124, 0x0 } }, | |
| 850 { {0}, {0} } | |
| 851 | |
| 852 }; | |
| 853 | |
| 854 const ShapeTable *s = shape_table; | |
| 855 while (s->unicode[0]) { | |
| 856 QVERIFY( shaping(face, s, HB_Script_Oriya) ); | |
| 857 ++s; | |
| 858 } | |
| 859 | |
| 860 FT_Done_Face(face); | |
| 861 } else { | |
| 862 QSKIP("couln't find utkalm.ttf", SkipAll); | |
| 863 } | |
| 864 } | |
| 865 } | |
| 866 | |
| 867 | |
| 868 void tst_QScriptEngine::tamil() | |
| 869 { | |
| 870 { | |
| 871 FT_Face face = loadFace("akruti1.ttf"); | |
| 872 if (face) { | |
| 873 const ShapeTable shape_table [] = { | |
| 874 { { 0x0b95, 0x0bc2, 0x0 }, | |
| 875 { 0x004e, 0x0 } }, | |
| 876 { { 0x0bae, 0x0bc2, 0x0 }, | |
| 877 { 0x009e, 0x0 } }, | |
| 878 { { 0x0b9a, 0x0bc2, 0x0 }, | |
| 879 { 0x0058, 0x0 } }, | |
| 880 { { 0x0b99, 0x0bc2, 0x0 }, | |
| 881 { 0x0053, 0x0 } }, | |
| 882 { { 0x0bb0, 0x0bc2, 0x0 }, | |
| 883 { 0x00a8, 0x0 } }, | |
| 884 { { 0x0ba4, 0x0bc2, 0x0 }, | |
| 885 { 0x008e, 0x0 } }, | |
| 886 { { 0x0b9f, 0x0bc2, 0x0 }, | |
| 887 { 0x0062, 0x0 } }, | |
| 888 { { 0x0b95, 0x0bc6, 0x0 }, | |
| 889 { 0x000a, 0x0031, 0x0 } }, | |
| 890 { { 0x0b95, 0x0bca, 0x0 }, | |
| 891 { 0x000a, 0x0031, 0x0007, 0x0 } }, | |
| 892 { { 0x0b95, 0x0bc6, 0x0bbe, 0x0 }, | |
| 893 { 0x000a, 0x0031, 0x007, 0x0 } }, | |
| 894 { { 0x0b95, 0x0bcd, 0x0bb7, 0x0 }, | |
| 895 { 0x0049, 0x0 } }, | |
| 896 { { 0x0b95, 0x0bcd, 0x0bb7, 0x0bca, 0x0 }, | |
| 897 { 0x000a, 0x0049, 0x007, 0x0 } }, | |
| 898 { { 0x0b95, 0x0bcd, 0x0bb7, 0x0bc6, 0x0bbe, 0x0 }, | |
| 899 { 0x000a, 0x0049, 0x007, 0x0 } }, | |
| 900 { { 0x0b9f, 0x0bbf, 0x0 }, | |
| 901 { 0x005f, 0x0 } }, | |
| 902 { { 0x0b9f, 0x0bc0, 0x0 }, | |
| 903 { 0x0060, 0x0 } }, | |
| 904 { { 0x0bb2, 0x0bc0, 0x0 }, | |
| 905 { 0x00ab, 0x0 } }, | |
| 906 { { 0x0bb2, 0x0bbf, 0x0 }, | |
| 907 { 0x00aa, 0x0 } }, | |
| 908 { { 0x0bb0, 0x0bcd, 0x0 }, | |
| 909 { 0x00a4, 0x0 } }, | |
| 910 { { 0x0bb0, 0x0bbf, 0x0 }, | |
| 911 { 0x00a5, 0x0 } }, | |
| 912 { { 0x0bb0, 0x0bc0, 0x0 }, | |
| 913 { 0x00a6, 0x0 } }, | |
| 914 { { 0x0b83, 0x0 }, | |
| 915 { 0x0025, 0x0 } }, | |
| 916 { { 0x0b83, 0x0b95, 0x0 }, | |
| 917 { 0x0025, 0x0031, 0x0 } }, | |
| 918 | |
| 919 { {0}, {0} } | |
| 920 }; | |
| 921 | |
| 922 | |
| 923 const ShapeTable *s = shape_table; | |
| 924 while (s->unicode[0]) { | |
| 925 QVERIFY( shaping(face, s, HB_Script_Tamil) ); | |
| 926 ++s; | |
| 927 } | |
| 928 | |
| 929 FT_Done_Face(face); | |
| 930 } else { | |
| 931 QSKIP("couln't find akruti1.ttf", SkipAll); | |
| 932 } | |
| 933 } | |
| 934 } | |
| 935 | |
| 936 | |
| 937 void tst_QScriptEngine::telugu() | |
| 938 { | |
| 939 { | |
| 940 FT_Face face = loadFace("Pothana2000.ttf"); | |
| 941 if (face) { | |
| 942 const ShapeTable shape_table [] = { | |
| 943 { { 0xc15, 0xc4d, 0x0 }, | |
| 944 { 0xbb, 0x0 } }, | |
| 945 { { 0xc15, 0xc4d, 0xc37, 0x0 }, | |
| 946 { 0x4b, 0x0 } }, | |
| 947 { { 0xc15, 0xc4d, 0xc37, 0xc4d, 0x0 }, | |
| 948 { 0xe0, 0x0 } }, | |
| 949 { { 0xc15, 0xc4d, 0xc37, 0xc4d, 0xc23, 0x0 }, | |
| 950 { 0x4b, 0x91, 0x0 } }, | |
| 951 { { 0xc15, 0xc4d, 0xc30, 0x0 }, | |
| 952 { 0x5a, 0xb2, 0x0 } }, | |
| 953 { { 0xc15, 0xc4d, 0xc30, 0xc4d, 0x0 }, | |
| 954 { 0xbb, 0xb2, 0x0 } }, | |
| 955 { { 0xc15, 0xc4d, 0xc30, 0xc4d, 0xc15, 0x0 }, | |
| 956 { 0x5a, 0xb2, 0x83, 0x0 } }, | |
| 957 { { 0xc15, 0xc4d, 0xc30, 0xc3f, 0x0 }, | |
| 958 { 0xe2, 0xb2, 0x0 } }, | |
| 959 { { 0xc15, 0xc4d, 0xc15, 0xc48, 0x0 }, | |
| 960 { 0xe6, 0xb3, 0x83, 0x0 } }, | |
| 961 { { 0xc15, 0xc4d, 0xc30, 0xc48, 0x0 }, | |
| 962 { 0xe6, 0xb3, 0x9f, 0x0 } }, | |
| 963 { { 0xc15, 0xc46, 0xc56, 0x0 }, | |
| 964 { 0xe6, 0xb3, 0x0 } }, | |
| 965 { {0}, {0} } | |
| 966 }; | |
| 967 | |
| 968 const ShapeTable *s = shape_table; | |
| 969 while (s->unicode[0]) { | |
| 970 QVERIFY( shaping(face, s, HB_Script_Telugu) ); | |
| 971 ++s; | |
| 972 } | |
| 973 | |
| 974 FT_Done_Face(face); | |
| 975 } else { | |
| 976 QSKIP("couln't find Pothana2000.ttf", SkipAll); | |
| 977 } | |
| 978 } | |
| 979 } | |
| 980 | |
| 981 | |
| 982 void tst_QScriptEngine::kannada() | |
| 983 { | |
| 984 { | |
| 985 FT_Face face = loadFace("Sampige.ttf"); | |
| 986 if (face) { | |
| 987 const ShapeTable shape_table [] = { | |
| 988 { { 0x0ca8, 0x0ccd, 0x0ca8, 0x0 }, | |
| 989 { 0x0049, 0x00ba, 0x0 } }, | |
| 990 { { 0x0ca8, 0x0ccd, 0x0ca1, 0x0 }, | |
| 991 { 0x0049, 0x00b3, 0x0 } }, | |
| 992 { { 0x0caf, 0x0cc2, 0x0 }, | |
| 993 { 0x004f, 0x005d, 0x0 } }, | |
| 994 { { 0x0ce0, 0x0 }, | |
| 995 { 0x006a, 0x0 } }, | |
| 996 { { 0x0ce6, 0x0ce7, 0x0ce8, 0x0 }, | |
| 997 { 0x006b, 0x006c, 0x006d, 0x0 } }, | |
| 998 { { 0x0cb5, 0x0ccb, 0x0 }, | |
| 999 { 0x015f, 0x0067, 0x0 } }, | |
| 1000 { { 0x0cb0, 0x0ccd, 0x0cae, 0x0 }, | |
| 1001 { 0x004e, 0x0082, 0x0 } }, | |
| 1002 { { 0x0cb0, 0x0ccd, 0x0c95, 0x0 }, | |
| 1003 { 0x0036, 0x0082, 0x0 } }, | |
| 1004 { { 0x0c95, 0x0ccd, 0x0cb0, 0x0 }, | |
| 1005 { 0x0036, 0x00c1, 0x0 } }, | |
| 1006 { { 0x0cb0, 0x0ccd, 0x200d, 0x0c95, 0x0 }, | |
| 1007 { 0x0050, 0x00a7, 0x0 } }, | |
| 1008 { {0}, {0} } | |
| 1009 }; | |
| 1010 | |
| 1011 | |
| 1012 const ShapeTable *s = shape_table; | |
| 1013 while (s->unicode[0]) { | |
| 1014 QVERIFY( shaping(face, s, HB_Script_Kannada) ); | |
| 1015 ++s; | |
| 1016 } | |
| 1017 | |
| 1018 FT_Done_Face(face); | |
| 1019 } else { | |
| 1020 QSKIP("couln't find Sampige.ttf", SkipAll); | |
| 1021 } | |
| 1022 } | |
| 1023 { | |
| 1024 FT_Face face = loadFace("tunga.ttf"); | |
| 1025 if (face) { | |
| 1026 const ShapeTable shape_table [] = { | |
| 1027 { { 0x0cb7, 0x0cc6, 0x0 }, | |
| 1028 { 0x00b0, 0x006c, 0x0 } }, | |
| 1029 { { 0x0cb7, 0x0ccd, 0x0 }, | |
| 1030 { 0x0163, 0x0 } }, | |
| 1031 { { 0xc95, 0xcbf, 0xcd5, 0x0 }, | |
| 1032 { 0x114, 0x73, 0x0 } }, | |
| 1033 { { 0xc95, 0xcc6, 0xcd5, 0x0 }, | |
| 1034 { 0x90, 0x6c, 0x73, 0x0 } }, | |
| 1035 { { 0xc95, 0xcc6, 0xcd6, 0x0 }, | |
| 1036 { 0x90, 0x6c, 0x74, 0x0 } }, | |
| 1037 { { 0xc95, 0xcc6, 0xcc2, 0x0 }, | |
| 1038 { 0x90, 0x6c, 0x69, 0x0 } }, | |
| 1039 { { 0xc95, 0xcca, 0xcd5, 0x0 }, | |
| 1040 { 0x90, 0x6c, 0x69, 0x73, 0x0 } }, | |
| 1041 | |
| 1042 | |
| 1043 { {0}, {0} } | |
| 1044 }; | |
| 1045 | |
| 1046 | |
| 1047 const ShapeTable *s = shape_table; | |
| 1048 while (s->unicode[0]) { | |
| 1049 QVERIFY( shaping(face, s, HB_Script_Kannada) ); | |
| 1050 ++s; | |
| 1051 } | |
| 1052 | |
| 1053 FT_Done_Face(face); | |
| 1054 } else { | |
| 1055 QSKIP("couln't find tunga.ttf", SkipAll); | |
| 1056 } | |
| 1057 } | |
| 1058 } | |
| 1059 | |
| 1060 | |
| 1061 | |
| 1062 void tst_QScriptEngine::malayalam() | |
| 1063 { | |
| 1064 { | |
| 1065 FT_Face face = loadFace("AkrutiMal2Normal.ttf"); | |
| 1066 if (face) { | |
| 1067 const ShapeTable shape_table [] = { | |
| 1068 { { 0x0d15, 0x0d46, 0x0 }, | |
| 1069 { 0x005e, 0x0034, 0x0 } }, | |
| 1070 { { 0x0d15, 0x0d47, 0x0 }, | |
| 1071 { 0x005f, 0x0034, 0x0 } }, | |
| 1072 { { 0x0d15, 0x0d4b, 0x0 }, | |
| 1073 { 0x005f, 0x0034, 0x0058, 0x0 } }, | |
| 1074 { { 0x0d15, 0x0d48, 0x0 }, | |
| 1075 { 0x0060, 0x0034, 0x0 } }, | |
| 1076 { { 0x0d15, 0x0d4a, 0x0 }, | |
| 1077 { 0x005e, 0x0034, 0x0058, 0x0 } }, | |
| 1078 { { 0x0d30, 0x0d4d, 0x0d15, 0x0 }, | |
| 1079 { 0x009e, 0x0034, 0x0 } }, | |
| 1080 { { 0x0d15, 0x0d4d, 0x0d35, 0x0 }, | |
| 1081 { 0x0034, 0x007a, 0x0 } }, | |
| 1082 { { 0x0d15, 0x0d4d, 0x0d2f, 0x0 }, | |
| 1083 { 0x0034, 0x00a2, 0x0 } }, | |
| 1084 { { 0x0d1f, 0x0d4d, 0x0d1f, 0x0 }, | |
| 1085 { 0x0069, 0x0 } }, | |
| 1086 { { 0x0d26, 0x0d4d, 0x0d26, 0x0 }, | |
| 1087 { 0x0074, 0x0 } }, | |
| 1088 { { 0x0d30, 0x0d4d, 0x0 }, | |
| 1089 { 0x009e, 0x0 } }, | |
| 1090 { { 0x0d30, 0x0d4d, 0x200c, 0x0 }, | |
| 1091 { 0x009e, 0x0 } }, | |
| 1092 { { 0x0d30, 0x0d4d, 0x200d, 0x0 }, | |
| 1093 { 0x009e, 0x0 } }, | |
| 1094 { { 0xd15, 0xd46, 0xd3e, 0x0 }, | |
| 1095 { 0x5e, 0x34, 0x58, 0x0 } }, | |
| 1096 { { 0xd15, 0xd47, 0xd3e, 0x0 }, | |
| 1097 { 0x5f, 0x34, 0x58, 0x0 } }, | |
| 1098 { { 0xd15, 0xd46, 0xd57, 0x0 }, | |
| 1099 { 0x5e, 0x34, 0x65, 0x0 } }, | |
| 1100 { { 0xd15, 0xd57, 0x0 }, | |
| 1101 { 0x34, 0x65, 0x0 } }, | |
| 1102 { { 0xd1f, 0xd4d, 0xd1f, 0xd41, 0xd4d, 0x0 }, | |
| 1103 { 0x69, 0x5b, 0x64, 0x0 } }, | |
| 1104 | |
| 1105 { {0}, {0} } | |
| 1106 }; | |
| 1107 | |
| 1108 | |
| 1109 const ShapeTable *s = shape_table; | |
| 1110 while (s->unicode[0]) { | |
| 1111 QVERIFY( shaping(face, s, HB_Script_Malayalam) ); | |
| 1112 ++s; | |
| 1113 } | |
| 1114 | |
| 1115 FT_Done_Face(face); | |
| 1116 } else { | |
| 1117 QSKIP("couln't find AkrutiMal2Normal.ttf", SkipAll); | |
| 1118 } | |
| 1119 } | |
| 1120 | |
| 1121 { | |
| 1122 FT_Face face = loadFace("Rachana.ttf"); | |
| 1123 if (face) { | |
| 1124 const ShapeTable shape_table [] = { | |
| 1125 { { 0xd37, 0xd4d, 0xd1f, 0xd4d, 0xd30, 0xd40, 0x0 }, | |
| 1126 { 0x385, 0xa3, 0x0 } }, | |
| 1127 { { 0xd2f, 0xd4d, 0xd15, 0xd4d, 0xd15, 0xd41, 0x0 }, | |
| 1128 { 0x2ff, 0x0 } }, | |
| 1129 { { 0xd33, 0xd4d, 0xd33, 0x0 }, | |
| 1130 { 0x3f8, 0x0 } }, | |
| 1131 { { 0xd2f, 0xd4d, 0xd15, 0xd4d, 0xd15, 0xd41, 0x0 }, | |
| 1132 { 0x2ff, 0x0 } }, | |
| 1133 { { 0xd30, 0xd4d, 0x200d, 0xd35, 0xd4d, 0xd35, 0x0 }, | |
| 1134 { 0xf3, 0x350, 0x0 } }, | |
| 1135 | |
| 1136 { {0}, {0} } | |
| 1137 }; | |
| 1138 | |
| 1139 | |
| 1140 const ShapeTable *s = shape_table; | |
| 1141 while (s->unicode[0]) { | |
| 1142 QVERIFY( shaping(face, s, HB_Script_Malayalam) ); | |
| 1143 ++s; | |
| 1144 } | |
| 1145 | |
| 1146 FT_Done_Face(face); | |
| 1147 } else { | |
| 1148 QSKIP("couln't find Rachana.ttf", SkipAll); | |
| 1149 } | |
| 1150 } | |
| 1151 | |
| 1152 } | |
| 1153 | |
| 1154 void tst_QScriptEngine::sinhala() | |
| 1155 { | |
| 1156 { | |
| 1157 FT_Face face = loadFace("FM-MalithiUW46.ttf"); | |
| 1158 if (face) { | |
| 1159 const ShapeTable shape_table [] = { | |
| 1160 { { 0xd9a, 0xdd9, 0xdcf, 0x0 }, | |
| 1161 { 0x4a, 0x61, 0x42, 0x0 } }, | |
| 1162 { { 0xd9a, 0xdd9, 0xddf, 0x0 }, | |
| 1163 { 0x4a, 0x61, 0x50, 0x0 } }, | |
| 1164 { { 0xd9a, 0xdd9, 0xdca, 0x0 }, | |
| 1165 { 0x4a, 0x62, 0x0 } }, | |
| 1166 { { 0xd9a, 0xddc, 0xdca, 0x0 }, | |
| 1167 { 0x4a, 0x61, 0x42, 0x41, 0x0 } }, | |
| 1168 { { 0xd9a, 0xdda, 0x0 }, | |
| 1169 { 0x4a, 0x62, 0x0 } }, | |
| 1170 { { 0xd9a, 0xddd, 0x0 }, | |
| 1171 { 0x4a, 0x61, 0x42, 0x41, 0x0 } }, | |
| 1172 { {0}, {0} } | |
| 1173 }; | |
| 1174 | |
| 1175 const ShapeTable *s = shape_table; | |
| 1176 while (s->unicode[0]) { | |
| 1177 QVERIFY( shaping(face, s, HB_Script_Sinhala) ); | |
| 1178 ++s; | |
| 1179 } | |
| 1180 | |
| 1181 FT_Done_Face(face); | |
| 1182 } else { | |
| 1183 QSKIP("couln't find FM-MalithiUW46.ttf", SkipAll); | |
| 1184 } | |
| 1185 } | |
| 1186 } | |
| 1187 | |
| 1188 | |
| 1189 void tst_QScriptEngine::khmer() | |
| 1190 { | |
| 1191 { | |
| 1192 FT_Face face = loadFace("KhmerOS.ttf"); | |
| 1193 if (face) { | |
| 1194 const ShapeTable shape_table [] = { | |
| 1195 { { 0x179a, 0x17cd, 0x0 }, | |
| 1196 { 0x24c, 0x27f, 0x0 } }, | |
| 1197 { { 0x179f, 0x17c5, 0x0 }, | |
| 1198 { 0x273, 0x203, 0x0 } }, | |
| 1199 { { 0x1790, 0x17d2, 0x1784, 0x17c3, 0x0 }, | |
| 1200 { 0x275, 0x242, 0x182, 0x0 } }, | |
| 1201 { { 0x179a, 0x0 }, | |
| 1202 { 0x24c, 0x0 } }, | |
| 1203 { { 0x1781, 0x17d2, 0x1798, 0x17c2, 0x0 }, | |
| 1204 { 0x274, 0x233, 0x197, 0x0 } }, | |
| 1205 { { 0x1798, 0x17b6, 0x0 }, | |
| 1206 { 0x1cb, 0x0 } }, | |
| 1207 { { 0x179a, 0x17b8, 0x0 }, | |
| 1208 { 0x24c, 0x26a, 0x0 } }, | |
| 1209 { { 0x1787, 0x17b6, 0x0 }, | |
| 1210 { 0x1ba, 0x0 } }, | |
| 1211 { { 0x1798, 0x17d2, 0x1796, 0x17bb, 0x0 }, | |
| 1212 { 0x24a, 0x195, 0x26d, 0x0 } }, | |
| 1213 { {0}, {0} } | |
| 1214 }; | |
| 1215 | |
| 1216 | |
| 1217 const ShapeTable *s = shape_table; | |
| 1218 while (s->unicode[0]) { | |
| 1219 QVERIFY( shaping(face, s, HB_Script_Khmer) ); | |
| 1220 ++s; | |
| 1221 } | |
| 1222 | |
| 1223 FT_Done_Face(face); | |
| 1224 } else { | |
| 1225 QSKIP("couln't find KhmerOS.ttf", SkipAll); | |
| 1226 } | |
| 1227 } | |
| 1228 } | |
| 1229 | |
| 1230 void tst_QScriptEngine::nko() | |
| 1231 { | |
| 1232 { | |
| 1233 FT_Face face = loadFace("DejaVuSans.ttf"); | |
| 1234 if (face) { | |
| 1235 const ShapeTable shape_table [] = { | |
| 1236 { { 0x7ca, 0x0 }, | |
| 1237 { 0x5c1, 0x0 } }, | |
| 1238 { { 0x7ca, 0x7ca, 0x0 }, | |
| 1239 { 0x14db, 0x14d9, 0x0 } }, | |
| 1240 { { 0x7ca, 0x7fa, 0x7ca, 0x0 }, | |
| 1241 { 0x14db, 0x5ec, 0x14d9, 0x0 } }, | |
| 1242 { { 0x7ca, 0x7f3, 0x7ca, 0x0 }, | |
| 1243 { 0x14db, 0x5e7, 0x14d9, 0x0 } }, | |
| 1244 { { 0x7ca, 0x7f3, 0x7fa, 0x7ca, 0x0 }, | |
| 1245 { 0x14db, 0x5e7, 0x5ec, 0x14d9, 0x0 } }, | |
| 1246 { {0}, {0} } | |
| 1247 }; | |
| 1248 | |
| 1249 | |
| 1250 const ShapeTable *s = shape_table; | |
| 1251 while (s->unicode[0]) { | |
| 1252 QVERIFY( shaping(face, s, HB_Script_Nko) ); | |
| 1253 ++s; | |
| 1254 } | |
| 1255 | |
| 1256 FT_Done_Face(face); | |
| 1257 } else { | |
| 1258 QSKIP("couln't find DejaVuSans.ttf", SkipAll); | |
| 1259 } | |
| 1260 } | |
| 1261 } | |
| 1262 | |
| 1263 | |
| 1264 void tst_QScriptEngine::linearB() | |
| 1265 { | |
| 1266 { | |
| 1267 FT_Face face = loadFace("penuture.ttf"); | |
| 1268 if (face) { | |
| 1269 const ShapeTable shape_table [] = { | |
| 1270 { { 0xd800, 0xdc01, 0xd800, 0xdc02, 0xd800, 0xdc03, 0 }, | |
| 1271 { 0x5, 0x6, 0x7, 0 } }, | |
| 1272 { {0}, {0} } | |
| 1273 }; | |
| 1274 | |
| 1275 | |
| 1276 const ShapeTable *s = shape_table; | |
| 1277 while (s->unicode[0]) { | |
| 1278 QVERIFY( shaping(face, s, HB_Script_Common) ); | |
| 1279 ++s; | |
| 1280 } | |
| 1281 | |
| 1282 FT_Done_Face(face); | |
| 1283 } else { | |
| 1284 QSKIP("couln't find PENUTURE.TTF", SkipAll); | |
| 1285 } | |
| 1286 } | |
| 1287 } | |
| 1288 | |
| 1289 | |
| 1290 QTEST_MAIN(tst_QScriptEngine) | |
| 1291 #include "main.moc" | |
| OLD | NEW |