From 8db35fe685d115f136bb2ec0305300dd082b278b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 26 Mar 2010 22:36:34 +0100 Subject: Fix a bug in greek shaping causing infinite loops Update harfbuzz to 33b9cde6a08293d26047734e046c6677a2959adb Reviewed-By: TrustMe AutoTest: qtextscriptengine Task-number: QTBUG-391 --- src/3rdparty/harfbuzz/src/harfbuzz-greek.c | 27 +++++++++------ src/3rdparty/harfbuzz/tests/shaping/main.cpp | 40 ++++++++++++++++++++-- .../qtextscriptengine/tst_qtextscriptengine.cpp | 36 +++++++++++++++++++ 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-greek.c b/src/3rdparty/harfbuzz/src/harfbuzz-greek.c index 59f3077..2e9b858 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-greek.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-greek.c @@ -77,10 +77,12 @@ static HB_UChar16 compose_0x300(HB_UChar16 base) return 0x1fdd; return 0; } - const hb_greek_decomposition *d = decompose_0x300; - while (d->base && d->base != base) - ++d; - return d->composed; + { + const hb_greek_decomposition *d = decompose_0x300; + while (d->base && d->base != base) + ++d; + return d->composed; + } } static const hb_greek_decomposition decompose_0x301[] = { @@ -115,10 +117,12 @@ static HB_UChar16 compose_0x301(HB_UChar16 base) if (base == 0x1ffe) return 0x1fde; } - const hb_greek_decomposition *d = decompose_0x301; - while (d->base && d->base != base) - ++d; - return d->composed; + { + const hb_greek_decomposition *d = decompose_0x301; + while (d->base && d->base != base) + ++d; + return d->composed; + } } static const hb_greek_decomposition decompose_0x304[] = { @@ -351,8 +355,7 @@ static HB_UChar16 compose_0x345(HB_UChar16 base) */ HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item) { - assert(shaper_item->item.script == HB_Script_Greek); - + const int availableGlyphs = shaper_item->num_glyphs; const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos; unsigned short *logClusters = shaper_item->log_clusters; HB_GlyphAttributes *attributes = shaper_item->attributes; @@ -363,6 +366,9 @@ HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item) hb_uint32 i; HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length); + + assert(shaper_item->item.script == HB_Script_Greek); + *shapedChars = *uc; logClusters[0] = 0; @@ -430,7 +436,6 @@ HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item) #ifndef NO_OPENTYPE if (HB_SelectScript(shaper_item, greek_features)) { - const int availableGlyphs = shaper_item->num_glyphs; HB_OpenTypeShape(shaper_item, /*properties*/0); return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE); } diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp index b48b0a9..320e8ee 100644 --- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp +++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp @@ -272,7 +272,6 @@ Shaper::Shaper(FT_Face face, HB_Script script, const QString &str) } -#if defined(Q_WS_X11) static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch) { QString uc = QString().append(ch); @@ -318,7 +317,6 @@ static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch) qDebug(" decomposed glyph result = %s", str.toLatin1().constData()); return false; } -#endif struct ShapeTable { unsigned short unicode[16]; @@ -382,6 +380,44 @@ void tst_QScriptEngine::greek() continue; QVERIFY( decomposedShaping(face, HB_Script_Greek, QChar(uc)) ); } + FT_Done_Face(face); + } else { + QSKIP("couln't find DejaVu Sans", SkipAll); + } + + + face = loadFace("SBL_grk.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)) ); + + } + + const ShapeTable shape_table [] = { + { { 0x3b1, 0x300, 0x313, 0x0 }, + { 0xb8, 0x3d3, 0x3c7, 0x0 } }, + { { 0x3b1, 0x313, 0x300, 0x0 }, + { 0xd4, 0x0 } }, + + { {0}, {0} } + }; + + + const ShapeTable *s = shape_table; + while (s->unicode[0]) { + QVERIFY( shaping(face, s, HB_Script_Greek) ); + ++s; + } + + FT_Done_Face(face); } else { QSKIP("couln't find DejaVu Sans", SkipAll); } diff --git a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp index 841f5b9..018c036 100644 --- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp +++ b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp @@ -1068,6 +1068,42 @@ void tst_QTextScriptEngine::greek() QSKIP("couln't find DejaVu Sans", SkipAll); } } + + { + if (QFontDatabase().families(QFontDatabase::Any).contains("SBL Greek")) { + QFont f("SBL Greek"); + 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(f, QChar(uc) ) ); + + } + + const ShapeTable shape_table [] = { + { { 0x3b1, 0x300, 0x313, 0x0 }, + { 0xb8, 0x3d3, 0x3c7, 0x0 } }, + { { 0x3b1, 0x313, 0x300, 0x0 }, + { 0xd4, 0x0 } }, + + { {0}, {0} } + }; + + + const ShapeTable *s = shape_table; + while (s->unicode[0]) { + QVERIFY( shaping(f, s) ); + ++s; + } + } else { + QSKIP("couln't find SBL_grk", SkipAll); + } + } #else QSKIP("X11 specific test", SkipAll); #endif -- cgit v0.12