src/3rdparty/harfbuzz/tests/shaping/main.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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_uint32 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_uint32 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 length)
       
    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_HINTING : 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 font, HB_Glyph glyph, HB_GlyphMetrics *metrics)
       
   140 {
       
   141     // ###
       
   142     metrics->x = metrics->y = metrics->width = metrics->height = metrics->xOffset = metrics->yOffset = 0;
       
   143 }
       
   144 
       
   145 HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
       
   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 devanagari();
       
   173     void bengali();
       
   174     void gurmukhi();
       
   175     // gujarati missing
       
   176     void oriya();
       
   177     void tamil();
       
   178     void telugu();
       
   179     void kannada();
       
   180     void malayalam();
       
   181     // sinhala missing
       
   182 
       
   183     void khmer();
       
   184     void linearB();
       
   185 };
       
   186 
       
   187 tst_QScriptEngine::tst_QScriptEngine()
       
   188 {
       
   189 }
       
   190 
       
   191 tst_QScriptEngine::~tst_QScriptEngine()
       
   192 {
       
   193 }
       
   194 
       
   195 void tst_QScriptEngine::initTestCase()
       
   196 {
       
   197     FT_Init_FreeType(&freetype);
       
   198 }
       
   199 
       
   200 void tst_QScriptEngine::cleanupTestCase()
       
   201 {
       
   202     FT_Done_FreeType(freetype);
       
   203 }
       
   204 
       
   205 struct ShapeTable {
       
   206     unsigned short unicode[16];
       
   207     unsigned short glyphs[16];
       
   208 };
       
   209 
       
   210 static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script)
       
   211 {
       
   212     QString str = QString::fromUtf16( s->unicode );
       
   213 
       
   214     HB_Face hbFace = HB_NewFace(face, hb_getSFntTable);
       
   215 
       
   216     HB_FontRec hbFont;
       
   217     hbFont.klass = &hb_fontClass;
       
   218     hbFont.userData = face;
       
   219     hbFont.x_ppem  = face->size->metrics.x_ppem;
       
   220     hbFont.y_ppem  = face->size->metrics.y_ppem;
       
   221     hbFont.x_scale = face->size->metrics.x_scale;
       
   222     hbFont.y_scale = face->size->metrics.y_scale;
       
   223 
       
   224     HB_ShaperItem shaper_item;
       
   225     shaper_item.kerning_applied = false;
       
   226     shaper_item.string = reinterpret_cast<const HB_UChar16 *>(str.constData());
       
   227     shaper_item.stringLength = str.length();
       
   228     shaper_item.item.script = script;
       
   229     shaper_item.item.pos = 0;
       
   230     shaper_item.item.length = shaper_item.stringLength;
       
   231     shaper_item.item.bidiLevel = 0; // ###
       
   232     shaper_item.shaperFlags = 0;
       
   233     shaper_item.font = &hbFont;
       
   234     shaper_item.face = hbFace;
       
   235     shaper_item.num_glyphs = shaper_item.item.length;
       
   236     shaper_item.glyphIndicesPresent = false;
       
   237     shaper_item.initialGlyphCount = 0;
       
   238 
       
   239     QVarLengthArray<HB_Glyph> hb_glyphs(shaper_item.num_glyphs);
       
   240     QVarLengthArray<HB_GlyphAttributes> hb_attributes(shaper_item.num_glyphs);
       
   241     QVarLengthArray<HB_Fixed> hb_advances(shaper_item.num_glyphs);
       
   242     QVarLengthArray<HB_FixedPoint> hb_offsets(shaper_item.num_glyphs);
       
   243     QVarLengthArray<unsigned short> hb_logClusters(shaper_item.num_glyphs);
       
   244 
       
   245     while (1) {
       
   246         hb_glyphs.resize(shaper_item.num_glyphs);
       
   247         hb_attributes.resize(shaper_item.num_glyphs);
       
   248         hb_advances.resize(shaper_item.num_glyphs);
       
   249         hb_offsets.resize(shaper_item.num_glyphs);
       
   250         hb_logClusters.resize(shaper_item.num_glyphs);
       
   251 
       
   252         memset(hb_glyphs.data(), 0, hb_glyphs.size() * sizeof(HB_Glyph));
       
   253         memset(hb_attributes.data(), 0, hb_attributes.size() * sizeof(HB_GlyphAttributes));
       
   254         memset(hb_advances.data(), 0, hb_advances.size() * sizeof(HB_Fixed));
       
   255         memset(hb_offsets.data(), 0, hb_offsets.size() * sizeof(HB_FixedPoint));
       
   256 
       
   257         shaper_item.glyphs = hb_glyphs.data();
       
   258         shaper_item.attributes = hb_attributes.data();
       
   259         shaper_item.advances = hb_advances.data();
       
   260         shaper_item.offsets = hb_offsets.data();
       
   261         shaper_item.log_clusters = hb_logClusters.data();
       
   262 
       
   263         if (HB_ShapeItem(&shaper_item))
       
   264             break;
       
   265 
       
   266     }
       
   267 
       
   268     HB_FreeFace(hbFace);
       
   269 
       
   270     hb_uint32 nglyphs = 0;
       
   271     const unsigned short *g = s->glyphs;
       
   272     while ( *g ) {
       
   273 	nglyphs++;
       
   274 	g++;
       
   275     }
       
   276 
       
   277     if( nglyphs != shaper_item.num_glyphs )
       
   278 	goto error;
       
   279 
       
   280     for (hb_uint32 i = 0; i < nglyphs; ++i) {
       
   281 	if ((shaper_item.glyphs[i]&0xffffff) != s->glyphs[i])
       
   282 	    goto error;
       
   283     }
       
   284     return true;
       
   285  error:
       
   286     str = "";
       
   287     const unsigned short *uc = s->unicode;
       
   288     while (*uc) {
       
   289 	str += QString("%1 ").arg(*uc, 4, 16);
       
   290 	++uc;
       
   291     }
       
   292     qDebug("%s: shaping of string %s failed, nglyphs=%d, expected %d",
       
   293            face->family_name,
       
   294            str.toLatin1().constData(),
       
   295            shaper_item.num_glyphs, nglyphs);
       
   296 
       
   297     str = "";
       
   298     hb_uint32 i = 0;
       
   299     while (i < shaper_item.num_glyphs) {
       
   300 	str += QString("%1 ").arg(shaper_item.glyphs[i], 4, 16);
       
   301 	++i;
       
   302     }
       
   303     qDebug("    glyph result = %s", str.toLatin1().constData());
       
   304     return false;
       
   305 }
       
   306 
       
   307 void tst_QScriptEngine::devanagari()
       
   308 {
       
   309     {
       
   310         FT_Face face = loadFace("raghu.ttf");
       
   311         if (face) {
       
   312 	    const ShapeTable shape_table [] = {
       
   313 		// Ka
       
   314 		{ { 0x0915, 0x0 },
       
   315 		  { 0x0080, 0x0 } },
       
   316 		// Ka Halant
       
   317 		{ { 0x0915, 0x094d, 0x0 },
       
   318 		  { 0x0080, 0x0051, 0x0 } },
       
   319 		// Ka Halant Ka
       
   320 		{ { 0x0915, 0x094d, 0x0915, 0x0 },
       
   321 		  { 0x00c8, 0x0080, 0x0 } },
       
   322 		// Ka MatraI
       
   323 		{ { 0x0915, 0x093f, 0x0 },
       
   324 		  { 0x01d1, 0x0080, 0x0 } },
       
   325 		// Ra Halant Ka
       
   326 		{ { 0x0930, 0x094d, 0x0915, 0x0 },
       
   327 		  { 0x0080, 0x005b, 0x0 } },
       
   328 		// Ra Halant Ka MatraI
       
   329 		{ { 0x0930, 0x094d, 0x0915, 0x093f, 0x0 },
       
   330 		  { 0x01d1, 0x0080, 0x005b, 0x0 } },
       
   331 		// MatraI
       
   332 		{ { 0x093f, 0x0 },
       
   333 		  { 0x01d4, 0x029c, 0x0 } },
       
   334 		// Ka Nukta
       
   335 		{ { 0x0915, 0x093c, 0x0 },
       
   336 		  { 0x00a4, 0x0 } },
       
   337 		// Ka Halant Ra
       
   338 		{ { 0x0915, 0x094d, 0x0930, 0x0 },
       
   339 		  { 0x0110, 0x0 } },
       
   340 		// Ka Halant Ra Halant Ka
       
   341 		{ { 0x0915, 0x094d, 0x0930, 0x094d, 0x0915, 0x0 },
       
   342 		  { 0x0158, 0x0080, 0x0 } },
       
   343 		{ { 0x0930, 0x094d, 0x200d, 0x0 },
       
   344 		  { 0x00e2, 0x0 } },
       
   345 		{ { 0x0915, 0x094d, 0x0930, 0x094d, 0x200d, 0x0 },
       
   346 		  { 0x0158, 0x0 } },
       
   347 
       
   348 		{ {0}, {0} }
       
   349 	    };
       
   350 
       
   351 
       
   352 	    const ShapeTable *s = shape_table;
       
   353 	    while (s->unicode[0]) {
       
   354 		QVERIFY( shaping(face, s, HB_Script_Devanagari) );
       
   355 		++s;
       
   356 	    }
       
   357 
       
   358             FT_Done_Face(face);
       
   359 	} else {
       
   360 	    QSKIP("couln't find raghu.ttf", SkipAll);
       
   361 	}
       
   362     }
       
   363 
       
   364     {
       
   365         FT_Face face = loadFace("mangal.ttf");
       
   366         if (face) {
       
   367 	    const ShapeTable shape_table [] = {
       
   368 		// Ka
       
   369 		{ { 0x0915, 0x0 },
       
   370 		  { 0x0080, 0x0 } },
       
   371 		// Ka Halant
       
   372 		{ { 0x0915, 0x094d, 0x0 },
       
   373 		  { 0x0080, 0x0051, 0x0 } },
       
   374 		// Ka Halant Ka
       
   375 		{ { 0x0915, 0x094d, 0x0915, 0x0 },
       
   376 		  { 0x00c8, 0x0080, 0x0 } },
       
   377 		// Ka MatraI
       
   378 		{ { 0x0915, 0x093f, 0x0 },
       
   379 		  { 0x01d1, 0x0080, 0x0 } },
       
   380 		// Ra Halant Ka
       
   381 		{ { 0x0930, 0x094d, 0x0915, 0x0 },
       
   382 		  { 0x0080, 0x005b, 0x0 } },
       
   383 		// Ra Halant Ka MatraI
       
   384 		{ { 0x0930, 0x094d, 0x0915, 0x093f, 0x0 },
       
   385 		  { 0x01d1, 0x0080, 0x005b, 0x0 } },
       
   386 		// MatraI
       
   387 		{ { 0x093f, 0x0 },
       
   388 		  { 0x01d4, 0x029c, 0x0 } },
       
   389 		// Ka Nukta
       
   390 		{ { 0x0915, 0x093c, 0x0 },
       
   391 		  { 0x00a4, 0x0 } },
       
   392 		// Ka Halant Ra
       
   393 		{ { 0x0915, 0x094d, 0x0930, 0x0 },
       
   394 		  { 0x0110, 0x0 } },
       
   395 		// Ka Halant Ra Halant Ka
       
   396 		{ { 0x0915, 0x094d, 0x0930, 0x094d, 0x0915, 0x0 },
       
   397 		  { 0x0158, 0x0080, 0x0 } },
       
   398 
       
   399                 { { 0x92b, 0x94d, 0x930, 0x0 },
       
   400                   { 0x125, 0x0 } },
       
   401                 { { 0x92b, 0x93c, 0x94d, 0x930, 0x0 },
       
   402                   { 0x149, 0x0 } }, 
       
   403 		{ {0}, {0} }
       
   404 	    };
       
   405 
       
   406 	    const ShapeTable *s = shape_table;
       
   407 	    while (s->unicode[0]) {
       
   408 		QVERIFY( shaping(face, s, HB_Script_Devanagari) );
       
   409 		++s;
       
   410 	    }
       
   411 
       
   412             FT_Done_Face(face);
       
   413 	} else {
       
   414 	    QSKIP("couldn't find mangal.ttf", SkipAll);
       
   415 	}
       
   416     }
       
   417 }
       
   418 
       
   419 void tst_QScriptEngine::bengali()
       
   420 {
       
   421     {
       
   422         FT_Face face = loadFace("AkaashNormal.ttf");
       
   423         if (face) {
       
   424 	    const ShapeTable shape_table [] = {
       
   425 		// Ka
       
   426 		{ { 0x0995, 0x0 },
       
   427 		  { 0x0151, 0x0 } },
       
   428 		// Ka Halant
       
   429 		{ { 0x0995, 0x09cd, 0x0 },
       
   430 		  { 0x0151, 0x017d, 0x0 } },
       
   431 		// Ka Halant Ka
       
   432 		{ { 0x0995, 0x09cd, 0x0995, 0x0 },
       
   433 		  { 0x019b, 0x0 } },
       
   434 		// Ka MatraI
       
   435 		{ { 0x0995, 0x09bf, 0x0 },
       
   436 		  { 0x0173, 0x0151, 0x0 } },
       
   437 		// Ra Halant Ka
       
   438 		{ { 0x09b0, 0x09cd, 0x0995, 0x0 },
       
   439 		  { 0x0151, 0x0276, 0x0 } },
       
   440 		// Ra Halant Ka MatraI
       
   441 		{ { 0x09b0, 0x09cd, 0x0995, 0x09bf, 0x0 },
       
   442 		  { 0x0173, 0x0151, 0x0276, 0x0 } },
       
   443 		// Ka Nukta
       
   444 		{ { 0x0995, 0x09bc, 0x0 },
       
   445 		  { 0x0151, 0x0171, 0x0 } },
       
   446 		// Ka Halant Ra
       
   447 		{ { 0x0995, 0x09cd, 0x09b0, 0x0 },
       
   448 		  { 0x01f4, 0x0 } },
       
   449 		// Ka Halant Ra Halant Ka
       
   450 		{ { 0x0995, 0x09cd, 0x09b0, 0x09cd, 0x0995, 0x0 },
       
   451 		  { 0x025c, 0x0276, 0x0151, 0x0 } },
       
   452 		// Ya + Halant
       
   453 		{ { 0x09af, 0x09cd, 0x0 },
       
   454 		  { 0x016a, 0x017d, 0x0 } },
       
   455 		// Da Halant Ya -> Da Ya-Phala
       
   456 		{ { 0x09a6, 0x09cd, 0x09af, 0x0 },
       
   457 		  { 0x01e5, 0x0 } },
       
   458 		// A Halant Ya -> A Ya-phala
       
   459 		{ { 0x0985, 0x09cd, 0x09af, 0x0 },
       
   460 		  { 0x0145, 0x01cf, 0x0 } },
       
   461 		// Na Halant Ka
       
   462 		{ { 0x09a8, 0x09cd, 0x0995, 0x0 },
       
   463 		  { 0x026f, 0x0151, 0x0 } },
       
   464 		// Na Halant ZWNJ Ka
       
   465 		{ { 0x09a8, 0x09cd, 0x200c, 0x0995, 0x0 },
       
   466 		  { 0x0164, 0x017d, 0x0151, 0x0 } },
       
   467 		// Na Halant ZWJ Ka
       
   468 		{ { 0x09a8, 0x09cd, 0x200d, 0x0995, 0x0 },
       
   469 		  { 0x026f, 0x0151, 0x0 } },
       
   470 		// Ka Halant ZWNJ Ka
       
   471 		{ { 0x0995, 0x09cd, 0x200c, 0x0995, 0x0 },
       
   472 		  { 0x0151, 0x017d, 0x0151, 0x0 } },
       
   473 		// Ka Halant ZWJ Ka
       
   474 		{ { 0x0995, 0x09cd, 0x200d, 0x0995, 0x0 },
       
   475 		  { 0x025c, 0x0151, 0x0 } },
       
   476 		// Na Halant Ra
       
   477 		{ { 0x09a8, 0x09cd, 0x09b0, 0x0 },
       
   478 		  { 0x0207, 0x0 } },
       
   479 		// Na Halant ZWNJ Ra
       
   480 		{ { 0x09a8, 0x09cd, 0x200c, 0x09b0, 0x0 },
       
   481 		  { 0x0164, 0x017d, 0x016b, 0x0 } },
       
   482 		// Na Halant ZWJ Ra
       
   483 		{ { 0x09a8, 0x09cd, 0x200d, 0x09b0, 0x0 },
       
   484 		  { 0x026f, 0x016b, 0x0 } },
       
   485 		// Na Halant Ba
       
   486 		{ { 0x09a8, 0x09cd, 0x09ac, 0x0 },
       
   487 		  { 0x022f, 0x0 } },
       
   488 		// Na Halant ZWNJ Ba
       
   489 		{ { 0x09a8, 0x09cd, 0x200c, 0x09ac, 0x0 },
       
   490 		  { 0x0164, 0x017d, 0x0167, 0x0 } },
       
   491 		// Na Halant ZWJ Ba
       
   492 		{ { 0x09a8, 0x09cd, 0x200d, 0x09ac, 0x0 },
       
   493 		  { 0x026f, 0x0167, 0x0 } },
       
   494 		// Na Halant Dha
       
   495 		{ { 0x09a8, 0x09cd, 0x09a7, 0x0 },
       
   496 		  { 0x01d3, 0x0 } },
       
   497 		// Na Halant ZWNJ Dha
       
   498 		{ { 0x09a8, 0x09cd, 0x200c, 0x09a7, 0x0 },
       
   499 		  { 0x0164, 0x017d, 0x0163, 0x0 } },
       
   500 		// Na Halant ZWJ Dha
       
   501 		{ { 0x09a8, 0x09cd, 0x200d, 0x09a7, 0x0 },
       
   502 		  { 0x026f, 0x0163, 0x0 } },
       
   503 		// Ra Halant Ka MatraAU
       
   504 		{ { 0x09b0, 0x09cd, 0x0995, 0x09cc, 0x0 },
       
   505 		  { 0x0179, 0x0151, 0x0276, 0x017e, 0x0 } },
       
   506 		// Ra Halant Ba Halant Ba
       
   507 		{ { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 },
       
   508 		  { 0x0232, 0x0276, 0x0 } },
       
   509                 { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x982, 0x0 },
       
   510                   { 0x151, 0x276, 0x172, 0x143, 0x0 } },
       
   511                 { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x983, 0x0 },
       
   512                   { 0x151, 0x276, 0x172, 0x144, 0x0 } }, 
       
   513 
       
   514 		{ {0}, {0} }
       
   515 	    };
       
   516 
       
   517 
       
   518 	    const ShapeTable *s = shape_table;
       
   519 	    while (s->unicode[0]) {
       
   520 		QVERIFY( shaping(face, s, HB_Script_Bengali) );
       
   521 		++s;
       
   522 	    }
       
   523 
       
   524             FT_Done_Face(face);
       
   525 	} else {
       
   526 	    QSKIP("couln't find AkaashNormal.ttf", SkipAll);
       
   527 	}
       
   528     }
       
   529     {
       
   530         FT_Face face = loadFace("MuktiNarrow.ttf");
       
   531         if (face) {
       
   532 	    const ShapeTable shape_table [] = {
       
   533 		// Ka
       
   534 		{ { 0x0995, 0x0 },
       
   535 		  { 0x0073, 0x0 } },
       
   536 		// Ka Halant
       
   537 		{ { 0x0995, 0x09cd, 0x0 },
       
   538 		  { 0x00b9, 0x0 } },
       
   539 		// Ka Halant Ka
       
   540 		{ { 0x0995, 0x09cd, 0x0995, 0x0 },
       
   541 		  { 0x0109, 0x0 } },
       
   542 		// Ka MatraI
       
   543 		{ { 0x0995, 0x09bf, 0x0 },
       
   544 		  { 0x0095, 0x0073, 0x0 } },
       
   545 		// Ra Halant Ka
       
   546 		{ { 0x09b0, 0x09cd, 0x0995, 0x0 },
       
   547 		  { 0x0073, 0x00e1, 0x0 } },
       
   548 		// Ra Halant Ka MatraI
       
   549 		{ { 0x09b0, 0x09cd, 0x0995, 0x09bf, 0x0 },
       
   550 		  { 0x0095, 0x0073, 0x00e1, 0x0 } },
       
   551 		// MatraI
       
   552  		{ { 0x09bf, 0x0 },
       
   553 		  { 0x0095, 0x01c8, 0x0 } },
       
   554 		// Ka Nukta
       
   555 		{ { 0x0995, 0x09bc, 0x0 },
       
   556 		  { 0x0073, 0x0093, 0x0 } },
       
   557 		// Ka Halant Ra
       
   558 		{ { 0x0995, 0x09cd, 0x09b0, 0x0 },
       
   559 		  { 0x00e5, 0x0 } },
       
   560 		// Ka Halant Ra Halant Ka
       
   561                 { { 0x995, 0x9cd, 0x9b0, 0x9cd, 0x995, 0x0 },
       
   562                   { 0x234, 0x24e, 0x73, 0x0 } }, 
       
   563 		// Ya + Halant
       
   564 		{ { 0x09af, 0x09cd, 0x0 },
       
   565 		  { 0x00d2, 0x0 } },
       
   566 		// Da Halant Ya -> Da Ya-Phala
       
   567 		{ { 0x09a6, 0x09cd, 0x09af, 0x0 },
       
   568 		  { 0x0084, 0x00e2, 0x0 } },
       
   569 		// A Halant Ya -> A Ya-phala
       
   570 		{ { 0x0985, 0x09cd, 0x09af, 0x0 },
       
   571 		  { 0x0067, 0x00e2, 0x0 } },
       
   572 		// Na Halant Ka
       
   573 		{ { 0x09a8, 0x09cd, 0x0995, 0x0 },
       
   574 		  { 0x0188, 0x0 } },
       
   575 		// Na Halant ZWNJ Ka
       
   576                 { { 0x9a8, 0x9cd, 0x200c, 0x995, 0x0 },
       
   577                   { 0xcc, 0x73, 0x0 } }, 
       
   578 		// Na Halant ZWJ Ka
       
   579                 { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 },
       
   580                   { 0x247, 0x73, 0x0 } }, 
       
   581 		// Ka Halant ZWNJ Ka
       
   582                 { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 },
       
   583                   { 0x247, 0x73, 0x0 } }, 
       
   584 		// Ka Halant ZWJ Ka
       
   585                 { { 0x9a8, 0x9cd, 0x200d, 0x995, 0x0 },
       
   586                   { 0x247, 0x73, 0x0 } }, 
       
   587 		// Na Halant Ra
       
   588 		{ { 0x09a8, 0x09cd, 0x09b0, 0x0 },
       
   589 		  { 0x00f8, 0x0 } },
       
   590 		// Na Halant ZWNJ Ra
       
   591 		{ { 0x09a8, 0x09cd, 0x200c, 0x09b0, 0x0 },
       
   592 		  { 0xcc, 0x8d, 0x0 } },
       
   593 		// Na Halant ZWJ Ra
       
   594                 { { 0x9a8, 0x9cd, 0x200d, 0x9b0, 0x0 },
       
   595                   { 0x247, 0x8d, 0x0 } }, 
       
   596 		// Na Halant Ba
       
   597 		{ { 0x09a8, 0x09cd, 0x09ac, 0x0 },
       
   598 		  { 0x0139, 0x0 } },
       
   599 		// Na Halant ZWNJ Ba
       
   600                 { { 0x9a8, 0x9cd, 0x200c, 0x9ac, 0x0 },
       
   601                   { 0xcc, 0x89, 0x0 } }, 
       
   602 		// Na Halant ZWJ Ba
       
   603                 { { 0x9a8, 0x9cd, 0x200d, 0x9ac, 0x0 },
       
   604                   { 0x247, 0x89, 0x0 } }, 
       
   605 		// Na Halant Dha
       
   606 		{ { 0x09a8, 0x09cd, 0x09a7, 0x0 },
       
   607 		  { 0x0145, 0x0 } },
       
   608 		// Na Halant ZWNJ Dha
       
   609 		{ { 0x09a8, 0x09cd, 0x200c, 0x09a7, 0x0 },
       
   610 		  { 0xcc, 0x85, 0x0 } },
       
   611 		// Na Halant ZWJ Dha
       
   612 		{ { 0x09a8, 0x09cd, 0x200d, 0x09a7, 0x0 },
       
   613 		  { 0x247, 0x85, 0x0 } },
       
   614 		// Ra Halant Ka MatraAU
       
   615                 { { 0x9b0, 0x9cd, 0x995, 0x9cc, 0x0 },
       
   616                   { 0x232, 0x73, 0xe1, 0xa0, 0x0 } }, 
       
   617 		// Ra Halant Ba Halant Ba
       
   618 		{ { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 },
       
   619 		  { 0x013b, 0x00e1, 0x0 } },
       
   620 
       
   621 		{ {0}, {0} }
       
   622 	    };
       
   623 
       
   624 
       
   625 	    const ShapeTable *s = shape_table;
       
   626 	    while (s->unicode[0]) {
       
   627 		QVERIFY( shaping(face, s, HB_Script_Bengali) );
       
   628 		++s;
       
   629 	    }
       
   630 
       
   631             FT_Done_Face(face);
       
   632 	} else {
       
   633 	    QSKIP("couln't find MuktiNarrow.ttf", SkipAll);
       
   634 	}
       
   635     }
       
   636     {
       
   637         FT_Face face = loadFace("LikhanNormal.ttf");
       
   638         if (face) {
       
   639 	    const ShapeTable shape_table [] = {
       
   640 		{ { 0x09a8, 0x09cd, 0x09af, 0x0 },
       
   641 		  { 0x0192, 0x0 } },
       
   642 		{ { 0x09b8, 0x09cd, 0x09af, 0x0 },
       
   643 		  { 0x01d6, 0x0 } },
       
   644 		{ { 0x09b6, 0x09cd, 0x09af, 0x0 },
       
   645 		  { 0x01bc, 0x0 } },
       
   646 		{ { 0x09b7, 0x09cd, 0x09af, 0x0 },
       
   647 		  { 0x01c6, 0x0 } },
       
   648 		{ { 0x09b0, 0x09cd, 0x09a8, 0x09cd, 0x200d, 0x0 },
       
   649 		  { 0xd3, 0x12f, 0x0 } },
       
   650 
       
   651 		{ {0}, {0} }
       
   652 	    };
       
   653 
       
   654 
       
   655 	    const ShapeTable *s = shape_table;
       
   656 	    while (s->unicode[0]) {
       
   657 		QVERIFY( shaping(face, s, HB_Script_Bengali) );
       
   658 		++s;
       
   659 	    }
       
   660 
       
   661             FT_Done_Face(face);
       
   662 	} else {
       
   663 	    QSKIP("couln't find LikhanNormal.ttf", SkipAll);
       
   664 	}
       
   665     }
       
   666 }
       
   667 
       
   668 void tst_QScriptEngine::gurmukhi()
       
   669 {
       
   670     {
       
   671         FT_Face face = loadFace("lohit.punjabi.1.1.ttf");
       
   672         if (face) {
       
   673 	    const ShapeTable shape_table [] = {
       
   674 		{ { 0xA15, 0xA4D, 0xa39, 0x0 },
       
   675 		  { 0x3b, 0x8b, 0x0 } },
       
   676 		{ {0}, {0} }
       
   677 	    };
       
   678 
       
   679 
       
   680 	    const ShapeTable *s = shape_table;
       
   681 	    while (s->unicode[0]) {
       
   682 		QVERIFY( shaping(face, s, HB_Script_Gurmukhi) );
       
   683 		++s;
       
   684 	    }
       
   685 
       
   686             FT_Done_Face(face);
       
   687 	} else {
       
   688 	    QSKIP("couln't find lohit.punjabi.1.1.ttf", SkipAll);
       
   689 	}
       
   690     }
       
   691 }
       
   692 
       
   693 void tst_QScriptEngine::oriya()
       
   694 {
       
   695     {
       
   696         FT_Face face = loadFace("utkalm.ttf");
       
   697         if (face) {
       
   698 	    const ShapeTable shape_table [] = {
       
   699                 { { 0xb15, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 },
       
   700                   { 0x150, 0x125, 0x0 } }, 
       
   701                 { { 0xb24, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 },
       
   702                   { 0x151, 0x120, 0x0 } }, 
       
   703                 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 },
       
   704                   { 0x152, 0x120, 0x0 } }, 
       
   705                 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb2c, 0x0 },
       
   706                   { 0x152, 0x120, 0x0 } }, 
       
   707                 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 },
       
   708                   { 0x176, 0x0 } }, 
       
   709                 { { 0xb38, 0xb4d, 0xb24, 0xb4d, 0xb30, 0x0 },
       
   710                   { 0x177, 0x0 } }, 
       
   711                 { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0xb4d, 0xb2f, 0x0 },
       
   712                   { 0x176, 0x124, 0x0 } }, 
       
   713                 { {0}, {0} }
       
   714 
       
   715             };
       
   716 
       
   717 	    const ShapeTable *s = shape_table;
       
   718 	    while (s->unicode[0]) {
       
   719 		QVERIFY( shaping(face, s, HB_Script_Oriya) );
       
   720 		++s;
       
   721 	    }
       
   722 
       
   723             FT_Done_Face(face);
       
   724 	} else {
       
   725 	    QSKIP("couln't find utkalm.ttf", SkipAll);
       
   726 	}
       
   727     }
       
   728 }
       
   729 
       
   730 
       
   731 void tst_QScriptEngine::tamil()
       
   732 {
       
   733     {
       
   734         FT_Face face = loadFace("akruti1.ttf");
       
   735         if (face) {
       
   736 	    const ShapeTable shape_table [] = {
       
   737 		{ { 0x0b95, 0x0bc2, 0x0 },
       
   738 		  { 0x004e, 0x0 } },
       
   739 		{ { 0x0bae, 0x0bc2, 0x0 },
       
   740 		  { 0x009e, 0x0 } },
       
   741 		{ { 0x0b9a, 0x0bc2, 0x0 },
       
   742 		  { 0x0058, 0x0 } },
       
   743 		{ { 0x0b99, 0x0bc2, 0x0 },
       
   744 		  { 0x0053, 0x0 } },
       
   745 		{ { 0x0bb0, 0x0bc2, 0x0 },
       
   746 		  { 0x00a8, 0x0 } },
       
   747 		{ { 0x0ba4, 0x0bc2, 0x0 },
       
   748 		  { 0x008e, 0x0 } },
       
   749 		{ { 0x0b9f, 0x0bc2, 0x0 },
       
   750 		  { 0x0062, 0x0 } },
       
   751 		{ { 0x0b95, 0x0bc6, 0x0 },
       
   752 		  { 0x000a, 0x0031, 0x0 } },
       
   753 		{ { 0x0b95, 0x0bca, 0x0 },
       
   754 		  { 0x000a, 0x0031, 0x0007, 0x0 } },
       
   755 		{ { 0x0b95, 0x0bc6, 0x0bbe, 0x0 },
       
   756 		  { 0x000a, 0x0031, 0x007, 0x0 } },
       
   757 		{ { 0x0b95, 0x0bcd, 0x0bb7, 0x0 },
       
   758 		  { 0x0049, 0x0 } },
       
   759 		{ { 0x0b95, 0x0bcd, 0x0bb7, 0x0bca, 0x0 },
       
   760 		  { 0x000a, 0x0049, 0x007, 0x0 } },
       
   761 		{ { 0x0b95, 0x0bcd, 0x0bb7, 0x0bc6, 0x0bbe, 0x0 },
       
   762 		  { 0x000a, 0x0049, 0x007, 0x0 } },
       
   763 		{ { 0x0b9f, 0x0bbf, 0x0 },
       
   764 		  { 0x005f, 0x0 } },
       
   765 		{ { 0x0b9f, 0x0bc0, 0x0 },
       
   766 		  { 0x0060, 0x0 } },
       
   767 		{ { 0x0bb2, 0x0bc0, 0x0 },
       
   768 		  { 0x00ab, 0x0 } },
       
   769 		{ { 0x0bb2, 0x0bbf, 0x0 },
       
   770 		  { 0x00aa, 0x0 } },
       
   771 		{ { 0x0bb0, 0x0bcd, 0x0 },
       
   772 		  { 0x00a4, 0x0 } },
       
   773 		{ { 0x0bb0, 0x0bbf, 0x0 },
       
   774 		  { 0x00a5, 0x0 } },
       
   775 		{ { 0x0bb0, 0x0bc0, 0x0 },
       
   776 		  { 0x00a6, 0x0 } },
       
   777 		{ { 0x0b83, 0x0 },
       
   778 		  { 0x0025, 0x0 } },
       
   779 		{ { 0x0b83, 0x0b95, 0x0 },
       
   780 		  { 0x0025, 0x0031, 0x0 } },
       
   781 
       
   782 		{ {0}, {0} }
       
   783 	    };
       
   784 
       
   785 
       
   786 	    const ShapeTable *s = shape_table;
       
   787 	    while (s->unicode[0]) {
       
   788 		QVERIFY( shaping(face, s, HB_Script_Tamil) );
       
   789 		++s;
       
   790 	    }
       
   791 
       
   792             FT_Done_Face(face);
       
   793 	} else {
       
   794 	    QSKIP("couln't find akruti1.ttf", SkipAll);
       
   795 	}
       
   796     }
       
   797 }
       
   798 
       
   799 
       
   800 void tst_QScriptEngine::telugu()
       
   801 {
       
   802     {
       
   803         FT_Face face = loadFace("Pothana2000.ttf");
       
   804         if (face) {
       
   805 	    const ShapeTable shape_table [] = {
       
   806                 { { 0xc15, 0xc4d, 0x0 },
       
   807                   { 0xbb, 0x0 } }, 
       
   808                 { { 0xc15, 0xc4d, 0xc37, 0x0 },
       
   809                   { 0x4b, 0x0 } }, 
       
   810                 { { 0xc15, 0xc4d, 0xc37, 0xc4d, 0x0 },
       
   811                   { 0xe0, 0x0 } }, 
       
   812                 { { 0xc15, 0xc4d, 0xc37, 0xc4d, 0xc23, 0x0 },
       
   813                   { 0x4b, 0x91, 0x0 } }, 
       
   814                 { { 0xc15, 0xc4d, 0xc30, 0x0 },
       
   815                   { 0x5a, 0xb2, 0x0 } }, 
       
   816                 { { 0xc15, 0xc4d, 0xc30, 0xc4d, 0x0 },
       
   817                   { 0xbb, 0xb2, 0x0 } }, 
       
   818                 { { 0xc15, 0xc4d, 0xc30, 0xc4d, 0xc15, 0x0 },
       
   819                   { 0x5a, 0xb2, 0x83, 0x0 } }, 
       
   820                 { { 0xc15, 0xc4d, 0xc30, 0xc3f, 0x0 },
       
   821                   { 0xe2, 0xb2, 0x0 } }, 
       
   822                 { { 0xc15, 0xc4d, 0xc15, 0xc48, 0x0 },
       
   823                   { 0xe6, 0xb3, 0x83, 0x0 } },
       
   824                 { { 0xc15, 0xc4d, 0xc30, 0xc48, 0x0 },
       
   825                   { 0xe6, 0xb3, 0x9f, 0x0 } }, 
       
   826 		{ {0}, {0} }
       
   827 
       
   828             };
       
   829 
       
   830 	    const ShapeTable *s = shape_table;
       
   831 	    while (s->unicode[0]) {
       
   832 		QVERIFY( shaping(face, s, HB_Script_Telugu) );
       
   833 		++s;
       
   834 	    }
       
   835 
       
   836             FT_Done_Face(face);
       
   837 	} else {
       
   838 	    QSKIP("couln't find Pothana2000.ttf", SkipAll);
       
   839 	}
       
   840     }
       
   841 }
       
   842 
       
   843 
       
   844 void tst_QScriptEngine::kannada()
       
   845 {
       
   846     {
       
   847         FT_Face face = loadFace("Sampige.ttf");
       
   848         if (face) {
       
   849 	    const ShapeTable shape_table [] = {
       
   850 		{ { 0x0ca8, 0x0ccd, 0x0ca8, 0x0 },
       
   851 		  { 0x0049, 0x00ba, 0x0 } },
       
   852 		{ { 0x0ca8, 0x0ccd, 0x0ca1, 0x0 },
       
   853 		  { 0x0049, 0x00b3, 0x0 } },
       
   854 		{ { 0x0caf, 0x0cc2, 0x0 },
       
   855 		  { 0x004f, 0x005d, 0x0 } },
       
   856 		{ { 0x0ce0, 0x0 },
       
   857 		  { 0x006a, 0x0 } },
       
   858 		{ { 0x0ce6, 0x0ce7, 0x0ce8, 0x0 },
       
   859 		  { 0x006b, 0x006c, 0x006d, 0x0 } },
       
   860 		{ { 0x0cb5, 0x0ccb, 0x0 },
       
   861 		  { 0x015f, 0x0067, 0x0 } },
       
   862 		{ { 0x0cb0, 0x0ccd, 0x0cae, 0x0 },
       
   863 		  { 0x004e, 0x0082, 0x0 } },
       
   864 		{ { 0x0cb0, 0x0ccd, 0x0c95, 0x0 },
       
   865 		  { 0x0036, 0x0082, 0x0 } },
       
   866 		{ { 0x0c95, 0x0ccd, 0x0cb0, 0x0 },
       
   867 		  { 0x0036, 0x00c1, 0x0 } },
       
   868 		{ { 0x0cb0, 0x0ccd, 0x200d, 0x0c95, 0x0 },
       
   869 		  { 0x0050, 0x00a7, 0x0 } },
       
   870 
       
   871 		{ {0}, {0} }
       
   872 	    };
       
   873 
       
   874 
       
   875 	    const ShapeTable *s = shape_table;
       
   876 	    while (s->unicode[0]) {
       
   877 		QVERIFY( shaping(face, s, HB_Script_Kannada) );
       
   878 		++s;
       
   879 	    }
       
   880 
       
   881             FT_Done_Face(face);
       
   882 	} else {
       
   883 	    QSKIP("couln't find Sampige.ttf", SkipAll);
       
   884 	}
       
   885     }
       
   886     {
       
   887         FT_Face face = loadFace("tunga.ttf");
       
   888         if (face) {
       
   889 	    const ShapeTable shape_table [] = {
       
   890 		{ { 0x0cb7, 0x0cc6, 0x0 },
       
   891 		  { 0x00b0, 0x006c, 0x0 } },
       
   892 		{ { 0x0cb7, 0x0ccd, 0x0 },
       
   893 		  { 0x0163, 0x0 } },
       
   894 
       
   895 		{ {0}, {0} }
       
   896 	    };
       
   897 
       
   898 
       
   899 	    const ShapeTable *s = shape_table;
       
   900 	    while (s->unicode[0]) {
       
   901 		QVERIFY( shaping(face, s, HB_Script_Kannada) );
       
   902 		++s;
       
   903 	    }
       
   904 
       
   905             FT_Done_Face(face);
       
   906 	} else {
       
   907 	    QSKIP("couln't find tunga.ttf", SkipAll);
       
   908 	}
       
   909     }
       
   910 }
       
   911 
       
   912 
       
   913 
       
   914 void tst_QScriptEngine::malayalam()
       
   915 {
       
   916     {
       
   917         FT_Face face = loadFace("AkrutiMal2Normal.ttf");
       
   918         if (face) {
       
   919 	    const ShapeTable shape_table [] = {
       
   920 		{ { 0x0d15, 0x0d46, 0x0 },
       
   921 		  { 0x005e, 0x0034, 0x0 } },
       
   922 		{ { 0x0d15, 0x0d47, 0x0 },
       
   923 		  { 0x005f, 0x0034, 0x0 } },
       
   924 		{ { 0x0d15, 0x0d4b, 0x0 },
       
   925 		  { 0x005f, 0x0034, 0x0058, 0x0 } },
       
   926 		{ { 0x0d15, 0x0d48, 0x0 },
       
   927 		  { 0x0060, 0x0034, 0x0 } },
       
   928 		{ { 0x0d15, 0x0d4a, 0x0 },
       
   929 		  { 0x005e, 0x0034, 0x0058, 0x0 } },
       
   930 		{ { 0x0d30, 0x0d4d, 0x0d15, 0x0 },
       
   931 		  { 0x009e, 0x0034, 0x0 } },
       
   932 		{ { 0x0d15, 0x0d4d, 0x0d35, 0x0 },
       
   933 		  { 0x0034, 0x007a, 0x0 } },
       
   934 		{ { 0x0d15, 0x0d4d, 0x0d2f, 0x0 },
       
   935 		  { 0x0034, 0x00a2, 0x0 } },
       
   936 		{ { 0x0d1f, 0x0d4d, 0x0d1f, 0x0 },
       
   937 		  { 0x0069, 0x0 } },
       
   938 		{ { 0x0d26, 0x0d4d, 0x0d26, 0x0 },
       
   939 		  { 0x0074, 0x0 } },
       
   940 		{ { 0x0d30, 0x0d4d, 0x0 },
       
   941 		  { 0x009e, 0x0 } },
       
   942 		{ { 0x0d30, 0x0d4d, 0x200c, 0x0 },
       
   943 		  { 0x009e, 0x0 } },
       
   944 		{ { 0x0d30, 0x0d4d, 0x200d, 0x0 },
       
   945 		  { 0x009e, 0x0 } },
       
   946 
       
   947 
       
   948 		{ {0}, {0} }
       
   949 	    };
       
   950 
       
   951 
       
   952 	    const ShapeTable *s = shape_table;
       
   953 	    while (s->unicode[0]) {
       
   954 		QVERIFY( shaping(face, s, HB_Script_Malayalam) );
       
   955 		++s;
       
   956 	    }
       
   957 
       
   958             FT_Done_Face(face);
       
   959 	} else {
       
   960 	    QSKIP("couln't find AkrutiMal2Normal.ttf", SkipAll);
       
   961 	}
       
   962     }
       
   963 }
       
   964 
       
   965 
       
   966 
       
   967 void tst_QScriptEngine::khmer()
       
   968 {
       
   969     {
       
   970         FT_Face face = loadFace("KhmerOS.ttf");
       
   971         if (face) {
       
   972 	    const ShapeTable shape_table [] = {
       
   973 		{ { 0x179a, 0x17cd, 0x0 },
       
   974 		  { 0x24c, 0x27f, 0x0 } },
       
   975 		{ { 0x179f, 0x17c5, 0x0 },
       
   976 		  { 0x273, 0x203, 0x0 } },
       
   977 		{ { 0x1790, 0x17d2, 0x1784, 0x17c3, 0x0 },
       
   978 		  { 0x275, 0x242, 0x182, 0x0 } },
       
   979 		{ { 0x179a, 0x0 },
       
   980 		  { 0x24c, 0x0 } },
       
   981 		{ { 0x1781, 0x17d2, 0x1798, 0x17c2, 0x0 },
       
   982 		  { 0x274, 0x233, 0x197, 0x0 } },
       
   983 		{ { 0x1798, 0x17b6, 0x0 },
       
   984 		  { 0x1cb, 0x0 } },
       
   985 		{ { 0x179a, 0x17b8, 0x0 },
       
   986 		  { 0x24c, 0x26a, 0x0 } },
       
   987 		{ { 0x1787, 0x17b6, 0x0 },
       
   988 		  { 0x1ba, 0x0 } },
       
   989 		{ { 0x1798, 0x17d2, 0x1796, 0x17bb, 0x0 },
       
   990 		  { 0x24a, 0x195, 0x26d, 0x0 } },
       
   991 		{ {0}, {0} }
       
   992 	    };
       
   993 
       
   994 
       
   995 	    const ShapeTable *s = shape_table;
       
   996 	    while (s->unicode[0]) {
       
   997 		QVERIFY( shaping(face, s, HB_Script_Khmer) );
       
   998 		++s;
       
   999 	    }
       
  1000 
       
  1001             FT_Done_Face(face);
       
  1002 	} else {
       
  1003 	    QSKIP("couln't find KhmerOS.ttf", SkipAll);
       
  1004 	}
       
  1005     }
       
  1006 }
       
  1007 
       
  1008 void tst_QScriptEngine::linearB()
       
  1009 {
       
  1010     {
       
  1011         FT_Face face = loadFace("PENUTURE.TTF");
       
  1012         if (face) {
       
  1013 	    const ShapeTable shape_table [] = {
       
  1014 		{ { 0xd800, 0xdc01, 0xd800, 0xdc02, 0xd800, 0xdc03,  0 },
       
  1015                   { 0x5, 0x6, 0x7, 0 } },
       
  1016 		{ {0}, {0} }
       
  1017 	    };
       
  1018 
       
  1019 
       
  1020 	    const ShapeTable *s = shape_table;
       
  1021 	    while (s->unicode[0]) {
       
  1022 		QVERIFY( shaping(face, s, HB_Script_Common) );
       
  1023 		++s;
       
  1024 	    }
       
  1025 
       
  1026             FT_Done_Face(face);
       
  1027 	} else {
       
  1028 	    QSKIP("couln't find PENUTURE.TTF", SkipAll);
       
  1029 	}
       
  1030     }
       
  1031 }
       
  1032 
       
  1033 
       
  1034 QTEST_MAIN(tst_QScriptEngine)
       
  1035 #include "main.moc"