diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2010-03-22 09:46:00 (GMT) |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2010-03-22 09:46:00 (GMT) |
commit | 74f5e34979b8a08a91aa3c2fa6d252e68eca7817 (patch) | |
tree | 9361f50e54e5b9168fb891012e9c78a67799d1ba /src/3rdparty/harfbuzz/tests | |
parent | 572ebf1586f4e995527eee126fcf0bd4fdb18bee (diff) | |
download | Qt-74f5e34979b8a08a91aa3c2fa6d252e68eca7817.zip Qt-74f5e34979b8a08a91aa3c2fa6d252e68eca7817.tar.gz Qt-74f5e34979b8a08a91aa3c2fa6d252e68eca7817.tar.bz2 |
Add support for polyphonic greek
Merge patch c0006e05f32ecd6f16825b799d2bce345c166433 from
harfbuzz and add autotests to QTextScriptEngine.
Support for polyphonic greek is implemented by mapping decomposed
greek character sequences to their composed characters in the
greek extended unicode range (U+1f00 - U+1fff).
Task-number: QTBUG-391
Reviewed-By: Simon Hausmann
Diffstat (limited to 'src/3rdparty/harfbuzz/tests')
-rw-r--r-- | src/3rdparty/harfbuzz/tests/shaping/main.cpp | 127 |
1 files changed, 105 insertions, 22 deletions
diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp index 827ac30..b48b0a9 100644 --- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp +++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp @@ -136,13 +136,13 @@ HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 return HB_Err_Ok; } -void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics) +void hb_getGlyphMetrics(HB_Font, HB_Glyph, HB_GlyphMetrics *metrics) { // ### metrics->x = metrics->y = metrics->width = metrics->height = metrics->xOffset = metrics->yOffset = 0; } -HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric) +HB_Fixed hb_getFontMetric(HB_Font, HB_FontMetric ) { return 0; // #### } @@ -169,6 +169,8 @@ public slots: void initTestCase(); void cleanupTestCase(); private slots: + void greek(); + void devanagari(); void bengali(); void gurmukhi(); @@ -203,18 +205,25 @@ void tst_QScriptEngine::cleanupTestCase() FT_Done_FreeType(freetype); } -struct ShapeTable { - unsigned short unicode[16]; - unsigned short glyphs[16]; +class Shaper +{ +public: + Shaper(FT_Face face, HB_Script script, const QString &str); + + HB_FontRec hbFont; + HB_ShaperItem shaper_item; + QVarLengthArray<HB_Glyph> hb_glyphs; + QVarLengthArray<HB_GlyphAttributes> hb_attributes; + QVarLengthArray<HB_Fixed> hb_advances; + QVarLengthArray<HB_FixedPoint> hb_offsets; + QVarLengthArray<unsigned short> hb_logClusters; + }; -static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) +Shaper::Shaper(FT_Face face, HB_Script script, const QString &str) { - QString str = QString::fromUtf16( s->unicode ); - HB_Face hbFace = HB_NewFace(face, hb_getSFntTable); - HB_FontRec hbFont; hbFont.klass = &hb_fontClass; hbFont.userData = face; hbFont.x_ppem = face->size->metrics.x_ppem; @@ -222,7 +231,6 @@ static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) hbFont.x_scale = face->size->metrics.x_scale; hbFont.y_scale = face->size->metrics.y_scale; - HB_ShaperItem shaper_item; shaper_item.kerning_applied = false; shaper_item.string = reinterpret_cast<const HB_UChar16 *>(str.constData()); shaper_item.stringLength = str.length(); @@ -237,11 +245,6 @@ static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) shaper_item.glyphIndicesPresent = false; shaper_item.initialGlyphCount = 0; - QVarLengthArray<HB_Glyph> hb_glyphs(shaper_item.num_glyphs); - QVarLengthArray<HB_GlyphAttributes> hb_attributes(shaper_item.num_glyphs); - QVarLengthArray<HB_Fixed> hb_advances(shaper_item.num_glyphs); - QVarLengthArray<HB_FixedPoint> hb_offsets(shaper_item.num_glyphs); - QVarLengthArray<unsigned short> hb_logClusters(shaper_item.num_glyphs); while (1) { hb_glyphs.resize(shaper_item.num_glyphs); @@ -263,10 +266,68 @@ static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) if (HB_ShapeItem(&shaper_item)) break; - } HB_FreeFace(hbFace); +} + + +#if defined(Q_WS_X11) +static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch) +{ + QString uc = QString().append(ch); + Shaper shaper(face, script, uc); + + uc = uc.normalized(QString::NormalizationForm_D); + Shaper decomposed(face, script, uc); + + if( shaper.shaper_item.num_glyphs != decomposed.shaper_item.num_glyphs ) + goto error; + + for (unsigned int i = 0; i < shaper.shaper_item.num_glyphs; ++i) { + if ((shaper.shaper_item.glyphs[i]&0xffffff) != (decomposed.shaper_item.glyphs[i]&0xffffff)) + goto error; + } + return true; + error: + QString str = ""; + int i = 0; + while (i < uc.length()) { + str += QString("%1 ").arg(uc[i].unicode(), 4, 16); + ++i; + } + qDebug("%s: decomposedShaping of char %4x failed\n decomposedString: %s\n nglyphs=%d, decomposed nglyphs %d", + face->family_name, + ch.unicode(), str.toLatin1().data(), + shaper.shaper_item.num_glyphs, + decomposed.shaper_item.num_glyphs); + + str = ""; + i = 0; + while (i < shaper.shaper_item.num_glyphs) { + str += QString("%1 ").arg(shaper.shaper_item.glyphs[i], 4, 16); + ++i; + } + qDebug(" composed glyph result = %s", str.toLatin1().constData()); + str = ""; + i = 0; + while (i < decomposed.shaper_item.num_glyphs) { + str += QString("%1 ").arg(decomposed.shaper_item.glyphs[i], 4, 16); + ++i; + } + qDebug(" decomposed glyph result = %s", str.toLatin1().constData()); + return false; +} +#endif + +struct ShapeTable { + unsigned short unicode[16]; + unsigned short glyphs[16]; +}; + +static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) +{ + Shaper shaper(face, script, QString::fromUtf16( s->unicode )); hb_uint32 nglyphs = 0; const unsigned short *g = s->glyphs; @@ -275,16 +336,16 @@ static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) g++; } - if( nglyphs != shaper_item.num_glyphs ) + if( nglyphs != shaper.shaper_item.num_glyphs ) goto error; for (hb_uint32 i = 0; i < nglyphs; ++i) { - if ((shaper_item.glyphs[i]&0xffffff) != s->glyphs[i]) + if ((shaper.shaper_item.glyphs[i]&0xffffff) != s->glyphs[i]) goto error; } return true; error: - str = ""; + QString str = ""; const unsigned short *uc = s->unicode; while (*uc) { str += QString("%1 ").arg(*uc, 4, 16); @@ -293,18 +354,40 @@ static bool shaping(FT_Face face, const ShapeTable *s, HB_Script script) qDebug("%s: shaping of string %s failed, nglyphs=%d, expected %d", face->family_name, str.toLatin1().constData(), - shaper_item.num_glyphs, nglyphs); + shaper.shaper_item.num_glyphs, nglyphs); str = ""; hb_uint32 i = 0; - while (i < shaper_item.num_glyphs) { - str += QString("%1 ").arg(shaper_item.glyphs[i], 4, 16); + while (i < shaper.shaper_item.num_glyphs) { + str += QString("%1 ").arg(shaper.shaper_item.glyphs[i], 4, 16); ++i; } qDebug(" glyph result = %s", str.toLatin1().constData()); return false; } + +void tst_QScriptEngine::greek() +{ + FT_Face face = loadFace("DejaVuSans.ttf"); + if (face) { + for (int uc = 0x1f00; uc <= 0x1fff; ++uc) { + QString str; + str.append(uc); + if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { + //qDebug() << "skipping" << hex << uc; + continue; + } + if (uc == 0x1fc1 || uc == 0x1fed) + continue; + QVERIFY( decomposedShaping(face, HB_Script_Greek, QChar(uc)) ); + } + } else { + QSKIP("couln't find DejaVu Sans", SkipAll); + } +} + + void tst_QScriptEngine::devanagari() { { |