Warning, file /multimedia/subtitlecomposer/src/tests/richdocumentlayouttest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2022 Mladen Milinkovic <max@smoothware.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "richdocumentlayouttest.h"
0008 
0009 #include "core/richtext/richdocument.h"
0010 #include "helpers/debug.h"
0011 
0012 #include <QDebug>
0013 #include <QString>
0014 #include <QTest>
0015 #include <QTextCharFormat>
0016 #include <QTextLayout>
0017 
0018 using namespace SubtitleComposer;
0019 
0020 RichDocumentLayoutTest::RichDocumentLayoutTest()
0021     : richLayout(new RichDocument(this))
0022 {
0023 }
0024 
0025 // format helper
0026 static QVector<QTextLayout::FormatRange>
0027 parseFormat(const QString &str, bool merged=false)
0028 {
0029     static QMap<QChar, QTextCharFormat> fmtMap;
0030     if(fmtMap.isEmpty()) {
0031         fmtMap[QChar(' ')] = QTextCharFormat();
0032         {
0033             QTextCharFormat d;
0034             d.setFontWeight(QFont::Bold);
0035             d.setFontItalic(false);
0036             d.setForeground(Qt::red);
0037             fmtMap[QChar('d')] = d;
0038         }
0039         {
0040             QTextCharFormat l;
0041             l.setFontWeight(QFont::Normal);
0042             l.setFontItalic(true);
0043             l.setForeground(Qt::green);
0044             fmtMap[QChar('l')] = l;
0045         }
0046         {
0047             QTextCharFormat m;
0048             m.setFontWeight(QFont::Bold);
0049             m.setFontItalic(true);
0050             m.setForeground(Qt::green);
0051             fmtMap[QChar('m')] = m;
0052         }
0053     };
0054 
0055     QVector<QTextLayout::FormatRange> fmts;
0056     int start = 0;
0057     int end = 1;
0058     for(;;) {
0059         if(str.length() <= end || str.at(start) != str.at(end)) {
0060             QTextCharFormat fmt = fmtMap[str.at(start)];
0061             if(!fmt.isEmpty()) {
0062                 if(merged)
0063                     fmt.setProperty(RichDocument::Merged, QTextCharFormat());
0064                 fmts.push_back(QTextLayout::FormatRange{start, end - start, fmt});
0065             }
0066             start = end;
0067         }
0068         if(str.length() <= end)
0069             break;
0070         end++;
0071     }
0072     return fmts;
0073 }
0074 
0075 // Qt's QTextCharFormat::operator==() fails if properties/styles are not it same order
0076 static bool
0077 compare(const QVector<QTextLayout::FormatRange> &lhs, const QVector<QTextLayout::FormatRange> &rhs)
0078 {
0079     if(lhs.size() != rhs.size())
0080         return false;
0081     for(int i = 0; i < lhs.size(); i++) {
0082         const QTextLayout::FormatRange &a = lhs.at(i);
0083         const QTextLayout::FormatRange &b = rhs.at(i);
0084         if(a.start != b.start || a.length != b.length)
0085             return false;
0086         const QMap<int, QVariant> &fa = a.format.properties();
0087         const QMap<int, QVariant> &fb = b.format.properties();
0088         for(auto it = fa.constBegin(); it != fa.constEnd(); ++it) {
0089             if(it.key() == RichDocument::Merged)
0090                 continue;
0091             const auto v = fb.find(it.key());
0092             if(v == fb.cend()) {
0093                 qDebug() << "rhs doesn't contain" << propertyName(QTextFormat::Property(it.key()));
0094                 return false;
0095             }
0096             if(it.value() != v.value()) {
0097                 qDebug() << "rhs mismatch" << propertyName(QTextFormat::Property(it.key())) << it.value() << "!=" << v.value();
0098                 return false;
0099             }
0100         }
0101     }
0102     return true;
0103 }
0104 
0105 void
0106 RichDocumentLayoutTest::testMerge_data()
0107 {
0108     QTest::addColumn<QString>("doc");
0109     QTest::addColumn<QString>("layout");
0110     QTest::addColumn<QString>("merged");
0111 
0112     QTest::newRow("test1")
0113             << "ddddd   ddddd"
0114             << "lllll   lllll"
0115             << "mmmmm   mmmmm";
0116     QTest::newRow("test2")
0117             << "ddddd   ddddd"
0118             << "  llllllll   "
0119             << "ddmmmlllmmddd";
0120     QTest::newRow("test3")
0121             << " dd d   ddd d"
0122             << "  llllllll   "
0123             << " dmlmlllmmd d";
0124     QTest::newRow("test4")
0125             << "  dddddddd   "
0126             << "lllll   lllll"
0127             << "llmmmdddmmlll";
0128     QTest::newRow("test5")
0129             << " ddd   ddd    "
0130             << "   lll   lll  "
0131             << " ddmll ddmll  ";
0132     QTest::newRow("test6")
0133             << "   ddd   ddd  "
0134             << " lll   lll    "
0135             << " llmdd llmdd  ";
0136     QTest::newRow("test7")
0137             << "ddddddddddddd"
0138             << "    llll     "
0139             << "ddddmmmmddddd";
0140 }
0141 
0142 void
0143 RichDocumentLayoutTest::testMerge()
0144 {
0145     QFETCH(QString, doc);
0146     QFETCH(QString, layout);
0147     QFETCH(QString, merged);
0148 
0149     QVector<QTextLayout::FormatRange> docFmts = parseFormat(doc);
0150     QVector<QTextLayout::FormatRange> layoutFmts = parseFormat(layout);
0151     QVector<QTextLayout::FormatRange> mergedFmts = parseFormat(merged, true);
0152     QVector<QTextLayout::FormatRange> res = richLayout.mergeCSS(docFmts, layoutFmts);
0153 
0154 //  qDebug().noquote() << dumpFormatRanges(merged, mergedFmts);
0155 //  qDebug().noquote() << dumpFormatRanges(merged, res);
0156     QVERIFY2(compare(res, mergedFmts), "Compared values are not the same");
0157 
0158     QVERIFY2(compare(richLayout.mergeCSS(docFmts, res), mergedFmts), "Compared values are not the same");
0159 }
0160 
0161 QTEST_MAIN(RichDocumentLayoutTest)