From 904089839b164dff3eb3230e6345b0a6d456dabf Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 10 Jun 2010 10:15:09 +0200 Subject: Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit/qtwebkit-4.6 ( d8a9d09376a47b92ea49f1a078c392cbfdbc0ed6 ) Changes in WebKit/qt since the last update: * https://bugs.webkit.org/show_bug.cgi?id=39958 -- [Qt] TextBreakIterator Qt performance --- src/3rdparty/webkit/VERSION | 2 +- src/3rdparty/webkit/WebCore/ChangeLog | 31 +++++++++++ .../platform/text/qt/TextBreakIteratorQt.cpp | 64 ++++++++++++---------- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index 51d663b..b92486d 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -8,4 +8,4 @@ The commit imported was from the and has the sha1 checksum - d6d6c3821ed111b214a753f1ce8fa969c1a94dc3 + d8a9d09376a47b92ea49f1a078c392cbfdbc0ed6 diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index c3df1bf..bf8b745 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,34 @@ +2010-06-08 Kenneth Rohde Christiansen + + Unreviewed Buildbot fix. + + Reset the Qt TextBreakIterator when reusing it. + + * platform/text/qt/TextBreakIteratorQt.cpp: + (WebCore::setUpIterator): + +2010-06-08 Kenneth Rohde Christiansen + + Reviewed by Antti Koivisto. + + [Qt] TextBreakIterator Qt performance + https://bugs.webkit.org/show_bug.cgi?id=39958 + + Rework TextBreakIteratorQt to be more in line with the ICU version. + + We now reuse iterators where ever possible. The string data is compared + with memcmp, which should be faster than using a hash, as you need + to traverse the full buffer in the case the strings don't match, + where as the compare would fail quickly. + + * platform/text/qt/TextBreakIteratorQt.cpp: + (WebCore::TextBreakIterator::TextBreakIterator): + (WebCore::setUpIterator): + (WebCore::wordBreakIterator): + (WebCore::characterBreakIterator): + (WebCore::lineBreakIterator): + (WebCore::sentenceBreakIterator): + 2010-04-19 Balazs Kelemen Reviewed by Kenneth Rohde Christiansen. diff --git a/src/3rdparty/webkit/WebCore/platform/text/qt/TextBreakIteratorQt.cpp b/src/3rdparty/webkit/WebCore/platform/text/qt/TextBreakIteratorQt.cpp index d80e270..0302db8 100644 --- a/src/3rdparty/webkit/WebCore/platform/text/qt/TextBreakIteratorQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/text/qt/TextBreakIteratorQt.cpp @@ -36,31 +36,49 @@ namespace WebCore { + static unsigned char buffer[1024]; + class TextBreakIterator : public QTextBoundaryFinder { + public: + TextBreakIterator(QTextBoundaryFinder::BoundaryType type, const UChar* string, int length) + : QTextBoundaryFinder(type, (const QChar*)string, length, buffer, sizeof(buffer)) + , length(length) + , string(string) {} + TextBreakIterator() + : QTextBoundaryFinder() + , length(0) + , string(0) {} + + int length; + const UChar* string; }; - static QTextBoundaryFinder* iterator = 0; - static unsigned char buffer[1024]; - TextBreakIterator* wordBreakIterator(const UChar* string, int length) + TextBreakIterator* setUpIterator(TextBreakIterator& iterator, QTextBoundaryFinder::BoundaryType type, const UChar* string, int length) { if (!string) return 0; - if (!iterator) - iterator = new QTextBoundaryFinder; - *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Word, (const QChar *)string, length, buffer, sizeof(buffer)); - return static_cast(iterator); + if (iterator.isValid() && type == iterator.type() && length == iterator.length + && memcmp(string, iterator.string, length) == 0) { + iterator.toStart(); + return &iterator; + } + + iterator = TextBreakIterator(type, string, length); + + return &iterator; } - TextBreakIterator* characterBreakIterator(const UChar* string, int length) + TextBreakIterator* wordBreakIterator(const UChar* string, int length) { - if (!string) - return 0; - if (!iterator) - iterator = new QTextBoundaryFinder; + static TextBreakIterator staticWordBreakIterator; + return setUpIterator(staticWordBreakIterator, QTextBoundaryFinder::Word, string, length); + } - *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Grapheme, (const QChar *)string, length, buffer, sizeof(buffer)); - return static_cast(iterator); + TextBreakIterator* characterBreakIterator(const UChar* string, int length) + { + static TextBreakIterator staticCharacterBreakIterator; + return setUpIterator(staticCharacterBreakIterator, QTextBoundaryFinder::Grapheme, string, length); } TextBreakIterator* cursorMovementIterator(const UChar* string, int length) @@ -70,25 +88,15 @@ namespace WebCore { TextBreakIterator* lineBreakIterator(const UChar* string, int length) { - static QTextBoundaryFinder *iterator = 0; - if (!string) - return 0; - if (!iterator) - iterator = new QTextBoundaryFinder; - - *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Line, (const QChar *)string, length, buffer, sizeof(buffer)); - return static_cast(iterator); + static TextBreakIterator staticLineBreakIterator; + return setUpIterator(staticLineBreakIterator, QTextBoundaryFinder::Line, string, length); } TextBreakIterator* sentenceBreakIterator(const UChar* string, int length) { - if (!string) - return 0; - if (!iterator) - iterator = new QTextBoundaryFinder; + static TextBreakIterator staticSentenceBreakIterator; + return setUpIterator(staticSentenceBreakIterator, QTextBoundaryFinder::Sentence, string, length); - *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Sentence, (const QChar *)string, length, buffer, sizeof(buffer)); - return static_cast(iterator); } int textBreakFirst(TextBreakIterator* bi) -- cgit v0.12 From 90518a59df46312d56e4c6bc7080415b44b928f4 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 10 Jun 2010 12:36:15 +0200 Subject: tst_qlocalsocket: pro files of client / server examples fixed Reviewed-by: ossi --- tests/auto/qlocalsocket/example/client/client.pro | 6 ------ tests/auto/qlocalsocket/example/server/server.pro | 6 ------ 2 files changed, 12 deletions(-) diff --git a/tests/auto/qlocalsocket/example/client/client.pro b/tests/auto/qlocalsocket/example/client/client.pro index eb7e6e6..84f20d6 100644 --- a/tests/auto/qlocalsocket/example/client/client.pro +++ b/tests/auto/qlocalsocket/example/client/client.pro @@ -1,14 +1,8 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Wed Jun 6 17:07:12 2007 -###################################################################### - TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG += console -include(../../src/src.pri) -# Input QT = core network SOURCES += main.cpp diff --git a/tests/auto/qlocalsocket/example/server/server.pro b/tests/auto/qlocalsocket/example/server/server.pro index 438462d..bfd14d2 100644 --- a/tests/auto/qlocalsocket/example/server/server.pro +++ b/tests/auto/qlocalsocket/example/server/server.pro @@ -1,7 +1,3 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Wed Jun 6 15:16:48 2007 -###################################################################### - TEMPLATE = app TARGET = DEPENDPATH += . @@ -11,8 +7,6 @@ CONFIG += console QT = core network -include(../../src/src.pri) - # Input SOURCES += main.cpp -- cgit v0.12 From 6c8b980a8ea8009a7b80fcce419e331df778a989 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 10 Jun 2010 12:37:47 +0200 Subject: tst_QLocalSocket::threadedConnection autotest stabilized Fixed race condition on connection. Done-with: ossi Reviewed-by: ossi --- tests/auto/qlocalsocket/tst_qlocalsocket.cpp | 38 +++++++++------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp index 44f3c12..dbb58c1 100644 --- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp @@ -683,25 +683,11 @@ public: QString testLine = "test"; LocalSocket socket; QSignalSpy spyReadyRead(&socket, SIGNAL(readyRead())); - int tries = 0; - do { - socket.connectToServer("qlocalsocket_threadtest"); - if (socket.error() != QLocalSocket::ServerNotFoundError - && socket.error() != QLocalSocket::ConnectionRefusedError) - break; - QTest::qWait(100); - ++tries; - } while ((socket.error() == QLocalSocket::ServerNotFoundError - || socket.error() == QLocalSocket::ConnectionRefusedError) - && tries < 1000); - if (tries == 0 && socket.state() != QLocalSocket::ConnectedState) { - QVERIFY(socket.waitForConnected(7000)); - QVERIFY(socket.state() == QLocalSocket::ConnectedState); - } + socket.connectToServer("qlocalsocket_threadtest"); + QVERIFY(socket.waitForConnected(1000)); // We should *not* have this signal yet! - if (tries == 0) - QCOMPARE(spyReadyRead.count(), 0); + QCOMPARE(spyReadyRead.count(), 0); socket.waitForReadyRead(); QCOMPARE(spyReadyRead.count(), 1); QTextStream in(&socket); @@ -715,6 +701,8 @@ class Server : public QThread public: int clients; + QMutex mutex; + QWaitCondition wc; void run() { QString testLine = "test"; @@ -722,6 +710,9 @@ public: server.setMaxPendingConnections(10); QVERIFY2(server.listen("qlocalsocket_threadtest"), server.errorString().toLatin1().constData()); + mutex.lock(); + wc.wakeAll(); + mutex.unlock(); int done = clients; while (done > 0) { bool timedOut = true; @@ -746,14 +737,9 @@ void tst_QLocalSocket::threadedConnection_data() QTest::addColumn("threads"); QTest::newRow("1 client") << 1; QTest::newRow("2 clients") << 2; -#ifdef Q_OS_WINCE - QTest::newRow("4 clients") << 4; -#endif -#ifndef Q_OS_WIN QTest::newRow("5 clients") << 5; - QTest::newRow("10 clients") << 10; -#endif #ifndef Q_OS_WINCE + QTest::newRow("10 clients") << 10; QTest::newRow("20 clients") << 20; #endif } @@ -770,7 +756,9 @@ void tst_QLocalSocket::threadedConnection() server.setStackSize(0x14000); #endif server.clients = threads; + server.mutex.lock(); server.start(); + server.wc.wait(&server.mutex); QList clients; for (int i = 0; i < threads; ++i) { @@ -784,9 +772,7 @@ void tst_QLocalSocket::threadedConnection() server.wait(); while (!clients.isEmpty()) { QVERIFY(clients.first()->wait(3000)); - Client *client =clients.takeFirst(); - client->terminate(); - delete client; + delete clients.takeFirst(); } } -- cgit v0.12 From cbe3425a3bd226c61c94f92c521dc5c9b090ef96 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 10 Jun 2010 12:42:13 +0200 Subject: QLocalServer: make many simultaneous connection attempts work on Windows Don't call GetOverlappedResult if ConnectNamedPipe connects instantly. Autotest: tst_qlocalsocket::threadedConnection Task-number: QTBUG-8477 Done-with: ossi Reviewed-by: ossi --- src/network/socket/qlocalserver_p.h | 1 + src/network/socket/qlocalserver_win.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h index feaaae0..4f92b64 100644 --- a/src/network/socket/qlocalserver_p.h +++ b/src/network/socket/qlocalserver_p.h @@ -99,6 +99,7 @@ public: struct Listener { HANDLE handle; OVERLAPPED overlapped; + bool connected; }; void setError(const QString &function); diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index 50d6ca4..940455c 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -85,8 +85,10 @@ bool QLocalServerPrivate::addListener() if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) { switch (GetLastError()) { case ERROR_IO_PENDING: + listener.connected = false; break; case ERROR_PIPE_CONNECTED: + listener.connected = true; SetEvent(eventHandle); break; default: @@ -155,7 +157,9 @@ void QLocalServerPrivate::_q_onNewConnection() // a client connection first, so there is no way around polling all of them. for (int i = 0; i < listeners.size(); ) { HANDLE handle = listeners[i].handle; - if (GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) { + if (listeners[i].connected + || GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) + { listeners.removeAt(i); addListener(); -- cgit v0.12 From 12614b2c5aaaed44ef9b3d1b3f6dbf50fd2d405f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 10 Jun 2010 13:10:27 +0200 Subject: QLocalSocket: fix reading from a socket after broken connection Reading from a socket with a broken connection didn't work, even if there were still bytes to read in the internal read buffer. Autotest: tst_QLocalSocket::writeToClientAndDisconnect Task-number: QTBUG-10921 Reviewed-by: ossi --- src/network/socket/qlocalsocket_win.cpp | 10 ++++++---- tests/auto/qlocalsocket/tst_qlocalsocket.cpp | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 5f46ecb..dc87ade 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -192,6 +192,9 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize) { Q_D(QLocalSocket); + if (d->pipeClosed && d->actualReadBufferSize == 0) + return -1; // signal EOF + qint64 readSoFar; // If startAsyncRead() read data, copy it to its destination. if (maxSize == 1 && d->actualReadBufferSize > 0) { @@ -213,10 +216,8 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize) } if (d->pipeClosed) { - if (readSoFar == 0) { + if (d->actualReadBufferSize == 0) QTimer::singleShot(0, this, SLOT(_q_pipeClosed())); - return -1; // signal EOF - } } else { if (!d->readSequenceStarted) d->startAsyncRead(); @@ -345,7 +346,8 @@ DWORD QLocalSocketPrivate::bytesAvailable() if (!pipeClosed) { pipeClosed = true; emit q->readChannelFinished(); - QTimer::singleShot(0, q, SLOT(_q_pipeClosed())); + if (actualReadBufferSize == 0) + QTimer::singleShot(0, q, SLOT(_q_pipeClosed())); } } return 0; diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp index dbb58c1..87a30c2 100644 --- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp @@ -980,6 +980,7 @@ void tst_QLocalSocket::writeToClientAndDisconnect() QLocalServer server; QLocalSocket client; + QSignalSpy readChannelFinishedSpy(&client, SIGNAL(readChannelFinished())); QVERIFY(server.listen("writeAndDisconnectServer")); client.connectToServer("writeAndDisconnectServer"); @@ -992,10 +993,19 @@ void tst_QLocalSocket::writeToClientAndDisconnect() memset(buffer, 0, sizeof(buffer)); QCOMPARE(clientSocket->write(buffer, sizeof(buffer)), (qint64)sizeof(buffer)); clientSocket->waitForBytesWritten(); - clientSocket->disconnectFromServer(); - QVERIFY(client.waitForReadyRead()); + clientSocket->close(); + server.close(); + + // Wait for the client to notice the broken connection. + int timeout = 5000; + do { + const int timestep = 100; + QTest::qWait(timestep); + timeout -= timestep; + } while (!readChannelFinishedSpy.count() && timeout > 0); + + QVERIFY(!readChannelFinishedSpy.isEmpty()); QCOMPARE(client.read(buffer, sizeof(buffer)), (qint64)sizeof(buffer)); - QVERIFY(client.waitForDisconnected()); QCOMPARE(client.state(), QLocalSocket::UnconnectedState); } -- cgit v0.12 From 98da12415aa8bb7497120cd841e7a798e3e5206e Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 10 Jun 2010 14:14:18 +0200 Subject: QLocalSocket/Win: QLocalSocketPrivate::bytesAvailable renamed QLocalSocketPrivate::bytesAvailable has been renamed to QLocalSocketPrivate::checkPipeState to match the purpose of this method. Reviewed-by: ossi --- src/network/socket/qlocalsocket_p.h | 2 +- src/network/socket/qlocalsocket_win.cpp | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 0f1c23c..57ca3c2 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -135,7 +135,7 @@ public: void _q_canWrite(); void _q_pipeClosed(); void _q_emitReadyRead(); - DWORD bytesAvailable(); + DWORD checkPipeState(); void startAsyncRead(); bool completeAsyncRead(); void checkReadyRead(); diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index dc87ade..aa597da 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -251,7 +251,7 @@ void QLocalSocketPrivate::checkReadyRead() void QLocalSocketPrivate::startAsyncRead() { do { - DWORD bytesToRead = bytesAvailable(); + DWORD bytesToRead = checkPipeState(); if (bytesToRead == 0) { // There are no bytes in the pipe but we need to // start the overlapped read with some buffer size. @@ -334,9 +334,11 @@ void QLocalSocket::abort() } /*! - The number of bytes available from the pipe - */ -DWORD QLocalSocketPrivate::bytesAvailable() + \internal + Returns the number of available bytes in the pipe. + Sets QLocalSocketPrivate::pipeClosed to true if the connection is broken. + */ +DWORD QLocalSocketPrivate::checkPipeState() { Q_Q(QLocalSocket); DWORD bytes; @@ -531,7 +533,7 @@ bool QLocalSocket::waitForDisconnected(int msecs) } QIncrementalSleepTimer timer(msecs); forever { - d->bytesAvailable(); // to check if PeekNamedPipe fails + d->checkPipeState(); if (d->pipeClosed) close(); if (state() == UnconnectedState) -- cgit v0.12 From 073d04f1c2c5dc7020469bfc92708dce634f4779 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 10 Jun 2010 14:16:24 +0200 Subject: QLocalSocket: don't emit readChannelFinished() twice on Windows Reviewed-by: ossi --- src/network/socket/qlocalsocket_win.cpp | 3 +++ tests/auto/qlocalsocket/tst_qlocalsocket.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index aa597da..2223ebe 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -252,6 +252,9 @@ void QLocalSocketPrivate::startAsyncRead() { do { DWORD bytesToRead = checkPipeState(); + if (pipeClosed) + return; + if (bytesToRead == 0) { // There are no bytes in the pipe but we need to // start the overlapped read with some buffer size. diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp index 87a30c2..d2cba6e 100644 --- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp @@ -1004,7 +1004,7 @@ void tst_QLocalSocket::writeToClientAndDisconnect() timeout -= timestep; } while (!readChannelFinishedSpy.count() && timeout > 0); - QVERIFY(!readChannelFinishedSpy.isEmpty()); + QCOMPARE(readChannelFinishedSpy.count(), 1); QCOMPARE(client.read(buffer, sizeof(buffer)), (qint64)sizeof(buffer)); QCOMPARE(client.state(), QLocalSocket::UnconnectedState); } -- cgit v0.12 From e6ac173991223dbf3b1b6f7213550ebca4608cb6 Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Tue, 27 Apr 2010 17:21:25 +0200 Subject: Fix incorrect line breaking in QtWebKit. QTextBoundaryFinder was not consistent with ICU. See also: https://bugs.webkit.org/show_bug.cgi?id=31076 The previous definition of a line break was that the index in the string after which the line break should occur. Now it is the index of the boundary at which the break should occur (hence one more). Task-number: QT-3495 Reviewed-by: Simon Hausmann Reviewed-by: Lars Knoll --- src/corelib/tools/qtextboundaryfinder.cpp | 12 ++- .../tst_qtextboundaryfinder.cpp | 111 +++++++++++++++++++-- 2 files changed, 114 insertions(+), 9 deletions(-) diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp index 7c40e35..ca4d3c3 100644 --- a/src/corelib/tools/qtextboundaryfinder.cpp +++ b/src/corelib/tools/qtextboundaryfinder.cpp @@ -130,6 +130,11 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int Line break boundaries give possible places where a line break might happen and sentence boundaries will show the beginning and end of whole sentences. + + The first position in a string is always a valid boundary and + refers to the position before the first character. The last + position at the length of the string is also valid and refers + to the position after the last character. */ /*! @@ -362,7 +367,8 @@ int QTextBoundaryFinder::toNextBoundary() ++pos; break; case Line: - while (pos < length && d->attributes[pos].lineBreakType < HB_Break) + Q_ASSERT(pos); + while (pos < length && d->attributes[pos-1].lineBreakType < HB_Break) ++pos; break; } @@ -404,7 +410,7 @@ int QTextBoundaryFinder::toPreviousBoundary() --pos; break; case Line: - while (pos > 0 && d->attributes[pos].lineBreakType < HB_Break) + while (pos > 0 && d->attributes[pos-1].lineBreakType < HB_Break) --pos; break; } @@ -429,7 +435,7 @@ bool QTextBoundaryFinder::isAtBoundary() const case Word: return d->attributes[pos].wordBoundary; case Line: - return d->attributes[pos].lineBreakType >= HB_Break; + return (pos > 0) ? d->attributes[pos-1].lineBreakType >= HB_Break : true; case Sentence: return d->attributes[pos].sentenceBoundary; } diff --git a/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp b/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp index c60af5e..a562fbe 100644 --- a/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp +++ b/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp @@ -71,6 +71,10 @@ private slots: void isAtWordStart(); void fastConstructor(); void isAtBoundaryLine(); + void toNextBoundary_data(); + void toNextBoundary(); + void toPreviousBoundary_data(); + void toPreviousBoundary(); }; tst_QTextBoundaryFinder::tst_QTextBoundaryFinder() @@ -292,25 +296,120 @@ void tst_QTextBoundaryFinder::fastConstructor() void tst_QTextBoundaryFinder::isAtBoundaryLine() { - // idx 0 1 2 3 4 5 - // break? - - - + - + + // idx 0 1 2 3 4 5 6 + // break? - - - - + - + QChar s[] = { 0x0061, 0x00AD, 0x0062, 0x0009, 0x0063, 0x0064 }; QString text(s, sizeof(s)/sizeof(s[0])); - qDebug() << "text = " << text << ", length = " << text.length(); +// qDebug() << "text = " << text << ", length = " << text.length(); QTextBoundaryFinder finder(QTextBoundaryFinder::Line, text.constData(), text.length(), /*buffer*/0, /*buffer size*/0); finder.setPosition(0); - QVERIFY(!finder.isAtBoundary()); + QVERIFY(finder.isAtBoundary()); finder.setPosition(1); QVERIFY(!finder.isAtBoundary()); finder.setPosition(2); QVERIFY(!finder.isAtBoundary()); finder.setPosition(3); - QVERIFY(finder.isAtBoundary()); - finder.setPosition(4); QVERIFY(!finder.isAtBoundary()); + finder.setPosition(4); + QVERIFY(finder.isAtBoundary()); finder.setPosition(5); + QVERIFY(!finder.isAtBoundary()); + finder.setPosition(6); QVERIFY(finder.isAtBoundary()); } +Q_DECLARE_METATYPE(QList) + +void tst_QTextBoundaryFinder::toNextBoundary_data() +{ + QTest::addColumn("text"); + QTest::addColumn("type"); + QTest::addColumn< QList >("boundaries"); + + QList boundaries; + boundaries << 0 << 3 << 4 << 7 << 8 << 11 << 12 << 13 << 16 << 17 << 20 << 21 << 24 << 25; + QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Word) \ + << boundaries; + + boundaries.clear(); + boundaries << 0 << 13 << 25; + QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Sentence) \ + << boundaries; + + boundaries.clear(); + boundaries << 0 << 4 << 8 << 13 << 17 << 21 << 25; + QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Line) \ + << boundaries; + + boundaries.clear(); + boundaries << 0 << 5 << 9 << 15 << 17 << 21 << 28; + QTest::newRow("Line") << QString::fromUtf8("Diga-nos qualé a sua opinião") << int(QTextBoundaryFinder::Line) + << boundaries; + +} + +void tst_QTextBoundaryFinder::toNextBoundary() +{ + QFETCH(QString, text); + QFETCH(int, type); + QFETCH(QList, boundaries); + + QList foundBoundaries; + QTextBoundaryFinder boundaryFinder(QTextBoundaryFinder::BoundaryType(type), text); + boundaryFinder.toStart(); + for(int next = 0; next != -1; next = boundaryFinder.toNextBoundary()) + foundBoundaries << next; + QCOMPARE(boundaries, foundBoundaries); +} + +void tst_QTextBoundaryFinder::toPreviousBoundary_data() +{ + QTest::addColumn("text"); + QTest::addColumn("type"); + QTest::addColumn< QList >("boundaries"); + + QList boundaries; + boundaries << 25 << 24 << 21 << 20 << 17 << 16 << 13 << 12 << 11 << 8 << 7 << 4 << 3 << 0; + QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Word) + << boundaries; + + boundaries.clear(); + boundaries << 25 << 13 << 0; + QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Sentence) + << boundaries; + + boundaries.clear(); + boundaries << 25 << 21 << 17 << 13 << 8 << 4 << 0; + QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Line) + << boundaries; + + boundaries.clear(); + boundaries << 28 << 21 << 17 << 15 << 9 << 5 << 0; + QTest::newRow("Line") << QString::fromUtf8("Diga-nos qualé a sua opinião") << int(QTextBoundaryFinder::Line) + << boundaries; + +} + +void tst_QTextBoundaryFinder::toPreviousBoundary() +{ + QFETCH(QString, text); + QFETCH(int, type); + QFETCH(QList, boundaries); + + QList foundBoundaries; + QTextBoundaryFinder boundaryFinder(QTextBoundaryFinder::BoundaryType(type), text); + boundaryFinder.toEnd(); + for (int previous = boundaryFinder.position(); + previous != -1; + previous = boundaryFinder.toPreviousBoundary()) + { + foundBoundaries << previous; + } + QCOMPARE(boundaries, foundBoundaries); +} + + + + QTEST_MAIN(tst_QTextBoundaryFinder) #include "tst_qtextboundaryfinder.moc" -- cgit v0.12 From e311bd0b23cf8696f284b8da3dcc5a591c7b689e Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 11 Jun 2010 14:21:15 +0200 Subject: Allow to build Qt in static with mingw Some functions were marked with Q_DECL_IMPORT where they should just be Q_CORE_EXPORT. The reason is that this macro is expanded to nothing in case of static builds whereas Q_DECL_IMPORT isn't (it is a dllimport). That leads the linker to try to import it and it shouldn't. Task-number: QTBUG-10791 Reviewed-by: gabi --- src/gui/kernel/qapplication.cpp | 2 +- src/gui/kernel/qwhatsthis.cpp | 2 +- src/script/api/qscriptengine.cpp | 2 +- src/script/parser/qscriptlexer.cpp | 2 +- src/xmlpatterns/data/qdecimal_p.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index de74f53..33b96e4 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -138,7 +138,7 @@ static void initResources() QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern void qt_call_post_routines(); +Q_CORE_EXPORT void qt_call_post_routines(); int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp index 6181b62..ff4641e 100644 --- a/src/gui/kernel/qwhatsthis.cpp +++ b/src/gui/kernel/qwhatsthis.cpp @@ -143,7 +143,7 @@ QT_BEGIN_NAMESPACE \sa QToolTip */ -Q_DECL_IMPORT extern void qDeleteInEventHandler(QObject *o); +Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o); class QWhatsThat : public QWidget { diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index f44f33d..fe12fc8 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1603,7 +1603,7 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, #ifndef QT_NO_REGEXP -Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); +Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); /*! Creates a QtScript object of class RegExp with the given diff --git a/src/script/parser/qscriptlexer.cpp b/src/script/parser/qscriptlexer.cpp index ca64776..3ddc3aa 100644 --- a/src/script/parser/qscriptlexer.cpp +++ b/src/script/parser/qscriptlexer.cpp @@ -31,7 +31,7 @@ QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern double qstrtod(const char *s00, char const **se, bool *ok); +Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); #define shiftWindowsLineBreak() \ do { \ diff --git a/src/xmlpatterns/data/qdecimal_p.h b/src/xmlpatterns/data/qdecimal_p.h index d17b647..2a5e0b3 100644 --- a/src/xmlpatterns/data/qdecimal_p.h +++ b/src/xmlpatterns/data/qdecimal_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE /** * Defined in QtCore's qlocale.cpp. */ -Q_DECL_IMPORT extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp); +Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp); namespace QPatternist { -- cgit v0.12 From 5471f3cc5f3b1ec9fbe15ba35ab23dfd9fcc42c9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 11 Jun 2010 12:11:05 +0100 Subject: Thread safety for QFontEngineS60 On symbian, creating fonts requires a connection to the window server. Window server sessions are not sharable across threads. To avoid QFont crashing when used outside the GUI thread, we construct a private session to the window server when the shared CONE session is not available. (CCoeEnv::Static() uses TLS, so it returns null outside of GUI thread) The private session and screen device are stored in QThreadStorage, so they are automatically deleted when the QThread exits. Task-number: QTBUG-8874 Reviewed-by: mread --- src/gui/kernel/qapplication_s60.cpp | 25 +++++++++++++++++++++++++ src/gui/kernel/qt_s60_p.h | 26 ++++++++++++++++++++++---- src/gui/text/qfontdatabase_s60.cpp | 18 ++++++++++-------- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 78027b2..f39b462 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -2046,4 +2046,29 @@ void QApplication::restoreOverrideCursor() #endif // QT_NO_CURSOR +QS60ThreadLocalData::QS60ThreadLocalData() +{ + CCoeEnv *env = CCoeEnv::Static(); + if (env) { + //if this is the UI thread, share objects owned by CONE + usingCONEinstances = true; + wsSession = env->WsSession(); + screenDevice = env->ScreenDevice(); + } + else { + usingCONEinstances = false; + qt_symbian_throwIfError(wsSession.Connect(qt_s60GetRFs())); + screenDevice = new CWsScreenDevice(wsSession); + screenDevice->Construct(); + } +} + +QS60ThreadLocalData::~QS60ThreadLocalData() +{ + if (!usingCONEinstances) { + delete screenDevice; + wsSession.Close(); + } +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 58da302..bec51b8 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -62,6 +62,7 @@ #include "QtGui/qevent.h" #include "qpointer.h" #include "qapplication.h" +#include "QtCore/qthreadstorage.h" #include #include #include @@ -85,10 +86,21 @@ const TInt KInternalStatusPaneChange = 0x50000000; //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 #define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13) +class QS60ThreadLocalData +{ +public: + QS60ThreadLocalData(); + ~QS60ThreadLocalData(); + bool usingCONEinstances; + RWsSession wsSession; + CWsScreenDevice *screenDevice; +}; + class QS60Data { public: QS60Data(); + QThreadStorage tls; TUid uid; int screenDepth; QPoint lastCursorPos; @@ -125,9 +137,9 @@ public: int menuBeingConstructed : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static inline void updateScreenSize(); - static inline RWsSession& wsSession(); + inline RWsSession& wsSession(); static inline RWindowGroup& windowGroup(); - static inline CWsScreenDevice* screenDevice(); + inline CWsScreenDevice* screenDevice(); static inline CCoeAppUi* appUi(); static inline CEikMenuBar* menuBar(); #ifdef Q_WS_S60 @@ -256,7 +268,10 @@ inline void QS60Data::updateScreenSize() inline RWsSession& QS60Data::wsSession() { - return CCoeEnv::Static()->WsSession(); + if(!tls.hasLocalData()) { + tls.setLocalData(new QS60ThreadLocalData); + } + return tls.localData()->wsSession; } inline RWindowGroup& QS60Data::windowGroup() @@ -266,7 +281,10 @@ inline RWindowGroup& QS60Data::windowGroup() inline CWsScreenDevice* QS60Data::screenDevice() { - return CCoeEnv::Static()->ScreenDevice(); + if(!tls.hasLocalData()) { + tls.setLocalData(new QS60ThreadLocalData); + } + return tls.localData()->screenDevice; } inline CCoeAppUi* QS60Data::appUi() diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 40fe3b7..61c5271 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -218,17 +218,19 @@ QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd) */ qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation) { + CWsScreenDevice* device = S60->screenDevice(); return (orientation == Qt::Horizontal? - S60->screenDevice()->HorizontalPixelsToTwips(pixels) - :S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; + device->HorizontalPixelsToTwips(pixels) + :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; } qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation) { + CWsScreenDevice* device = S60->screenDevice(); const int twips = points * KTwipsPerPoint; return orientation == Qt::Horizontal? - S60->screenDevice()->HorizontalTwipsToPixels(twips) - :S60->screenDevice()->VerticalTwipsToPixels(twips); + device->HorizontalTwipsToPixels(twips) + :device->VerticalTwipsToPixels(twips); } QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies) @@ -267,16 +269,16 @@ static void initializeDb() QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces(); + const int numTypeFaces = S60->screenDevice()->NumTypefaces(); const QSymbianFontDatabaseExtrasImplementation *dbExtras = static_cast(db->symbianExtras); bool fontAdded = false; for (int i = 0; i < numTypeFaces; i++) { TTypefaceSupport typefaceSupport; - QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i); + S60->screenDevice()->TypefaceSupport(typefaceSupport, i); CFont *font; // We have to get a font instance in order to know all the details TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); - if (QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) + if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) continue; if (font->TypeUid() == KCFbsFontUid) { TOpenFontFaceAttrib faceAttrib; @@ -318,7 +320,7 @@ static void initializeDb() fontAdded = true; } - QS60Data::screenDevice()->ReleaseFont(font); + S60->screenDevice()->ReleaseFont(font); } Q_ASSERT(fontAdded); -- cgit v0.12 From a82ac93ee26a2d74264578304aa4cd01aad2ccaa Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 13 Jun 2010 22:42:10 +0200 Subject: Prospective S60 build fix QS60Data::screenDevice() has moved from being process global to being thread local, therefore it must be accessed through the S60 macro that returns the thread-local data. --- src/gui/text/qfontdatabase_s60.cpp | 6 +++--- src/gui/text/qfontengine_s60.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 9999159..cdfba3d 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -118,7 +118,7 @@ public: { if (!font) return; - QS60Data::screenDevice()->ReleaseFont(font); + S60->screenDevice()->ReleaseFont(font); } }; @@ -205,7 +205,7 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c CFont* font = NULL; #ifdef Q_SYMBIAN_HAS_FONTTABLE_API - const TInt err = QS60Data::screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec); + const TInt err = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec); Q_ASSERT(err == KErrNone && font); QScopedPointer sFont(font); QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font); @@ -311,7 +311,7 @@ static void initializeDb() QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces(); + const int numTypeFaces = S60->screenDevice()->NumTypefaces(); const QSymbianFontDatabaseExtrasImplementation *dbExtras = static_cast(db->symbianExtras); bool fontAdded = false; diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 925b3bf..f691413 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -66,7 +66,7 @@ QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras() { - QS60Data::screenDevice()->ReleaseFont(m_cFont); + S60->screenDevice()->ReleaseFont(m_cFont); } QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const -- cgit v0.12