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/* 26 !!!!!! Warning !!!!! 27 Please don't save this file in emacs. It contains utf8 text sequences emacs will 28 silently convert to a series of question marks. 29 */ 30#include <QtTest/QtTest> 31#include <QtCore/qdebug.h> 32 33#include <harfbuzz-shaper.h> 34 35static QVector<HB_CharAttributes> getCharAttributes(const QString &str, HB_Script script = HB_Script_Common) 36{ 37 QVector<HB_CharAttributes> attrs(str.length()); 38 HB_ScriptItem item; 39 item.pos = 0; 40 item.length = str.length(); 41 item.script = script; 42 HB_GetCharAttributes(str.utf16(), str.length(), 43 &item, 1, 44 attrs.data()); 45 return attrs; 46} 47 48class tst_CharAttributes : public QObject 49{ 50 Q_OBJECT 51 52public: 53 tst_CharAttributes(); 54 virtual ~tst_CharAttributes(); 55 56public slots: 57 void init(); 58 void cleanup(); 59private slots: 60 void lineBreaking(); 61 void charWordStopOnLineSeparator(); 62 void charStopForSurrogatePairs(); 63 void thaiWordBreak(); 64}; 65 66 67tst_CharAttributes::tst_CharAttributes() 68{ 69} 70 71tst_CharAttributes::~tst_CharAttributes() 72{ 73} 74 75void tst_CharAttributes::init() 76{ 77} 78 79void tst_CharAttributes::cleanup() 80{ 81} 82 83 84void tst_CharAttributes::lineBreaking() 85{ 86 struct Breaks { 87 const char *utf8; 88 uchar breaks[32]; 89 }; 90 Breaks brks[] = { 91 { "11", { false, 0xff } }, 92 { "aa", { false, 0xff } }, 93 { "++", { false, 0xff } }, 94 { "--", { false, 0xff } }, 95 { "((", { false, 0xff } }, 96 { "))", { false, 0xff } }, 97 { "..", { false, 0xff } }, 98 { "\"\"", { false, 0xff } }, 99 { "$$", { false, 0xff } }, 100 { "!!", { false, 0xff } }, 101 { "??", { false, 0xff } }, 102 { ",,", { false, 0xff } }, 103 104 { ")()", { true, false, 0xff } }, 105 { "?!?", { false, false, 0xff } }, 106 { ".,.", { false, false, 0xff } }, 107 { "+-+", { false, false, 0xff } }, 108 { "+=+", { false, false, 0xff } }, 109 { "+(+", { false, false, 0xff } }, 110 { "+)+", { false, false, 0xff } }, 111 112 { "a b", { false, true, 0xff } }, 113 { "a(b", { false, false, 0xff } }, 114 { "a)b", { false, false, 0xff } }, 115 { "a-b", { false, true, 0xff } }, 116 { "a.b", { false, false, 0xff } }, 117 { "a+b", { false, false, 0xff } }, 118 { "a?b", { false, false, 0xff } }, 119 { "a!b", { false, false, 0xff } }, 120 { "a$b", { false, false, 0xff } }, 121 { "a,b", { false, false, 0xff } }, 122 { "a/b", { false, false, 0xff } }, 123 { "1/2", { false, false, 0xff } }, 124 { "./.", { false, false, 0xff } }, 125 { ",/,", { false, false, 0xff } }, 126 { "!/!", { false, false, 0xff } }, 127 { "\\/\\", { false, false, 0xff } }, 128 { "1 2", { false, true, 0xff } }, 129 { "1(2", { false, false, 0xff } }, 130 { "1)2", { false, false, 0xff } }, 131 { "1-2", { false, false, 0xff } }, 132 { "1.2", { false, false, 0xff } }, 133 { "1+2", { false, false, 0xff } }, 134 { "1?2", { false, true, 0xff } }, 135 { "1!2", { false, true, 0xff } }, 136 { "1$2", { false, false, 0xff } }, 137 { "1,2", { false, false, 0xff } }, 138 { "1/2", { false, false, 0xff } }, 139 { "\330\260\331\216\331\204\331\220\331\203\331\216", { false, false, false, false, false, 0xff } }, 140 { "\330\247\331\204\331\205 \330\247\331\204\331\205", { false, false, false, true, false, false, 0xff } }, 141 { "1#2", { false, false, 0xff } }, 142 { "!#!", { false, false, 0xff } }, 143 { 0, {} } 144 }; 145 Breaks *b = brks; 146 while (b->utf8) { 147 QString str = QString::fromUtf8(b->utf8); 148 149 QVector<HB_CharAttributes> attrs = getCharAttributes(str); 150 151 int i; 152 for (i = 0; i < (int)str.length() - 1; ++i) { 153 QVERIFY(b->breaks[i] != 0xff); 154 if ( (attrs[i].lineBreakType != HB_NoBreak) != (bool)b->breaks[i] ) { 155 qDebug("test case \"%s\" failed at char %d; break type: %d", b->utf8, i, attrs[i].lineBreakType); 156 QCOMPARE( (attrs[i].lineBreakType != HB_NoBreak), (bool)b->breaks[i] ); 157 } 158 } 159 QVERIFY(attrs[i].lineBreakType == HB_ForcedBreak); 160 QCOMPARE(b->breaks[i], (uchar)0xff); 161 ++b; 162 } 163} 164 165void tst_CharAttributes::charWordStopOnLineSeparator() 166{ 167 const QChar lineSeparator(QChar::LineSeparator); 168 QString txt; 169 txt.append(lineSeparator); 170 txt.append(lineSeparator); 171 QVector<HB_CharAttributes> attrs = getCharAttributes(txt); 172 QVERIFY(attrs[1].charStop); 173} 174 175void tst_CharAttributes::charStopForSurrogatePairs() 176{ 177 QString txt; 178 txt.append("a"); 179 txt.append(0xd87e); 180 txt.append(0xdc25); 181 txt.append("b"); 182 QVector<HB_CharAttributes> attrs = getCharAttributes(txt); 183 QVERIFY(attrs[0].charStop); 184 QVERIFY(attrs[1].charStop); 185 QVERIFY(!attrs[2].charStop); 186 QVERIFY(attrs[3].charStop); 187} 188 189void tst_CharAttributes::thaiWordBreak() 190{ 191 // สวัสà¸à¸µà¸à¸£à¸±à¸ à¸à¸µà¹à¹à¸à¹à¸à¸à¸²à¸£à¸à¸à¸à¸ªà¸à¸à¸à¸±à¸§à¹à¸ 192 QTextCodec *codec = QTextCodec::codecForMib(2259); 193 QString txt = codec->toUnicode(QByteArray("\xca\xc7\xd1\xca\xb4\xd5\xa4\xc3\xd1\xba\x20\xb9\xd5\xe8\xe0\xbb\xe7\xb9\xa1\xd2\xc3\xb7\xb4\xca\xcd\xba\xb5\xd1\xc7\xe0\xcd\xa7")); 194 195 196 QCOMPARE(txt.length(), 32); 197 QVector<HB_CharAttributes> attrs = getCharAttributes(txt, HB_Script_Thai); 198 QVERIFY(attrs[0].lineBreakType == HB_NoBreak); 199 QVERIFY(attrs[1].lineBreakType == HB_NoBreak); 200 QVERIFY(attrs[2].lineBreakType == HB_NoBreak); 201 QVERIFY(attrs[3].lineBreakType == HB_NoBreak); 202 QVERIFY(attrs[4].lineBreakType == HB_NoBreak); 203 QVERIFY(attrs[5].lineBreakType == HB_Break); 204 QVERIFY(attrs[6].lineBreakType == HB_NoBreak); 205 QVERIFY(attrs[7].lineBreakType == HB_NoBreak); 206 QVERIFY(attrs[8].lineBreakType == HB_NoBreak); 207 QVERIFY(attrs[9].lineBreakType == HB_NoBreak); 208 QVERIFY(attrs[10].lineBreakType == HB_Break); 209 QVERIFY(attrs[11].lineBreakType == HB_NoBreak); 210 QVERIFY(attrs[12].lineBreakType == HB_NoBreak); 211 QVERIFY(attrs[13].lineBreakType == HB_Break); 212 QVERIFY(attrs[14].lineBreakType == HB_NoBreak); 213 QVERIFY(attrs[15].lineBreakType == HB_NoBreak); 214 QVERIFY(attrs[16].lineBreakType == HB_NoBreak); 215 QVERIFY(attrs[17].lineBreakType == HB_Break); 216 QVERIFY(attrs[18].lineBreakType == HB_NoBreak); 217 QVERIFY(attrs[19].lineBreakType == HB_NoBreak); 218 QVERIFY(attrs[20].lineBreakType == HB_Break); 219 QVERIFY(attrs[21].lineBreakType == HB_NoBreak); 220 QVERIFY(attrs[22].lineBreakType == HB_NoBreak); 221 QVERIFY(attrs[23].lineBreakType == HB_NoBreak); 222 QVERIFY(attrs[24].lineBreakType == HB_NoBreak); 223 QVERIFY(attrs[25].lineBreakType == HB_Break); 224 QVERIFY(attrs[26].lineBreakType == HB_NoBreak); 225 for (int i = 27; i < 32; ++i) 226 QVERIFY(attrs[i].lineBreakType == HB_NoBreak); 227} 228 229QTEST_MAIN(tst_CharAttributes) 230#include "main.moc" 231