// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include #include #include #include #include #include #include #include #include static const int fontPixelSize = 25; static const QLatin1String fontFamily("Series 60 Sans"); struct testDataSet { QString language; QString name; QString input; QString inputOriginal; QString output; QString outputOriginal; QList outputGlyphIDs; QString outputGlyphIDsOriginal; }; QString charHexCsv2String(const QString &csv) { QString result; foreach (const QString &charString, csv.split(QLatin1Char(','), Qt::SkipEmptyParts)) { bool isOk; const uint charUInt = charString.toUInt(&isOk, 16); Q_ASSERT(isOk); const int size = charUInt >= SHRT_MAX ? 2:1; result.append(QString::fromUtf16((const ushort*)&charUInt, size)); } return result; } QList testDataSetList() { QList result; QFile file("glyphshaping_data.xml"); const bool success = file.open(QIODevice::ReadOnly); Q_ASSERT(success); const QLatin1String language("language"); const QLatin1String test("test"); const QLatin1String inputUtf16("inpututf16"); const QLatin1String outputUtf16("outpututf16"); const QLatin1String outputGlyphIDs("outputglyphids"); const QLatin1String name("name"); QString languageName; QXmlStreamReader reader(&file); while (!reader.atEnd()) { const QXmlStreamReader::TokenType token = reader.readNext(); switch (token) { case QXmlStreamReader::StartElement: if (reader.name() == language) { Q_ASSERT(reader.attributes().hasAttribute(name)); languageName = reader.attributes().value(name).toString(); } else if (reader.name() == test) { if (!reader.attributes().hasAttribute(outputUtf16) && !reader.attributes().hasAttribute(outputGlyphIDs)) continue; Q_ASSERT(!languageName.isEmpty()); Q_ASSERT(reader.attributes().hasAttribute(name)); Q_ASSERT(reader.attributes().hasAttribute(inputUtf16)); testDataSet set; set.language = languageName; set.name = reader.attributes().value(name).toString(); set.inputOriginal = reader.attributes().value(inputUtf16).toString(); set.input = charHexCsv2String(set.inputOriginal); set.outputOriginal = reader.attributes().value(outputUtf16).toString(); set.output = charHexCsv2String(set.outputOriginal); set.outputGlyphIDsOriginal = reader.attributes().value(outputGlyphIDs).toString(); result.append(set); } break; default: break; } } return result; } QImage renderedText(const QString &text, const QFont &font) { const QFontMetrics metrics(font); const QRect boundingRect = metrics.boundingRect(text); QImage result(boundingRect.size(), QImage::Format_ARGB32); result.fill(0); QPainter p(&result); p.setFont(font); p.drawText(boundingRect.translated(-boundingRect.topLeft()), text); return result; } QString dumpImageHtml(const QString &text, const QString &pathName) { if (text.isEmpty()) return QLatin1String(""); QFont font(fontFamily); font.setPixelSize(fontPixelSize); const QImage textImage = renderedText(text, font); const QString imageFileName = (pathName + QDir::separator() + QLatin1String("%1.png")) .arg(textImage.cacheKey()); const bool success = textImage.save(imageFileName); Q_ASSERT(success); return QString::fromLatin1("\"%2\"") .arg(QDir::cleanPath(imageFileName)).arg(text).arg(textImage.width()).arg(textImage.height()); } QString dlItem(const QString &dt, const QString &dd) { if (!dd.trimmed().isEmpty()) return QString::fromLatin1("\t\t\t\t\t\t
%1
%2
\n").arg(dt).arg(dd); return QString(); } bool dumpHtml(const QString &pathName) { QFile htmlPage(pathName + QDir::separator() + QLatin1String("index.html")); if (!htmlPage.open(QFile::WriteOnly)) return false; QString platformName = QString::fromLatin1( #if defined(Q_OS_WIN) "Win32" #else "" #endif ); QString result = QString::fromLatin1( "\n\n" "\n" "\t\n" "\t\tQt on %1 glyph shaping (%2)\n" "\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\t

Qt on %1 glyph shaping (%2)

\n" "\t\t
\n" "\t\t\t
I
Input Utf-16 to shaper
\n" "\t\t\t
O-Utf
expected output Utf-16
\n" "\t\t\t
O-ID
expected output Glyph IDs for \"Series 60 Sans\"
\n" "\t\t
\n" "\t\t\n" ).arg(platformName).arg(fontFamily).arg(fontPixelSize); QString languageName; foreach (const testDataSet &dataSet, testDataSetList()) { if (languageName != dataSet.language) { result.append(QString::fromLatin1( "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" ).arg(dataSet.language).arg(platformName)); languageName = dataSet.language; } QString glyphsData; if (!dataSet.inputOriginal.isEmpty()) glyphsData.append(dlItem(QLatin1String("I"), dataSet.inputOriginal)); if (!dataSet.outputOriginal.isEmpty()) glyphsData.append(dlItem(QLatin1String("O-Utf"), dataSet.outputOriginal)); if (!dataSet.outputGlyphIDsOriginal.isEmpty()) glyphsData.append(dlItem(QLatin1String("O-ID"), dataSet.outputGlyphIDsOriginal)); if (!glyphsData.isEmpty()) { glyphsData.prepend(QLatin1String("\t\t\t\t\t
\n")); glyphsData.append(QLatin1String("\t\t\t\t\t
\n")); } result.append(QString::fromLatin1( "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%2\n" "\t\t\t\t%3\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" ).arg(dataSet.name) .arg(dumpImageHtml(dataSet.input, pathName)) .arg(dumpImageHtml(dataSet.output, pathName)) .arg(glyphsData) .arg(dataSet.input) .arg(dataSet.output) ); } result.append(QString::fromLatin1( "\t\t

%1

Qt/%2GlyphsBrowser
InOutInOut
%1\n" "%4" "\t\t\t\t%5%6
\n" "\t\n" "") ); htmlPage.write(result.toUtf8()); return true; } int main(int argc, char *argv[]) { QApplication a(argc, argv); return dumpHtml(QLatin1String(".")) ? 0 : 1; }