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 |