tests/manual/textrendering/glyphshaping/main.cpp
changeset 3 41300fa6a67c
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtGui>
       
    43 
       
    44 static const int fontPixelSize = 25;
       
    45 static const QLatin1String fontFamily("Series 60 Sans");
       
    46 
       
    47 struct testDataSet
       
    48 {
       
    49     QString language;
       
    50     QString name;
       
    51     QString input;
       
    52     QString inputOriginal;
       
    53     QString output;
       
    54     QString outputOriginal;
       
    55     QVector<uint> outputGlyphIDs;
       
    56     QString outputGlyphIDsOriginal;
       
    57 };
       
    58 
       
    59 QString charHexCsv2String(const QString &csv)
       
    60 {
       
    61     QString result;
       
    62     foreach (const QString &charString, csv.split(QLatin1Char(','), QString::SkipEmptyParts)) {
       
    63         bool isOk;
       
    64         const uint charUInt = charString.toUInt(&isOk, 16);
       
    65         Q_ASSERT(isOk);
       
    66         const int size = charUInt >= SHRT_MAX ? 2:1;
       
    67         result.append(QString::fromUtf16((const ushort*)&charUInt, size));
       
    68     }
       
    69     return result;
       
    70 }
       
    71 
       
    72 QList<testDataSet> testDataSetList()
       
    73 {
       
    74     QList<testDataSet> result;
       
    75     QFile file("glyphshaping_data.xml");
       
    76     const bool success = file.open(QIODevice::ReadOnly);
       
    77     Q_ASSERT(success);
       
    78 
       
    79     const QLatin1String language("language");
       
    80     const QLatin1String test("test");
       
    81     const QLatin1String inputUtf16("inpututf16");
       
    82     const QLatin1String outputUtf16("outpututf16");
       
    83     const QLatin1String outputGlyphIDs("outputglyphids");
       
    84     const QLatin1String name("name");
       
    85 
       
    86     QString languageName;
       
    87 
       
    88     QXmlStreamReader reader(&file);
       
    89     while (!reader.atEnd()) {
       
    90         const QXmlStreamReader::TokenType token = reader.readNext();
       
    91         switch (token) {
       
    92         case QXmlStreamReader::StartElement:
       
    93             if (reader.name() == language) {
       
    94                 Q_ASSERT(reader.attributes().hasAttribute(name));
       
    95                 languageName = reader.attributes().value(name).toString();
       
    96             } else if (reader.name() == test) {
       
    97                 if (!reader.attributes().hasAttribute(outputUtf16)
       
    98                     && !reader.attributes().hasAttribute(outputGlyphIDs))
       
    99                     continue;
       
   100                 Q_ASSERT(!languageName.isEmpty());
       
   101                 Q_ASSERT(reader.attributes().hasAttribute(name));
       
   102                 Q_ASSERT(reader.attributes().hasAttribute(inputUtf16));
       
   103                 testDataSet set;
       
   104                 set.language = languageName;
       
   105                 set.name = reader.attributes().value(name).toString();
       
   106                 set.inputOriginal = reader.attributes().value(inputUtf16).toString();
       
   107                 set.input = charHexCsv2String(set.inputOriginal);
       
   108                 set.outputOriginal = reader.attributes().value(outputUtf16).toString();
       
   109                 set.output = charHexCsv2String(set.outputOriginal);
       
   110                 set.outputGlyphIDsOriginal = reader.attributes().value(outputGlyphIDs).toString();
       
   111                 result.append(set);
       
   112             }
       
   113             break;
       
   114         default:
       
   115             break;
       
   116         }
       
   117     }
       
   118     return result;
       
   119 }
       
   120 
       
   121 QImage renderedText(const QString &text, const QFont &font)
       
   122 {
       
   123     const QFontMetrics metrics(font);
       
   124     const QRect boundingRect = metrics.boundingRect(text);
       
   125     QImage result(boundingRect.size(), QImage::Format_ARGB32);
       
   126     result.fill(0);
       
   127 
       
   128     QPainter p(&result);
       
   129     p.setFont(font);
       
   130     p.drawText(boundingRect.translated(-boundingRect.topLeft()), text);
       
   131 
       
   132     return result;
       
   133 }
       
   134 
       
   135 QString dumpImageHtml(const QString &text, const QString &pathName)
       
   136 {
       
   137     if (text.isEmpty())
       
   138         return QLatin1String("<td/>");
       
   139     QFont font(fontFamily);
       
   140     font.setPixelSize(fontPixelSize);
       
   141     const QImage textImage = renderedText(text, font);
       
   142     const QString imageFileName =
       
   143             (pathName + QDir::separator() + QLatin1String("%1.png"))
       
   144             .arg(textImage.cacheKey());
       
   145     const bool success = textImage.save(imageFileName);
       
   146     Q_ASSERT(success);
       
   147     return
       
   148         QString::fromLatin1("<td title=\"%2\"><img src=\"%1\" alt=\"%2\" width=\"%3\" height=\"%4\"/></td>")
       
   149         .arg(QDir::cleanPath(imageFileName)).arg(text).arg(textImage.width()).arg(textImage.height());
       
   150 }
       
   151 
       
   152 QString dlItem(const QString &dt, const QString &dd)
       
   153 {
       
   154     if (!dd.trimmed().isEmpty())
       
   155         return QString::fromLatin1("\t\t\t\t\t\t<dt>%1</dt><dd>%2</dd>\n").arg(dt).arg(dd);
       
   156     return QString();
       
   157 }
       
   158 
       
   159 bool dumpHtml(const QString &pathName)
       
   160 {
       
   161     QFile htmlPage(pathName + QDir::separator() + QLatin1String("index.html"));
       
   162     if (!htmlPage.open(QFile::WriteOnly))
       
   163         return false;
       
   164 
       
   165     QString platformName = QString::fromLatin1(
       
   166 #if defined(Q_OS_WIN)
       
   167             "Win32"
       
   168 #elif defined(Q_WS_X11)
       
   169             "X11"
       
   170 #elif defined(Q_OS_SYMBIAN)
       
   171             "Symbian"
       
   172 #else
       
   173             ""
       
   174 #endif
       
   175     );
       
   176 
       
   177     QString result = QString::fromLatin1(
       
   178             "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
       
   179             " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
       
   180             "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
       
   181             "\t<head>\n"
       
   182             "\t\t<title>Qt on %1 glyph shaping (%2)</title>\n"
       
   183             "\t\t<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\" />\n"
       
   184             "\t\t<style type=\"text/css\" media=\"screen\">\n"
       
   185             "\t\t\ttable { font-family: Arial; background-color: #ccccff; font-size: 12pt; }\n"
       
   186             "\t\t\ttd { font-family:\"%2\"; background-color: #eeeeee; font-size: %3px; }\n"
       
   187             "\t\t\tth { font-weight:normal; }\n"
       
   188             "\t\t\tdl { font-family: Arial; font-size: 8pt; margin: 3px; }\n"
       
   189             "\t\t\tdt { font-weight: bold; float: left; }\n"
       
   190             "\t\t\ttr:hover { background-color: #ddddff; }\n"
       
   191             "\t\t\ttd:hover { background-color: #ddddff; }\n"
       
   192             "\t\t</style>\n"
       
   193             "\t</head>\n"
       
   194             "\t<body>\n"
       
   195             "\t\t<h1>Qt on %1 glyph shaping (%2)</h1>\n"
       
   196             "\t\t<dl>\n"
       
   197             "\t\t\t<dt>I</dt><dd>Input Utf-16 to shaper</dd>\n"
       
   198             "\t\t\t<dt>O-Utf</dt><dd>expected output Utf-16</dd>\n"
       
   199             "\t\t\t<dt>O-ID</dt><dd>expected output Glyph IDs for \"Series 60 Sans\"</dd>\n"
       
   200             "\t\t</dl>\n"
       
   201             "\t\t<table>\n"
       
   202             ).arg(platformName).arg(fontFamily).arg(fontPixelSize);
       
   203 
       
   204     QString languageName;
       
   205     foreach (const testDataSet &dataSet, testDataSetList()) {
       
   206         if (languageName != dataSet.language) {
       
   207             result.append(QString::fromLatin1(
       
   208                     "\t\t\t<tr>\n"
       
   209                     "\t\t\t\t<th rowspan=\"2\"><h2>%1</h2></th>\n"
       
   210                     "\t\t\t\t<th colspan=\"2\">Qt/%2</th>\n"
       
   211                     "\t\t\t\t<th rowspan=\"2\">Glyphs</th>\n"
       
   212                     "\t\t\t\t<th colspan=\"2\">Browser</th>\n"
       
   213                     "\t\t\t</tr>\n"
       
   214                     "\t\t\t<tr>\n"
       
   215                     "\t\t\t\t<th>In</th>\n"
       
   216                     "\t\t\t\t<th>Out</th>\n"
       
   217                     "\t\t\t\t<th>In</th>\n"
       
   218                     "\t\t\t\t<th>Out</th>\n"
       
   219                     "\t\t\t</tr>\n"
       
   220                     ).arg(dataSet.language).arg(platformName));
       
   221             languageName = dataSet.language;
       
   222         }
       
   223         QString glyphsData;
       
   224         if (!dataSet.inputOriginal.isEmpty())
       
   225             glyphsData.append(dlItem(QLatin1String("I"), dataSet.inputOriginal));
       
   226         if (!dataSet.outputOriginal.isEmpty())
       
   227             glyphsData.append(dlItem(QLatin1String("O-Utf"), dataSet.outputOriginal));
       
   228         if (!dataSet.outputGlyphIDsOriginal.isEmpty())
       
   229             glyphsData.append(dlItem(QLatin1String("O-ID"), dataSet.outputGlyphIDsOriginal));
       
   230         if (!glyphsData.isEmpty()) {
       
   231             glyphsData.prepend(QLatin1String("\t\t\t\t\t<dl>\n"));
       
   232             glyphsData.append(QLatin1String("\t\t\t\t\t</dl>\n"));
       
   233         }
       
   234         result.append(QString::fromLatin1(
       
   235                 "\t\t\t<tr>\n"
       
   236                 "\t\t\t\t<th>%1</th>\n"
       
   237                 "\t\t\t\t%2\n"
       
   238                 "\t\t\t\t%3\n"
       
   239                 "\t\t\t\t<td>\n"
       
   240                 "%4"
       
   241                 "\t\t\t\t</td>\n"
       
   242                 "\t\t\t\t<td>%5</td>\n"
       
   243                 "\t\t\t\t<td>%6</td>\n"
       
   244                 "\t\t\t</tr>\n"
       
   245                 ).arg(dataSet.name)
       
   246                 .arg(dumpImageHtml(dataSet.input, pathName))
       
   247                 .arg(dumpImageHtml(dataSet.output, pathName))
       
   248                 .arg(glyphsData)
       
   249                 .arg(dataSet.input)
       
   250                 .arg(dataSet.output)
       
   251         );
       
   252     }
       
   253 
       
   254     result.append(QString::fromLatin1(
       
   255             "\t\t</table>\n"
       
   256             "\t</body>\n"
       
   257             "</html>")
       
   258     );
       
   259 
       
   260     htmlPage.write(result.toUtf8());
       
   261 
       
   262     return true;
       
   263 }
       
   264 
       
   265 int main(int argc, char *argv[])
       
   266 {
       
   267     QApplication a(argc, argv);
       
   268     return dumpHtml(QLatin1String(".")) ? 0 : 1;
       
   269 }