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

Lars Knoll lars at kemper.freedesktop.org
Fri Nov 6 02:57:47 PST 2009


 src/harfbuzz-arabic.c   |   60 +++++++++++++++++++++-
 src/harfbuzz-impl.c     |    4 -
 src/harfbuzz-indic.cpp  |  127 +++++++++++++++++++++++++++++-------------------
 src/harfbuzz-shaper.cpp |   36 +++++++++++--
 src/harfbuzz-shaper.h   |    2 
 src/harfbuzz-stream.c   |    2 
 tests/shaping/main.cpp  |  125 +++++++++++++++++++++++++++++++++++++++++++----
 7 files changed, 284 insertions(+), 72 deletions(-)

New commits:
commit 797fe54d9ebbafb0cdc00705c008ea09e7ac1e9e
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Fri Nov 6 11:56:44 2009 +0100

    add N'Ko support to the arabic shaper
    
    Long outstanding bug report for Qt. See
    http://bugreports.qt.nokia.com/browse/QTBUG-1042

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 f92bb55..f3ec8e1 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 41f2dbb..12fa7c4 100644
--- a/tests/shaping/main.cpp
+++ b/tests/shaping/main.cpp
@@ -181,6 +181,7 @@ private slots:
     void sinhala();
 
     void khmer();
+    void nko();
     void linearB();
 };
 
@@ -1075,6 +1076,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()
 {
     {
commit e6636cadacf220785fca12b741b4587ff1ee42ec
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Thu Nov 5 16:28:49 2009 +0100

    fix bug with Malayalam Samvruthokaram.
    
    As reported on the mailing list on June 10, 2009
    by Praveen A.

diff --git a/src/harfbuzz-indic.cpp b/src/harfbuzz-indic.cpp
index df447e6..3008fca 100644
--- a/src/harfbuzz-indic.cpp
+++ b/src/harfbuzz-indic.cpp
@@ -1746,6 +1746,10 @@ static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int
                 ++pos;
                 continue;
             }
+            if (script == HB_Script_Malayalam && state == Matra && uc[pos-1] == 0x0d41) {
+                ++pos;
+                continue;
+            }
             goto finish;
         case Nukta:
             if (state == Consonant)
diff --git a/tests/shaping/main.cpp b/tests/shaping/main.cpp
index 9b6aa31..41f2dbb 100644
--- a/tests/shaping/main.cpp
+++ b/tests/shaping/main.cpp
@@ -979,6 +979,8 @@ void tst_QScriptEngine::malayalam()
                   { 0x5e, 0x34, 0x65, 0x0 } },
                 { { 0xd15, 0xd57, 0x0 },
                   { 0x34, 0x65, 0x0 } },
+                { { 0xd1f, 0xd4d, 0xd1f, 0xd41, 0xd4d, 0x0 },
+                  { 0x69, 0x5b, 0x64, 0x0 } },
 
 		{ {0}, {0} }
 	    };
commit e66916e33821e71ba19479c32108a2be8bb539b2
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Thu Nov 5 15:57:16 2009 +0100

    fix shaping of assamese ra
    
    See http://bugreports.qt.nokia.com/browse/QTBUG-1802

diff --git a/src/harfbuzz-indic.cpp b/src/harfbuzz-indic.cpp
index 48f4f90..df447e6 100644
--- a/src/harfbuzz-indic.cpp
+++ b/src/harfbuzz-indic.cpp
@@ -566,7 +566,7 @@ static const unsigned char indicPosition[0xe00-0x900] = {
     None, None, None, None,
     None, None, None, None,
 
-    None, None, None, None,
+    Below, None, None, None,
     None, None, None, None,
     None, None, None, None,
     None, None, None, None,
@@ -1252,7 +1252,9 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv
         //   farther than 3 consonants from the end of the syllable.
         // #### replace the HasReph property by testing if the feature exists in the font!
         if (form(*uc) == Consonant || (script == HB_Script_Bengali && form(*uc) == IndependentVowel)) {
-            beginsWithRa = (properties & HasReph) && ((len > 2) && *uc == ra && *(uc+1) == halant);
+            if ((properties & HasReph) && (len > 2) &&
+                (*uc == ra || *uc == 0x9f0) && *(uc+1) == halant)
+                beginsWithRa = true;
 
             if (beginsWithRa && form(*(uc+2)) == Control)
                 beginsWithRa = false;
diff --git a/tests/shaping/main.cpp b/tests/shaping/main.cpp
index a7ea417..9b6aa31 100644
--- a/tests/shaping/main.cpp
+++ b/tests/shaping/main.cpp
@@ -515,6 +515,12 @@ void tst_QScriptEngine::bengali()
                   { 0x179, 0x151, 0x172, 0x0 } },
                 { { 0x995, 0x9c7, 0x9d7, 0x0 },
                   { 0x179, 0x151, 0x17e, 0x0 } },
+                { { 0x9b0, 0x9cd, 0x9ad, 0x0 },
+                  { 0x168, 0x276, 0x0 } },
+                { { 0x9f0, 0x9cd, 0x9ad, 0x0 },
+                  { 0x168, 0x276, 0x0 } },
+                { { 0x9f1, 0x9cd, 0x9ad, 0x0 },
+                  { 0x191, 0x17d, 0x168, 0x0 } },
 
 		{ {0}, {0} }
 	    };
@@ -652,6 +658,12 @@ void tst_QScriptEngine::bengali()
                   { 0x01fe, 0x0 } },
 		{ { 0x09b0, 0x09cd, 0x09a8, 0x09cd, 0x200d, 0x0 },
                   { 0x10b, 0x167, 0x0 } },
+                { { 0x9b0, 0x9cd, 0x9ad, 0x0 },
+                  { 0xa1, 0x167, 0x0 } },
+                { { 0x9f0, 0x9cd, 0x9ad, 0x0 },
+                  { 0xa1, 0x167, 0x0 } },
+                { { 0x9f1, 0x9cd, 0x9ad, 0x0 },
+                  { 0x11c, 0xa1, 0x0 } },
 
 		{ {0}, {0} }
 	    };
commit e8a057fb67a0242e5a125d8cb2c823ad63e01449
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Wed Nov 4 14:14:12 2009 +0100

    correctly support decomposed forms of two or three part matras
    
    The indic shaping engine wasn't correctly determining syllable
    bondaries and shaping decomposed forms of two part matras.
    
    This fixes it and adds a set of unit tests for them.

diff --git a/src/harfbuzz-indic.cpp b/src/harfbuzz-indic.cpp
index 7104d2a..48f4f90 100644
--- a/src/harfbuzz-indic.cpp
+++ b/src/harfbuzz-indic.cpp
@@ -419,7 +419,7 @@ static const unsigned char indicForms[0xe00-0x900] = {
     Matra, Halant, Invalid, Invalid,
 
     Invalid, Invalid, Invalid, Invalid,
-    Invalid, Invalid, Invalid, LengthMark,
+    Invalid, Invalid, Invalid, Matra,
     Invalid, Invalid, Invalid, Invalid,
     Invalid, Invalid, Invalid, Invalid,
 
@@ -1050,62 +1050,59 @@ static const IndicOrdering * const indic_order[] = {
 
 // vowel matras that have to be split into two parts.
 static const unsigned short split_matras[]  = {
-    //  matra, split1, split2
+    //  matra, split1, split2, split3
 
     // bengalis
-    0x9cb, 0x9c7, 0x9be,
-    0x9cc, 0x9c7, 0x9d7,
+    0x9cb, 0x9c7, 0x9be, 0x0,
+    0x9cc, 0x9c7, 0x9d7, 0x0,
     // oriya
-    0xb48, 0xb47, 0xb56,
-    0xb4b, 0xb47, 0xb3e,
-    0xb4c, 0xb47, 0xb57,
+    0xb48, 0xb47, 0xb56, 0x0,
+    0xb4b, 0xb47, 0xb3e, 0x0,
+    0xb4c, 0xb47, 0xb57, 0x0,
     // tamil
-    0xbca, 0xbc6, 0xbbe,
-    0xbcb, 0xbc7, 0xbbe,
-    0xbcc, 0xbc6, 0xbd7,
+    0xbca, 0xbc6, 0xbbe, 0x0,
+    0xbcb, 0xbc7, 0xbbe, 0x0,
+    0xbcc, 0xbc6, 0xbd7, 0x0,
     // telugu
-    0xc48, 0xc46, 0xc56,
+    0xc48, 0xc46, 0xc56, 0x0,
     // kannada
-    0xcc0, 0xcbf, 0xcd5,
-    0xcc7, 0xcc6, 0xcd5,
-    0xcc8, 0xcc6, 0xcd6,
-    0xcca, 0xcc6, 0xcc2,
-    0xccb, 0xcca, 0xcd5,
+    0xcc0, 0xcbf, 0xcd5, 0x0,
+    0xcc7, 0xcc6, 0xcd5, 0x0,
+    0xcc8, 0xcc6, 0xcd6, 0x0,
+    0xcca, 0xcc6, 0xcc2, 0x0,
+    0xccb, 0xcc6, 0xcc2, 0xcd5,
     // malayalam
-    0xd4a, 0xd46, 0xd3e,
-    0xd4b, 0xd47, 0xd3e,
-    0xd4c, 0xd46, 0xd57,
+    0xd4a, 0xd46, 0xd3e, 0x0,
+    0xd4b, 0xd47, 0xd3e, 0x0,
+    0xd4c, 0xd46, 0xd57, 0x0,
     // sinhala
-    0xdda, 0xdd9, 0xdca,
-    0xddc, 0xdd9, 0xdcf,
-    0xddd, 0xddc, 0xdca,
-    0xdde, 0xdd9, 0xddf,
+    0xdda, 0xdd9, 0xdca, 0x0,
+    0xddc, 0xdd9, 0xdcf, 0x0,
+    0xddd, 0xdd9, 0xdcf, 0xdca,
+    0xdde, 0xdd9, 0xddf, 0x0,
     0xffff
 };
 
-static inline void splitMatra(unsigned short *reordered, int matra, int &len, int &base)
+static inline void splitMatra(unsigned short *reordered, int matra, int &len)
 {
     unsigned short matra_uc = reordered[matra];
     //qDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]);
 
     const unsigned short *split = split_matras;
     while (split[0] < matra_uc)
-        split += 3;
+        split += 4;
 
     assert(*split == matra_uc);
     ++split;
 
-    if (indic_position(*split) == Pre) {
-        reordered[matra] = split[1];
-        memmove(reordered + 1, reordered, len*sizeof(unsigned short));
-        reordered[0] = split[0];
-        base++;
-    } else {
-        memmove(reordered + matra + 1, reordered + matra, (len-matra)*sizeof(unsigned short));
-        reordered[matra] = split[0];
-        reordered[matra+1] = split[1];
-    }
-    len++;
+    int added_chars = split[2] == 0x0 ? 1 : 2;
+
+    memmove(reordered + matra + added_chars, reordered + matra, (len-matra)*sizeof(unsigned short));
+    reordered[matra] = split[0];
+    reordered[matra+1] = split[1];
+    if(added_chars == 2)
+        reordered[matra+2] = split[2];
+    len += added_chars;
 }
 
 #ifndef NO_OPENTYPE
@@ -1130,12 +1127,23 @@ static const HB_OpenTypeFeature indic_features[] = {
 
 // #define INDIC_DEBUG
 #ifdef INDIC_DEBUG
-#define IDEBUG qDebug
+#define IDEBUG hb_debug
+#include <stdarg.h>
+
+static void hb_debug(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg); // use variable arg list
+    vfprintf(stderr, msg, ap);
+    va_end(ap);
+    fprintf(stderr, "\n");
+}
+
 #else
 #define IDEBUG if(0) printf
 #endif
 
-#ifdef INDIC_DEBUG
+#if 0 //def INDIC_DEBUG
 static QString propertiesToString(int properties)
 {
     QString res;
@@ -1386,12 +1394,12 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv
             //      to be at the beginning of the syllable, so we just move
             //      them there now.
             if (matra_position == Split) {
-                splitMatra(uc, matra, len, base);
+                splitMatra(uc, matra, len);
                 // Handle three-part matras (0xccb in Kannada)
                 matra_position = indic_position(uc[matra]);
-                if (matra_position == Split)
-                    splitMatra(uc, matra, len, base);
-            } else if (matra_position == Pre) {
+            }
+
+            if (matra_position == Pre) {
                 unsigned short m = uc[matra];
                 while (matra--)
                     uc[matra+1] = uc[matra];
@@ -1609,11 +1617,11 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv
         // halant always applies
 
 #ifdef INDIC_DEBUG
-        {
-            IDEBUG("OT properties:");
-            for (int i = 0; i < len; ++i)
-                qDebug("    i: %s", ::propertiesToString(properties[i]).toLatin1().data());
-        }
+//        {
+//            IDEBUG("OT properties:");
+//            for (int i = 0; i < len; ++i)
+//                qDebug("    i: %s", ::propertiesToString(properties[i]).toLatin1().data());
+//        }
 #endif
 
         // initialize
@@ -1731,6 +1739,11 @@ static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int
             if (script == HB_Script_Bengali && pos == 1 &&
                  (uc[0] == 0x0985 || uc[0] == 0x098f))
                 break;
+            // Sinhala uses the Halant as a component of certain matras. Allow these, but keep the state on Matra.
+            if (script == HB_Script_Sinhala && state == Matra) {
+                ++pos;
+                continue;
+            }
             goto finish;
         case Nukta:
             if (state == Consonant)
@@ -1741,12 +1754,16 @@ static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int
                 break;
             // fall through
         case VowelMark:
-            if (state == Matra || state == IndependentVowel)
+            if (state == Matra || state == LengthMark || state == IndependentVowel)
                 break;
             // fall through
         case Matra:
             if (state == Consonant || state == Nukta)
                 break;
+            if (state == Matra) {
+                // ### needs proper testing for correct two/three part matras
+                break;
+            }
             // ### not sure if this is correct. If it is, does it apply only to Bengali or should
             // it work for all Indic languages?
             // the combination Independent_A + Vowel Sign AA is allowed.
@@ -1762,6 +1779,10 @@ static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int
             goto finish;
 
         case LengthMark:
+            if (state == Matra) {
+                // ### needs proper testing for correct two/three part matras
+                break;
+            }
         case IndependentVowel:
         case Invalid:
         case Other:
diff --git a/tests/shaping/main.cpp b/tests/shaping/main.cpp
index 1a3ef4f..a7ea417 100644
--- a/tests/shaping/main.cpp
+++ b/tests/shaping/main.cpp
@@ -178,7 +178,7 @@ private slots:
     void telugu();
     void kannada();
     void malayalam();
-    // sinhala missing
+    void sinhala();
 
     void khmer();
     void linearB();
@@ -510,6 +510,11 @@ void tst_QScriptEngine::bengali()
                   { 0x151, 0x276, 0x172, 0x143, 0x0 } },
                 { { 0x9b0, 0x9cd, 0x995, 0x9be, 0x983, 0x0 },
                   { 0x151, 0x276, 0x172, 0x144, 0x0 } }, 
+                // test decomposed two parts matras
+                { { 0x995, 0x9c7, 0x9be, 0x0 },
+                  { 0x179, 0x151, 0x172, 0x0 } },
+                { { 0x995, 0x9c7, 0x9d7, 0x0 },
+                  { 0x179, 0x151, 0x17e, 0x0 } },
 
 		{ {0}, {0} }
 	    };
@@ -638,15 +643,15 @@ void tst_QScriptEngine::bengali()
         if (face) {
 	    const ShapeTable shape_table [] = {
 		{ { 0x09a8, 0x09cd, 0x09af, 0x0 },
-		  { 0x0192, 0x0 } },
+                  { 0x01ca, 0x0 } },
 		{ { 0x09b8, 0x09cd, 0x09af, 0x0 },
-		  { 0x01d6, 0x0 } },
+                  { 0x020e, 0x0 } },
 		{ { 0x09b6, 0x09cd, 0x09af, 0x0 },
-		  { 0x01bc, 0x0 } },
+                  { 0x01f4, 0x0 } },
 		{ { 0x09b7, 0x09cd, 0x09af, 0x0 },
-		  { 0x01c6, 0x0 } },
+                  { 0x01fe, 0x0 } },
 		{ { 0x09b0, 0x09cd, 0x09a8, 0x09cd, 0x200d, 0x0 },
-		  { 0xd3, 0x12f, 0x0 } },
+                  { 0x10b, 0x167, 0x0 } },
 
 		{ {0}, {0} }
 	    };
@@ -823,8 +828,9 @@ void tst_QScriptEngine::telugu()
                   { 0xe6, 0xb3, 0x83, 0x0 } },
                 { { 0xc15, 0xc4d, 0xc30, 0xc48, 0x0 },
                   { 0xe6, 0xb3, 0x9f, 0x0 } }, 
-		{ {0}, {0} }
-
+                { { 0xc15, 0xc46, 0xc56, 0x0 },
+                  { 0xe6, 0xb3, 0x0 } },
+                { {0}, {0} }
             };
 
 	    const ShapeTable *s = shape_table;
@@ -867,7 +873,6 @@ void tst_QScriptEngine::kannada()
 		  { 0x0036, 0x00c1, 0x0 } },
 		{ { 0x0cb0, 0x0ccd, 0x200d, 0x0c95, 0x0 },
 		  { 0x0050, 0x00a7, 0x0 } },
-
 		{ {0}, {0} }
 	    };
 
@@ -891,6 +896,17 @@ void tst_QScriptEngine::kannada()
 		  { 0x00b0, 0x006c, 0x0 } },
 		{ { 0x0cb7, 0x0ccd, 0x0 },
 		  { 0x0163, 0x0 } },
+                { { 0xc95, 0xcbf, 0xcd5, 0x0 },
+                  { 0x114, 0x73, 0x0 } },
+                { { 0xc95, 0xcc6, 0xcd5, 0x0 },
+                  { 0x90, 0x6c, 0x73, 0x0 } },
+                { { 0xc95, 0xcc6, 0xcd6, 0x0 },
+                  { 0x90, 0x6c, 0x74, 0x0 } },
+                { { 0xc95, 0xcc6, 0xcc2, 0x0 },
+                  { 0x90, 0x6c, 0x69, 0x0 } },
+                { { 0xc95, 0xcca, 0xcd5, 0x0 },
+                  { 0x90, 0x6c, 0x69, 0x73, 0x0 } },
+
 
 		{ {0}, {0} }
 	    };
@@ -943,7 +959,14 @@ void tst_QScriptEngine::malayalam()
 		  { 0x009e, 0x0 } },
 		{ { 0x0d30, 0x0d4d, 0x200d, 0x0 },
 		  { 0x009e, 0x0 } },
-
+                { { 0xd15, 0xd46, 0xd3e, 0x0 },
+                  { 0x5e, 0x34, 0x58, 0x0 } },
+                { { 0xd15, 0xd47, 0xd3e, 0x0 },
+                  { 0x5f, 0x34, 0x58, 0x0 } },
+                { { 0xd15, 0xd46, 0xd57, 0x0 },
+                  { 0x5e, 0x34, 0x65, 0x0 } },
+                { { 0xd15, 0xd57, 0x0 },
+                  { 0x34, 0x65, 0x0 } },
 
 		{ {0}, {0} }
 	    };
@@ -962,6 +985,39 @@ void tst_QScriptEngine::malayalam()
     }
 }
 
+void tst_QScriptEngine::sinhala()
+{
+    {
+        FT_Face face = loadFace("FM-MalithiUW46.ttf");
+        if (face) {
+            const ShapeTable shape_table [] = {
+                { { 0xd9a, 0xdd9, 0xdcf, 0x0 },
+                  { 0x4a, 0x61, 0x42, 0x0 } },
+                { { 0xd9a, 0xdd9, 0xddf, 0x0 },
+                  { 0x4a, 0x61, 0x50, 0x0 } },
+                { { 0xd9a, 0xdd9, 0xdca, 0x0 },
+                  { 0x4a, 0x62, 0x0 } },
+                { { 0xd9a, 0xddc, 0xdca, 0x0 },
+                  { 0x4a, 0x61, 0x42, 0x41, 0x0 } },
+                { { 0xd9a, 0xdda, 0x0 },
+                  { 0x4a, 0x62, 0x0 } },
+                { { 0xd9a, 0xddd, 0x0 },
+                  { 0x4a, 0x61, 0x42, 0x41, 0x0 } },
+                { {0}, {0} }
+            };
+
+            const ShapeTable *s = shape_table;
+            while (s->unicode[0]) {
+                QVERIFY( shaping(face, s, HB_Script_Sinhala) );
+                ++s;
+            }
+
+            FT_Done_Face(face);
+        } else {
+            QSKIP("couln't find FM-MalithiUW46.ttf", SkipAll);
+        }
+    }
+}
 
 
 void tst_QScriptEngine::khmer()
commit 6a5f37fba3d2db2a740dff5b0a9a2f896747b15c
Author: Lars Knoll <lars.knoll at nokia.com>
Date:   Wed Nov 4 13:48:33 2009 +0100

    fix a few compiler warnings and make the code more exception safe.

diff --git a/src/harfbuzz-impl.c b/src/harfbuzz-impl.c
index 9056a55..ddbf36b 100644
--- a/src/harfbuzz-impl.c
+++ b/src/harfbuzz-impl.c
@@ -33,7 +33,7 @@ HB_INTERNAL HB_Pointer
 _hb_alloc(size_t     size,
 	  HB_Error  *perror )
 {
-  HB_Error    error = 0;
+  HB_Error    error = (HB_Error)0;
   HB_Pointer  block = NULL;
 
   if ( size > 0 )
@@ -54,7 +54,7 @@ _hb_realloc(HB_Pointer  block,
 	    HB_Error   *perror )
 {
     HB_Pointer  block2 = NULL;
-    HB_Error    error  = 0;
+    HB_Error    error  = (HB_Error)0;
 
     block2 = realloc( block, new_size );
     if ( block2 == NULL && new_size != 0 )
diff --git a/src/harfbuzz-shaper.cpp b/src/harfbuzz-shaper.cpp
index 36b9282..f92bb55 100644
--- a/src/harfbuzz-shaper.cpp
+++ b/src/harfbuzz-shaper.cpp
@@ -935,7 +935,13 @@ static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Ta
     if (error)
         return 0;
     stream = (HB_Stream)malloc(sizeof(HB_StreamRec));
+    if (!stream)
+        return 0;
     stream->base = (HB_Byte*)malloc(length);
+    if (!stream->base) {
+        free(stream);
+        return 0;
+    }
     error = tableFunc(font, tag, stream->base, &length);
     if (error) {
         _hb_close_stream(stream);
@@ -950,6 +956,8 @@ static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Ta
 HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
 {
     HB_Face face = (HB_Face )malloc(sizeof(HB_FaceRec));
+    if (!face)
+        return 0;
 
     face->isSymbolFont = false;
     face->gdef = 0;
@@ -961,6 +969,7 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
     face->tmpAttributes = 0;
     face->tmpLogClusters = 0;
     face->glyphs_substituted = false;
+    face->buffer = 0;
 
     HB_Error error;
     HB_Stream stream;
@@ -996,7 +1005,10 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
     for (unsigned int i = 0; i < HB_ScriptCount; ++i)
         face->supported_scripts[i] = checkScript(face, i);
 
-    hb_buffer_new(&face->buffer);
+    if (hb_buffer_new(&face->buffer) != HB_Err_Ok) {
+        HB_FreeFace(face);
+        return 0;
+    }
 
     return face;
 }
@@ -1116,6 +1128,8 @@ HB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *fe
 
 HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties)
 {
+    HB_GlyphAttributes *tmpAttributes;
+    unsigned int *tmpLogClusters;
 
     HB_Face face = item->face;
 
@@ -1123,8 +1137,16 @@ HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties)
 
     hb_buffer_clear(face->buffer);
 
-    face->tmpAttributes = (HB_GlyphAttributes *) realloc(face->tmpAttributes, face->length*sizeof(HB_GlyphAttributes));
-    face->tmpLogClusters = (unsigned int *) realloc(face->tmpLogClusters, face->length*sizeof(unsigned int));
+    tmpAttributes = (HB_GlyphAttributes *) realloc(face->tmpAttributes, face->length*sizeof(HB_GlyphAttributes));
+    if (!tmpAttributes)
+        return false;
+    face->tmpAttributes = tmpAttributes;
+
+    tmpLogClusters = (unsigned int *) realloc(face->tmpLogClusters, face->length*sizeof(unsigned int));
+    if (!tmpLogClusters)
+        return false;
+    face->tmpLogClusters = tmpLogClusters;
+
     for (int i = 0; i < face->length; ++i) {
         hb_buffer_add_glyph(face->buffer, item->glyphs[i], properties ? properties[i] : 0, i);
         face->tmpAttributes[i] = item->attributes[i];
diff --git a/src/harfbuzz-stream.c b/src/harfbuzz-stream.c
index 3dcee82..2d9638f 100644
--- a/src/harfbuzz-stream.c
+++ b/src/harfbuzz-stream.c
@@ -70,7 +70,7 @@ HB_INTERNAL HB_Error
 _hb_stream_seek( HB_Stream stream,
 		 HB_UInt pos )
 {
-  HB_Error  error = 0;
+  HB_Error  error = (HB_Error)0;
 
   stream->pos = pos;
   if (pos > stream->size)



More information about the HarfBuzz mailing list