[HarfBuzz] harfbuzz: Branch 'master' - 3 commits

Lars Knoll lars at kemper.freedesktop.org
Fri Mar 26 13:58:59 PDT 2010


 src/harfbuzz-greek.c   |   27 ++++++++++++++++-----------
 tests/shaping/main.cpp |   40 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 54 insertions(+), 13 deletions(-)

New commits:
commit 33b9cde6a08293d26047734e046c6677a2959adb
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Fri Mar 26 21:54:54 2010 +0100

    fix a bug in the greek shaper that could lead to an endless loop.
    
    availableGlyphs has to be initialized before we call
    stringToCMap.
    
    Added a test case that triggered the problem.

diff --git a/src/harfbuzz-greek.c b/src/harfbuzz-greek.c
index 59f3077..2e9b858 100644
--- a/src/harfbuzz-greek.c
+++ b/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/tests/shaping/main.cpp b/tests/shaping/main.cpp
index b48b0a9..320e8ee 100644
--- a/tests/shaping/main.cpp
+++ b/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);
     }
commit b6951137d935535319829de616938cf558fb7a70
Merge: aee5ca2... c0006e0...
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Fri Mar 26 21:27:48 2010 +0100

    Merge branch 'master' of ssh://git.freedesktop.org/git/harfbuzz

commit aee5ca262692519ef4408cd1c07b742355ce07d0
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Thu Nov 5 22:59:03 2009 +0100

    add support for N'Ko
    
    Extend the arabic shaping module to also support N'Ko.

diff --git a/src/harfbuzz-arabic.c b/src/harfbuzz-arabic.c
index 4d85c19..3837087 100644
--- a/src/harfbuzz-arabic.c
+++ b/src/harfbuzz-arabic.c
@@ -489,6 +489,56 @@ static void getArabicProperties(const unsigned short *chars, int len, HB_ArabicP
     */
 }
 
+static Joining getNkoJoining(unsigned short uc)
+{
+    if (uc < 0x7ca)
+        return JNone;
+    if (uc <= 0x7ea)
+        return JDual;
+    if (uc <= 0x7f3)
+        return JTransparent;
+    if (uc <= 0x7f9)
+        return JNone;
+    if (uc == 0x7fa)
+        return JCausing;
+    return JNone;
+}
+
+static void getNkoProperties(const unsigned short *chars, int len, HB_ArabicProperties *properties)
+{
+    int lastPos = 0;
+    int i = 0;
+
+    Joining j = getNkoJoining(chars[0]);
+    ArabicShape shape = joining_table[XIsolated][j].form2;
+    properties[0].justification = HB_NoJustification;
+
+    for (i = 1; i < len; ++i) {
+        properties[i].justification = (HB_GetUnicodeCharCategory(chars[i]) == HB_Separator_Space) ?
+                                      ArabicSpace : ArabicNone;
+
+        j = getNkoJoining(chars[i]);
+
+        if (j == JTransparent) {
+            properties[i].shape = XIsolated;
+            continue;
+        }
+
+        properties[lastPos].shape = joining_table[shape][j].form1;
+        shape = joining_table[shape][j].form2;
+
+
+        lastPos = i;
+    }
+    properties[lastPos].shape = joining_table[shape][JNone].form1;
+
+
+    /*
+     for (int i = 0; i < len; ++i)
+         qDebug("nko properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification);
+    */
+}
+
 /*
 // The unicode to unicode shaping codec.
 // does only presentation forms B at the moment, but that should be enough for
@@ -1012,7 +1062,10 @@ static HB_Bool arabicSyriacOpenTypeShape(HB_ShaperItem *item, HB_Bool *ot_ok)
     if (f + l + item->item.pos < item->stringLength) {
         ++l;
     }
-    getArabicProperties(uc+f, l, props);
+    if (item->item.script == HB_Script_Nko)
+        getNkoProperties(uc+f, l, props);
+    else
+        getArabicProperties(uc+f, l, props);
 
     for (i = 0; i < (int)item->num_glyphs; i++) {
         apply[i] = 0;
@@ -1051,7 +1104,8 @@ HB_Bool HB_ArabicShape(HB_ShaperItem *item)
     HB_Bool haveGlyphs;
     HB_STACKARRAY(HB_UChar16, shapedChars, item->item.length);
 
-    assert(item->item.script == HB_Script_Arabic || item->item.script == HB_Script_Syriac);
+    assert(item->item.script == HB_Script_Arabic || item->item.script == HB_Script_Syriac
+           || item->item.script == HB_Script_Nko);
 
 #ifndef NO_OPENTYPE
 
@@ -1065,7 +1119,7 @@ HB_Bool HB_ArabicShape(HB_ShaperItem *item)
     }
 #endif
 
-    if (item->item.script == HB_Script_Syriac)
+    if (item->item.script != HB_Script_Arabic)
         return HB_BasicShape(item);
 
     shapedString(item->string, item->stringLength, item->item.pos, item->item.length, shapedChars, &slen,
diff --git a/src/harfbuzz-shaper.cpp b/src/harfbuzz-shaper.cpp
index 36b9282..62bfba1 100644
--- a/src/harfbuzz-shaper.cpp
+++ b/src/harfbuzz-shaper.cpp
@@ -637,7 +637,9 @@ const HB_ScriptEngine HB_ScriptEngines[] = {
     // Runic
     { HB_BasicShape, 0 },
     // Khmer
-    { HB_KhmerShape, HB_KhmerAttributes }
+    { HB_KhmerShape, HB_KhmerAttributes },
+    // N'Ko
+    { HB_ArabicShape, 0}
 };
 
 void HB_GetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,
@@ -877,7 +879,9 @@ static const OTScripts ot_scripts [] = {
     // Runic
     { HB_MAKE_TAG('r', 'u', 'n', 'r'), 0 },
     // Khmer
-    { HB_MAKE_TAG('k', 'h', 'm', 'r'), 1 }
+    { HB_MAKE_TAG('k', 'h', 'm', 'r'), 1 },
+    // N'Ko
+    { HB_MAKE_TAG('n', 'k', 'o', ' '), 1 }
 };
 enum { NumOTScripts = sizeof(ot_scripts)/sizeof(OTScripts) };
 
diff --git a/src/harfbuzz-shaper.h b/src/harfbuzz-shaper.h
index d2357f4..f7c7714 100644
--- a/src/harfbuzz-shaper.h
+++ b/src/harfbuzz-shaper.h
@@ -62,6 +62,7 @@ typedef enum {
         HB_Script_Ogham,
         HB_Script_Runic,
         HB_Script_Khmer,
+        HB_Script_Nko,
         HB_Script_Inherited,
         HB_ScriptCount = HB_Script_Inherited
         /*
@@ -102,7 +103,6 @@ typedef enum {
         HB_Script_Cuneiform = Common,
         HB_Script_Phoenician = Common,
         HB_Script_PhagsPa = Common,
-        HB_Script_Nko = Common
         */
 } HB_Script;
 
diff --git a/tests/shaping/main.cpp b/tests/shaping/main.cpp
index 1a3ef4f..3b5148d 100644
--- a/tests/shaping/main.cpp
+++ b/tests/shaping/main.cpp
@@ -181,6 +181,7 @@ private slots:
     // sinhala missing
 
     void khmer();
+    void nko();
     void linearB();
 };
 
@@ -1005,6 +1006,40 @@ void tst_QScriptEngine::khmer()
     }
 }
 
+void tst_QScriptEngine::nko()
+{
+    {
+        FT_Face face = loadFace("DejaVuSans.ttf");
+        if (face) {
+	    const ShapeTable shape_table [] = {
+                { { 0x7ca, 0x0 },
+                  { 0x5c1, 0x0 } },
+                { { 0x7ca, 0x7ca, 0x0 },
+                  { 0x14db, 0x14d9, 0x0 } },
+                { { 0x7ca, 0x7fa, 0x7ca, 0x0 },
+                  { 0x14db, 0x5ec, 0x14d9, 0x0 } },
+                { { 0x7ca, 0x7f3, 0x7ca, 0x0 },
+                  { 0x14db, 0x5e7, 0x14d9, 0x0 } },
+                { { 0x7ca, 0x7f3, 0x7fa, 0x7ca, 0x0 },
+                  { 0x14db, 0x5e7, 0x5ec, 0x14d9, 0x0 } },
+                { {0}, {0} }
+	    };
+
+
+	    const ShapeTable *s = shape_table;
+	    while (s->unicode[0]) {
+                QVERIFY( shaping(face, s, HB_Script_Nko) );
+		++s;
+	    }
+
+            FT_Done_Face(face);
+	} else {
+	    QSKIP("couln't find DejaVuSans.ttf", SkipAll);
+	}
+    }
+}
+
+
 void tst_QScriptEngine::linearB()
 {
     {



More information about the HarfBuzz mailing list