diff options
57 files changed, 2526 insertions, 402 deletions
diff --git a/doc/src/declarative/qdeclarativemodels.qdoc b/doc/src/declarative/qdeclarativemodels.qdoc index c0e028e..f7d1a73 100644 --- a/doc/src/declarative/qdeclarativemodels.qdoc +++ b/doc/src/declarative/qdeclarativemodels.qdoc @@ -208,7 +208,7 @@ QStringList provides the contents of the list via the \e modelData role: QStringList dataList; dataList.append("Fred"); dataList.append("Ginger"); -dataList.appenf("Skipper"); +dataList.append("Skipper"); QDeclarativeContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(&dataList)); diff --git a/doc/src/examples/svgalib.qdoc b/doc/src/examples/svgalib.qdoc index cf6512c..9142112 100644 --- a/doc/src/examples/svgalib.qdoc +++ b/doc/src/examples/svgalib.qdoc @@ -43,9 +43,6 @@ \example qws/svgalib \title Accelerated Graphics Driver Example - \warning This example was designed to work with Qt 4.4 and will not work - with current versions of Qt. It will be removed from Qt 4.7. - The Accelerated Graphics Driver example shows how you can write your own accelerated graphics driver and \l {add your graphics driver to Qt for Embedded Linux}. In \l{Qt for Embedded Linux}, diff --git a/examples/qws/svgalib/README b/examples/qws/svgalib/README index 0b2831f..227c066 100644 --- a/examples/qws/svgalib/README +++ b/examples/qws/svgalib/README @@ -1,5 +1,9 @@ -This is the SVGA screen driver plugin example from Qt 4.4. The code does -not compile with Qt 4.5, because the internal graphics engine has changed. +This is the SVGA screen driver plugin example for QWS. -This is unsupported code, provided for convenience in case there is -interest in porting it to Qt 4.5. +You may need to set the SVGALIB_DEFAULT_MODE environment +variable. These values have been confirmed to work on one specific +machine using svgalib 1.4.3: 18, 24, 34, 35, 36 + +There is a bug in the example causing missing updates in 8-bit mode +(e.g. modes 10 and 12). Fixing this bug is left as an exercise for the +reader. diff --git a/examples/qws/svgalib/svgalibpaintdevice.cpp b/examples/qws/svgalib/svgalibpaintdevice.cpp index 090311f..86613d2 100644 --- a/examples/qws/svgalib/svgalibpaintdevice.cpp +++ b/examples/qws/svgalib/svgalibpaintdevice.cpp @@ -48,7 +48,7 @@ SvgalibPaintDevice::SvgalibPaintDevice(QWidget *w) : QCustomRasterPaintDevice(w) { - pengine = new SvgalibPaintEngine; + pengine = new SvgalibPaintEngine(this); } SvgalibPaintDevice::~SvgalibPaintDevice() diff --git a/examples/qws/svgalib/svgalibpaintengine.cpp b/examples/qws/svgalib/svgalibpaintengine.cpp index 8713863..59740da 100644 --- a/examples/qws/svgalib/svgalibpaintengine.cpp +++ b/examples/qws/svgalib/svgalibpaintengine.cpp @@ -45,7 +45,8 @@ #include <vga.h> #include <vgagl.h> -SvgalibPaintEngine::SvgalibPaintEngine() +SvgalibPaintEngine::SvgalibPaintEngine(QPaintDevice *device) + : QRasterPaintEngine(device) { } @@ -61,7 +62,7 @@ bool SvgalibPaintEngine::begin(QPaintDevice *dev) simplePen = true; brush = Qt::NoBrush; simpleBrush = true; - matrix = QMatrix(); + matrix = QTransform(); simpleMatrix = true; setClip(QRect(0, 0, device->width(), device->height())); opaque = true; @@ -81,54 +82,52 @@ bool SvgalibPaintEngine::end() //! [1] //! [2] -void SvgalibPaintEngine::updateState(const QPaintEngineState &state) +void SvgalibPaintEngine::updateState() { - QPaintEngine::DirtyFlags flags = state.state(); + QRasterPaintEngineState *s = state(); - if (flags & DirtyTransform) { - matrix = state.matrix(); + if (s->dirty & DirtyTransform) { + matrix = s->matrix; simpleMatrix = (matrix.m12() == 0 && matrix.m21() == 0); } - if (flags & DirtyPen) { - pen = state.pen(); + if (s->dirty & DirtyPen) { + pen = s->pen; simplePen = (pen.width() == 0 || pen.widthF() <= 1) && (pen.style() == Qt::NoPen || pen.style() == Qt::SolidLine) && (pen.color().alpha() == 255); } - if (flags & DirtyBrush) { - brush = state.brush(); + if (s->dirty & DirtyBrush) { + brush = s->brush; simpleBrush = (brush.style() == Qt::SolidPattern || brush.style() == Qt::NoBrush) && (brush.color().alpha() == 255); } - if (flags & DirtyClipRegion) - setClip(state.clipRegion()); + if (s->dirty & DirtyClipRegion) + setClip(s->clipRegion); - if (flags & DirtyClipEnabled) { - clipEnabled = state.isClipEnabled(); + if (s->dirty & DirtyClipEnabled) { + clipEnabled = s->isClipEnabled(); updateClip(); } - if (flags & DirtyClipPath) { + if (s->dirty & DirtyClipPath) { setClip(QRegion()); simpleClip = false; } - if (flags & DirtyCompositionMode) { - const QPainter::CompositionMode m = state.compositionMode(); + if (s->dirty & DirtyCompositionMode) { + const QPainter::CompositionMode m = s->composition_mode; sourceOver = (m == QPainter::CompositionMode_SourceOver); } - if (flags & DirtyOpacity) - opaque = (state.opacity() == 256); + if (s->dirty & DirtyOpacity) + opaque = (s->opacity == 256); - if (flags & DirtyHints) - aliased = !(state.renderHints() & QPainter::Antialiasing); - - QRasterPaintEngine::updateState(state); + if (s->dirty & DirtyHints) + aliased = !(s->flags.antialiased); } //! [2] diff --git a/examples/qws/svgalib/svgalibpaintengine.h b/examples/qws/svgalib/svgalibpaintengine.h index f43d201..27b77ee 100644 --- a/examples/qws/svgalib/svgalibpaintengine.h +++ b/examples/qws/svgalib/svgalibpaintengine.h @@ -48,12 +48,12 @@ class SvgalibPaintEngine : public QRasterPaintEngine { public: - SvgalibPaintEngine(); + SvgalibPaintEngine(QPaintDevice *device); ~SvgalibPaintEngine(); bool begin(QPaintDevice *device); bool end(); - void updateState(const QPaintEngineState &state); + void updateState(); void drawRects(const QRect *rects, int rectCount); private: @@ -64,7 +64,7 @@ private: bool simplePen; QBrush brush; bool simpleBrush; - QMatrix matrix; + QTransform matrix; bool simpleMatrix; QRegion clip; bool clipEnabled; diff --git a/src/corelib/codecs/codecs.pri b/src/corelib/codecs/codecs.pri index 17f4d91..c572e08 100644 --- a/src/corelib/codecs/codecs.pri +++ b/src/corelib/codecs/codecs.pri @@ -31,7 +31,7 @@ unix { DEFINES += GNU_LIBICONV !mac:LIBS_PRIVATE *= -liconv - } else { + } else:!symbian { # no iconv, so we put all plugins in the library HEADERS += \ ../plugins/codecs/cn/qgb18030codec.h \ @@ -52,3 +52,4 @@ unix { ../plugins/codecs/jp/qfontjpcodec.cpp } } +symbian:LIBS += -lcharconv diff --git a/src/corelib/codecs/qsimplecodec.cpp b/src/corelib/codecs/qsimplecodec.cpp index 4cc7912..a6f5c9e 100644 --- a/src/corelib/codecs/qsimplecodec.cpp +++ b/src/corelib/codecs/qsimplecodec.cpp @@ -54,6 +54,7 @@ static const struct { int mib; quint16 values[128]; } unicodevalues[QSimpleTextCodec::numSimpleCodecs] = { +#ifndef Q_OS_SYMBIAN // from RFC 1489, ftp://ftp.isi.edu/in-notes/rfc1489.txt { "KOI8-R", { "csKOI8R", 0 }, 2084, { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, @@ -288,6 +289,7 @@ static const struct { 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF} }, +#endif { "ISO-8859-16", { "iso-ir-226", "latin10", 0 }, 112, { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, @@ -309,7 +311,7 @@ static const struct { // next bits generated again from tables on the Unicode 3.0 CD. // $ for a in CP* ; do (awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a) | sort | sed -e 's/#UNDEF.*$/0xFFFD/' | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done - +#ifndef Q_OS_SYMBIAN { "IBM850", { "CP850", "csPC850Multilingual", 0 }, 2009, { 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, @@ -344,6 +346,7 @@ static const struct { 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, +#endif //Q_OS_SYMBIAN { "IBM866", { "CP866", "csIBM866", 0 }, 2086, { 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, @@ -362,6 +365,7 @@ static const struct { 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0} }, +#ifndef Q_OS_SYMBIAN { "windows-1250", { "CP1250", 0 }, 2250, { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, 0xFFFD, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, @@ -516,6 +520,7 @@ static const struct { 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF} }, +#endif { "Apple Roman", { "macintosh", "MacRoman", 0 }, -168, { 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, @@ -534,8 +539,6 @@ static const struct { 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7} }, - - // This one is based on the charmap file // /usr/share/i18n/charmaps/SAMI-WS2.gz, which is manually adapted // to this format by Boerre Gaup <boerre@subdimension.com> @@ -557,7 +560,7 @@ static const struct { 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, - +#ifndef Q_OS_SYMBIAN // this one is generated from the charmap file located in /usr/share/i18n/charmaps // on most Linux distributions. The thai character set tis620 is byte by byte equivalent // to iso8859-11, so we name it 8859-11 here, but recognise the name tis620 too. @@ -581,6 +584,7 @@ static const struct { 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD } }, +#endif /* Name: hp-roman8 [HP-PCL5,RFC1345,KXS2] MIBenum: 2004 diff --git a/src/corelib/codecs/qsimplecodec_p.h b/src/corelib/codecs/qsimplecodec_p.h index b53eb95..57503b2 100644 --- a/src/corelib/codecs/qsimplecodec_p.h +++ b/src/corelib/codecs/qsimplecodec_p.h @@ -64,7 +64,11 @@ template <typename T> class QAtomicPointer; class QSimpleTextCodec: public QTextCodec { public: +#ifdef Q_OS_SYMBIAN + enum { numSimpleCodecs = 5 }; +#else enum { numSimpleCodecs = 30 }; +#endif explicit QSimpleTextCodec(int); ~QSimpleTextCodec(); diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index ca5e658..4034218 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -64,6 +64,7 @@ #ifndef QT_NO_CODECS # include "qtsciicodec_p.h" # include "qisciicodec_p.h" +#ifndef Q_OS_SYMBIAN # if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED) // no iconv(3) support, must build all codecs into the library # include "../../plugins/codecs/cn/qgb18030codec.h" @@ -77,6 +78,7 @@ # include "qfontlaocodec_p.h" # include "../../plugins/codecs/jp/qfontjpcodec.h" # endif +#endif // QT_NO_SYMBIAN #endif // QT_NO_CODECS #include "qlocale.h" #include "qmutex.h" @@ -93,6 +95,11 @@ # define QT_NO_SETLOCALE #endif +#ifdef Q_OS_SYMBIAN +#include "qtextcodec_symbian.cpp" +#endif + + // enabling this is not exception safe! // #define Q_DEBUG_TEXTCODEC @@ -537,6 +544,12 @@ static QTextCodec *checkForCodec(const QByteArray &name) { */ static void setupLocaleMapper() { +#ifdef Q_OS_SYMBIAN + localeMapper = QSymbianTextCodec::localeMapper; + if (localeMapper) + return; +#endif + #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) localeMapper = QTextCodec::codecForName("System"); #else @@ -680,6 +693,17 @@ static void setup() (void) createQTextCodecCleanup(); #ifndef QT_NO_CODECS + (void)new QTsciiCodec; + for (int i = 0; i < 9; ++i) + (void)new QIsciiCodec(i); + + for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i) + (void)new QSimpleTextCodec(i); + +#ifdef Q_OS_SYMBIAN + localeMapper = QSymbianTextCodec::init(); +#endif + # if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED) // no font codecs when bootstrapping (void)new QFontLaoCodec; @@ -696,12 +720,8 @@ static void setup() # endif // QT_NO_ICONV && !QT_BOOTSTRAPPED # endif // Q_WS_X11 - (void)new QTsciiCodec; - - for (int i = 0; i < 9; ++i) - (void)new QIsciiCodec(i); - +#ifndef Q_OS_SYMBIAN # if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED) // no asian codecs when bootstrapping, sorry (void)new QGb18030Codec; @@ -715,6 +735,7 @@ static void setup() (void)new QBig5Codec; (void)new QBig5hkscsCodec; # endif // QT_NO_ICONV && !QT_BOOTSTRAPPED +#endif //Q_OS_SYMBIAN #endif // QT_NO_CODECS #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) @@ -727,17 +748,18 @@ static void setup() (void)new QUtf32Codec; (void)new QUtf32BECodec; (void)new QUtf32LECodec; +#ifndef Q_OS_SYMBIAN (void)new QLatin15Codec; +#endif (void)new QLatin1Codec; (void)new QUtf8Codec; - for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i) - (void)new QSimpleTextCodec(i); - +#ifndef Q_OS_SYMBIAN #if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED) // QIconvCodec depends on the UTF-16 codec, so it needs to be created last (void) new QIconvCodec(); #endif +#endif if (!localeMapper) setupLocaleMapper(); @@ -1124,6 +1146,9 @@ QList<int> QTextCodec::availableMibs() */ void QTextCodec::setCodecForLocale(QTextCodec *c) { +#ifndef QT_NO_THREAD + QMutexLocker locker(textCodecsMutex()); +#endif localeMapper = c; if (!localeMapper) setupLocaleMapper(); diff --git a/src/corelib/codecs/qtextcodec_symbian.cpp b/src/corelib/codecs/qtextcodec_symbian.cpp new file mode 100644 index 0000000..e4db9d7 --- /dev/null +++ b/src/corelib/codecs/qtextcodec_symbian.cpp @@ -0,0 +1,678 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtextcodec_p.h" + +#include <private/qcore_symbian_p.h> +#include <QThreadStorage> +#include <QScopedPointer> + +#include <charconv.h> + +struct QSymbianCodecInitData { + uint charsetId; + int mib; + const char *aliases; +}; + +/* This table contains the known Symbian codecs aliases. It is ordered by charsetId. + It is required as symbian does not provide have aliases. + */ +static const QSymbianCodecInitData codecsData[] = { + { /*268439485*/ KCharacterSetIdentifierShiftJis, 17, "Shift_JIS\0MS_Kanji\0csShiftJIS\0MS_KANJI\0SJIS\0" }, + { /*268439486*/ KCharacterSetIdentifierGb2312, 57, "GB2312\0csGB2312\0CN-GB\0EUC-CN\0" }, + { /*268439487*/ KCharacterSetIdentifierBig5, 2026, "Big5\0csBig5\0Big5-ETen\0CP950\0BIG-FIVE\0CN-BIG5\0" }, + { /*268440246*/ KCharacterSetIdentifierCodePage1252, 2252, "windows-1252\0Code Page 1252\0CP1252\0MS-ANSI\0" }, +// { /*268450576*/ KCharacterSetIdentifierIso88591, 4, "ISO-8859-1\0ISO_8859-1:1987\0iso-ir-100\0ISO_8859-1\0latin1\0l1\0IBM819\0CP819\0csISOLatin1\0ISO-IR-100\0ISO8859-1\0L1\0LATIN1\0CSISOLATIN1\0" }, + { /*268451531*/ KCharacterSetIdentifierGbk, 113, "GBK\0MS936\0windows-936\0CP936\0" }, + { /*268451866*/ KCharacterSetIdentifierGb12345, 0, "GB12345\0" }, + { /*268455110*/ KCharacterSetIdentifierAscii, 3, "US-ASCII\0ANSI_X3.4-1968\0iso-ir-6\0ANSI_X3.4-1986\0ISO_646.irv:1991\0ASCII\0ISO646-US\0us\0IBM367\0cp367\0csASCII\0ISO-IR-6\0ISO_646.IRV:1991\0"}, + { /*268456062*/ KCharacterSetIdentifierIso88592, 5, "ISO-8859-2\0ISO_8859-2:1987\0iso-ir-101\0latin2\0l2\0csISOLatin2\0" }, + { /*268456063*/ KCharacterSetIdentifierIso88594, 7, "ISO-8859-4\0ISO_8859-4:1988\0iso-ir-110\0latin4\0l4\0csISOLatin4\0" }, + { /*268456064*/ KCharacterSetIdentifierIso88595, 8, "ISO-8859-5\0ISO_8859-5:1988\0iso-ir-144\0cyrillic\0csISOLatinCyrillic\0" }, + { /*268456065*/ KCharacterSetIdentifierIso88597, 10, "ISO-8859-7\0ISO_8859-7:1987\0iso-ir-126\0ELOT_928\0ECMA-118\0greek\0greek8\0csISOLatinGreek\0" }, + { /*268456066*/ KCharacterSetIdentifierIso88599, 12, "ISO-8859-9\0ISO_8859-9:1989\0iso-ir-148\0latin5\0l5\0csISOLatin5\0" }, + { /*268456875*/ KCharacterSetIdentifierSms7Bit, 0, "SMS 7-bit\0" }, + { /*268458028*/ KCharacterSetIdentifierUtf7, 103, "UTF-7\0UNICODE-1-1-UTF-7\0CSUNICODE11UTF7\0" }, +// { /*268458029*/ KCharacterSetIdentifierUtf8, 106, "UTF-8\0" }, + { /*268458030*/ KCharacterSetIdentifierImapUtf7, 0, "IMAP UTF-7\0" }, + { /*268458031*/ KCharacterSetIdentifierJavaConformantUtf8, 0, "JAVA UTF-8\0" }, + { /*268458454*/ 268458454, 2250, "Windows-1250\0CP1250\0MS-EE\0" }, + { /*268458455*/ 268458455, 2251, "Windows-1251\0CP1251\0MS-CYRL\0" }, + { /*268458456*/ 268458456, 2253, "Windows-1253\0CP1253\0MS-GREEK\0" }, + { /*268458457*/ 268458457, 2254, "Windows-1254\0CP1254\0MS-TURK\0" }, + { /*268458458*/ 268458458, 2257, "Windows-1257\0CP1257\0WINBALTRIM\0" }, + { /*268460133*/ KCharacterSetIdentifierHz, 2085, "HZ-GB-2312\0HZ\0" }, + { /*268460134*/ KCharacterSetIdentifierJis, 16, "JIS_Encoding\0JIS\0" }, + { /*268460135*/ KCharacterSetIdentifierEucJpPacked, 18, "EUC-JP\0Extended_UNIX_Code_Packed_Format_for_Japanese\0csEUCPkdFmtJapanese\0EUCJP_PACKED\0" }, + { /*268461728*/ KCharacterSetIdentifierIso2022Jp, 39, "ISO-2022-JP\0csISO2022JP\0JIS7\0" }, + { /*268461731*/ KCharacterSetIdentifierIso2022Jp1, 0, "ISO2022JP1\0" }, + { /*268470824*/ KCharacterSetIdentifierIso88593, 6, "ISO-8859-3\0ISO_8859-3:1988\0iso-ir-109\0latin3\0l3\0csISOLatin3\0" }, + { /*268470825*/ KCharacterSetIdentifierIso88596, 9, "ISO-8859-6\0ISO_8859-6:1987\0iso-ir-127\0ECMA-114\0ASMO-708\0arabic\0ISO88596\0csISOLatinArabic\0ARABIC\0" }, + { /*268470826*/ KCharacterSetIdentifierIso88598, 11, "ISO-8859-8\0ISO_8859-8:1988\0iso-ir-138\0hebrew\0csISOLatinHebrew\0" }, + { /*268470827*/ KCharacterSetIdentifierIso885910, 13, "ISO-8859-10\0iso-ir-157\0l6\0ISO_8859-10:1992\0csISOLatin6\0latin6\0" }, + { /*268470828*/ KCharacterSetIdentifierIso885913, 109, "ISO-8859-13\0ISO885913\0ISO-IR-179\0ISO8859-13\0L7\0LATIN7\0CSISOLATIN7\0" }, + { /*268470829*/ KCharacterSetIdentifierIso885914, 110, "ISO-8859-14\0iso-ir-199\0ISO_8859-14:1998\0latin8\0iso-celtic\0l8\0" }, + { /*268470830*/ KCharacterSetIdentifierIso885915, 111, "ISO-8859-15\0latin-9\0ISO-IR-203\0" }, +// { /*270483374*/ KCharacterSetIdentifierUnicodeLittle, 1014, "UTF-16LE\0Little-Endian UNICODE\0" }, +// { /*270483538*/ KCharacterSetIdentifierUnicodeBig, 1013, "UTF-16BE\0Big-Endian UNICODE\0" }, + { /*270501191*/ 270501191, 2255, "Windows-1255\0CP1255\0MS-HEBR\0" }, + { /*270501192*/ 270501192, 2256, "Windows-1256\0CP1256\0MS-ARAB\0" }, + { /*270501193*/ 270501193, 2259, "TIS-620\0ISO-IR-166\0TIS620-0\0TIS620.2529-1\0TIS620.2533-0\0TIS620.2533-1\0" }, + { /*270501194*/ 270501194, 0, "windows-874\0CP874\0IBM874\0" }, + { /*270501325*/ 270501325, 0, "SmsStrict\0" }, + { /*270501521*/ 270501521, 0, "ShiftJisDirectmap\0" }, + { /*270501542*/ 270501542, 0, "EucJpDirectmap\0" }, + /* 270501691 (duplicate) Windows-1252 | windows-1252 |Windows-1252 |Code Page 1252 |CP1252 |MS-ANSI |WINDOWS-1252 |2252 */ + { /*270501729*/ 270501729, 2088, "KOI8-U\0" }, + { /*270501752*/ 270501752, 2084, "KOI8-R\0csKOI8R\0" }, + { /*270529682*/ 270529682, 1000, "ISO-10646-UCS-2\0UCS-2\0CSUNICODE\0" }, + { /*270562232*/ 270562232, 2258, "Windows-1258\0CP1258\0WINDOWS-1258\0" }, + { /*270586888*/ 270586888, 0, "J5\0" }, + { /*271011982*/ 271011982, 0, "ISCII\0" }, + { /*271066541*/ 271066541, 2009, "CP850\0IBM850\0""850\0csPC850Multilingual\0" }, + { /*271082493*/ 271082493, 0, "EXTENDED_SMS_7BIT\0" }, + { /*271082494*/ 271082494, 0, "gsm7_turkish_single\0" }, + { /*271082495*/ 271082495, 0, "turkish_locking_gsm7ext\0" }, + { /*271082496*/ 271082496, 0, "turkish_locking_single\0" }, + { /*536929574*/ 536929574, 38, "EUC-KR\0" }, + { /*536936703*/ 536936703, 0, "CP949\0" }, + { /*536936705*/ 536936705, 37, "ISO-2022-KR\0" }, + { /*536941517*/ 536941517, 36, "KS_C_5601-1987\0" } + }; + + +class QSymbianTextCodec : public QTextCodec +{ +public: + QString convertToUnicode(const char*, int, ConverterState*) const; + QByteArray convertFromUnicode(const QChar*, int, ConverterState*) const; + QList<QByteArray> aliases() const; + QByteArray name() const; + int mibEnum() const; + + explicit QSymbianTextCodec(uint charsetId, int staticIndex = -1) : m_charsetId(charsetId), m_staticIndex(staticIndex) { } + + static QSymbianTextCodec *init(); + static QSymbianTextCodec *localeMapper; +private: + static CCnvCharacterSetConverter *converter(); + static uint getLanguageDependentCharacterSet(); + uint m_charsetId; + int m_staticIndex; +}; + +QSymbianTextCodec *QSymbianTextCodec::localeMapper = 0; + +class QSymbianTextCodecWithName : public QSymbianTextCodec +{ +public: + QSymbianTextCodecWithName(uint charsetId, const QByteArray &name) + : QSymbianTextCodec(charsetId) , m_name(name) { } + QByteArray name() const { return m_name; } + QList<QByteArray> aliases() const { return QList<QByteArray>(); } +private: + QByteArray m_name; +}; + +Q_GLOBAL_STATIC(QThreadStorage<CCnvCharacterSetConverter *>,gs_converterStore); + +CCnvCharacterSetConverter *QSymbianTextCodec::converter() +{ + CCnvCharacterSetConverter *&conv = gs_converterStore()->localData(); + if (!conv) + QT_TRAP_THROWING(conv = CCnvCharacterSetConverter::NewL()) + return conv; +} + + +QByteArray QSymbianTextCodec::name() const +{ + if (m_staticIndex >= 0) + return QByteArray(codecsData[m_staticIndex].aliases); + QScopedPointer<HBufC8> buf; + QT_TRAP_THROWING(buf.reset(converter()->ConvertCharacterSetIdentifierToStandardNameL(m_charsetId, qt_s60GetRFs()))) + if (buf) + return QByteArray(reinterpret_cast<const char *>(buf->Ptr()), buf->Length()); + return QByteArray(); +} + +int QSymbianTextCodec::mibEnum() const +{ + if (m_staticIndex >= 0) + return codecsData[m_staticIndex].mib; + int mib; + QT_TRAP_THROWING(mib = converter()->ConvertCharacterSetIdentifierToMibEnumL(m_charsetId, qt_s60GetRFs())) + return mib; +} + +QList<QByteArray> QSymbianTextCodec::aliases() const +{ + QList<QByteArray> result; + if (m_staticIndex >= 0) { + const char *aliases = codecsData[m_staticIndex].aliases; + aliases += strlen(aliases) + 1; + while (*aliases) { + int len = strlen(aliases); + result += QByteArray(aliases, len); + aliases += len + 1; + } + } + return result; +} + + +QString QSymbianTextCodec::convertToUnicode(const char *str, int len, ConverterState *state) const +{ + uint charsetId = m_charsetId; + + // no support for utf7 with state + if (state && (charsetId == KCharacterSetIdentifierUtf7 || + charsetId == KCharacterSetIdentifierImapUtf7)) { + return QString(); + } + CCnvCharacterSetConverter *converter = QSymbianTextCodec::converter(); + if (!str) { + return QString(); + } + + //Search the character set array containing all of the character sets for which conversion is available + CCnvCharacterSetConverter::TAvailability av; + QT_TRAP_THROWING(av = converter->PrepareToConvertToOrFromL(charsetId, qt_s60GetRFs())) + if (av == CCnvCharacterSetConverter::ENotAvailable) { + return QString(); + } + + char *str2; + int len2; + QByteArray helperBA; + if (state && (state->remainingChars > 0)) { + // we should prepare the input string ourselves + // the real size + len2 = len + state->remainingChars; + helperBA.resize(len2); + str2 = helperBA.data(); + if (state->remainingChars > 3) { // doesn't happen usually + memcpy(str2, state->d, state->remainingChars); + qFree(state->d); + state->d = 0; + } else { + char charTbl[3]; + charTbl[0] = state->state_data[0]; + charTbl[1] = state->state_data[1]; + charTbl[2] = state->state_data[2]; + memcpy(str2, charTbl, state->remainingChars); + } + memcpy(str2+state->remainingChars, str, len); + } + else { + len2 = len; + str2 = const_cast<char*>(str); + } + + QString UnicodeText(len2, Qt::Uninitialized); + TPtrC8 remainderOfForeignText; + remainderOfForeignText.Set(reinterpret_cast<const unsigned char *>(str2), len2); + + int numberOfUnconvertibleCharacters = 0; + int indexOfFirstUnconvertibleCharacter; + + // Use null character as replacement, if it is asked + bool convertToNull = (state && (state->flags & QTextCodec::ConvertInvalidToNull)); + if (convertToNull) { + _LIT8(KReplacement, "\x00"); + QT_TRAP_THROWING(converter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacement)) + } + // use state->invalidChars for keeping symbian state + int sState = CCnvCharacterSetConverter::KStateDefault; + if (state && (state->invalidChars != CCnvCharacterSetConverter::KStateDefault)) { + sState = state->invalidChars; + } + //Convert text encoded in a non-Unicode character set into the Unicode character set (UCS-2). + int remainingChars = -1; + int initial_size=0; + while (1) { + TPtr16 UnicodePtr(reinterpret_cast<unsigned short *>(UnicodeText.data()+initial_size), UnicodeText.size()); + QT_TRAP_THROWING(remainingChars = converter->ConvertToUnicode(UnicodePtr, + remainderOfForeignText, + sState, + numberOfUnconvertibleCharacters, + indexOfFirstUnconvertibleCharacter)) + + initial_size += UnicodePtr.Length(); + // replace 0xFFFD with 0x0000 and only if state set to convert to it + if (numberOfUnconvertibleCharacters>0 && convertToNull) { + int len2 = UnicodePtr.Length(); + for (int i = indexOfFirstUnconvertibleCharacter; i < len2; i++) { + UnicodePtr[i] = 0x0000; + } + } + // success + if (remainingChars==KErrNone) { + break; + } + // if ConvertToUnicode could not consume the foreign text at all + // UTF-8: EErrorIllFormedInput = KErrCorrupt + // UCS-2: KErrNotFound + if (remainingChars == CCnvCharacterSetConverter::EErrorIllFormedInput || + remainingChars == KErrNotFound) { + remainingChars = remainderOfForeignText.Size(); + break; + } + else { + if (remainingChars < 0) { + return QString(); + } + } + // + UnicodeText.resize(UnicodeText.size() + remainingChars*2); + remainderOfForeignText.Set(reinterpret_cast<const unsigned char *>(str2+len2-remainingChars), remainingChars); + } + // save symbian state + if (state) { + state->invalidChars = sState; + } + + if (remainingChars > 0) { + if (!state) { + // No way to signal, if there is still remaining chars, for ex. UTF-8 still can have + // some characters hanging around. + return QString(); + } + const unsigned char *charPtr = remainderOfForeignText.Right(remainingChars).Ptr(); + if (remainingChars > 3) { // doesn't happen usually + state->d = (void*)qMalloc(remainingChars); + if (!state->d) + return QString(); + // copy characters there + memcpy(state->d, charPtr, remainingChars); + } + else { + // fallthru is correct + switch (remainingChars) { + case 3: + state->state_data[2] = charPtr[2]; + case 2: + state->state_data[1] = charPtr[1]; + case 1: + state->state_data[0] = charPtr[0]; + } + } + state->remainingChars = remainingChars; + } + else { + if (state) { + // If we continued from an earlier iteration + state->remainingChars = 0; + } + } + // check if any ORIGINAL headers should be left + if (initial_size > 0) { + if (!state || (state && !(state->flags & QTextCodec::IgnoreHeader))) { + // always skip headers on following state loops + if (state) { + state->flags |= QTextCodec::IgnoreHeader; + } + const TUint16 *ptr = reinterpret_cast<const TUint16 *>(UnicodeText.data()); + if (ptr[0] == QChar::ByteOrderMark || ptr[0] == QChar::ByteOrderSwapped) { + return UnicodeText.mid(1, initial_size - 1); + } + } + } + if (initial_size >= 0) { + UnicodeText.resize(initial_size); + return UnicodeText; + } + else { + return QString(); + } +} + + +QByteArray QSymbianTextCodec::convertFromUnicode(const QChar *str, int len, ConverterState *state) const +{ + uint charsetId = m_charsetId; + CCnvCharacterSetConverter *converter = QSymbianTextCodec::converter(); + if (!str) + return QByteArray(); + + if (len == 0) + return QByteArray(); + + // no support for utf7 with state + if (state && (charsetId == KCharacterSetIdentifierUtf7 || + charsetId == KCharacterSetIdentifierImapUtf7)) + return QByteArray(); + + //Get reference file session from backend + RFs &fileSession = qt_s60GetRFs(); + + //Search the character set array containing all of the character sets for which conversion is available + CCnvCharacterSetConverter::TAvailability av = CCnvCharacterSetConverter::ENotAvailable; + QT_TRAP_THROWING(av = converter->PrepareToConvertToOrFromL(charsetId, fileSession)) + if (av == CCnvCharacterSetConverter::ENotAvailable) + return QByteArray(); + + // Use null character as replacement, if it is asked + if (state && (state->flags & QTextCodec::ConvertInvalidToNull)) { + _LIT8(KReplacement, "\x00"); + QT_TRAP_THROWING(converter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacement)) + } + else { + _LIT8(KReplacement, "?"); + QT_TRAP_THROWING(converter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacement)) + } + QByteArray outputBuffer; + + // add header if no state (one run), or if no ignoreheader (from first state) + int bomofs = 0; + if (!state || (state && !(state->flags & QTextCodec::IgnoreHeader))) { + + QChar bom(QChar::ByteOrderMark); + + if (state) + state->flags |= QTextCodec::IgnoreHeader; // bom handling only on first state + + switch (charsetId) { + case KCharacterSetIdentifierUcs2: + outputBuffer.append(bom.row()); + outputBuffer.append(bom.cell()); + bomofs = 2; + break; + + case KCharacterSetIdentifierUtf8: // we don't add bom for UTF-8 + case KCharacterSetIdentifierJavaConformantUtf8: + /*outputBuffer.append("\xef\xbb\xbf"); + bomofs = 3; + */ + break; + + case KCharacterSetIdentifierUnicodeLittle: + outputBuffer.append(bom.cell()); + outputBuffer.append(bom.row()); + bomofs = 2; + break; + + case KCharacterSetIdentifierUnicodeBig: + outputBuffer.append(bom.row()); + outputBuffer.append(bom.cell()); + bomofs = 2; + break; + + default: + break; + } + } + + // len is 16bit chars, reserve 3 8bit chars for each input char + // jsz - it could be differentiated, to allocate less + outputBuffer.resize(len * 3 + bomofs); + + // loop for too short output buffer + int unconverted; + int numberOfUnconvertibleCharacters = len; + int indexOfFirstUnconvertibleCharacter; + int convertedSize; + int lastUnconverted = 0; + int initial_size=0; + int remainderToConvert = len; + while (1) { + TPtr8 outputPtr(reinterpret_cast<unsigned char *>(outputBuffer.data() + bomofs + initial_size), outputBuffer.size() - bomofs); + + TPtrC16 UnicodeText(reinterpret_cast<const unsigned short *>(str+len-remainderToConvert), remainderToConvert); + + //Convert text encoded in the Unicode character set (UCS-2) into other character sets + unconverted = -1; + QT_TRAP_THROWING( unconverted = converter->ConvertFromUnicode(outputPtr, + UnicodeText, + numberOfUnconvertibleCharacters, + indexOfFirstUnconvertibleCharacter)) + initial_size += outputPtr.Length(); + if (unconverted < 0) { + return QByteArray(); + } + + + if (unconverted == 0 ) { + convertedSize = initial_size; + break; + } + + // check what means unconverted > 0 + if (indexOfFirstUnconvertibleCharacter<0) { + // 8859-6 and 8859-8 break with certain input (string of \xc0 - \xd9 converted to unicode and back) + if (unconverted == lastUnconverted) { + return QByteArray(); + } + lastUnconverted = unconverted; + } + else { + // were some character not possible to convert + + } + remainderToConvert = unconverted; // len - indexOfFirstUnconvertibleCharacter; + // resize output buffer, use =op for the null check + outputBuffer.resize(outputBuffer.size() + remainderToConvert * 3 + bomofs); + }; + + // shorten output + outputBuffer.resize(convertedSize + bomofs); + + if (state) { + state->invalidChars = numberOfUnconvertibleCharacters; + + // check if any Symbian CONVERTED headers should be removed + if (state->flags & QTextCodec::IgnoreHeader && state->state_data[0] == 0) { + + state->state_data[0] = 0xff; // bom handling only on first state + + if (charsetId == KCharacterSetIdentifierUcs2 && outputBuffer.size() > 1) { + + QChar bom(QChar::ByteOrderMark); + if (outputBuffer.at(0) == bom.row() && outputBuffer.at(1) == bom.cell()) { + outputBuffer.remove(0, 2); + } else if (outputBuffer.at(0) == bom.cell() && outputBuffer.at(1) == bom.row()) { + outputBuffer.remove(0, 2); + } + + } else if ((charsetId == KCharacterSetIdentifierUtf8 || + charsetId == KCharacterSetIdentifierJavaConformantUtf8) && + outputBuffer.size() > 2) { + if (outputBuffer.at(0) == 0xef && outputBuffer.at(1) == 0xbb && outputBuffer.at(2) == 0xbf) { + outputBuffer.remove(0, 3); + } + + } else if (charsetId == KCharacterSetIdentifierUnicodeLittle && + outputBuffer.size() > 1) { + + QChar bom(QChar::ByteOrderMark); + if (outputBuffer.at(0) == bom.row() && outputBuffer.at(1) == bom.cell()) { + outputBuffer.remove(0, 2); + } + + } else if (charsetId == KCharacterSetIdentifierUnicodeBig && + outputBuffer.size() > 1) { + + QChar bom(QChar::ByteOrderSwapped); + if (outputBuffer.at(0) == bom.row() && outputBuffer.at(1) == bom.cell()) { + outputBuffer.remove(0, 2); + } + } + + } + } + + return outputBuffer; +} + + +uint QSymbianTextCodec::getLanguageDependentCharacterSet() +{ + TLanguage lang = User::Language(); + + uint langIndex = 0; + + switch (lang) { + case 14: //ELangTurkish + langIndex = KCharacterSetIdentifierIso88599; break; + case 16: //ELangRussian + langIndex = KCharacterSetIdentifierIso88595; break; + case 17: //ELangHungarian + langIndex = KCharacterSetIdentifierIso88592; break; + case 25: //ELangCzec + case 26: //ELangSlovak + case 27: //ELangPolish + case 28: //ELangSlovenian + langIndex = KCharacterSetIdentifierIso88592; break; + case 29: //ELangTaiwanChinese + case 30: //ELangHongKongChinese + langIndex = KCharacterSetIdentifierBig5; break; + case 31: //ELangPrcChinese + langIndex = KCharacterSetIdentifierGbk; break; + case 32: //ELangJapanese + langIndex = KCharacterSetIdentifierShiftJis; break; + case 33: //ELangThai + langIndex = 270501193 /*KCharacterSetIdentifierTis620*/; break; + case 37: //ELangArabic + langIndex = KCharacterSetIdentifierIso88596; break; + case 40: //ELangBelarussian + case 42: //ELangBulgarian + langIndex = KCharacterSetIdentifierIso88595; break; + case 45: //ELangCroatian + langIndex = KCharacterSetIdentifierIso88592; break; + case 49: //ELangEstonian + langIndex = KCharacterSetIdentifierIso88594; break; + case 54: //ELangGreek + case 55: //ELangCyprusGreek + langIndex = KCharacterSetIdentifierIso88597; break; + case 57: //ELangHebrew + langIndex = KCharacterSetIdentifierIso88598; break; + case 58: //ELangHindi + langIndex = 271011982/*KCharacterSetIdentifierIscii*/; break; + case 67: //ELangLatvian + case 68: //ELangLithuanian + langIndex = KCharacterSetIdentifierIso88594; break; + case 69: //ELangMacedonian + langIndex = KCharacterSetIdentifierIso88595; break; + case 78: //ELangRomanian + langIndex = KCharacterSetIdentifierIso88592; break; + case 79: //ELangSerbian + langIndex = KCharacterSetIdentifierIso88592; break; + case 91: //ELangCyprusTurkish + langIndex = KCharacterSetIdentifierIso88599; break; + case 93: //ELangUkrainian + langIndex = KCharacterSetIdentifierIso88595; break; + case 94: //ELangUrdu + langIndex = KCharacterSetIdentifierIso88596; break; + case 157: //ELangEnglish_Taiwan + case 158: //ELangEnglish_HongKong + langIndex = KCharacterSetIdentifierBig5; break; + case 159: //ELangEnglish_Prc + langIndex = KCharacterSetIdentifierGbk; break; + case 160: + langIndex = KCharacterSetIdentifierShiftJis; break; + case 161: //ELangEnglish_Thailand + langIndex = 270501193/*KCharacterSetIdentifierTis620*/; break; + } + + if (langIndex > 0) { + return langIndex; + } + return KCharacterSetIdentifierCodePage1252; +} + +/* Create the codecs that have aliases and return the locale mapper*/ +QSymbianTextCodec *QSymbianTextCodec::init() +{ + const uint localeMapperId = getLanguageDependentCharacterSet(); + QScopedPointer<CArrayFix<CCnvCharacterSetConverter::SCharacterSet> > array; + QT_TRAP_THROWING(array.reset(CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(qt_s60GetRFs()))) + CCnvCharacterSetConverter *converter = QSymbianTextCodec::converter(); + int count = array->Count(); + for (int i = 0; i < count; i++) { + int charsetId = array->At(i).Identifier(); + + // skip builtin Qt codecs + if (charsetId == KCharacterSetIdentifierUtf8 || charsetId == KCharacterSetIdentifierUnicodeLittle + || charsetId == KCharacterSetIdentifierUnicodeLittle || charsetId == KCharacterSetIdentifierUnicodeBig + || charsetId == KCharacterSetIdentifierIso88591 + || charsetId == 270501691 /* skip Windows-1252 duplicate*/) { + continue; + } + + int begin = 0; + int n = sizeof(codecsData) / sizeof(codecsData[0]); + int half; + + while (n > 0) { + half = n >> 1; + int middle = begin + half; + if (codecsData[middle].charsetId < charsetId) { + begin = middle + 1; + n -= half + 1; + } else { + n = half; + } + } + if (codecsData[begin].charsetId == charsetId) { + QSymbianTextCodec *c = new QSymbianTextCodec(charsetId, begin); + if (charsetId == localeMapperId) + localeMapper = c; + } else { + QScopedPointer<HBufC8> buf; + QT_TRAP_THROWING(buf.reset(converter->ConvertCharacterSetIdentifierToStandardNameL(charsetId, qt_s60GetRFs()))) + QByteArray name; + if (buf && buf->Length()) { + name = QByteArray(reinterpret_cast<const char *>(buf->Ptr()), buf->Length()); + } else { + TPtrC charSetName = array->At(i).NameIsFileName() ? TParsePtrC(array->At(i).Name()).Name() : array->At(i).Name(); + int len = charSetName.Length(); + QString str; + str.setUnicode(reinterpret_cast<const QChar*>(charSetName.Ptr()), len); + name = str.toLatin1(); + } + if (!name.isEmpty()) + new QSymbianTextCodecWithName(charsetId, name); + } + + } + return localeMapper; +} diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 9e79894..b1c403f 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -70,7 +70,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; have reached the end of the data stream, with stdin. The reason for this is that as long as stdin doesn't give any input to the QTextStream, \c atEnd() will return true even if the stdin is open and waiting for more characters. - + Besides using QTextStream's constructors, you can also set the device or string QTextStream operates on by calling setDevice() or setString(). You can seek to a position by calling seek(), and @@ -1196,6 +1196,7 @@ bool QTextStream::seek(qint64 pos) resetCodecConverterStateHelper(&d->writeConverterState); delete d->readConverterSavedState; d->readConverterSavedState = 0; + d->writeConverterState.flags |= QTextCodec::IgnoreHeader; #endif return true; } diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 76ebcb4..55df063 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -101,7 +101,7 @@ private: qreal m_height; }; -class QDeclarativeItemPrivate : public QGraphicsItemPrivate +class Q_DECLARATIVE_EXPORT QDeclarativeItemPrivate : public QGraphicsItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeItem) @@ -259,7 +259,7 @@ public: static int consistentTime; static QTime currentTime(); - static void Q_DECLARATIVE_EXPORT setConsistentTime(int t); + static void setConsistentTime(int t); static void start(QTime &); static int elapsed(QTime &); static int restart(QTime &); diff --git a/src/declarative/graphicsitems/qdeclarativeparticles.cpp b/src/declarative/graphicsitems/qdeclarativeparticles.cpp index ec0bf6c..593c80a 100644 --- a/src/declarative/graphicsitems/qdeclarativeparticles.cpp +++ b/src/declarative/graphicsitems/qdeclarativeparticles.cpp @@ -1263,7 +1263,7 @@ void QDeclarativeParticlesPainter::paint(QPainter *p, const QStyleOptionGraphics const int myY = y() + parentItem()->y(); #if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) - QVarLengthArray<QPainter::Fragment, 256> pixmapData; + QVarLengthArray<QPainter::PixmapFragment, 256> pixmapData; #else QVarLengthArray<QDrawPixmaps::Data, 256> pixmapData; #endif diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h index 4083ab5..62f7d95 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h @@ -66,11 +66,6 @@ QT_BEGIN_NAMESPACE -typedef struct PathViewItem{ - int index; - QDeclarativeItem* item; -}PathViewItem; - class QDeclarativeOpenMetaObjectType; class QDeclarativePathViewAttached; class QDeclarativePathViewPrivate : public QDeclarativeItemPrivate diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 1145235..78184a9 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -679,16 +679,20 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto d->defaultItemHeight = indexRowSizeHint(topLeft); bool sizeChanged = false; if (topViewIndex != -1) { - if (topLeft == bottomRight) { + if (topLeft.row() == bottomRight.row()) { int oldHeight = d->itemHeight(topViewIndex); d->invalidateHeightCache(topViewIndex); sizeChanged = (oldHeight != d->itemHeight(topViewIndex)); + if (topLeft.column() == 0) + d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft); } else { int bottomViewIndex = d->viewIndex(bottomRight); for (int i = topViewIndex; i <= bottomViewIndex; ++i) { int oldHeight = d->itemHeight(i); d->invalidateHeightCache(i); sizeChanged |= (oldHeight != d->itemHeight(i)); + if (topLeft.column() == 0) + d->viewItems[i].hasChildren = d->hasVisibleChildren(d->viewItems.at(i).index); } } } diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp index d76c709..a62f06b 100644 --- a/src/gui/painting/qdrawutil.cpp +++ b/src/gui/painting/qdrawutil.cpp @@ -1081,7 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs, according to the \a margins structure. */ -typedef QVarLengthArray<QPainter::Fragment, 16> QPixmapFragmentsArray; +typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray; /*! \since 4.6 @@ -1102,7 +1102,7 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) { - QPainter::Fragment d; + QPainter::PixmapFragment d; d.opacity = 1.0; d.rotation = 0.0; diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 98762f0..1fd622d 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -970,8 +970,8 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con fill(path, brush); } -void QPaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, QPainter::FragmentHints /*hints*/) +void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/) { qreal oldOpacity = state()->opacity; QTransform oldTransform = state()->matrix; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 2401b94..6c654bd 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -197,7 +197,8 @@ public: virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints); + virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QFlags<QPainter::PixmapFragmentHint> hints); virtual void updateState(const QPaintEngineState &state); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 9d83718..c5ce76c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7994,10 +7994,11 @@ start_lengthVariant: for (int i = 0; i < textLayout.lineCount(); i++) { QTextLine line = textLayout.lineAt(i); + qreal advance = textLayout.engine()->lines[i].textAdvance.toReal(); if (tf & Qt::AlignRight) - xoff = r.width() - line.naturalTextWidth(); + xoff = r.width() - advance; else if (tf & Qt::AlignHCenter) - xoff = (r.width() - line.naturalTextWidth())/2; + xoff = (r.width() - advance)/2; line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff)); } @@ -8914,11 +8915,11 @@ QTransform QPainter::combinedTransform() const This function is potentially faster than multiple calls to drawPixmap(), since the backend can optimize state changes. - \sa QPainter::Fragment, QPainter::FragmentHint + \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint */ -void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, FragmentHints hints) +void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, PixmapFragmentHints hints) { Q_D(QPainter); @@ -8959,7 +8960,7 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, /*! \since 4.7 - \class QPainter::Fragment + \class QPainter::PixmapFragment \brief This class is used in conjunction with the QPainter::drawPixmapFragments() function to specify how a pixmap, or @@ -8980,73 +8981,73 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, /*! \since 4.7 - This is a convenience function that returns a QPainter::Fragment that is + This is a convenience function that returns a QPainter::PixmapFragment that is initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a rotation, \a opacity parameters. */ -QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF &sourceRect, +QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX, qreal scaleY, qreal rotation, qreal opacity) { - Fragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), - sourceRect.height(), scaleX, scaleY, rotation, opacity}; + PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), + sourceRect.height(), scaleX, scaleY, rotation, opacity}; return fragment; } /*! - \variable QPainter::Fragment::x + \variable QPainter::PixmapFragment::x \brief the x coordinate of center point in the target rectangle. */ /*! - \variable QPainter::Fragment::y + \variable QPainter::PixmapFragment::y \brief the y coordinate of the center point in the target rectangle. */ /*! - \variable QPainter::Fragment::sourceLeft + \variable QPainter::PixmapFragment::sourceLeft \brief the left coordinate of the source rectangle. */ /*! - \variable QPainter::Fragment::sourceTop + \variable QPainter::PixmapFragment::sourceTop \brief the top coordinate of the source rectangle. */ /*! - \variable QPainter::Fragment::width + \variable QPainter::PixmapFragment::width \brief the width of the source rectangle and is used to calculate the width of the target rectangle. */ /*! - \variable QPainter::Fragment::height + \variable QPainter::PixmapFragment::height \brief the height of the source rectangle and is used to calculate the height of the target rectangle. */ /*! - \variable QPainter::Fragment::scaleX + \variable QPainter::PixmapFragment::scaleX \brief the horizontal scale of the target rectangle. */ /*! - \variable QPainter::Fragment::scaleY + \variable QPainter::PixmapFragment::scaleY \brief the vertical scale of the target rectangle. */ /*! - \variable QPainter::Fragment::rotation + \variable QPainter::PixmapFragment::rotation \brief the rotation of the target rectangle in degrees. The target rectangle is rotated after it has been scaled. */ /*! - \variable QPainter::Fragment::opacity + \variable QPainter::PixmapFragment::opacity \brief the opacity of the target rectangle, where 0.0 is fully transparent and 1.0 is fully opaque. @@ -9055,12 +9056,12 @@ QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF & /*! \since 4.7 - \enum QPainter::FragmentHint + \enum QPainter::PixmapFragmentHint \value OpaqueHint Indicates that the pixmap fragments to be drawn are opaque. Opaque fragments are potentially faster to draw. - \sa QPainter::drawPixmapFragments(), QPainter::Fragment + \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment */ void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation) diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index bcb0b50..443925b 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -99,7 +99,7 @@ public: Q_DECLARE_FLAGS(RenderHints, RenderHint) - class Fragment { + class PixmapFragment { public: qreal x; qreal y; @@ -111,16 +111,16 @@ public: qreal scaleY; qreal rotation; qreal opacity; - static Fragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, + static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX = 1, qreal scaleY = 1, qreal rotation = 0, qreal opacity = 1); }; - enum FragmentHint { + enum PixmapFragmentHint { OpaqueHint = 0x01 }; - Q_DECLARE_FLAGS(FragmentHints, FragmentHint) + Q_DECLARE_FLAGS(PixmapFragmentHints, PixmapFragmentHint) QPainter(); explicit QPainter(QPaintDevice *); @@ -375,8 +375,8 @@ public: inline void drawPixmap(const QRect &r, const QPixmap &pm); inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm); - void drawPixmapFragments(const Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, FragmentHints hints = 0); + void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, PixmapFragmentHints hints = 0); void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags = Qt::AutoColor); diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index f36cbd2..5054b66 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -382,6 +382,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine QFixed y; QFixed width; QFixed textWidth; + QFixed textAdvance; int from; signed int length : 29; mutable uint justified : 1; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index af91603..cc6793d 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1875,6 +1875,7 @@ void QTextLine::layout_helper(int maxGlyphs) line.textWidth += lbh.softHyphenWidth; } + line.textAdvance = line.textWidth; line.textWidth += lbh.rightBearing; goto found; @@ -1885,6 +1886,7 @@ void QTextLine::layout_helper(int maxGlyphs) } LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); + line.textAdvance = line.textWidth; line.textWidth += lbh.rightBearing; found: diff --git a/src/multimedia/effects/qsoundeffect.cpp b/src/multimedia/effects/qsoundeffect.cpp index f64d9ee..548ec74 100644 --- a/src/multimedia/effects/qsoundeffect.cpp +++ b/src/multimedia/effects/qsoundeffect.cpp @@ -134,7 +134,7 @@ QSoundEffect::QSoundEffect(QObject *parent) : QSoundEffect::~QSoundEffect() { - delete d; + d->deleteLater(); } QUrl QSoundEffect::source() const diff --git a/src/multimedia/effects/qsoundeffect_pulse_p.cpp b/src/multimedia/effects/qsoundeffect_pulse_p.cpp index c322722..e379259 100644 --- a/src/multimedia/effects/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/effects/qsoundeffect_pulse_p.cpp @@ -234,6 +234,7 @@ Q_GLOBAL_STATIC(PulseDaemon, daemon) QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): QObject(parent), + m_retry(false), m_muted(false), m_playQueued(false), m_sampleLoaded(false), @@ -250,7 +251,7 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): QSoundEffectPrivate::~QSoundEffectPrivate() { - delete m_reply; + m_reply->deleteLater(); unloadSample(); } @@ -310,6 +311,12 @@ void QSoundEffectPrivate::setMuted(bool muted) void QSoundEffectPrivate::play() { + if (m_retry) { + m_retry = false; + setSource(m_source); + return; + } + if (!m_sampleLoaded) { m_playQueued = true; return; @@ -338,6 +345,7 @@ void QSoundEffectPrivate::decoderReady() pa_stream_set_state_callback(stream, stream_state_callback, this); pa_stream_set_write_callback(stream, stream_write_callback, this); pa_stream_connect_upload(stream, (size_t)m_waveDecoder->size()); + m_pulseStream = stream; daemon()->unlock(); } @@ -377,6 +385,52 @@ void QSoundEffectPrivate::unloadSample() m_sampleLoaded = false; } +void QSoundEffectPrivate::uploadSample() +{ + daemon()->lock(); + + size_t bufferSize = qMin(pa_stream_writable_size(m_pulseStream), + size_t(m_waveDecoder->bytesAvailable())); + char buffer[bufferSize]; + + size_t len = 0; + while (len < (m_waveDecoder->size())) { + qint64 read = m_waveDecoder->read(buffer, qMin((int)bufferSize, + (int)(m_waveDecoder->size()-len))); + if (read > 0) { + if (pa_stream_write(m_pulseStream, buffer, size_t(read), 0, 0, PA_SEEK_RELATIVE) == 0) + len += size_t(read); + else + break; + } + } + + m_dataUploaded += len; + pa_stream_set_write_callback(m_pulseStream, NULL, NULL); + + if (m_waveDecoder->size() == m_dataUploaded) { + int err = pa_stream_finish_upload(m_pulseStream); + if(err != 0) { + qWarning("pa_stream_finish_upload() err=%d",err); + pa_stream_disconnect(m_pulseStream); + m_retry = true; + m_playQueued = false; + QMetaObject::invokeMethod(this, "play"); + daemon()->unlock(); + return; + } + m_duration = m_waveDecoder->duration(); + m_waveDecoder->deleteLater(); + m_stream->deleteLater(); + m_sampleLoaded = true; + if (m_playQueued) { + m_playQueued = false; + QMetaObject::invokeMethod(this, "play"); + } + } + daemon()->unlock(); +} + void QSoundEffectPrivate::playSample() { pa_volume_t volume = PA_VOLUME_NORM; @@ -412,36 +466,7 @@ void QSoundEffectPrivate::stream_write_callback(pa_stream *s, size_t length, voi QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata); - size_t bufferSize = qMin(pa_stream_writable_size(s), - size_t(self->m_waveDecoder->bytesAvailable())); - char buffer[bufferSize]; - - size_t len = 0; - while (len < length) { - qint64 read = self->m_waveDecoder->read(buffer, qMin(bufferSize, length -len)); - if (read > 0) { - if (pa_stream_write(s, buffer, size_t(read), 0, 0, PA_SEEK_RELATIVE) == 0) - len += size_t(read); - else - break; - } - } - self->m_dataUploaded += len; - - if (self->m_waveDecoder->size() == self->m_dataUploaded) { - pa_stream_finish_upload(s); - - self->m_duration = self->m_waveDecoder->duration(); - - self->m_waveDecoder->deleteLater(); - self->m_stream->deleteLater(); - - self->m_sampleLoaded = true; - if (self->m_playQueued) { - self->m_playQueued = false; - QMetaObject::invokeMethod(self, "play"); - } - } + QMetaObject::invokeMethod(self, "uploadSample", Qt::QueuedConnection); } void QSoundEffectPrivate::stream_state_callback(pa_stream *s, void *userdata) diff --git a/src/multimedia/effects/qsoundeffect_pulse_p.h b/src/multimedia/effects/qsoundeffect_pulse_p.h index 3aed018..aff729c 100644 --- a/src/multimedia/effects/qsoundeffect_pulse_p.h +++ b/src/multimedia/effects/qsoundeffect_pulse_p.h @@ -97,6 +97,7 @@ private Q_SLOTS: void decoderReady(); void decoderError(); void checkPlayTime(); + void uploadSample(); private: void loadSample(); @@ -109,6 +110,9 @@ private: static void stream_state_callback(pa_stream *s, void *userdata); static void play_callback(pa_context *c, int success, void *userdata); + pa_stream *m_pulseStream; + + bool m_retry; bool m_muted; bool m_playQueued; bool m_sampleLoaded; diff --git a/src/multimedia/effects/qsoundeffect_qmedia_p.cpp b/src/multimedia/effects/qsoundeffect_qmedia_p.cpp index 43ba22f..36c36dd 100644 --- a/src/multimedia/effects/qsoundeffect_qmedia_p.cpp +++ b/src/multimedia/effects/qsoundeffect_qmedia_p.cpp @@ -67,8 +67,6 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): m_player(0) { m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency); - connect(m_player, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged())); - connect(m_player, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged())); connect(m_player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(stateChanged(QMediaPlayer::State))); } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 8eb72b0..2b5f2f4 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1641,7 +1641,8 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp s->matrix = old; } -void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints) +void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints) { Q_D(QGL2PaintEngineEx); // Use fallback for extended composition modes. @@ -1655,9 +1656,9 @@ void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, } -void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::Fragment *fragments, +void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, - QPainter::FragmentHints hints) + QPainter::PixmapFragmentHints hints) { GLfloat dx = 1.0f / pixmap.size().width(); GLfloat dy = 1.0f / pixmap.size().height(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 5d3608b..ed8fbbc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -125,7 +125,8 @@ public: virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints); + virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); @@ -196,7 +197,8 @@ public: void fill(const QVectorPath &path); void stroke(const QVectorPath &path, const QPen &pen); void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); - void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints); + void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints); void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem, bool includeMatrixInCache); diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 4df894a..2c850c9 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3041,8 +3041,8 @@ void QVGPaintEngine::drawTiledPixmap // (i.e. no opacity), no rotation or scaling, and drawing the full // pixmap rather than parts of the pixmap. Even having just one of // these conditions will improve performance. -void QVGPaintEngine::drawPixmapFragments(const QPainter::Fragment *drawingData, int dataCount, - const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints) +void QVGPaintEngine::drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount, + const QPixmap &pixmap, QFlags<QPainter::PixmapFragmentHint> hints) { #if !defined(QT_SHIVAVG) Q_D(QVGPaintEngine); diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 1203af5..1e7e26c 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -137,7 +137,8 @@ public: void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - void drawPixmapFragments(const QPainter::Fragment *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints); + void drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount, const QPixmap &pixmap, + QFlags<QPainter::PixmapFragmentHint> hints); void drawTextItem(const QPointF &p, const QTextItem &textItem); void drawStaticTextItem(QStaticTextItem *staticTextItem); diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index 4a8fc0b..cb9086c 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -310,7 +310,6 @@ public: { *d_func()->stream << QLatin1String("fill=\"none\" "); *d_func()->stream << QLatin1String("stroke=\"black\" "); - *d_func()->stream << QLatin1String("vector-effect=\"non-scaling-stroke\" "); *d_func()->stream << QLatin1String("stroke-width=\"1\" "); *d_func()->stream << QLatin1String("fill-rule=\"evenodd\" "); *d_func()->stream << QLatin1String("stroke-linecap=\"square\" "); @@ -380,13 +379,10 @@ public: break; } - if (spen.widthF() == 0) { - width = QLatin1String("1"); - stream() << "vector-effect=\"non-scaling-stroke\" "; - } + if (spen.widthF() == 0) + stream() <<"stroke-width=\"1\" "; else - width = QString::number(spen.widthF()); - stream() <<"stroke-width=\""<<width<<"\" "; + stream() <<"stroke-width=\"" << spen.widthF() << "\" "; switch (spen.capStyle()) { case Qt::FlatCap: @@ -983,14 +979,11 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p) { Q_D(QSvgPaintEngine); - *d->stream << "<path " - "fill-rule="; - if (p.fillRule() == Qt::OddEvenFill) - *d->stream << "\"evenodd\" "; - else - *d->stream << "\"nonzero\" "; - - *d->stream << "d=\""; + *d->stream << "<path vector-effect=\"" + << (state->pen().isCosmetic() ? "non-scaling-stroke" : "none") + << "\" fill-rule=\"" + << (p.fillRule() == Qt::OddEvenFill ? "evenodd" : "nonzero") + << "\" d=\""; for (int i=0; i<p.elementCount(); ++i) { const QPainterPath::Element &e = p.elementAt(i); @@ -1038,7 +1031,9 @@ void QSvgPaintEngine::drawPolygon(const QPointF *points, int pointCount, path.lineTo(points[i]); if (mode == PolylineMode) { - stream() << "<polyline fill=\"none\" points=\""; + stream() << "<polyline fill=\"none\" vector-effect=\"" + << (state->pen().isCosmetic() ? "non-scaling-stroke" : "none") + << "\" points=\""; for (int i = 0; i < pointCount; ++i) { const QPointF &pt = points[i]; stream() << pt.x() << ',' << pt.y() << ' '; diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp index cd0e1ac..a29764a 100644 --- a/src/svg/qsvggraphics.cpp +++ b/src/svg/qsvggraphics.cpp @@ -78,33 +78,29 @@ void QSvgAnimation::draw(QPainter *, QSvgExtraStates &) qWarning("<animation> no implemented"); } -static inline QRectF boundsOnStroke(const QPainterPath &path, qreal width) +static inline QRectF boundsOnStroke(QPainter *p, const QPainterPath &path, qreal width) { QPainterPathStroker stroker; stroker.setWidth(width); QPainterPath stroke = stroker.createStroke(path); - return stroke.boundingRect(); + return p->transform().map(stroke).boundingRect(); } -QSvgCircle::QSvgCircle(QSvgNode *parent, const QRectF &rect) +QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect) : QSvgNode(parent), m_bounds(rect) { } -QRectF QSvgCircle::bounds() const +QRectF QSvgEllipse::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_bounds; - else { - QPainterPath path; - path.addRect(m_bounds); - return boundsOnStroke(path, sw); - } + QPainterPath path; + path.addEllipse(m_bounds); + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(path).boundingRect() : boundsOnStroke(p, path, sw); } -void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) +void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); @@ -112,9 +108,8 @@ void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) } QSvgArc::QSvgArc(QSvgNode *parent, const QPainterPath &path) - : QSvgNode(parent), cubic(path) + : QSvgNode(parent), m_path(path) { - m_cachedBounds = path.boundingRect(); } void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) @@ -123,36 +118,12 @@ void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); - p->drawPath(cubic); + p->drawPath(m_path); p->setOpacity(oldOpacity); } revertStyle(p, states); } -QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect) - : QSvgNode(parent), m_bounds(rect) -{ -} - -QRectF QSvgEllipse::bounds() const -{ - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_bounds; - else { - QPainterPath path; - path.addEllipse(m_bounds); - return boundsOnStroke(path, sw); - } -} - -void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) -{ - applyStyle(p, states); - QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); - revertStyle(p, states); -} - QSvgImage::QSvgImage(QSvgNode *parent, const QImage &image, const QRect &bounds) : QSvgNode(parent), m_image(image), @@ -173,7 +144,7 @@ void QSvgImage::draw(QPainter *p, QSvgExtraStates &states) QSvgLine::QSvgLine(QSvgNode *parent, const QLineF &line) - : QSvgNode(parent), m_bounds(line) + : QSvgNode(parent), m_line(line) { } @@ -184,7 +155,7 @@ void QSvgLine::draw(QPainter *p, QSvgExtraStates &states) if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); - p->drawLine(m_bounds); + p->drawLine(m_line); p->setOpacity(oldOpacity); } revertStyle(p, states); @@ -203,19 +174,11 @@ void QSvgPath::draw(QPainter *p, QSvgExtraStates &states) revertStyle(p, states); } -QRectF QSvgPath::bounds() const +QRectF QSvgPath::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) { - if (m_cachedBounds.isNull()) - //m_cachedBounds = m_path.controlPointRect(); - m_cachedBounds = m_path.boundingRect(); - - return m_cachedBounds; - } - else { - return boundsOnStroke(m_path, sw); - } + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(m_path).boundingRect() + : boundsOnStroke(p, m_path, sw); } QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly) @@ -223,15 +186,15 @@ QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly) { } -QRectF QSvgPolygon::bounds() const +QRectF QSvgPolygon::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_poly.boundingRect(); - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().map(m_poly).boundingRect(); + } else { QPainterPath path; path.addPolygon(m_poly); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } @@ -274,15 +237,15 @@ QSvgRect::QSvgRect(QSvgNode *node, const QRectF &rect, int rx, int ry) { } -QRectF QSvgRect::bounds() const +QRectF QSvgRect::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_rect; - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().mapRect(m_rect); + } else { QPainterPath path; path.addRect(m_rect); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } @@ -322,7 +285,7 @@ void QSvgText::setTextArea(const QSizeF &size) m_type = TEXTAREA; } -//QRectF QSvgText::bounds() const {} +//QRectF QSvgText::bounds(QPainter *p, QSvgExtraStates &) const {} void QSvgText::draw(QPainter *p, QSvgExtraStates &states) { @@ -593,80 +556,57 @@ QSvgNode::Type QSvgVideo::type() const return VIDEO; } -QRectF QSvgUse::bounds() const -{ - if (m_link && m_bounds.isEmpty()) { - m_bounds = m_link->bounds(); - m_bounds = QRectF(m_bounds.x()+m_start.x(), - m_bounds.y()+m_start.y(), - m_bounds.width(), - m_bounds.height()); - - return m_bounds; - } - return m_bounds; -} - -QRectF QSvgUse::transformedBounds(const QTransform &transform) const +QRectF QSvgUse::bounds(QPainter *p, QSvgExtraStates &states) const { QRectF bounds; - QTransform t = transform; - - if (m_link) { - QSvgTransformStyle *transStyle = m_style.transform; - if (transStyle) { - t = transStyle->qtransform() * t; - } - t.translate(m_start.x(), m_start.y()); - - bounds = m_link->transformedBounds(t); - - return bounds; + if (m_link) { + p->translate(m_start); + bounds = m_link->transformedBounds(p, states); + p->translate(-m_start); } return bounds; } -QRectF QSvgPolyline::bounds() const +QRectF QSvgPolyline::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_poly.boundingRect(); - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().map(m_poly).boundingRect(); + } else { QPainterPath path; path.addPolygon(m_poly); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } -QRectF QSvgArc::bounds() const +QRectF QSvgArc::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_cachedBounds; - else { - return boundsOnStroke(cubic, sw); - } + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(m_path).boundingRect() + : boundsOnStroke(p, m_path, sw); } -QRectF QSvgImage::bounds() const +QRectF QSvgImage::bounds(QPainter *p, QSvgExtraStates &) const { - return m_bounds; + return p->transform().mapRect(m_bounds); } -QRectF QSvgLine::bounds() const +QRectF QSvgLine::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); + qreal sw = strokeWidth(p); if (qFuzzyIsNull(sw)) { - qreal minX = qMin(m_bounds.x1(), m_bounds.x2()); - qreal minY = qMin(m_bounds.y1(), m_bounds.y2()); - qreal maxX = qMax(m_bounds.x1(), m_bounds.x2()); - qreal maxY = qMax(m_bounds.y1(), m_bounds.y2()); - return QRectF(minX, minY, maxX-minX, maxY-minY); + QPointF p1 = p->transform().map(m_line.p1()); + QPointF p2 = p->transform().map(m_line.p2()); + qreal minX = qMin(p1.x(), p2.x()); + qreal minY = qMin(p1.y(), p2.y()); + qreal maxX = qMax(p1.x(), p2.x()); + qreal maxY = qMax(p1.y(), p2.y()); + return QRectF(minX, minY, maxX - minX, maxY - minY); } else { QPainterPath path; - path.moveTo(m_bounds.x1(), m_bounds.y1()); - path.lineTo(m_bounds.x2(), m_bounds.y2()); - return boundsOnStroke(path, sw); + path.moveTo(m_line.p1()); + path.lineTo(m_line.p2()); + return boundsOnStroke(p, path, sw); } } diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h index ca06777..fdc770a 100644 --- a/src/svg/qsvggraphics_p.h +++ b/src/svg/qsvggraphics_p.h @@ -80,32 +80,27 @@ public: QSvgArc(QSvgNode *parent, const QPainterPath &path); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: - QPainterPath cubic; - QRectF m_cachedBounds; + QPainterPath m_path; }; -class QSvgCircle : public QSvgNode +class QSvgEllipse : public QSvgNode { public: - QSvgCircle(QSvgNode *parent, const QRectF &rect); + QSvgEllipse(QSvgNode *parent, const QRectF &rect); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QRectF m_bounds; }; -class QSvgEllipse : public QSvgNode +class QSvgCircle : public QSvgEllipse { public: - QSvgEllipse(QSvgNode *parent, const QRectF &rect); - virtual void draw(QPainter *p, QSvgExtraStates &states); + QSvgCircle(QSvgNode *parent, const QRectF &rect) : QSvgEllipse(parent, rect) { } virtual Type type() const; - virtual QRectF bounds() const; -private: - QRectF m_bounds; }; class QSvgImage : public QSvgNode @@ -115,7 +110,7 @@ public: const QRect &bounds); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QImage m_image; QRect m_bounds; @@ -127,9 +122,9 @@ public: QSvgLine(QSvgNode *parent, const QLineF &line); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: - QLineF m_bounds; + QLineF m_line; }; class QSvgPath : public QSvgNode @@ -138,14 +133,13 @@ public: QSvgPath(QSvgNode *parent, const QPainterPath &qpath); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; QPainterPath *qpath() { return &m_path; } private: QPainterPath m_path; - mutable QRectF m_cachedBounds; }; class QSvgPolygon : public QSvgNode @@ -154,7 +148,7 @@ public: QSvgPolygon(QSvgNode *parent, const QPolygonF &poly); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QPolygonF m_poly; }; @@ -165,7 +159,7 @@ public: QSvgPolyline(QSvgNode *parent, const QPolygonF &poly); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QPolygonF m_poly; }; @@ -176,7 +170,7 @@ public: QSvgRect(QSvgNode *paren, const QRectF &rect, int rx=0, int ry=0); virtual Type type() const; virtual void draw(QPainter *p, QSvgExtraStates &states); - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QRectF m_rect; int m_rx, m_ry; @@ -205,7 +199,7 @@ public: void addLineBreak() {m_tspans.append(LINEBREAK);} void setWhitespaceMode(WhitespaceMode mode) {m_mode = mode;} - //virtual QRectF bounds() const; + //virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: static QSvgTspan * const LINEBREAK; @@ -248,13 +242,11 @@ public: QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *link); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; - virtual QRectF transformedBounds(const QTransform &transform) const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QSvgNode *m_link; QPointF m_start; - mutable QRectF m_bounds; }; class QSvgVideo : public QSvgNode diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp index 86f2af5..f6bc1c0 100644 --- a/src/svg/qsvgnode.cpp +++ b/src/svg/qsvgnode.cpp @@ -45,6 +45,7 @@ #ifndef QT_NO_SVG #include "qdebug.h" +#include "qstack.h" QT_BEGIN_NAMESPACE @@ -114,12 +115,12 @@ void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id) } } -void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) +void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const { - m_style.apply(p, bounds(), this, states); + m_style.apply(p, this, states); } -void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) +void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const { m_style.revert(p, states); } @@ -195,11 +196,40 @@ QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const return doc ? doc->namedStyle(rid) : 0; } -QRectF QSvgNode::bounds() const +QRectF QSvgNode::bounds(QPainter *, QSvgExtraStates &) const { return QRectF(0, 0, 0, 0); } +QRectF QSvgNode::transformedBounds() const +{ + if (!m_cachedBounds.isEmpty()) + return m_cachedBounds; + + QImage dummy(1, 1, QImage::Format_RGB32); + QPainter p(&dummy); + QSvgExtraStates states; + + QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); + pen.setMiterLimit(4); + p.setPen(pen); + + QStack<QSvgNode*> parentApplyStack; + QSvgNode *parent = m_parent; + while (parent) { + parentApplyStack.push(parent); + parent = parent->parent(); + } + + for (int i = parentApplyStack.size() - 1; i >= 0; --i) + parentApplyStack[i]->applyStyle(&p, states); + + p.setWorldTransform(QTransform()); + + m_cachedBounds = transformedBounds(&p, states); + return m_cachedBounds; +} + QSvgTinyDocument * QSvgNode::document() const { QSvgTinyDocument *doc = 0; @@ -274,19 +304,11 @@ void QSvgNode::setVisible(bool visible) m_visible = visible; } -QRectF QSvgNode::transformedBounds(const QTransform &transform) const +QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const { - QTransform t = transform; - - QSvgTransformStyle *transStyle = m_style.transform; - if (transStyle) { - t = transStyle->qtransform() * t; - } - - QRectF rect = bounds(); - - rect = t.mapRect(rect); - + applyStyle(p, states); + QRectF rect = bounds(p, states); + revertStyle(p, states); return rect; } @@ -310,15 +332,12 @@ QSvgNode::DisplayMode QSvgNode::displayMode() const return m_displayMode; } -qreal QSvgNode::strokeWidth() const +qreal QSvgNode::strokeWidth(QPainter *p) { - QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle*>( - styleProperty(QSvgStyleProperty::STROKE)); - if (!stroke) - return 0; - if (stroke->stroke().brush().style() == Qt::NoBrush) + QPen pen = p->pen(); + if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic()) return 0; - return stroke->width(); + return pen.widthF(); } QT_END_NAMESPACE diff --git a/src/svg/qsvgnode_p.h b/src/svg/qsvgnode_p.h index 15466f2..a34c7c0 100644 --- a/src/svg/qsvgnode_p.h +++ b/src/svg/qsvgnode_p.h @@ -118,16 +118,17 @@ public: QSvgNode *parent() const; void appendStyleProperty(QSvgStyleProperty *prop, const QString &id); - void applyStyle(QPainter *p, QSvgExtraStates &states); - void revertStyle(QPainter *p, QSvgExtraStates &states); + void applyStyle(QPainter *p, QSvgExtraStates &states) const; + void revertStyle(QPainter *p, QSvgExtraStates &states) const; QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const; QSvgFillStyleProperty *styleProperty(const QString &id) const; QSvgTinyDocument *document() const; virtual Type type() const =0; - virtual QRectF bounds() const; - virtual QRectF transformedBounds(const QTransform &transform) const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; + virtual QRectF transformedBounds(QPainter *p, QSvgExtraStates &states) const; + QRectF transformedBounds() const; void setRequiredFeatures(const QStringList &lst); const QStringList & requiredFeatures() const; @@ -156,9 +157,9 @@ public: QString xmlClass() const; void setXmlClass(const QString &str); protected: - QSvgStyle m_style; + mutable QSvgStyle m_style; - qreal strokeWidth() const; + static qreal strokeWidth(QPainter *p); private: QSvgNode *m_parent; @@ -174,6 +175,7 @@ private: QString m_class; DisplayMode m_displayMode; + mutable QRectF m_cachedBounds; friend class QSvgTinyDocument; }; diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp index 34426b7..db5cb9e 100644 --- a/src/svg/qsvgstructure.cpp +++ b/src/svg/qsvgstructure.cpp @@ -357,15 +357,12 @@ void QSvgSwitch::init() m_systemLanguagePrefix = m_systemLanguage.mid(0, idx); } -QRectF QSvgStructureNode::bounds() const +QRectF QSvgStructureNode::bounds(QPainter *p, QSvgExtraStates &states) const { - if (m_bounds.isEmpty()) { - foreach(QSvgNode *node, m_renderers) { - m_bounds |= node->transformedBounds(QTransform()); - } - } - - return m_bounds; + QRectF bounds; + foreach(QSvgNode *node, m_renderers) + bounds |= node->transformedBounds(p, states); + return bounds; } QSvgNode * QSvgStructureNode::previousSiblingNode(QSvgNode *n) const diff --git a/src/svg/qsvgstructure_p.h b/src/svg/qsvgstructure_p.h index fd6eb0a..dd82fc0 100644 --- a/src/svg/qsvgstructure_p.h +++ b/src/svg/qsvgstructure_p.h @@ -74,14 +74,13 @@ public: ~QSvgStructureNode(); QSvgNode *scopeNode(const QString &id) const; void addChild(QSvgNode *child, const QString &id); - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; QSvgNode *previousSiblingNode(QSvgNode *n) const; QList<QSvgNode*> renderers() const { return m_renderers; } protected: QList<QSvgNode*> m_renderers; QHash<QString, QSvgNode*> m_scope; QList<QSvgStructureNode*> m_linkedScopes; - mutable QRectF m_bounds; }; class QSvgG : public QSvgStructureNode diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 2b12c49..0d1bad9 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -73,7 +73,7 @@ QSvgStyleProperty::~QSvgStyleProperty() { } -void QSvgFillStyleProperty::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgFillStyleProperty::apply(QPainter *, const QSvgNode *, QSvgExtraStates &) { Q_ASSERT(!"This should not be called!"); } @@ -89,7 +89,7 @@ QSvgQualityStyle::QSvgQualityStyle(int color) { } -void QSvgQualityStyle::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgQualityStyle::apply(QPainter *, const QSvgNode *, QSvgExtraStates &) { } @@ -136,7 +136,7 @@ void QSvgFillStyle::setBrush(QBrush brush) m_fillSet = 1; } -void QSvgFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldFill = p->brush(); m_oldFillRule = states.fillRule; @@ -169,7 +169,7 @@ QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush) { } -void QSvgViewportFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgViewportFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldFill = p->brush(); p->setBrush(m_viewportFill); @@ -224,7 +224,7 @@ int QSvgFontStyle::SVGToQtWeight(int weight) { return QFont::Normal; } -void QSvgFontStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgFontStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldQFont = p->font(); m_oldSvgFont = states.svgFont; @@ -292,7 +292,7 @@ QSvgStrokeStyle::QSvgStrokeStyle() { } -void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgStrokeStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldStroke = p->pen(); m_oldStrokeOpacity = states.strokeOpacity; @@ -443,7 +443,7 @@ QSvgTransformStyle::QSvgTransformStyle(const QTransform &trans) { } -void QSvgTransformStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgTransformStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldWorldTransform = p->worldTransform(); p->setWorldTransform(m_transform, true); @@ -501,7 +501,7 @@ QSvgCompOpStyle::QSvgCompOpStyle(QPainter::CompositionMode mode) } -void QSvgCompOpStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgCompOpStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldMode = p->compositionMode(); p->setCompositionMode(m_mode); @@ -521,34 +521,34 @@ QSvgStyle::~QSvgStyle() { } -void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states) +void QSvgStyle::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) { if (quality) { - quality->apply(p, rect, node, states); + quality->apply(p, node, states); } if (fill) { - fill->apply(p, rect, node, states); + fill->apply(p, node, states); } if (viewportFill) { - viewportFill->apply(p, rect, node, states); + viewportFill->apply(p, node, states); } if (font) { - font->apply(p, rect, node, states); + font->apply(p, node, states); } if (stroke) { - stroke->apply(p, rect, node, states); + stroke->apply(p, node, states); } if (transform) { - transform->apply(p, rect, node, states); + transform->apply(p, node, states); } if (animateColor) { - animateColor->apply(p, rect, node, states); + animateColor->apply(p, node, states); } //animated transforms have to be applied @@ -572,16 +572,16 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra // Apply the animateTransforms after and including the last one with additive="replace". for (; itr != animateTransforms.constEnd(); ++itr) { if ((*itr)->animActive(totalTimeElapsed)) - (*itr)->apply(p, rect, node, states); + (*itr)->apply(p, node, states); } } if (opacity) { - opacity->apply(p, rect, node, states); + opacity->apply(p, node, states); } if (compop) { - compop->apply(p, rect, node, states); + compop->apply(p, node, states); } } @@ -655,7 +655,7 @@ void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const m_count = args.count() / 3; } -void QSvgAnimateTransform::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &) +void QSvgAnimateTransform::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &) { m_oldWorldTransform = p->worldTransform(); resolveMatrix(node); @@ -669,7 +669,7 @@ void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &) m_transformApplied = false; } -void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) +void QSvgAnimateTransform::resolveMatrix(const QSvgNode *node) { static const qreal deg2rad = qreal(0.017453292519943295769); qreal totalTimeElapsed = node->document()->currentElapsed(); @@ -834,7 +834,7 @@ void QSvgAnimateColor::setRepeatCount(qreal repeatCount) m_repeatCount = repeatCount; } -void QSvgAnimateColor::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &) +void QSvgAnimateColor::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &) { qreal totalTimeElapsed = node->document()->currentElapsed(); if (totalTimeElapsed < m_from || m_finished) @@ -912,7 +912,7 @@ QSvgOpacityStyle::QSvgOpacityStyle(qreal opacity) } -void QSvgOpacityStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgOpacityStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldOpacity = p->opacity(); p->setOpacity(m_opacity * m_oldOpacity); diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index 202de93..af3b4e5 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -172,7 +172,7 @@ public: }; public: virtual ~QSvgStyleProperty(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states) =0; + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0; virtual void revert(QPainter *p, QSvgExtraStates &states) =0; virtual Type type() const=0; }; @@ -181,7 +181,7 @@ class QSvgFillStyleProperty : public QSvgStyleProperty { public: virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0; - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); }; @@ -189,7 +189,7 @@ class QSvgQualityStyle : public QSvgStyleProperty { public: QSvgQualityStyle(int color); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -221,7 +221,7 @@ class QSvgOpacityStyle : public QSvgStyleProperty { public: QSvgOpacityStyle(qreal opacity); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -233,7 +233,7 @@ class QSvgFillStyle : public QSvgStyleProperty { public: QSvgFillStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -306,7 +306,7 @@ class QSvgViewportFillStyle : public QSvgStyleProperty { public: QSvgViewportFillStyle(const QBrush &brush); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -330,7 +330,7 @@ public: QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc); QSvgFontStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -410,7 +410,7 @@ class QSvgStrokeStyle : public QSvgStyleProperty { public: QSvgStrokeStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -617,7 +617,7 @@ class QSvgTransformStyle : public QSvgStyleProperty { public: QSvgTransformStyle(const QTransform &transform); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -654,7 +654,7 @@ public: void setArgs(TransformType type, Additive additive, const QVector<qreal> &args); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; QSvgAnimateTransform::Additive additiveType() const @@ -688,7 +688,7 @@ public: } protected: - void resolveMatrix(QSvgNode *node); + void resolveMatrix(const QSvgNode *node); private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; @@ -712,7 +712,7 @@ public: void setArgs(bool fill, const QList<QColor> &colors); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -732,7 +732,7 @@ class QSvgCompOpStyle : public QSvgStyleProperty { public: QSvgCompOpStyle(QPainter::CompositionMode mode); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -766,7 +766,7 @@ public: {} ~QSvgStyle(); - void apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states); + void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); void revert(QPainter *p, QSvgExtraStates &states); QSvgRefCounter<QSvgQualityStyle> quality; QSvgRefCounter<QSvgFillStyle> fill; diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index 17618f7..b21b99f 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -277,7 +277,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id, p->save(); - const QRectF elementBounds = node->transformedBounds(QTransform()); + const QRectF elementBounds = node->transformedBounds(); mapSourceToTarget(p, bounds, elementBounds); QTransform originalTransform = p->worldTransform(); @@ -299,7 +299,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id, for (int i = parentApplyStack.size() - 1; i >= 0; --i) parentApplyStack[i]->applyStyle(p, m_states); - + // Reset the world transform so that our parents don't affect // the position QTransform currentTransform = p->worldTransform(); @@ -432,8 +432,7 @@ QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const const QSvgNode *node = scopeNode(id); if (!node) node = this; - - return node->transformedBounds(QTransform()); + return node->transformedBounds(); } bool QSvgTinyDocument::elementExists(const QString &id) const diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h index c03c798..3b40770 100644 --- a/src/svg/qsvgtinydocument_p.h +++ b/src/svg/qsvgtinydocument_p.h @@ -173,9 +173,8 @@ inline bool QSvgTinyDocument::heightPercent() const inline QRectF QSvgTinyDocument::viewBox() const { - if (m_viewBox.isNull()) { - m_viewBox = transformedBounds(QTransform()); - } + if (m_viewBox.isNull()) + m_viewBox = transformedBounds(); return m_viewBox; } diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml b/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml index 12b1b7b..5e1891a 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml @@ -10,7 +10,7 @@ Rectangle { width: 100; height: 100 color: Qt.rgba(1,0,0) Behavior on x { - NumberAnimation { objectName: "MyAnim"; running: true } + NumberAnimation {id: myAnim; objectName: "MyAnim"; running: true } } } diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml index 6419a6b..11b2d3a 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml @@ -8,8 +8,8 @@ Rectangle { width: 100; height: 100; color: "green" Behavior on x { objectName: "MyBehavior" - NumberAnimation { duration: 200 } - NumberAnimation { duration: 1000 } + NumberAnimation {id: na1; duration: 200 } + NumberAnimation {id: na2; duration: 1000 } } } MouseArea { diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml b/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml index c28fa9a..5e72bca 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml @@ -8,7 +8,7 @@ Rectangle { width: 100; height: 100; color: "green" Behavior on x { objectName: "MyBehavior"; - NumberAnimation { duration: 500; } + NumberAnimation {id: na; duration: 500; } } } MouseArea { diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index a03b2c7..701dc2e 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -999,10 +999,10 @@ void tst_QPainter::drawPixmapFragments() { QPixmap origPixmap(20, 20); QPixmap resPixmap(20, 20); - QPainter::Fragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, - { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, - {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, - { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; + QPainter::PixmapFragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, + { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, + {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, + { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; { QPainter p(&origPixmap); p.fillRect(0, 0, 10, 10, Qt::red); @@ -1025,7 +1025,7 @@ void tst_QPainter::drawPixmapFragments() QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5)); - QPainter::Fragment fragment = QPainter::Fragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); + QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); QVERIFY(fragment.x == 20); QVERIFY(fragment.y == 20); QVERIFY(fragment.sourceLeft == 30); diff --git a/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg b/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg index 99926b3..f1f9e35 100644 --- a/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg +++ b/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg @@ -4,12 +4,12 @@ <desc>Generated with Qt</desc> <defs> </defs> -<g fill="none" stroke="black" vector-effect="non-scaling-stroke" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > +<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > <g fill="#ff0000" fill-opacity="1" stroke="none" transform="matrix(1,0,0,1,0,0)" -font-family="Arial" font-size="11pt" font-weight="400" font-style="normal" +font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal" > -<path fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> +<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> </g> </g> </svg> diff --git a/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg b/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg index f61dd40..84afbf3 100644 --- a/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg +++ b/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg @@ -13,18 +13,18 @@ <stop offset="1" stop-color="#0000ff" stop-opacity="1" /> </radialGradient> </defs> -<g fill="none" stroke="black" vector-effect="non-scaling-stroke" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > +<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > <g fill="url(#gradient1)" stroke="none" transform="matrix(1,0,0,1,0,0)" -font-family="Sans Serif" font-size="9pt" font-weight="400" font-style="normal" +font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal" > -<path fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> +<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> </g> <g fill="url(#gradient2)" stroke="none" transform="matrix(1,0,0,1,0,0)" -font-family="Sans Serif" font-size="9pt" font-weight="400" font-style="normal" +font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal" > -<path fill-rule="evenodd" d="M100,0 L200,0 L200,100 L100,100 L100,0"/> +<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M100,0 L200,0 L200,100 L100,100 L100,0"/> </g> </g> </svg> diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 16dd2b4..106fd8c 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -74,6 +74,7 @@ private slots: void nestedQXmlStreamReader() const; void stylePropagation() const; void matrixForElement() const; + void boundsOnElement() const; void gradientStops() const; void gradientRefs(); void fillRule(); @@ -470,6 +471,36 @@ void tst_QSvgRenderer::matrixForElement() const compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("firkant")))); } +void tst_QSvgRenderer::boundsOnElement() const +{ + QByteArray data("<svg>" + "<g id=\"prim\" transform=\"translate(-3,1)\">" + "<g id=\"sjokade\" stroke=\"none\" stroke-width=\"10\">" + "<rect id=\"kaviar\" transform=\"rotate(45)\" x=\"-10\" y=\"-10\" width=\"20\" height=\"20\"/>" + "</g>" + "<g id=\"nugatti\" stroke=\"black\" stroke-width=\"2\">" + "<use x=\"0\" y=\"0\" transform=\"rotate(45)\" xlink:href=\"#kaviar\"/>" + "</g>" + "<g id=\"nutella\" stroke=\"none\" stroke-width=\"10\">" + "<path id=\"baconost\" transform=\"rotate(45)\" d=\"M-10 -10 L10 -10 L10 10 L-10 10 Z\"/>" + "</g>" + "<g id=\"hapaa\" transform=\"translate(-2,2)\" stroke=\"black\" stroke-width=\"2\">" + "<use x=\"0\" y=\"0\" transform=\"rotate(45)\" xlink:href=\"#baconost\"/>" + "</g>" + "</g>" + "</svg>"); + + qreal sqrt2 = qSqrt(2); + QSvgRenderer renderer(data); + QCOMPARE(renderer.boundsOnElement(QLatin1String("sjokade")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("kaviar")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("nugatti")), QRectF(-11, -11, 22, 22)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("nutella")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("baconost")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("hapaa")), QRectF(-13, -9, 22, 22)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("prim")), QRectF(-10 * sqrt2 - 3, -10 * sqrt2 + 1, 20 * sqrt2, 20 * sqrt2)); +} + void tst_QSvgRenderer::gradientStops() const { { diff --git a/tests/auto/qtextcodec/test/test.pro b/tests/auto/qtextcodec/test/test.pro index afd7f5e..efa2e85 100644 --- a/tests/auto/qtextcodec/test/test.pro +++ b/tests/auto/qtextcodec/test/test.pro @@ -27,6 +27,7 @@ wince*: { DEFINES += SRCDIR=\\\"\\\" }else:symbian { # Symbian can't define SRCDIR meaningfully here + LIBS += -lcharconv -lconvnames -lgb2312_shared -ljisx0201 -ljisx0208 -lefsrv } else { DEFINES += SRCDIR=\\\"$$PWD/../\\\" } diff --git a/tests/auto/qtextcodec/tst_qtextcodec.cpp b/tests/auto/qtextcodec/tst_qtextcodec.cpp index aa97e87..07fd480 100644 --- a/tests/auto/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/qtextcodec/tst_qtextcodec.cpp @@ -99,6 +99,13 @@ private slots: #ifdef Q_OS_UNIX void toLocal8Bit(); #endif + + void invalidNames(); + void checkAliases_data(); + void checkAliases(); + + void moreToFromUnicode_data(); + void moreToFromUnicode(); }; void tst_QTextCodec::toUnicode_data() @@ -119,6 +126,7 @@ void tst_QTextCodec::toUnicode() if ( file.open( QIODevice::ReadOnly ) ) { QByteArray ba = file.readAll(); + QVERIFY(!ba.isEmpty()); QTextCodec *c = QTextCodec::codecForName( codecName.toLatin1() ); QVERIFY(c != 0); QString uniString = c->toUnicode( ba ); @@ -126,6 +134,7 @@ void tst_QTextCodec::toUnicode() QCOMPARE(uniString, QString::fromUtf8(ba)); QCOMPARE(ba, uniString.toUtf8()); } + QVERIFY(!uniString.isEmpty()); QCOMPARE( ba, c->fromUnicode( uniString ) ); if (codecName == QLatin1String("eucKR")) { @@ -185,7 +194,9 @@ void tst_QTextCodec::fromUnicode_data() QTest::newRow("data16") << "ISO-8859-16" << true; QTest::newRow("data18") << "IBM850" << true; +#ifndef Q_OS_SYMBIAN //symbian implementation will return empty string if all char are invalid QTest::newRow("data19") << "IBM874" << true; +#endif QTest::newRow("data20") << "IBM866" << true; QTest::newRow("data21") << "windows-1250" << true; @@ -193,7 +204,9 @@ void tst_QTextCodec::fromUnicode_data() QTest::newRow("data23") << "windows-1252" << true; QTest::newRow("data24") << "windows-1253" << true; QTest::newRow("data25") << "windows-1254" << true; +#ifndef Q_OS_SYMBIAN //symbian implementation will return empty string if all char are invalid QTest::newRow("data26") << "windows-1255" << true; +#endif QTest::newRow("data27") << "windows-1256" << true; QTest::newRow("data28") << "windows-1257" << true; QTest::newRow("data28") << "windows-1258" << true; @@ -205,6 +218,39 @@ void tst_QTextCodec::fromUnicode_data() QTest::newRow("data32") << "SJIS" << false; QTest::newRow("data33") << "EUC-KR" << false; + + // all codecs from documentation + QTest::newRow("doc2") << "Big5" << false; + QTest::newRow("doc3") << "Big5-HKSCS" << false; + QTest::newRow("doc4") << "CP949" << false; + QTest::newRow("doc5") << "EUC-JP" << false; + QTest::newRow("doc6") << "EUC-KR" << false; + //QTest::newRow("doc7") << "GB18030-0" << false; // only GB18030 works + QTest::newRow("doc7-bis") << "GB18030" << false; + QTest::newRow("doc8") << "IBM 850" << false; + QTest::newRow("doc9") << "IBM 866" << false; + QTest::newRow("doc10") << "IBM 874" << false; + QTest::newRow("doc11") << "ISO 2022-JP" << false; + //ISO 8859-1 to 10 and ISO 8859-13 to 16 tested previously + // Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml tested in Iscii test + //QTest::newRow("doc12") << "JIS X 0201" << false; //actually not there + //QTest::newRow("doc13") << "JIS X 0208" << false; // actually not there + QTest::newRow("doc14") << "KOI8-R" << false; + QTest::newRow("doc15") << "KOI8-U" << false; + //QTest::newRow("doc16") << "MuleLao-1" << false; //only on x11 + QTest::newRow("doc17") << "ROMAN8" << false; + QTest::newRow("doc18") << "Shift-JIS" << false; + QTest::newRow("doc19") << "TIS-620" << false; + QTest::newRow("doc20") << "TSCII" << false; + QTest::newRow("doc21") << "UTF-8" << false; + QTest::newRow("doc22") << "UTF-16" << false; + QTest::newRow("doc23") << "UTF-16BE" << false; + QTest::newRow("doc24") << "UTF-16LE" << false; + QTest::newRow("doc25") << "UTF-32" << false; + QTest::newRow("doc26") << "UTF-32BE" << false; + QTest::newRow("doc27") << "UTF-32LE" << false; + //Windows-1250 to 1258 tested previously + QTest::newRow("doc3") << "WINSAMI2" << false; } void tst_QTextCodec::fromUnicode() @@ -222,6 +268,7 @@ void tst_QTextCodec::fromUnicode() chars[i] = i + 128; QString s = codec->toUnicode(chars, 128); QByteArray c = codec->fromUnicode(s); + QCOMPARE(c.size(), 128); int numberOfQuestionMarks = 0; for (int i = 0; i < 128; ++i) { @@ -360,7 +407,7 @@ void tst_QTextCodec::asciiToIscii() const /* For each codec. */ const QTextCodec *const textCodec = QTextCodec::codecForName(isciiCodecs[i]); - Q_ASSERT(textCodec); + QVERIFY(textCodec); for(int i2 = 0; i2 < len; ++i2) { /* For each character in ascii. */ @@ -478,7 +525,9 @@ void tst_QTextCodec::aliasForUTF16() const void tst_QTextCodec::mibForTSCII() const { - QCOMPARE(QTextCodec::codecForName("TSCII")->mibEnum(), 2107); + QTextCodec *codec = QTextCodec::codecForName("TSCII"); + QVERIFY(codec); + QCOMPARE(codec->mibEnum(), 2107); } static QString fromInvalidUtf8Sequence(const QByteArray &ba) @@ -1938,17 +1987,210 @@ static int loadAndConvertMIB(int mib) void tst_QTextCodec::threadSafety() { + QList<QByteArray> codecList = QTextCodec::availableCodecs(); + QList<int> mibList = QTextCodec::availableMibs(); +#ifndef QT_NO_CONCURRENT QThreadPool::globalInstance()->setMaxThreadCount(12); - QList<QByteArray> codecList = QTextCodec::availableCodecs(); QFuture<QByteArray> res = QtConcurrent::mapped(codecList, loadAndConvert); - QList<int> mibList = QTextCodec::availableMibs(); + QFuture<int> res2 = QtConcurrent::mapped(mibList, loadAndConvertMIB); QCOMPARE(res.results(), codecList); QCOMPARE(res2.results(), mibList); +#endif } +void tst_QTextCodec::invalidNames() +{ + QVERIFY(!QTextCodec::codecForName("")); + QVERIFY(!QTextCodec::codecForName(QByteArray())); + QVERIFY(!QTextCodec::codecForName("-")); + QVERIFY(!QTextCodec::codecForName("\1a\2b\3a\4d\5c\6s\7a\xffr\xec_\x9c_")); + QVERIFY(!QTextCodec::codecForName("\n")); + QVERIFY(!QTextCodec::codecForName("don't exist")); + QByteArray huge = "azertyuiop^$qsdfghjklm<wxcvbn,;:=1234567890°_"; + huge = huge + huge + huge + huge + huge + huge + huge + huge; + huge = huge + huge + huge + huge + huge + huge + huge + huge; + huge = huge + huge + huge + huge + huge + huge + huge + huge; + huge = huge + huge + huge + huge + huge + huge + huge + huge; + QVERIFY(!QTextCodec::codecForName(huge)); +} + +void tst_QTextCodec::checkAliases_data() +{ + QTest::addColumn<QByteArray>("codecName"); + QList<QByteArray> codecList = QTextCodec::availableCodecs(); + foreach (const QByteArray &a, codecList) { + QTest::newRow( a.constData() ) << a; + } +} + +void tst_QTextCodec::checkAliases() +{ + QFETCH( QByteArray, codecName ); + QTextCodec *c = QTextCodec::codecForName(codecName); + QVERIFY(c); + QCOMPARE(QTextCodec::codecForName(codecName), c); + QCOMPARE(QTextCodec::codecForName(c->name()), c); + + foreach(const QByteArray &a, c->aliases()) { + QCOMPARE(QTextCodec::codecForName(a), c); + } +} + + +void tst_QTextCodec::moreToFromUnicode_data() { + QTest::addColumn<QByteArray>("codecName"); + QTest::addColumn<QByteArray>("testData"); + + QTest::newRow("russian") << QByteArray("ISO-8859-5") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF\x00"); + + QTest::newRow("arabic") << QByteArray("ISO-8859-6") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA4\xAC\xAD\xBB\xBF\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2"); + + QTest::newRow("greek") << QByteArray("ISO-8859-7") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA6\xA7\xA8\xA9\xAB\xAC\xAD\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE"); + + QTest::newRow("turkish") << QByteArray("ISO-8859-9") + << QByteArray("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + +#ifdef Q_OS_SYMBIAN + QTest::newRow("thai") << QByteArray("TIS-620") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB"); +#endif + + QTest::newRow("latin1") << QByteArray("ISO-8859-1") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QByteArray sms7bit_ba; + for (int i=1; i <= 0x7f; ++i) { + if (i!='\x1b') { + sms7bit_ba.append(i); + } + } +#ifdef Q_OS_SYMBIAN + QTest::newRow("sms7bit") << QByteArray("SMS 7-bit") << sms7bit_ba; +#endif + + QTest::newRow("latin2") << QByteArray("ISO-8859-2") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("latin3") << QByteArray("ISO-8859-3") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBF\xC0\xC1\xC2\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("latin4") << QByteArray("ISO-8859-4") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("russian 2") << QByteArray("ISO-8859-5") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("arabic 2") << QByteArray("ISO-8859-6") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA4\xAC\xAD\xBB\xBF\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2"); + + QTest::newRow("greek 2") << QByteArray("ISO-8859-7") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA6\xA7\xA8\xA9\xAB\xAC\xAD\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE"); + +#ifdef Q_OS_SYMBIAN + QTest::newRow("hebriew") << QByteArray("ISO-8859-8") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFD\xFE"); +#endif + + QTest::newRow("latin5") << QByteArray("ISO-8859-9") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("latin6") << QByteArray("ISO-8859-10") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + +#if 0 + QByteArray iso8859_11_ba; + for (int x=0x20; x<=0x7f; ++x) { + iso8859_11_ba.append(x); + } + for (int x=0xa0; x<0xff; ++x) { + if ((x>=0xdb && x<0xdf) || x>0xfb){ + continue; + } + iso8859_11_ba.append(x); + } + QTest::newRow("latin-thai") << QByteArray("ISO-8859-11") << iso8859_11_ba; +#endif + + QTest::newRow("latin7") << QByteArray("ISO-8859-13") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("celtic") << QByteArray("ISO-8859-14") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("latin9") << QByteArray("ISO-8859-15") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("latin10") << QByteArray("ISO-8859-16") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp850") << QByteArray("CP850") + << QByteArray("\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"); + + QTest::newRow("cp874") << QByteArray("CP874") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x85\x91\x92\x93\x94\x95\x96\x97\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB"); + + QTest::newRow("cp1250") << QByteArray("CP1250") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x84\x85\x86\x87\x89\x8A\x8B\x8C\x8D\x8E\x8F\x91\x92\x93\x94\x95\x96\x97\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp1251") << QByteArray("CP1251") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp1252") << QByteArray("CP1252") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8E\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp1253") << QByteArray("CP1253") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x83\x84\x85\x86\x87\x89\x8B\x91\x92\x93\x94\x95\x96\x97\x99\x9B\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE"); + + QTest::newRow("cp1254") << QByteArray("CP1254") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp1255") << QByteArray("CP1255") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x83\x84\x85\x86\x87\x88\x89,x8B\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9B\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFD\xFE"); + + QTest::newRow("cp1256") << QByteArray("CP1256") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp1257") << QByteArray("CP1257") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x84\x85\x86\x87\x89\x8B\x8D\x8E\x8F\x91\x92\x93\x94\x95\x96\x97\x99\x9B\x9D\x9E\xA0\xA2\xA3\xA4\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QTest::newRow("cp1258") << QByteArray("CP1258") + << QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8B\x8C\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9B\x9C\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"); + + QByteArray koi8_r_ba; + for (int x=0x20; x<=0xff; ++x) { + if (x!=0x9A && x!=0xbf) { + koi8_r_ba.append(x); + } + } + QTest::newRow("KOI8-R") << QByteArray("KOI8-R") << koi8_r_ba; + + QByteArray koi8_u_ba; + for (int x=0x20; x<=0xff; ++x) { + koi8_u_ba.append(x); + } + QTest::newRow("KOI8-U") << QByteArray("KOI8-U") << koi8_u_ba; +} + +void tst_QTextCodec::moreToFromUnicode() +{ + QFETCH( QByteArray, codecName ); + QFETCH( QByteArray, testData ); + + QTextCodec *c = QTextCodec::codecForName( codecName.data() ); + QVERIFY(c); + + QString uStr = c->toUnicode(testData); + QByteArray cStr = c->fromUnicode(uStr); + QCOMPARE(testData, cStr); +} + + QTEST_MAIN(tst_QTextCodec) #include "tst_qtextcodec.moc" diff --git a/tests/auto/qtextstream/tst_qtextstream.cpp b/tests/auto/qtextstream/tst_qtextstream.cpp index 9146be2..4c78ef0 100644 --- a/tests/auto/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/qtextstream/tst_qtextstream.cpp @@ -221,6 +221,7 @@ private slots: void nanInf(); void utf8IncompleteAtBufferBoundary_data(); void utf8IncompleteAtBufferBoundary(); + void writeSeekWriteNoBOM(); // status void status_real_read_data(); @@ -1847,6 +1848,63 @@ void tst_QTextStream::utf8IncompleteAtBufferBoundary() } // ------------------------------------------------------------------------------ + +// Make sure we don't write a BOM after seek()ing + +void tst_QTextStream::writeSeekWriteNoBOM() +{ + + //First with the default codec (normally either latin-1 or UTF-8) + + QBuffer out; + out.open(QIODevice::WriteOnly); + QTextStream stream(&out); + + int number = 0; + QString sizeStr = QLatin1String("Size=") + + QString::number(number).rightJustified(10, QLatin1Char('0')); + stream << sizeStr << endl; + stream << "Version=" << QString::number(14) << endl; + stream << "blah blah blah" << endl; + stream.flush(); + + QCOMPARE(out.buffer().constData(), "Size=0000000000\nVersion=14\nblah blah blah\n"); + + // Now overwrite the size header item + number = 42; + stream.seek(0); + sizeStr = QLatin1String("Size=") + + QString::number(number).rightJustified(10, QLatin1Char('0')); + stream << sizeStr << endl; + stream.flush(); + + // Check buffer is still OK + QCOMPARE(out.buffer().constData(), "Size=0000000042\nVersion=14\nblah blah blah\n"); + + + //Then UTF-16 + + QBuffer out16; + out16.open(QIODevice::WriteOnly); + QTextStream stream16(&out16); + stream16.setCodec("UTF-16"); + + stream16 << "one" << "two" << QLatin1String("three"); + stream16.flush(); + + // save that output + QByteArray first = out16.buffer(); + + stream16.seek(0); + stream16 << "one"; + stream16.flush(); + + QCOMPARE(out16.buffer(), first); +} + + + +// ------------------------------------------------------------------------------ void tst_QTextStream::generateOperatorCharData(bool for_QString) { QTest::addColumn<QByteArray>("input"); diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro index 2c042b5..76c26c1 100644 --- a/tests/benchmarks/gui/painting/painting.pro +++ b/tests/benchmarks/gui/painting/painting.pro @@ -3,4 +3,5 @@ SUBDIRS = \ qpainter \ qregion \ qtransform \ - qtracebench + qtracebench \ + qtbench diff --git a/tests/benchmarks/gui/painting/qtbench/benchmarktests.h b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h new file mode 100644 index 0000000..362d121 --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h @@ -0,0 +1,841 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BENCHMARKTESTS_H +#define BENCHMARKTESTS_H + +#include <QApplication> +#include <QTextDocument> +#include <QDesktopWidget> +#include <QTextLayout> +#include <QFontMetrics> +#include <QDebug> + +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) +# include <QStaticText> +#endif + +class Benchmark +{ +public: + virtual ~Benchmark() {} + + Benchmark(const QSize &size) + : m_size(size) + { + for (int i=0; i<16; ++i) { + m_colors[i] = QColor::fromRgbF((rand() % 4) / 3.0, + (rand() % 4) / 3.0, + (rand() % 4) / 3.0, + 1); + } + } + + virtual void draw(QPainter *p, const QRect &rect, int iteration) = 0; + virtual QString name() const = 0; + + inline const QSize &size() const + { + return m_size; + } + virtual void begin(QPainter *, int iterations = 1) { Q_UNUSED(iterations); } + virtual void end(QPainter *) { } + + inline const QColor &randomColor(int i) { return m_colors[i % 16]; } + +protected: + QColor m_colors[16]; + QSize m_size; +}; + +class PaintingRectAdjuster +{ +public: + PaintingRectAdjuster() + : m_benchmark(0), + m_bounds(), + m_screen_filled(false) + { + } + + const QRect &newPaintingRect() { + m_rect.translate(m_rect.width(), 0); + + if (m_rect.right() > m_bounds.width()) { + m_rect.moveLeft(m_bounds.left()); + m_rect.translate(0,m_rect.height()); + if (m_rect.bottom() > m_bounds.height()) { + m_screen_filled = true; + m_rect.moveTo(m_bounds.topLeft()); + } + } + return m_rect; + } + + inline bool isScreenFilled() const + { return m_screen_filled; } + + void reset(const QRect &bounds) + { + m_bounds = bounds; + m_rect.moveTo(m_bounds.topLeft()); + m_rect = QRect(m_bounds.topLeft(),m_benchmark->size()); + m_rect.translate(-m_rect.width(),0); + m_screen_filled = false; + } + + inline void setNewBenchmark( Benchmark *benchmark ) + { + m_benchmark = benchmark; + } + +protected: + Benchmark *m_benchmark; + QRect m_rect; + QRect m_bounds; + bool m_screen_filled; +}; + +class FillRectBenchmark : public Benchmark +{ +public: + FillRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + } + + virtual void draw(QPainter *p, const QRect &rect, int iterationCount) { + p->fillRect(rect, randomColor(iterationCount)); + } + + virtual QString name() const { + return QString::fromLatin1("fillRect(%1)").arg(m_size.width()); + } +}; + +class ImageFillRectBenchmark : public Benchmark +{ +public: + ImageFillRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + int s = rand() % 24 + 8; + m_content = QImage(s, s, QImage::Format_ARGB32_Premultiplied); + QPainter p(&m_content); + p.fillRect(0, 0, s, s, Qt::white); + p.fillRect(s/2, 0, s/2, s/2, Qt::gray); + p.fillRect(0, s/2, s/2, s/2, Qt::gray); + p.end(); + + m_brush = QBrush(m_content); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->fillRect(rect, m_brush); + } + + virtual QString name() const { + return QString::fromLatin1("fillRect with image(%1)").arg(m_size.width()); + } + +private: + QImage m_content; + QBrush m_brush; +}; + + +class DrawRectBenchmark : public Benchmark +{ +public: + DrawRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + } + + virtual void begin(QPainter *p, int) { + p->setPen(Qt::NoPen); + p->setBrush(randomColor(m_size.width())); + } + + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->drawRect(rect); + } + + virtual QString name() const { + return QString::fromLatin1("drawRect(%1)").arg(m_size.width()); + } +}; + + +class DrawRectWithBrushChangeBenchmark : public Benchmark +{ +public: + DrawRectWithBrushChangeBenchmark(int size) + : Benchmark(QSize(size, size)) + { + } + + virtual void begin(QPainter *p, int) { + p->setPen(Qt::NoPen); + } + + + virtual void draw(QPainter *p, const QRect &rect, int i) { + p->setBrush(randomColor(i)); + p->drawRect(rect); + } + + virtual QString name() const { + return QString::fromLatin1("drawRect with brushchange(%1)").arg(m_size.width()); + } +}; + +class RoundRectBenchmark : public Benchmark +{ +public: + RoundRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + m_roundness = size / 4.; + } + + virtual void begin(QPainter *p, int) { + p->setPen(Qt::NoPen); + p->setBrush(Qt::red); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->drawRoundedRect(rect, m_roundness, m_roundness); + } + + virtual QString name() const { + return QString::fromLatin1("drawRoundedRect(%1)").arg(m_size.width()); + } + + qreal m_roundness; +}; + + +class ArcsBenchmark : public Benchmark +{ +public: + enum Type { + Stroked = 0x0001, + Filled = 0x0002, + + ArcShape = 0x0010, + ChordShape = 0x0020, + PieShape = 0x0040, + CircleShape = 0x0080, + Shapes = 0x00f0 + + }; + + ArcsBenchmark(int size, uint type) + : Benchmark(QSize(size, size)), + m_type(type) + { + } + + virtual void begin(QPainter *p, int) { + if (m_type & Stroked) + p->setPen(Qt::black); + else + p->setPen(Qt::NoPen); + + if (m_type & Filled) + p->setBrush(Qt::red); + else + p->setBrush(Qt::NoBrush); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + switch (m_type & Shapes) { + case ArcShape: + p->drawArc(rect, 45*16, 120*16); + break; + case ChordShape: + p->drawChord(rect, 45*16, 120*16); + break; + case PieShape: + p->drawPie(rect, 45*16, 120*16); + break; + case CircleShape: + p->drawEllipse(rect); + break; + } + } + + virtual QString name() const { + QString fillStroke; + + if ((m_type & (Stroked|Filled)) == (Stroked|Filled)) { + fillStroke = QLatin1String("Fill & Outline"); + } else if (m_type & Stroked) { + fillStroke = QLatin1String("Outline"); + } else if (m_type & Filled) { + fillStroke = QLatin1String("Fill"); + } + + QString shape; + if (m_type & PieShape) shape = QLatin1String("drawPie"); + else if (m_type & ChordShape) shape = QLatin1String("drawChord"); + else if (m_type & ArcShape) shape = QLatin1String("drawArc"); + else if (m_type & CircleShape) shape = QLatin1String("drawEllipse"); + + return QString::fromLatin1("%1(%2) %3").arg(shape).arg(m_size.width()).arg(fillStroke); + } + + uint m_type; +}; + + +class DrawScaledImage : public Benchmark +{ +public: + DrawScaledImage(const QImage &image, qreal scale, bool asPixmap) + : Benchmark(QSize(image.width(), image.height())), + m_image(image), + m_type(m_as_pixmap ? "Pixmap" : "Image"), + m_scale(scale), + m_as_pixmap(asPixmap) + { + m_pixmap = QPixmap::fromImage(m_image); + } + DrawScaledImage(const QString& type, const QPixmap &pixmap, qreal scale) + : Benchmark(QSize(pixmap.width(), pixmap.height())), + m_type(type), + m_scale(scale), + m_as_pixmap(true), + m_pixmap(pixmap) + { + } + + virtual void begin(QPainter *p, int) { + p->scale(m_scale, m_scale); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + if (m_as_pixmap) + p->drawPixmap(rect.topLeft(), m_pixmap); + else + p->drawImage(rect.topLeft(), m_image); + } + + virtual QString name() const { + return QString::fromLatin1("draw%4(%1) at scale=%2, depth=%3") + .arg(m_size.width()) + .arg(m_scale) + .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth()) + .arg(m_type); + } + +private: + QImage m_image; + QString m_type; + qreal m_scale; + bool m_as_pixmap; + QPixmap m_pixmap; +}; + +class DrawTransformedImage : public Benchmark +{ +public: + DrawTransformedImage(const QImage &image, bool asPixmap) + : Benchmark(QSize(image.width(), image.height())), + m_image(image), + m_type(m_as_pixmap ? "Pixmap" : "Image"), + m_as_pixmap(asPixmap) + { + m_pixmap = QPixmap::fromImage(m_image); + } + DrawTransformedImage(const QString& type, const QPixmap &pixmap) + : Benchmark(QSize(pixmap.width(), pixmap.height())), + m_type(type), + m_as_pixmap(true), + m_pixmap(pixmap) + { + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + QTransform oldTransform = p->transform(); + p->translate(0.5 * rect.width() + rect.left(), 0.5 * rect.height() + rect.top()); + p->shear(0.25, 0.0); + p->rotate(5.0); + if (m_as_pixmap) + p->drawPixmap(-0.5 * rect.width(), -0.5 * rect.height(), m_pixmap); + else + p->drawImage(-0.5 * rect.width(), -0.5 * rect.height(), m_image); + p->setTransform(oldTransform); + } + + virtual QString name() const { + return QString::fromLatin1("draw%3(%1) w/transform, depth=%2") + .arg(m_size.width()) + .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth()) + .arg(m_type); + } + +private: + QImage m_image; + QString m_type; + bool m_as_pixmap; + QPixmap m_pixmap; +}; + + +class DrawImage : public Benchmark +{ +public: + DrawImage(const QImage &image, bool asPixmap) + : Benchmark(QSize(image.width(), image.height())), + m_image(image), + m_type(m_as_pixmap ? "Pixmap" : "Image"), + m_as_pixmap(asPixmap) + { + m_pixmap = QPixmap::fromImage(image); + } + DrawImage(const QString& type, const QPixmap &pixmap) + : Benchmark(QSize(pixmap.width(), pixmap.height())), + m_type(type), + m_as_pixmap(true), + m_pixmap(pixmap) + { + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + if (m_as_pixmap) + p->drawPixmap(rect.topLeft(), m_pixmap); + else + p->drawImage(rect.topLeft(), m_image); + } + + virtual QString name() const { + return QString::fromLatin1("draw%2(%1), depth=%3") + .arg(m_size.width()) + .arg(m_type) + .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth()); + } + +private: + QImage m_image; + QString m_type; + bool m_as_pixmap; + QPixmap m_pixmap; +}; + + +class DrawText : public Benchmark +{ +public: + enum Mode { + PainterMode, + PainterQPointMode, + LayoutMode, + DocumentMode, + PixmapMode + +#if QT_VERSION >= 0x040700 + , StaticTextMode, + StaticTextWithMaximumSizeMode, + StaticTextBackendOptimizations +#endif + }; + + DrawText(const QString &text, Mode mode) + : Benchmark(QSize()), m_mode(mode), m_text(text), m_document(text), m_layout(text) + { + } + + virtual void begin(QPainter *p, int iterations) { +#if QT_VERSION >= 0x040700 + m_staticTexts.clear(); + m_currentStaticText = 0; +#else + Q_UNUSED(iterations); +#endif + m_pixmaps.clear(); + m_currentPixmap = 0; + QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height()); + switch (m_mode) { + case PainterMode: + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); +// m_rect = m_rect.translated(-m_rect.topLeft()); + break; + case DocumentMode: + m_size = QSize(m_document.size().toSize()); + break; + case PixmapMode: + for (int i=0; i<4; ++i) { + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); + QPixmap pixmap = QPixmap(m_size); + pixmap.fill(Qt::transparent); + { + QPainter p(&pixmap); + p.drawText(pixmap.rect(), m_text); + } + m_pixmaps.append(pixmap); + } + break; + + case LayoutMode: { + QRect r = p->boundingRect(m_bounds, 0, m_text); + QStringList lines = m_text.split('\n'); + int height = 0; + int leading = p->fontMetrics().leading(); + m_layout.beginLayout(); + for (int i=0; i<lines.size(); ++i) { + QTextLine textLine = m_layout.createLine(); + if (textLine.isValid()) { + textLine.setLineWidth(r.width()); + textLine.setPosition(QPointF(0, height)); + height += leading + textLine.height(); + } + } + m_layout.endLayout(); + m_layout.setCacheEnabled(true); + m_size = m_layout.boundingRect().toRect().size(); + break; } + +#if QT_VERSION >= 0x040700 + case StaticTextWithMaximumSizeMode: { + QStaticText staticText; + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); + staticText.setMaximumSize(m_size + QSize(10, 10)); + staticText.setText(m_text); + staticText.prepare(p->transform(), p->font()); + m_staticTexts.append(staticText); + break; + } + case StaticTextBackendOptimizations: { + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); + for (int i=0; i<iterations; ++i) { + QStaticText staticText; + staticText.setPerformanceHint(QStaticText::AggressiveCaching); + staticText.setMaximumSize(m_size + QSize(10, 10)); + staticText.setText(m_text); + staticText.prepare(p->transform(), p->font()); + m_staticTexts.append(staticText); + } + + break; + } + case StaticTextMode: { + QStaticText staticText; + staticText.setText(m_text); + staticText.prepare(p->transform(), p->font()); + m_staticTexts.append(staticText); + + QFontMetrics fm(p->font()); + m_size = QSize(fm.width(m_text, m_text.length()), fm.height()); + + break; + } +#endif + + case PainterQPointMode: { + QFontMetrics fm(p->font()); + m_size = QSize(fm.width(m_text, m_text.length()), fm.height()); + break; + } + + } + } + + virtual void draw(QPainter *p, const QRect &rect, int) + { + switch (m_mode) { + case PainterMode: + p->drawText(rect, 0, m_text); + break; + case PainterQPointMode: + p->drawText(rect.topLeft(), m_text); + break; + case PixmapMode: + p->drawPixmap(rect.topLeft(), m_pixmaps.at(m_currentPixmap)); + m_currentPixmap = (m_currentPixmap + 1) % m_pixmaps.size(); + break; + case DocumentMode: + p->translate(rect.topLeft()); + m_document.drawContents(p); + p->translate(-rect.topLeft()); + break; + case LayoutMode: + m_layout.draw(p, rect.topLeft()); + break; + +#if QT_VERSION >= 0x040700 + case StaticTextWithMaximumSizeMode: + case StaticTextMode: + p->drawStaticText(rect.topLeft(), m_staticTexts.at(0)); + break; + case StaticTextBackendOptimizations: + p->drawStaticText(rect.topLeft(), m_staticTexts.at(m_currentStaticText)); + m_currentStaticText = (m_currentStaticText + 1) % m_staticTexts.size(); + break; +#endif + } + } + + virtual QString name() const { + int letters = m_text.length(); + int lines = m_text.count('\n'); + if (lines == 0) + lines = 1; + QString type; + switch (m_mode) { + case PainterMode: type = "drawText(rect)"; break; + case PainterQPointMode: type = "drawText(point)"; break; + case LayoutMode: type = "layout.draw()"; break; + case DocumentMode: type = "doc.drawContents()"; break; + case PixmapMode: type = "pixmap cached text"; break; + +#if QT_VERSION >= 0x040700 + case StaticTextMode: type = "drawStaticText()"; break; + case StaticTextWithMaximumSizeMode: type = "drawStaticText() w/ maxsize"; break; + case StaticTextBackendOptimizations: type = "drawStaticText() w/ backend optimizations"; break; +#endif + } + + return QString::fromLatin1("%3, len=%1, lines=%2") + .arg(letters) + .arg(lines) + .arg(type); + } + +private: + Mode m_mode; + QString m_text; + QTextDocument m_document; + QTextLayout m_layout; + + QList<QPixmap> m_pixmaps; + int m_currentPixmap; + +#if QT_VERSION >= 0x040700 + int m_currentStaticText; + QList<QStaticText> m_staticTexts; +#endif +}; + + + + +class ClippedDrawRectBenchmark : public Benchmark +{ +public: + enum ClipType { + RectClip, + TwoRectRegionClip, + EllipseRegionClip, + TwoRectPathClip, + EllipsePathClip, + AAEllipsePathClip, + EllipseRegionThenRectClip, + EllipsePathThenRectClip + }; + + ClippedDrawRectBenchmark(int size, ClipType type) + : Benchmark(QSize(size, size)), m_type(type) + { + } + + virtual void begin(QPainter *p, int) { + QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height()); + p->setPen(Qt::NoPen); + p->setBrush(Qt::red); + + switch (m_type) { + case RectClip: + p->setClipRect(m_bounds.adjusted(1, 1, -1, -1)); + break; + case TwoRectRegionClip: + p->setClipRegion(QRegion(m_bounds.adjusted(0, 0, -1, -1)) + | QRegion(m_bounds.adjusted(1, 1, 0, 0))); + break; + case EllipseRegionClip: + p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse)); + break; + case TwoRectPathClip: + { + QPainterPath path; + path.addRect(m_bounds.adjusted(0, 0, -1, -1)); + path.addRect(m_bounds.adjusted(1, 1, 0, 0)); + path.setFillRule(Qt::WindingFill); + p->setClipPath(path); + } + break; + case EllipsePathClip: + { + QPainterPath path; + path.addEllipse(m_bounds); + p->setClipPath(path); + } + break; + case AAEllipsePathClip: + { + QPainterPath path; + path.addEllipse(m_bounds); + p->setRenderHint(QPainter::Antialiasing); + p->setClipPath(path); + p->setRenderHint(QPainter::Antialiasing, false); + } + break; + case EllipseRegionThenRectClip: + p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse)); + p->setClipRegion(QRegion(m_bounds.width() / 4, + m_bounds.height() / 4, + m_bounds.width() / 2, + m_bounds.height() / 2), Qt::IntersectClip); + break; + case EllipsePathThenRectClip: + { + QPainterPath path; + path.addEllipse(m_bounds); + p->setClipPath(path); + p->setClipRegion(QRegion(m_bounds.width() / 4, + m_bounds.height() / 4, + m_bounds.width() / 2, + m_bounds.height() / 2), Qt::IntersectClip); + } + break; + } + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->drawRect(rect); + } + + virtual QString name() const { + QString namedType; + switch (m_type) { + case RectClip: + namedType = "rect"; + break; + case TwoRectRegionClip: + namedType = "two-rect-region"; + break; + case EllipseRegionClip: + namedType = "ellipse-region"; + break; + case TwoRectPathClip: + namedType = "two-rect-path"; + break; + case EllipsePathClip: + namedType = "ellipse-path"; + break; + case AAEllipsePathClip: + namedType = "aa-ellipse-path"; + break; + case EllipseRegionThenRectClip: + namedType = "ellipseregion&rect"; + break; + case EllipsePathThenRectClip: + namedType = "ellipsepath&rect"; + break; + } + return QString::fromLatin1("%1-clipped-drawRect(%2)").arg(namedType).arg(m_size.width()); + } + + ClipType m_type; +}; + +class LinesBenchmark : public Benchmark +{ +public: + enum LineType { + Horizontal_Integer, + Diagonal_Integer, + Vertical_Integer, + Horizontal_Float, + Diagonal_Float, + Vertical_Float + }; + + LinesBenchmark(int length, LineType type) + : Benchmark(QSize(qAbs(length), qAbs(length))), + m_type(type), + m_length(length) + { + + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + switch (m_type) { + case Horizontal_Integer: + p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y())); + break; + case Diagonal_Integer: + p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length)); + break; + case Vertical_Integer: + p->drawLine(QLine(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length)); + break; + case Horizontal_Float: + p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y())); + break; + case Diagonal_Float: + p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length)); + break; + case Vertical_Float: + p->drawLine(QLineF(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length)); + break; + } + } + + virtual QString name() const { + const char *names[] = { + "Hor_I", + "Diag_I", + "Ver_I", + "Hor_F", + "Diag_F", + "Ver_F" + }; + return QString::fromLatin1("drawLine(size=%1,type=%2)").arg(m_length).arg(names[m_type]); + } + + LineType m_type; + int m_length; +}; + +#endif // BENCHMARKTESTS_H diff --git a/tests/benchmarks/gui/painting/qtbench/qtbench.pro b/tests/benchmarks/gui/painting/qtbench/qtbench.pro new file mode 100644 index 0000000..91f416d --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/qtbench.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qtbench + +SOURCES += tst_qtbench.cpp + diff --git a/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp new file mode 100644 index 0000000..8eef472 --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> + +#include <QtGui> + +#include "benchmarktests.h" + +//TESTED_FILES= + +class BenchWidget : public QWidget +{ +public: + BenchWidget(Benchmark *benchmark); + + void paintEvent(QPaintEvent *event); + + bool done() const { return m_done; } + qreal result() const { return m_result; } + +public: + QTime timer; + + Benchmark *m_benchmark; + + bool m_done; + qreal m_result; + + uint m_total; + uint m_iteration; + + QVector<uint> iterationTimes; +}; + +void BenchWidget::paintEvent(QPaintEvent *) +{ + if (m_done) + return; + + QPainter p(this); + + m_benchmark->begin(&p, 100); + + PaintingRectAdjuster adjuster; + adjuster.setNewBenchmark(m_benchmark); + adjuster.reset(rect()); + + for (int i = 0; i < 100; ++i) + m_benchmark->draw(&p, adjuster.newPaintingRect(), i); + + m_benchmark->end(&p); + + ++m_iteration; + + uint currentElapsed = timer.isNull() ? 0 : timer.elapsed(); + timer.restart(); + + m_total += currentElapsed; + + // warm up for at most 5 iterations or half a second + if (m_iteration >= 5 || m_total >= 500) { + iterationTimes << currentElapsed; + + if (iterationTimes.size() >= 5) { + qreal mean = 0; + qreal stddev = 0; + uint min = INT_MAX; + + for (int i = 0; i < iterationTimes.size(); ++i) { + mean += iterationTimes.at(i); + min = qMin(min, iterationTimes.at(i)); + } + + mean /= qreal(iterationTimes.size()); + + for (int i = 0; i < iterationTimes.size(); ++i) { + qreal delta = iterationTimes.at(i) - mean; + stddev += delta * delta; + } + + stddev = qSqrt(stddev / iterationTimes.size()); + + stddev = 100 * stddev / mean; + // do 50 iterations, break earlier if we spend more than 5 seconds or have a low std deviation after 2 seconds + if (iterationTimes.size() >= 50 || m_total >= 5000 || (m_total >= 2000 && stddev < 4)) { + m_result = min; + m_done = true; + return; + } + } + } +} + +BenchWidget::BenchWidget(Benchmark *benchmark) + : m_benchmark(benchmark) + , m_done(false) + , m_result(0) + , m_total(0) + , m_iteration(0) +{ + setWindowTitle(benchmark->name()); + resize(640, 480); +} + +class tst_QtBench : public QObject +{ + Q_OBJECT + +private slots: + void qtBench(); + void qtBench_data(); +}; + +QString makeString(int length) +{ + const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234"; + int len = strlen(chars); + + QString ret; + for (int j = 0; j < length; j++) { + ret += QChar(chars[(j * 97) % len]); + } + + return ret; +} + +void tst_QtBench::qtBench_data() +{ + QTest::addColumn<void *>("benchmark"); + + QString shortString = makeString(5); + QString middleString = makeString(50); + QString longString = makeString(35) + "\n" + + makeString(45) + "\n" + + makeString(75); + QString superLongString = "Lorem ipsum dolor sit am\n" + "et, consectetur adipisci\n" + "ng elit. Integer mi leo,\n" + "interdum ut congue at, p\n" + "ulvinar et tellus. Quisq\n" + "ue pretium eleifend laci\n" + "nia. Ut semper gravida l\n" + "ectus in commodo. Vestib\n" + "ulum pharetra arcu in en\n" + "im ultrices hendrerit. P\n" + "ellentesque habitant mor\n" + "bi tristique senectus et\n" + "netus et malesuada fames\n" + "ac turpis egestas. Ut er\n" + "os sem, feugiat in eleme\n" + "ntum in, porta sit amet \n" + "neque. Fusce mi tellus, \n" + "congue non dapibus eget,\n" + "pharetra quis quam. Duis\n" + "dui massa, pulvinar ac s\n" + "odales pharetra, dictum \n" + "in enim. Phasellus a nis\n" + "i erat, sed pellentesque\n" + "mi. Curabitur sed."; + + QList<Benchmark *> benchmarks; + benchmarks << (new DrawText(shortString, DrawText::PainterMode)); + benchmarks << (new DrawText(middleString, DrawText::PainterMode)); + benchmarks << (new DrawText(longString, DrawText::PainterMode)); + benchmarks << (new DrawText(superLongString, DrawText::PainterMode)); + + benchmarks << (new DrawText(shortString, DrawText::PainterQPointMode)); + benchmarks << (new DrawText(middleString, DrawText::PainterQPointMode)); + benchmarks << (new DrawText(longString, DrawText::PainterQPointMode)); + benchmarks << (new DrawText(superLongString, DrawText::PainterQPointMode)); + + benchmarks << (new DrawText(shortString, DrawText::PixmapMode)); + benchmarks << (new DrawText(middleString, DrawText::PixmapMode)); + benchmarks << (new DrawText(longString, DrawText::PixmapMode)); + benchmarks << (new DrawText(superLongString, DrawText::PixmapMode)); + +#if QT_VERSION >= 0x040700 + benchmarks << (new DrawText(shortString, DrawText::StaticTextMode)); + benchmarks << (new DrawText(middleString, DrawText::StaticTextMode)); + benchmarks << (new DrawText(longString, DrawText::StaticTextMode)); + benchmarks << (new DrawText(superLongString, DrawText::StaticTextMode)); + + benchmarks << (new DrawText(shortString, DrawText::StaticTextWithMaximumSizeMode)); + benchmarks << (new DrawText(middleString, DrawText::StaticTextWithMaximumSizeMode)); + benchmarks << (new DrawText(longString, DrawText::StaticTextWithMaximumSizeMode)); + benchmarks << (new DrawText(superLongString, DrawText::StaticTextWithMaximumSizeMode)); + + benchmarks << (new DrawText(shortString, DrawText::StaticTextBackendOptimizations)); + benchmarks << (new DrawText(middleString, DrawText::StaticTextBackendOptimizations)); + benchmarks << (new DrawText(longString, DrawText::StaticTextBackendOptimizations)); + benchmarks << (new DrawText(superLongString, DrawText::StaticTextBackendOptimizations)); +#endif + + foreach (Benchmark *benchmark, benchmarks) + QTest::newRow(qPrintable(benchmark->name())) << reinterpret_cast<void *>(benchmark); +} + +void tst_QtBench::qtBench() +{ + QFETCH(void *, benchmark); + + BenchWidget widget(reinterpret_cast<Benchmark *>(benchmark)); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + while (!widget.done()) { + widget.update(); + QApplication::processEvents(); + } + + QTest::setBenchmarkResult(widget.result(), QTest::WalltimeMilliseconds); +} + +QTEST_MAIN(tst_QtBench) +#include "tst_qtbench.moc" diff --git a/tools/qml/content/Browser.qml b/tools/qml/content/Browser.qml index 35120bc..62996ef 100644 --- a/tools/qml/content/Browser.qml +++ b/tools/qml/content/Browser.qml @@ -137,12 +137,12 @@ Rectangle { Transition { to: "current" SequentialAnimation { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } }, Transition { - NumberAnimation { matchProperties: "x"; duration: 250 } - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } ] Keys.onPressed: { root.keyPressed = true; } @@ -177,11 +177,11 @@ Rectangle { Transition { to: "current" SequentialAnimation { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } }, Transition { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } ] Keys.onPressed: { root.keyPressed = true; } |