diff options
Diffstat (limited to 'src')
93 files changed, 2976 insertions, 1126 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c b/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c index 2bda386..67029be 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c @@ -56,8 +56,6 @@ HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item) assert(shaper_item->item.script == HB_Script_Hebrew); - HB_HeuristicSetGlyphAttributes(shaper_item); - #ifndef NO_OPENTYPE if (HB_SelectScript(shaper_item, hebrew_features)) { @@ -65,7 +63,7 @@ HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item) if (!HB_ConvertStringToGlyphIndices(shaper_item)) return FALSE; - + HB_HeuristicSetGlyphAttributes(shaper_item); HB_OpenTypeShape(shaper_item, /*properties*/0); return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE); } diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp index bfb03ab..bfc7bd4 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp +++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp @@ -980,6 +980,7 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) HB_Stream gdefStream; gdefStream = getTableStream(font, tableFunc, TTAG_GDEF); + error = HB_Err_Not_Covered; if (!gdefStream || (error = HB_Load_GDEF_Table(gdefStream, &face->gdef))) { //DEBUG("error loading gdef table: %d", error); face->gdef = 0; @@ -987,6 +988,7 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) //DEBUG() << "trying to load gsub table"; stream = getTableStream(font, tableFunc, TTAG_GSUB); + error = HB_Err_Not_Covered; if (!stream || (error = HB_Load_GSUB_Table(stream, &face->gsub, face->gdef, gdefStream))) { face->gsub = 0; if (error != HB_Err_Not_Covered) { @@ -998,6 +1000,7 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) _hb_close_stream(stream); stream = getTableStream(font, tableFunc, TTAG_GPOS); + error = HB_Err_Not_Covered; if (!stream || (error = HB_Load_GPOS_Table(stream, &face->gpos, face->gdef, gdefStream))) { face->gpos = 0; DEBUG("error loading gpos table: %d", error); diff --git a/src/3rdparty/webkit/JavaScriptCore/ChangeLog b/src/3rdparty/webkit/JavaScriptCore/ChangeLog index d7d2d57..50cff63 100644 --- a/src/3rdparty/webkit/JavaScriptCore/ChangeLog +++ b/src/3rdparty/webkit/JavaScriptCore/ChangeLog @@ -1,3 +1,15 @@ +2009-12-18 Yongjun Zhang <yongjun.zhang@nokia.com> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=32713 + [Qt] make wtf/Assertions.h compile in winscw compiler. + + Add string arg before ellipsis to help winscw compiler resolve variadic + macro definitions in wtf/Assertions.h. + + * wtf/Assertions.h: + 2009-11-30 Jan-Arve Sæther <jan-arve.saether@nokia.com> Reviewed by Simon Hausmann. diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h index f529a62..aa72e5a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h @@ -158,8 +158,8 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #define ASSERT(assertion) ((void)0) #if COMPILER(MSVC7) #define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif PLATFORM(SYMBIAN) -#define ASSERT_WITH_MESSAGE(assertion...) ((void)0) +#elif COMPILER(WINSCW) +#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) #else #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) #endif /* COMPILER(MSVC7) */ @@ -176,8 +176,8 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann while (0) #if COMPILER(MSVC7) #define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif PLATFORM(SYMBIAN) -#define ASSERT_WITH_MESSAGE(assertion...) ((void)0) +#elif COMPILER(WINSCW) +#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) #else #define ASSERT_WITH_MESSAGE(assertion, ...) do \ if (!(assertion)) { \ @@ -219,11 +219,11 @@ while (0) /* FATAL */ -#if FATAL_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if FATAL_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define FATAL(...) ((void)0) #elif COMPILER(MSVC7) #define FATAL() ((void)0) -#elif PLATFORM(SYMBIAN) +#elif COMPILER(WINSCW) #define FATAL(args...) ((void)0) #else #define FATAL(...) do { \ @@ -234,24 +234,24 @@ while (0) /* LOG_ERROR */ -#if ERROR_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if ERROR_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define LOG_ERROR(...) ((void)0) #elif COMPILER(MSVC7) #define LOG_ERROR() ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG_ERROR(args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG_ERROR(arg...) ((void)0) #else #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) #endif /* LOG */ -#if LOG_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if LOG_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define LOG(channel, ...) ((void)0) #elif COMPILER(MSVC7) #define LOG() ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG(channel, args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG(arg...) ((void)0) #else #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) @@ -260,12 +260,12 @@ while (0) /* LOG_VERBOSE */ -#if LOG_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if LOG_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define LOG_VERBOSE(channel, ...) ((void)0) #elif COMPILER(MSVC7) #define LOG_VERBOSE(channel) ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG_VERBOSE(channel, args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG_VERBOSE(channel, arg...) ((void)0) #else #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #endif diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index 62acbdf..daa3be7 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 - 9de63cde0ac8aa08e207d4ffce2846df1a44a364 + 70b5989bdeea2f73bd950099fc0f0e954550ef54 diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index 4f6146f..03bb1fb 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,89 @@ +2009-12-30 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + [Qt] Add support for Symbian def files + + * WebCore.pro: + +2009-12-30 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed Qt/Symbian build fix. + + Don't build network state notifier support when building inside of Qt. + Otherwise the Qt build depends on an external module that itself depends + on Qt again. + + * WebCore.pro: + +2009-12-30 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + Turn off DataGrid support by default. + + No new tests, as there is no new functionality. + + * WebCore.pro: + +2009-12-17 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] support navigator.onLine and ononline/onoffline events. + https://bugs.webkit.org/show_bug.cgi?id=32555 + + Hooked up Bearer Management to NetworkStateNotifier. This solution is available + only if QtMobility's Bearer Management is installed. + + * WebCore.pro: + * platform/network/NetworkStateNotifier.h: + * platform/network/qt/NetworkStateNotifierPrivate.h: Added. + * platform/network/qt/NetworkStateNotifierQt.cpp: Added. + (WebCore::NetworkStateNotifierPrivate::NetworkStateNotifierPrivate): + (WebCore::NetworkStateNotifierPrivate::onlineStateChanged): + (WebCore::NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate): + (WebCore::NetworkStateNotifier::updateState): + (WebCore::NetworkStateNotifier::NetworkStateNotifier): + +2009-12-17 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Symbian build fix: Don't include QtXml/qxmlstream.h but omit the prefix, to + make sure we pick up the header file from QtCore. That is where the implementation + is compiled. + + * dom/XMLTokenizer.h: + +2009-12-14 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add manual test for JavaScript prompt corner case + https://bugs.webkit.org/show_bug.cgi?id=30914 + + The patch is based on the work done by Gupta Manish. + + Verify behavior of the JavaScript prompt function. Currently + Qt is not behaving like other WebKit ports and Firefox in + regards to accepting the prompt but not entering a text. + + * manual-tests/qt/java-script-prompt.html: Added. + +2009-12-21 Andreas Kling <andreas.kling@nokia.com> + + Reviewed by Darin Adler. + + Fix assertion failure when dragging an SVG image. + https://bugs.webkit.org/show_bug.cgi?id=32511 + + Test: fast/images/drag-svg-as-image.html + + * svg/graphics/SVGImage.cpp: + (WebCore::SVGImage::filenameExtension): Return "svg" + * svg/graphics/SVGImage.h: + 2009-11-23 Simon Hausmann <simon.hausmann@nokia.com> Reviewed by Kenneth Rohde Christiansen. diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 9239089..be64e3b 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -136,7 +136,7 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) { !contains(DEFINES, ENABLE_SHARED_WORKERS=.): DEFINES += ENABLE_SHARED_WORKERS=1 !contains(DEFINES, ENABLE_WORKERS=.): DEFINES += ENABLE_WORKERS=1 !contains(DEFINES, ENABLE_XHTMLMP=.): DEFINES += ENABLE_XHTMLMP=0 -!contains(DEFINES, ENABLE_DATAGRID=.): DEFINES += ENABLE_DATAGRID=1 +!contains(DEFINES, ENABLE_DATAGRID=.): DEFINES += ENABLE_DATAGRID=0 # SVG support !contains(DEFINES, ENABLE_SVG=0) { @@ -180,6 +180,15 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) { else:DEFINES += ENABLE_XSLT=0 } +!CONFIG(QTDIR_build):!contains(DEFINES, ENABLE_QT_BEARER=.) { + symbian: { + exists($${EPOCROOT}epoc32/release/winscw/udeb/QtBearer.lib)| \ + exists($${EPOCROOT}epoc32/release/armv5/lib/QtBearer.lib) { + DEFINES += ENABLE_QT_BEARER=1 + } + } +} + DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1 WTF_CHANGES=1 # Used to compute defaults for the build-webkit script @@ -2860,6 +2869,17 @@ contains(DEFINES, ENABLE_XHTMLMP=1) { FEATURE_DEFINES_JAVASCRIPT += ENABLE_XHTMLMP=1 } +contains(DEFINES, ENABLE_QT_BEARER=1) { + HEADERS += \ + platform/network/qt/NetworkStateNotifierPrivate.h + + SOURCES += \ + platform/network/qt/NetworkStateNotifierQt.cpp + + LIBS += -lQtBearer + +} + contains(DEFINES, ENABLE_SVG=1) { FEATURE_DEFINES_JAVASCRIPT += ENABLE_SVG=1 @@ -3382,16 +3402,15 @@ CONFIG(QTDIR_build):isEqual(QT_MAJOR_VERSION, 4):greaterThan(QT_MINOR_VERSION, 4 } } -# Temporary workaround to pick up the DEF file from the same place as all the others symbian { shared { contains(MMP_RULES, defBlock) { MMP_RULES -= defBlock MMP_RULES += "$${LITERAL_HASH}ifdef WINSCW" \ - "DEFFILE ../../../s60installs/bwins/$${TARGET}.def" \ + "DEFFILE ../WebKit/qt/symbian/bwins/$${TARGET}.def" \ "$${LITERAL_HASH}elif defined EABI" \ - "DEFFILE ../../../s60installs/eabi/$${TARGET}.def" \ + "DEFFILE ../WebKit/qt/symbian/eabi/$${TARGET}.def" \ "$${LITERAL_HASH}endif" } } diff --git a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h index e1ee09f..a83e73a 100644 --- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h +++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h @@ -34,7 +34,7 @@ #include <wtf/OwnPtr.h> #if USE(QXMLSTREAM) -#include <QtXml/qxmlstream.h> +#include <qxmlstream.h> #else #include <libxml/tree.h> #include <libxml/xmlstring.h> diff --git a/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h b/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h index 0189f5f..f8c5654 100644 --- a/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h +++ b/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h @@ -46,6 +46,10 @@ typedef const struct __SCDynamicStore * SCDynamicStoreRef; namespace WebCore { +#if (PLATFORM(QT) && ENABLE(QT_BEARER)) +class NetworkStateNotifierPrivate; +#endif + class NetworkStateNotifier { public: NetworkStateNotifier(); @@ -78,10 +82,14 @@ private: #elif PLATFORM(CHROMIUM) NetworkStateNotifierPrivate p; + +#elif PLATFORM(QT) && ENABLE(QT_BEARER) + friend class NetworkStateNotifierPrivate; + NetworkStateNotifierPrivate* p; #endif }; -#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) +#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) && !(PLATFORM(QT) && ENABLE(QT_BEARER)) inline NetworkStateNotifier::NetworkStateNotifier() : m_isOnLine(true) diff --git a/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h new file mode 100644 index 0000000..7af6392 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef NetworkStateNotifierPrivate_h +#define NetworkStateNotifierPrivate_h + +#include <QObject> + +namespace QtMobility { +class QNetworkConfigurationManager; +} + +namespace WebCore { + +class NetworkStateNotifier; + +class NetworkStateNotifierPrivate : public QObject { + Q_OBJECT +public: + NetworkStateNotifierPrivate(NetworkStateNotifier* notifier); + ~NetworkStateNotifierPrivate(); +public slots: + void onlineStateChanged(bool); + +public: + QtMobility::QNetworkConfigurationManager* m_configurationManager; + bool m_online; + NetworkStateNotifier* m_notifier; +}; + +} // namespace WebCore + +#endif diff --git a/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp new file mode 100644 index 0000000..f74398b --- /dev/null +++ b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -0,0 +1,73 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "NetworkStateNotifier.h" + +#include "NetworkStateNotifierPrivate.h" +#include "qnetworkconfigmanager.h" + +using namespace QtMobility; + +namespace WebCore { + +NetworkStateNotifierPrivate::NetworkStateNotifierPrivate(NetworkStateNotifier* notifier) + : m_configurationManager(new QNetworkConfigurationManager()) + , m_online(m_configurationManager->isOnline()) + , m_notifier(notifier) +{ + Q_ASSERT(notifier); + connect(m_configurationManager, SIGNAL(onlineStateChanged(bool)), this, SLOT(onlineStateChanged(bool))); +} + +void NetworkStateNotifierPrivate::onlineStateChanged(bool isOnline) +{ + if (m_online == isOnline) + return; + + m_online = isOnline; + m_notifier->updateState(); +} + +NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate() +{ + delete m_configurationManager; +} + +void NetworkStateNotifier::updateState() +{ + if (m_isOnLine == p->m_online) + return; + + m_isOnLine = p->m_online; + if (m_networkStateChangedFunction) + m_networkStateChangedFunction(); +} + +NetworkStateNotifier::NetworkStateNotifier() + : m_isOnLine(true) + , m_networkStateChangedFunction(0) +{ + p = new NetworkStateNotifierPrivate(this); + m_isOnLine = p->m_online; +} + +} // namespace WebCore + +#include "moc_NetworkStateNotifierPrivate.cpp" diff --git a/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.cpp b/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.cpp index 0a506f8..b74e912 100644 --- a/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.cpp +++ b/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.cpp @@ -267,6 +267,11 @@ bool SVGImage::dataChanged(bool allDataReceived) return m_page; } +String SVGImage::filenameExtension() const +{ + return "svg"; +} + } #endif // ENABLE(SVG) diff --git a/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.h b/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.h index 2cea91a..0f05429 100644 --- a/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.h +++ b/src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.h @@ -47,6 +47,8 @@ namespace WebCore { private: virtual ~SVGImage(); + virtual String filenameExtension() const; + virtual void setContainerSize(const IntSize&); virtual bool usesContainerSize() const; virtual bool hasRelativeWidth() const; diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebinspector.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebinspector.cpp index f43cbbf..1145744 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebinspector.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebinspector.cpp @@ -139,6 +139,9 @@ QSize QWebInspector::sizeHint() const /*! \reimp */ bool QWebInspector::event(QEvent* ev) { + if (ev->type() == QEvent::Close && d->page) + d->page->d->inspectorController()->setWindowVisible(false); + return QWidget::event(ev); } @@ -159,8 +162,6 @@ void QWebInspector::showEvent(QShowEvent* event) /*! \reimp */ void QWebInspector::hideEvent(QHideEvent* event) { - if (d->page) - d->page->d->inspectorController()->setWindowVisible(false); } /*! \internal */ diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp index 88b7271..6d08c32 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp @@ -1849,7 +1849,8 @@ bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue. If the prompt was cancelled by the user the implementation should return false; otherwise the - result should be written to \a result and true should be returned. + result should be written to \a result and true should be returned. If the prompt was not cancelled by the + user, the implementation should return true and the result string must not be null. The default implementation uses QInputDialog::getText. */ @@ -3080,7 +3081,7 @@ QString QWebPage::userAgentForUrl(const QUrl& url) const Q_UNUSED(url) QString ua = QLatin1String("Mozilla/5.0 (" - // Plastform + // Platform #ifdef Q_WS_MAC "Macintosh" #elif defined Q_WS_QWS @@ -3089,19 +3090,22 @@ QString QWebPage::userAgentForUrl(const QUrl& url) const "Windows" #elif defined Q_WS_X11 "X11" +#elif defined Q_OS_SYMBIAN + "SymbianOS" #else "Unknown" #endif - "; " + // Placeholder for Platform Version + "%1; " // Placeholder for security strength (N or U) - "%1; " + "%2; " // Subplatform" #ifdef Q_OS_AIX "AIX" #elif defined Q_OS_WIN32 - "%2" + "%3" #elif defined Q_OS_DARWIN #ifdef __i386__ || __x86_64__ "Intel Mac OS X" @@ -3153,6 +3157,8 @@ QString QWebPage::userAgentForUrl(const QUrl& url) const "Sun Solaris" #elif defined Q_OS_ULTRIX "DEC Ultrix" +#elif defined Q_WS_S60 + "Series60" #elif defined Q_OS_UNIX "UNIX BSD/SYSV system" #elif defined Q_OS_UNIXWARE @@ -3160,7 +3166,28 @@ QString QWebPage::userAgentForUrl(const QUrl& url) const #else "Unknown" #endif - "; "); + // Placeholder for SubPlatform Version + "%4; "); + + // Platform Version + QString osVer; +#ifdef Q_OS_SYMBIAN + QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); + switch (symbianVersion) { + case QSysInfo::SV_9_2: + osVer = "/9.2"; + break; + case QSysInfo::SV_9_3: + osVer = "/9.3"; + break; + case QSysInfo::SV_9_4: + osVer = "/9.4"; + break; + default: + osVer = "Unknown"; + } +#endif + ua = ua.arg(osVer); QChar securityStrength(QLatin1Char('N')); #if !defined(QT_NO_OPENSSL) @@ -3224,6 +3251,26 @@ QString QWebPage::userAgentForUrl(const QUrl& url) const ua = QString(ua).arg(ver); #endif + // SubPlatform Version + QString subPlatformVer; +#ifdef Q_OS_SYMBIAN + QSysInfo::S60Version s60Version = QSysInfo::s60Version(); + switch (s60Version) { + case QSysInfo::SV_S60_3_1: + subPlatformVer = "/3.1"; + break; + case QSysInfo::SV_S60_3_2: + subPlatformVer = "/3.2"; + break; + case QSysInfo::SV_S60_5_0: + subPlatformVer = "/5.0"; + break; + default: + subPlatformVer = " Unknown"; + } +#endif + ua = ua.arg(subPlatformVer); + // Language QLocale locale; if (view()) diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebview.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebview.h index e9c1ec8..0f79c70 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebview.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebview.h @@ -51,12 +51,7 @@ class QWEBKIT_EXPORT QWebView : public QWidget { Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false) Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) -// FIXME: temporary work around for elftran issue that it couldn't find the QPainter::staticMetaObject -// symbol from Qt lib; it should be reverted after the right symbol is exported. -// See bug: http://qt.nokia.com/developer/task-tracker/index_html?method=entry&id=258893 -#if defined(Q_QDOC) || !defined(Q_OS_SYMBIAN) Q_PROPERTY(QPainter::RenderHints renderHints READ renderHints WRITE setRenderHints) -#endif Q_FLAGS(QPainter::RenderHints) public: explicit QWebView(QWidget* parent = 0); diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 2f0bf17..4ab5bfb 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,89 @@ +2009-12-30 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + Upstream Symbian def files from Qt 4.6. + + These files define the ABI of QtWebKit on Symbian. + + * symbian/bwins/QtWebKitu.def: Added. + * symbian/eabi/QtWebKitu.def: Added. + +2009-12-14 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Fix JavaScript prompt behavior for empty/null strings. + https://bugs.webkit.org/show_bug.cgi?id=30914 + + The patch is based on the work done by Gupta Manish. + + In the default implementation of the JavaScript prompt + we are using a QInputDialog to get the text and this has + one quirk with regard to not entering any text. + + In other WebKit ports and in Firefox an empty string is + returned but in the Qt case it is a null string. + + Change the API documentation in QWebPage to mention we want to + have a non null string but do the fixup in the ChromeClientQt + to support existing code. + + * Api/qwebpage.cpp: + (QWebPage::javaScriptPrompt): Change API documentation + * WebCoreSupport/ChromeClientQt.cpp: + (WebCore::ChromeClientQt::runJavaScriptPrompt): Fixup null QString + +2009-12-21 David Boddie <dboddie@trolltech.com> + + Reviewed by Simon Hausmann. + + Doc: Minor fixes to language. + + * Api/qwebpage.cpp: + +2009-12-15 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by NOBODY (OOPS!). + + [Qt] Do not disable the inspector on show and hide + https://bugs.webkit.org/show_bug.cgi?id=31851 + + On Qt/X11 with some window managers the window will be + hidden when switching windows. In this case all the results + are gone when coming back to the window. + + Attempt to use the CloseEvent to figure out if the window + was closed and withdrawn as this is more friendly to the + user of the inspector client. + + * Api/qwebinspector.cpp: + (QWebInspector::event): + (QWebInspector::hideEvent): + +2009-12-13 Simon Hausmann <hausmann@webkit.org> + + Reviewed by Holger Freyther. + + [Qt] Re-enable QWebView::renderHints property for Qt for Symbian + + https://bugs.webkit.org/show_bug.cgi?id=28273 + + The bug in Qt's moc that triggered a linking error when declaring this + property has been fixed and we can remove the workaround. + + * Api/qwebview.h: + +2009-11-30 Abhinav Mithal <abhinav.mithal@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt][Symbian] Report SymbianOS in user agent string for Symbian + https://bugs.webkit.org/show_bug.cgi?id=31961 + + * Api/qwebpage.cpp: + (QWebPage::userAgentForUrl): + 2009-11-28 Simon Hausmann <simon.hausmann@nokia.com> Reviewed by Kenneth Rohde Christiansen. diff --git a/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index 26cf6f6..c5d2792 100644 --- a/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -278,7 +278,14 @@ bool ChromeClientQt::runJavaScriptPrompt(Frame* f, const String& message, const QString x = result; FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client()); bool rc = m_webPage->javaScriptPrompt(fl->webFrame(), (QString)message, (QString)defaultValue, &x); - result = x; + + // Fix up a quirk in the QInputDialog class. If no input happened the string should be empty + // but it is null. See https://bugs.webkit.org/show_bug.cgi?id=30914. + if (rc && result.isNull()) + result = String(""); + else + result = x; + return rc; } diff --git a/src/s60installs/bwins/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def index e5631f8..e5631f8 100644 --- a/src/s60installs/bwins/QtWebKitu.def +++ b/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def diff --git a/src/s60installs/eabi/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def index 4aad884..4aad884 100644 --- a/src/s60installs/eabi/QtWebKitu.def +++ b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp index 15b8ecd..e93394f 100644 --- a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp +++ b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp @@ -46,6 +46,9 @@ #include <mach/mach_time.h> #include <unistd.h> #elif defined(Q_OS_UNIX) +#if defined(Q_OS_HURD) +#include <sys/time.h> +#endif #include <time.h> #include <unistd.h> #elif defined(Q_OS_WIN) diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index ff8c6c8..c1c7812 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -93,7 +93,7 @@ public: inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; } inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); } - inline QDebug &operator<<(QBool t) { stream->ts << (bool(t) ? "true" : "false"); return maybeSpace(); } + inline QDebug &operator<<(QBool t) { stream->ts << (bool(t != 0) ? "true" : "false"); return maybeSpace(); } inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); } inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); } inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); } diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 61081a1..0a435b9 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -573,6 +573,8 @@ QString QFileInfo::canonicalFilePath() const QString QFileInfo::absolutePath() const { Q_D(const QFileInfo); + if (d->data->fileName.isEmpty()) + qWarning("QFileInfo::absolutePath: Constructed with empty filename"); if(!d->data->fileEngine) return QLatin1String(""); return d->getFileName(QAbstractFileEngine::AbsolutePathName); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 71414ce..ea262bf 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -825,10 +825,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const ret |= RootFlag; } else { QString baseName = fileName(BaseName); - if ((baseName.size() > 1 - && baseName.at(0) == QLatin1Char('.') && baseName.at(1) != QLatin1Char('.')) + if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) # if !defined(QWS) && defined(Q_OS_MAC) - || _q_isMacHidden(d->filePath) + || _q_isMacHidden(d->filePath) # endif ) { ret |= HiddenFlag; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index a6cb5a9..a7719a8 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1595,13 +1595,10 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil ret |= LocalDiskFlag; if (d->doStat()) { ret |= ExistsFlag; - if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) { + if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) ret |= RootFlag; - } else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) { - QString baseName = fileName(BaseName); - if (baseName != QLatin1String(".") && baseName != QLatin1String("..")) - ret |= HiddenFlag; - } + else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) + ret |= HiddenFlag; } } return ret; diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index fd51bcf..6ac6468 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3864,14 +3864,18 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const url += "//"; if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) { + bool hasUserOrPass = false; if (!userName.isEmpty()) { url += encodedUserName; - if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { - url += ':'; - url += encodedPassword; - } - url += '@'; + hasUserOrPass = true; } + if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { + url += ':'; + url += encodedPassword; + hasUserOrPass = true; + } + if (hasUserOrPass) + url += '@'; } if (host.startsWith(QLatin1Char('['))) { diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index af68434..3db308f 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -202,7 +202,7 @@ public: QStack<QEventLoop *> eventLoops; QPostEventList postEventList; bool canWait; - QMap<int, void *> tls; + QVector<void *> tls; QMutex mutex; diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index 8b1f255..a7d53d0 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -71,27 +71,32 @@ void qtsDebug(const char *fmt, ...) # define DEBUG_MSG if(false)qDebug #endif -static QBasicAtomicInt idCounter = Q_BASIC_ATOMIC_INITIALIZER(INT_MAX); Q_GLOBAL_STATIC(QMutex, mutex) -typedef QMap<int, void (*)(void *)> DestructorMap; +typedef QVector<void (*)(void *)> DestructorMap; Q_GLOBAL_STATIC(DestructorMap, destructors) QThreadStorageData::QThreadStorageData(void (*func)(void *)) - : id(idCounter.fetchAndAddRelaxed(-1)) { QMutexLocker locker(mutex()); - destructors()->insert(id, func); - + DestructorMap *destr = destructors(); + for (id = 0; id < destr->count(); id++) { + if (destr->at(id) == 0) + break; + } + if (id == destr->count()) { + destr->append(func); + } else { + (*destr)[id] = func; + } DEBUG_MSG("QThreadStorageData: Allocated id %d, destructor %p", id, func); } QThreadStorageData::~QThreadStorageData() { + DEBUG_MSG("QThreadStorageData: Released id %d", id); QMutexLocker locker(mutex()); if (destructors()) - destructors()->remove(id); - - DEBUG_MSG("QThreadStorageData: Released id %d", id); + (*destructors())[id] = 0; } void **QThreadStorageData::get() const @@ -101,14 +106,17 @@ void **QThreadStorageData::get() const qWarning("QThreadStorage::get: QThreadStorage can only be used with threads started with QThread"); return 0; } - QMap<int, void *>::const_iterator it = data->tls.constFind(id); + QVector<void *> &tls = data->tls; + if (tls.size() <= id) + tls.resize(id + 1); + void **v = &tls[id]; + DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p", id, - it != data->tls.end() ? it.value() : 0, + *v, data->thread); - // const_cast below is a bit evil - but we have to make sure not to detach here - // otherwise we'll go bonkers in oom situations - return it != data->tls.constEnd() && it.value() != 0 ? const_cast<void **>(&it.value()) : 0; + + return *v ? v : 0; } void **QThreadStorageData::set(void *p) @@ -118,51 +126,46 @@ void **QThreadStorageData::set(void *p) qWarning("QThreadStorage::set: QThreadStorage can only be used with threads started with QThread"); return 0; } + QVector<void *> &tls = data->tls; + if (tls.size() <= id) + tls.resize(id + 1); + + void *&value = tls[id]; + // delete any previous data + if (value != 0) { + DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p", + id, + value, + data->thread); - QMap<int, void *>::iterator it = data->tls.find(id); - if (it != data->tls.end()) { - // delete any previous data - if (it.value() != 0) { - DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p", - id, - it.value(), - data->thread); - - void *q = it.value(); - it.value() = 0; - - QMutexLocker locker(mutex()); - void (*destructor)(void *) = destructors()->value(id); - locker.unlock(); + QMutexLocker locker(mutex()); + void (*destructor)(void *) = destructors()->value(id); + locker.unlock(); - destructor(q); - } + void *q = value; + value = 0; - // store new data - it.value() = p; - DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p); - } else { - it = data->tls.insert(id, p); - DEBUG_MSG("QThreadStorageData: Inserted storage %d, data %p, for thread %p", id, p, data->thread); + destructor(q); } - return &it.value(); + // store new data + value = p; + DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p); + return &value; } void QThreadStorageData::finish(void **p) { - QMap<int, void *> *tls = reinterpret_cast<QMap<int, void *> *>(p); + QVector<void *> *tls = reinterpret_cast<QVector<void *> *>(p); if (!tls || tls->isEmpty() || !mutex()) return; // nothing to do DEBUG_MSG("QThreadStorageData: Destroying storage for thread %p", QThread::currentThread()); - QMap<int, void *>::iterator it = tls->begin(); - while (it != tls->end()) { - int id = it.key(); - void *q = it.value(); - it.value() = 0; - ++it; + for(int i = tls->size() - 1; i >= 0; i--) { + void *&value = (*tls)[i]; + void *q = value; + value = 0; if (!q) { // data already deleted @@ -170,16 +173,16 @@ void QThreadStorageData::finish(void **p) } QMutexLocker locker(mutex()); - void (*destructor)(void *) = destructors()->value(id); + void (*destructor)(void *) = destructors()->value(i); locker.unlock(); if (!destructor) { if (QThread::currentThread()) qWarning("QThreadStorage: Thread %p exited after QThreadStorage %d destroyed", - QThread::currentThread(), id); + QThread::currentThread(), i); continue; } - destructor(q); + destructor(q); //crash here might mean the thread exited after qthreadstorage was destroyed } tls->clear(); } diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 994da10..ff0a93e 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -561,13 +561,7 @@ void QDBusAbstractInterface::connectNotify(const char *signal) QDBusConnectionPrivate *conn = d->connectionPrivate(); if (conn) { - // do we know what our owner is? - QString owner; - if (!d->service.isEmpty() && d->currentOwner.isNull()) - owner = QLatin1String(""); - else - owner = d->currentOwner; - conn->connectRelay(d->service, owner, d->path, d->interface, + conn->connectRelay(d->service, d->path, d->interface, this, signal); } } @@ -585,7 +579,7 @@ void QDBusAbstractInterface::disconnectNotify(const char *signal) QDBusConnectionPrivate *conn = d->connectionPrivate(); if (conn) - conn->disconnectRelay(d->service, d->currentOwner, d->path, d->interface, + conn->disconnectRelay(d->service, d->path, d->interface, this, signal); } diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index d7088ff..47893cc 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -619,10 +619,8 @@ bool QDBusConnection::connect(const QString &service, const QString &path, const if (interface.isEmpty() && name.isEmpty()) return false; - QString owner = d->getNameOwner(service); // we don't care if the owner is empty - // it might get started later QDBusWriteLocker locker(ConnectAction, d); - return d->connectSignal(service, owner, path, interface, name, argumentMatch, signature, receiver, slot); + return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); } /*! diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index d6f7598..32e057c 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -119,7 +119,7 @@ public: struct SignalHook { inline SignalHook() : obj(0), midx(-1) { } - QString owner, service, path, signature; + QString service, path, signature; QObject* obj; int midx; QList<int> params; @@ -155,7 +155,13 @@ public: typedef QMultiHash<QString, SignalHook> SignalHookHash; typedef QHash<QString, QDBusMetaObject* > MetaObjectHash; typedef QHash<QByteArray, int> MatchRefCountHash; - typedef QHash<QString, int> WatchedServicesHash; + + struct WatchedServiceData { + WatchedServiceData() : refcount(0) {} + QString owner; + int refcount; + }; + typedef QHash<QString, WatchedServiceData> WatchedServicesHash; public: // public methods are entry points from other objects @@ -177,7 +183,7 @@ public: QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, int timeout = -1); int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, const char *returnMethod, const char *errorMethod, int timeout = -1); - bool connectSignal(const QString &service, const QString &owner, const QString &path, const QString& interface, + bool connectSignal(const QString &service, const QString &path, const QString& interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); void connectSignal(const QString &key, const SignalHook &hook); @@ -186,10 +192,10 @@ public: const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); void registerObject(const ObjectTreeNode *node); - void connectRelay(const QString &service, const QString ¤tOwner, + void connectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal); - void disconnectRelay(const QString &service, const QString ¤tOwner, + void disconnectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal); @@ -223,6 +229,8 @@ private: bool isServiceRegisteredByThread(const QString &serviceName) const; + QString getNameOwnerNoCache(const QString &service); + protected: void customEvent(QEvent *e); void timerEvent(QTimerEvent *e); @@ -271,7 +279,7 @@ public: QDBusError lastError; QStringList serviceNames; - WatchedServicesHash watchedServiceNames; + WatchedServicesHash watchedServices; SignalHookHash signalHooks; MatchRefCountHash matchRefCounts; ObjectTreeNode rootNode; @@ -284,7 +292,7 @@ public: // static methods static int findSlot(QObject *obj, const QByteArray &normalizedName, QList<int>& params); static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, - const QString &service, const QString &owner, + const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argMatch, QObject *receiver, const char *signal, int minMIdx, diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 40febc4..ea02005 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -390,7 +390,7 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v } // extern "C" -static QByteArray buildMatchRule(const QString &service, const QString & /*owner*/, +static QByteArray buildMatchRule(const QString &service, const QString &objectPath, const QString &interface, const QString &member, const QStringList &argMatch, const QString & /*signature*/) { @@ -523,7 +523,7 @@ qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message); - qDBusDebug() << QThread::currentThread() << "got message:" << amsg; + qDBusDebug() << d << "got message:" << amsg; return d->handleMessage(amsg) ? DBUS_HANDLER_RESULT_HANDLED : @@ -913,7 +913,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q if (msg.isReplyRequired() && !msg.isDelayedReply()) { if (!fail) { // normal reply - qDBusDebug() << QThread::currentThread() << "Automatically sending reply:" << outputArgs; + qDBusDebug() << this << "Automatically sending reply:" << outputArgs; send(msg.createReply(outputArgs)); } else { // generate internal error @@ -947,7 +947,6 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) QDBusMetaTypeId::init(); rootNode.flags = 0; - watchedServiceNames[QLatin1String(DBUS_SERVICE_DBUS)] = 1; } QDBusConnectionPrivate::~QDBusConnectionPrivate() @@ -1179,11 +1178,15 @@ void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, { Q_UNUSED(oldOwner); QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); - QMutableHashIterator<QString, SignalHook> it(signalHooks); - it.toFront(); - while (it.hasNext()) - if (it.next().value().service == name) - it.value().owner = newOwner; + WatchedServicesHash::Iterator it = watchedServices.find(name); + if (it == watchedServices.end()) + return; + if (oldOwner != it->owner) + qWarning("QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'", + qPrintable(name), qPrintable(oldOwner), qPrintable(it->owner)); + + qDBusDebug() << this << "Updating name" << name << "from" << oldOwner << "to" << newOwner; + it->owner = newOwner; } int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, @@ -1201,7 +1204,7 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedN } bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, - const QString &service, const QString &owner, + const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argMatch, QObject *receiver, const char *signal, int minMIdx, @@ -1220,7 +1223,6 @@ bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hoo } hook.service = service; - hook.owner = owner; // we don't care if the service has an owner yet hook.path = path; hook.obj = receiver; hook.argumentMatch = argMatch; @@ -1245,7 +1247,7 @@ bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hoo hook.signature += QLatin1String( QDBusMetaType::typeToSignature( hook.params.at(i) ) ); } - hook.matchRule = buildMatchRule(service, owner, path, interface, mname, argMatch, hook.signature); + hook.matchRule = buildMatchRule(service, path, interface, mname, argMatch, hook.signature); return true; // connect to this signal } @@ -1488,8 +1490,14 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage //qDBusDebug() << signalHooks.keys(); for ( ; it != end && it.key() == key; ++it) { const SignalHook &hook = it.value(); - if (!hook.owner.isNull() && hook.owner != msg.service()) - continue; + if (!hook.service.isEmpty()) { + const QString owner = + shouldWatchService(hook.service) ? + watchedServices.value(hook.service).owner : + hook.service; + if (owner != msg.service()) + continue; + } if (!hook.path.isEmpty() && hook.path != msg.path()) continue; if (!hook.signature.isEmpty() && hook.signature != msg.signature()) @@ -1652,15 +1660,18 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError } QString busService = QLatin1String(DBUS_SERVICE_DBUS); - connectSignal(busService, QString(), QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(), + WatchedServicesHash::mapped_type &bus = watchedServices[busService]; + bus.refcount = 1; + bus.owner = getNameOwnerNoCache(busService); + connectSignal(busService, QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(), this, SLOT(registerService(QString))); - connectSignal(busService, QString(), QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), + connectSignal(busService, QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), this, SLOT(unregisterService(QString))); q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); - //qDebug("base service: %s", service); + qDBusDebug() << this << ": connected successfully"; // schedule a dispatch: QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); @@ -1695,7 +1706,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) msg = QDBusMessagePrivate::fromDBusMessage(reply); q_dbus_message_unref(reply); } - qDBusDebug() << QThread::currentThread() << "got message reply (async):" << msg; + qDBusDebug() << connection << "got message reply (async):" << msg; // Check if the reply has the expected signature call->checkReceivedSignature(); @@ -1763,7 +1774,7 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message) q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything - qDBusDebug() << QThread::currentThread() << "sending message (no reply):" << message; + qDBusDebug() << this << "sending message (no reply):" << message; checkThread(); bool isOk = q_dbus_connection_send(connection, msg, 0); int serial = 0; @@ -1795,7 +1806,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, return QDBusMessage::createError(err); } - qDBusDebug() << QThread::currentThread() << "sending message (blocking):" << message; + qDBusDebug() << this << "sending message (blocking):" << message; QDBusErrorInternal error; DBusMessage *reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error); @@ -1808,7 +1819,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply); q_dbus_message_unref(reply); - qDBusDebug() << QThread::currentThread() << "got message reply (blocking):" << amsg; + qDBusDebug() << this << "got message reply (blocking):" << amsg; return amsg; } else { // use the event loop @@ -1835,7 +1846,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &message) { - qDBusDebug() << QThread::currentThread() << "sending message via local-loop:" << message; + qDBusDebug() << this << "sending message via local-loop:" << message; QDBusMessage localCallMsg = QDBusMessagePrivate::makeLocal(*this, message); bool handled = handleMessage(localCallMsg); @@ -1862,7 +1873,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &mess } // there is a reply - qDBusDebug() << QThread::currentThread() << "got message via local-loop:" << localReplyMsg; + qDBusDebug() << this << "got message via local-loop:" << localReplyMsg; return localReplyMsg; } @@ -1896,7 +1907,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM return pcall; } - qDBusDebug() << QThread::currentThread() << "sending message (async):" << message; + qDBusDebug() << this << "sending message (async):" << message; DBusPendingCall *pending = 0; QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); @@ -1968,7 +1979,7 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj return 1; } -bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString &owner, +bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot) @@ -1981,7 +1992,7 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString name2.detach(); hook.signature = signature; - if (!prepareHook(hook, key, service, owner, path, interface, name, argumentMatch, receiver, slot, 0, false)) + if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) return false; // don't connect // avoid duplicating: @@ -1990,7 +2001,6 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString for ( ; it != end && it.key() == key; ++it) { const QDBusConnectionPrivate::SignalHook &entry = it.value(); if (entry.service == hook.service && - entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2035,16 +2045,19 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook // Successfully connected the signal // Do we need to watch for this name? if (shouldWatchService(hook.service)) { - WatchedServicesHash::Iterator it = watchedServiceNames.find(hook.service); - if (it != watchedServiceNames.end()) { + WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; + if (data.refcount) { // already watching - ++it.value(); + ++data.refcount; } else { // we need to watch for this service changing QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); - connectSignal(dbusServerService, dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), + connectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + data.owner = getNameOwnerNoCache(hook.service); + qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" + << data.owner << ")"; } } } @@ -2064,7 +2077,7 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, name2.detach(); hook.signature = signature; - if (!prepareHook(hook, key, service, QString(), path, interface, name, argumentMatch, receiver, slot, 0, false)) + if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) return false; // don't disconnect // avoid duplicating: @@ -2073,7 +2086,6 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, for ( ; it != end && it.key() == key; ++it) { const QDBusConnectionPrivate::SignalHook &entry = it.value(); if (entry.service == hook.service && - //entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2093,16 +2105,16 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) { const SignalHook &hook = it.value(); - WatchedServicesHash::Iterator sit = watchedServiceNames.find(hook.service); - if (sit != watchedServiceNames.end()) { - if (sit.value() == 1) { - watchedServiceNames.erase(sit); + WatchedServicesHash::Iterator sit = watchedServices.find(hook.service); + if (sit != watchedServices.end()) { + if (sit.value().refcount == 1) { + watchedServices.erase(sit); QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); disconnectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); } else { - --sit.value(); + --sit.value().refcount; } } @@ -2154,7 +2166,7 @@ void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node) } } -void QDBusConnectionPrivate::connectRelay(const QString &service, const QString &owner, +void QDBusConnectionPrivate::connectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal) @@ -2164,7 +2176,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, const QString SignalHook hook; QString key; - if (!prepareHook(hook, key, service, owner, path, interface, QString(), QStringList(), receiver, signal, + if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, signal, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect @@ -2175,7 +2187,6 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, const QString for ( ; it != end && it.key() == key; ++it) { const SignalHook &entry = it.value(); if (entry.service == hook.service && - entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2186,7 +2197,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, const QString connectSignal(key, hook); } -void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QString &owner, +void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal) @@ -2196,7 +2207,7 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QStri SignalHook hook; QString key; - if (!prepareHook(hook, key, service, owner, path, interface, QString(), QStringList(), receiver, signal, + if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, signal, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect @@ -2207,7 +2218,6 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QStri for ( ; it != end && it.key() == key; ++it) { const SignalHook &entry = it.value(); if (entry.service == hook.service && - entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2225,9 +2235,23 @@ QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName) { if (QDBusUtil::isValidUniqueConnectionName(serviceName)) return serviceName; - if (!connection || !QDBusUtil::isValidBusName(serviceName)) + if (!connection) return QString(); + { + // acquire a read lock for the cache + QReadLocker locker(&lock); + WatchedServicesHash::ConstIterator it = watchedServices.constFind(serviceName); + if (it != watchedServices.constEnd()) + return it->owner; + } + + // not cached + return getNameOwnerNoCache(serviceName); +} + +QString QDBusConnectionPrivate::getNameOwnerNoCache(const QString &serviceName) +{ QDBusMessage msg = QDBusMessage::createMethodCall(QLatin1String(DBUS_SERVICE_DBUS), QLatin1String(DBUS_PATH_DBUS), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("GetNameOwner")); diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp index d732ad0..28cec7d 100644 --- a/src/dbus/qdbusmarshaller.cpp +++ b/src/dbus/qdbusmarshaller.cpp @@ -387,7 +387,6 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) switch (*signature) { #ifdef __OPTIMIZE__ case DBUS_TYPE_BYTE: - case DBUS_TYPE_BOOLEAN: case DBUS_TYPE_INT16: case DBUS_TYPE_UINT16: case DBUS_TYPE_INT32: @@ -397,6 +396,9 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) case DBUS_TYPE_DOUBLE: qIterAppend(&iterator, ba, *signature, arg.constData()); return true; + case DBUS_TYPE_BOOLEAN: + append( arg.toBool() ); + return true; #else case DBUS_TYPE_BYTE: append( qvariant_cast<uchar>(arg) ); diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp index ae5570f..07bb258 100644 --- a/src/gui/embedded/qscreen_qws.cpp +++ b/src/gui/embedded/qscreen_qws.cpp @@ -3150,6 +3150,7 @@ int QScreen::subScreenIndexAt(const QPoint &p) const #if 0 #ifdef QT_LOADABLE_MODULES +#include <dlfcn.h> // ### needs update after driver init changes diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fbfd8e6..726d571 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2181,7 +2181,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Enable subfocus - if (newVisible) { + if (scene && newVisible) { QGraphicsItem *p = parent; bool done = false; while (p) { diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index ffe64aa..3bb40fb 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1208,6 +1208,11 @@ void QGraphicsView::setTransformationAnchor(ViewportAnchor anchor) { Q_D(QGraphicsView); d->transformationAnchor = anchor; + + // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse + // in order to have up-to-date information for centering the view. + if (d->transformationAnchor == AnchorUnderMouse) + d->viewport->setMouseTracking(true); } /*! @@ -1235,6 +1240,11 @@ void QGraphicsView::setResizeAnchor(ViewportAnchor anchor) { Q_D(QGraphicsView); d->resizeAnchor = anchor; + + // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse + // in order to have up-to-date information for centering the view. + if (d->resizeAnchor == AnchorUnderMouse) + d->viewport->setMouseTracking(true); } /*! @@ -2597,9 +2607,12 @@ void QGraphicsView::setupViewport(QWidget *widget) } // We are only interested in mouse tracking if items - // accept hover events or use non-default cursors. - if (d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents - || !d->scene->d_func()->allItemsUseDefaultCursor)) { + // accept hover events or use non-default cursors or if + // AnchorUnderMouse is used as transformation or resize anchor. + if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents + || !d->scene->d_func()->allItemsUseDefaultCursor)) + || d->transformationAnchor == AnchorUnderMouse + || d->resizeAnchor == AnchorUnderMouse) { widget->setMouseTracking(true); } diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 074f3eb..7580446 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -471,7 +471,6 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq) handler = 0; quality = -1; imageReaderError = QImageReader::UnknownError; - errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error")); q = qq; } @@ -1214,11 +1213,12 @@ bool QImageReader::jumpToImage(int imageNumber) } /*! - For image formats that support animation, this function returns - the number of times the animation should loop. Otherwise, it - returns -1. + For image formats that support animation, this function returns the number + of times the animation should loop. If this function returns -1, it can + either mean the animation should loop forever, or that an error occurred. + If an error occurred, canRead() will return false. - \sa supportsAnimation(), QImageIOHandler::loopCount() + \sa supportsAnimation(), QImageIOHandler::loopCount(), canRead() */ int QImageReader::loopCount() const { @@ -1228,13 +1228,13 @@ int QImageReader::loopCount() const } /*! - For image formats that support animation, this function returns - the total number of images in the animation. + For image formats that support animation, this function returns the total + number of images in the animation. If the format does not support + animation, 0 is returned. - Certain animation formats do not support this feature, in which - case 0 is returned. + This function returns -1 if an error occurred. - \sa supportsAnimation(), QImageIOHandler::imageCount() + \sa supportsAnimation(), QImageIOHandler::imageCount(), canRead() */ int QImageReader::imageCount() const { @@ -1244,11 +1244,13 @@ int QImageReader::imageCount() const } /*! - For image formats that support animation, this function returns - the number of milliseconds to wait until displaying the next frame - in the animation. Otherwise, 0 is returned. + For image formats that support animation, this function returns the number + of milliseconds to wait until displaying the next frame in the animation. + If the image format doesn't support animation, 0 is returned. + + This function returns -1 if an error occurred. - \sa supportsAnimation(), QImageIOHandler::nextImageDelay() + \sa supportsAnimation(), QImageIOHandler::nextImageDelay(), canRead() */ int QImageReader::nextImageDelay() const { @@ -1258,11 +1260,13 @@ int QImageReader::nextImageDelay() const } /*! - For image formats that support animation, this function returns - the sequence number of the current frame. Otherwise, -1 is - returned. + For image formats that support animation, this function returns the + sequence number of the current frame. If the image format doesn't support + animation, 0 is returned. + + This function returns -1 if an error occurred. - \sa supportsAnimation(), QImageIOHandler::currentImageNumber() + \sa supportsAnimation(), QImageIOHandler::currentImageNumber(), canRead() */ int QImageReader::currentImageNumber() const { @@ -1302,6 +1306,8 @@ QImageReader::ImageReaderError QImageReader::error() const */ QString QImageReader::errorString() const { + if (d->errorString.isEmpty()) + return QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error")); return d->errorString; } diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 617cfe5..7e4597e 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -831,14 +831,13 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers if (QPixmapCache::find(key, *this)) return true; - if (!data) - data = QPixmapData::create(0, 0, QPixmapData::PixmapType); - - if (data->fromFile(fileName, format, flags)) { + QPixmapData *tmp = QPixmapData::create(0, 0, QPixmapData::PixmapType); + if (tmp->fromFile(fileName, format, flags)) { + data = tmp; QPixmapCache::insert(key, *this); return true; } - + delete tmp; return false; } diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 1b01e6f..3c1d7e9 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -375,7 +375,7 @@ int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const case QPaintDevice::PdmWidthMM: return qRound(d->width * 25.4 / qt_defaultDpiX()); case QPaintDevice::PdmHeightMM: - return qRound(d->width * 25.4 / qt_defaultDpiY()); + return qRound(d->height * 25.4 / qt_defaultDpiY()); case QPaintDevice::PdmNumColors: return d->colortable.size(); case QPaintDevice::PdmDepth: diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index caa0752..939b86d 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -602,7 +602,7 @@ QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const } template <int shift> -static inline int static_shift(int value) +inline int qt_static_shift(int value) { if (shift == 0) return value; @@ -613,15 +613,15 @@ static inline int static_shift(int value) } template<int aprec, int zprec> -static inline void blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, int alpha) +inline void qt_blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, int alpha) { QRgb *pixel = (QRgb *)bptr; #define Z_MASK (0xff << zprec) - const int A_zprec = static_shift<zprec - 24>(*pixel) & Z_MASK; - const int R_zprec = static_shift<zprec - 16>(*pixel) & Z_MASK; - const int G_zprec = static_shift<zprec - 8>(*pixel) & Z_MASK; - const int B_zprec = static_shift<zprec>(*pixel) & Z_MASK; + const int A_zprec = qt_static_shift<zprec - 24>(*pixel) & Z_MASK; + const int R_zprec = qt_static_shift<zprec - 16>(*pixel) & Z_MASK; + const int G_zprec = qt_static_shift<zprec - 8>(*pixel) & Z_MASK; + const int B_zprec = qt_static_shift<zprec>(*pixel) & Z_MASK; #undef Z_MASK const int zR_zprec = zR >> aprec; @@ -636,17 +636,17 @@ static inline void blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, in #define ZA_MASK (0xff << (zprec + aprec)) *pixel = - static_shift<24 - zprec - aprec>(zA & ZA_MASK) - | static_shift<16 - zprec - aprec>(zR & ZA_MASK) - | static_shift<8 - zprec - aprec>(zG & ZA_MASK) - | static_shift<-zprec - aprec>(zB & ZA_MASK); + qt_static_shift<24 - zprec - aprec>(zA & ZA_MASK) + | qt_static_shift<16 - zprec - aprec>(zR & ZA_MASK) + | qt_static_shift<8 - zprec - aprec>(zG & ZA_MASK) + | qt_static_shift<-zprec - aprec>(zB & ZA_MASK); #undef ZA_MASK } const int alphaIndex = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3); template<int aprec, int zprec> -static inline void blurinner_alphaOnly(uchar *bptr, int &z, int alpha) +inline void qt_blurinner_alphaOnly(uchar *bptr, int &z, int alpha) { const int A_zprec = int(*(bptr)) << zprec; const int z_zprec = z >> aprec; @@ -655,7 +655,7 @@ static inline void blurinner_alphaOnly(uchar *bptr, int &z, int alpha) } template<int aprec, int zprec, bool alphaOnly> -static inline void blurrow(QImage & im, int line, int alpha) +inline void qt_blurrow(QImage & im, int line, int alpha) { uchar *bptr = im.scanLine(line); @@ -668,9 +668,9 @@ static inline void blurrow(QImage & im, int line, int alpha) const int im_width = im.width(); for (int index = 0; index < im_width; ++index) { if (alphaOnly) - blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha); + qt_blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha); else - blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha); + qt_blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha); bptr += stride; } @@ -679,9 +679,9 @@ static inline void blurrow(QImage & im, int line, int alpha) for (int index = im_width - 2; index >= 0; --index) { bptr -= stride; if (alphaOnly) - blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha); + qt_blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha); else - blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha); + qt_blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha); } } @@ -723,7 +723,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp int img_height = img.height(); for (int row = 0; row < img_height; ++row) { for (int i = 0; i <= improvedQuality; ++i) - blurrow<aprec, zprec, alphaOnly>(img, row, alpha); + qt_blurrow<aprec, zprec, alphaOnly>(img, row, alpha); } QImage temp(img.height(), img.width(), img.format()); @@ -756,7 +756,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp img_height = temp.height(); for (int row = 0; row < img_height; ++row) { for (int i = 0; i <= improvedQuality; ++i) - blurrow<aprec, zprec, alphaOnly>(temp, row, alpha); + qt_blurrow<aprec, zprec, alphaOnly>(temp, row, alpha); } if (transposed == 0) { diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 14c863b..1de0f32 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -67,6 +67,9 @@ QT_BEGIN_NAMESPACE # define Q_INTERNAL_WIN_NO_THROW #endif +// avoid going through QImage::scanLine() which calls detach +#define FAST_SCAN_LINE(data, bpl, y) (data + (y) * bpl) + /* All PNG files load to the minimal QImage equivalent. @@ -510,7 +513,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) && outImage->format() == QImage::Format_Indexed8) { int color_table_size = outImage->colorCount(); for (int y=0; y<(int)height; ++y) { - uchar *p = outImage->scanLine(y); + uchar *p = FAST_SCAN_LINE(data, bpl, y); uchar *end = p + width; while (p < end) { if (*p >= color_table_size) diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 8ec9efb..f2d51f7 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -264,7 +264,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy bool gray = format == "pgm"; if (format == "pbm") { - image = image.convertToFormat(QImage::Format_MonoLSB); + image = image.convertToFormat(QImage::Format_Mono); } else if (image.depth() == 1) { image = image.convertToFormat(QImage::Format_Indexed8); } else { diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index fc82f30..646a3a1 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -734,6 +734,33 @@ void QSortFilterProxyModelPrivate::source_items_inserted( } } + if (model->rowCount(source_parent) == delta_item_count) { + // Items were inserted where there were none before. + // If it was new rows make sure to create mappings for columns so that a + // valid mapping can be retreived later and vice-versa. + + QVector<int> &orthogonal_proxy_to_source = (orient == Qt::Horizontal) ? m->source_rows : m->source_columns; + QVector<int> &orthogonal_source_to_proxy = (orient == Qt::Horizontal) ? m->proxy_rows : m->proxy_columns; + + if (orthogonal_source_to_proxy.isEmpty()) { + const int ortho_end = (orient == Qt::Horizontal) ? model->rowCount(source_parent) : model->columnCount(source_parent); + + for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) { + if ((orient == Qt::Horizontal) ? q->filterAcceptsRow(ortho_item, source_parent) + : q->filterAcceptsColumn(ortho_item, source_parent)) { + orthogonal_proxy_to_source.append(ortho_item); + } + } + orthogonal_source_to_proxy.resize(orthogonal_proxy_to_source.size()); + + if (orient == Qt::Horizontal) { + // We're reacting to columnsInserted, but we've just inserted new rows. Sort them. + sort_source_rows(orthogonal_proxy_to_source, source_parent); + } + build_source_to_proxy_mapping(orthogonal_proxy_to_source, orthogonal_source_to_proxy); + } + } + // Sort and insert the items if (orient == Qt::Vertical) // Only sort rows sort_source_rows(source_items, source_parent); @@ -1171,9 +1198,10 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged() { Q_Q(QSortFilterProxyModel); saved_persistent_indexes.clear(); + emit q->layoutAboutToBeChanged(); if (persistent.indexes.isEmpty()) return; - emit q->layoutAboutToBeChanged(); + saved_persistent_indexes = store_persistent_indexes(); } @@ -1181,7 +1209,8 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged() { Q_Q(QSortFilterProxyModel); if (saved_persistent_indexes.isEmpty()) { - q->invalidate(); + clear_mapping(); + emit q->layoutChanged(); return; } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index bd13423..4165c95 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -2096,7 +2096,11 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) if (prev) { #ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled()) { - if (prev->hasEditFocus() && reason != Qt::PopupFocusReason) + if (prev->hasEditFocus() && reason != Qt::PopupFocusReason +#ifdef Q_OS_SYMBIAN + && reason != Qt::ActiveWindowFocusReason +#endif + ) prev->setEditFocus(false); } #endif diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 6c06746..3352dbd 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -349,7 +349,9 @@ extern "C" { // since we accepted the drag enter event, the widget expects // future drage move events. // ### check if we need to treat this like the drag enter event. - nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDEEvent.dropAction()); + nsActions = NSDragOperationNone; + // Save as ignored in the answer rect. + qDMEvent.setDropAction(Qt::IgnoreAction); } else { nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDMEvent.dropAction()); } @@ -357,7 +359,6 @@ extern "C" { return nsActions; } } - - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { NSPoint windowPoint = [sender draggingLocation]; @@ -402,13 +403,15 @@ extern "C" { qDMEvent.setDropAction(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).lastAction); qDMEvent.accept(); QApplication::sendEvent(qwidget, &qDMEvent); - qt_mac_copy_answer_rect(qDMEvent); NSDragOperation operation = qt_mac_mapDropAction(qDMEvent.dropAction()); if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) { // ignore this event (we will still receive further notifications) operation = NSDragOperationNone; + // Save as ignored in the answer rect. + qDMEvent.setDropAction(Qt::IgnoreAction); } + qt_mac_copy_answer_rect(qDMEvent); return operation; } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e551a1d..81f38ec 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -9774,13 +9774,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) } #endif - if (newParent) { - if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { + if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { + if (newParent) oldBs->removeDirtyWidget(this); - // Move the widget and all its static children from - // the old backing store to the new one. - oldBs->moveStaticWidgets(this); - } + // Move the widget and all its static children from + // the old backing store to the new one. + oldBs->moveStaticWidgets(this); } if ((QApplicationPrivate::app_compile_version < 0x040200 diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 7dc4d85..0213af9 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4493,10 +4493,14 @@ void QWidgetPrivate::createTLSysExtra() void QWidgetPrivate::deleteTLSysExtra() { #ifndef QT_MAC_USE_COCOA - if(extra->topextra->group) { + if (extra->topextra->group) { qt_mac_release_window_group(extra->topextra->group); extra->topextra->group = 0; } + if (extra->topextra->windowIcon) { + ReleaseIconRef(extra->topextra->windowIcon); + extra->topextra->windowIcon = 0; + } #endif } diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 628a109..a6cc9c7 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -379,6 +379,13 @@ symbian { QMAKE_CXXFLAGS.ARMCC *= -O3 } +neon { + DEFINES += QT_HAVE_NEON + HEADERS += painting/qdrawhelper_neon_p.h + SOURCES += painting/qdrawhelper_neon.cpp + QMAKE_CXXFLAGS *= -mfpu=neon +} + contains(QT_CONFIG, zlib) { INCLUDEPATH += ../3rdparty/zlib } else:!contains(QT_CONFIG, no-zlib) { diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 1d15dac..81d1515 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -605,7 +605,7 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl, } -static void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, +void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, int const_alpha) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 23236ec..84cf5cc 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -44,6 +44,7 @@ #include <private/qpainter_p.h> #include <private/qdrawhelper_x86_p.h> #include <private/qdrawhelper_armv6_p.h> +#include <private/qdrawhelper_neon_p.h> #include <private/qmath_p.h> #include <qmath.h> @@ -7725,7 +7726,8 @@ enum CPUFeatures { SSE = 0x10, SSE2 = 0x20, CMOV = 0x40, - IWMMXT = 0x80 + IWMMXT = 0x80, + NEON = 0x100 }; static uint detectCPUFeatures() @@ -7751,6 +7753,9 @@ static uint detectCPUFeatures() // runtime detection only available when running as a previlegied process static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt(); return doIWMMXT ? IWMMXT : 0; +#elif defined(QT_HAVE_NEON) + static const bool doNEON = !qgetenv("QT_NO_NEON").toInt(); + return doNEON ? NEON : 0; #else uint features = 0; #if defined(__x86_64__) || defined(Q_OS_WIN64) @@ -8122,7 +8127,14 @@ void qInitDrawhelperAsm() qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; -#endif // Q_CC_RVCT && QT_HAVE_ARMV6 +#elif defined(QT_HAVE_NEON) + if (features & NEON) { + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; + } +#endif if (functionForModeSolidAsm) { const int destinationMode = QPainter::CompositionMode_Destination; diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp new file mode 100644 index 0000000..7fe11bf --- /dev/null +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 <private/qdrawhelper_p.h> + +#ifdef QT_HAVE_NEON + +#include <private/qdrawhelper_neon_p.h> +#include <arm_neon.h> + +QT_BEGIN_NAMESPACE + +static inline int16x8_t qvdiv_255_s16(int16x8_t x, int16x8_t half) +{ + // result = (x + (x >> 8) + 0x80) >> 8 + + const int16x8_t temp = vshrq_n_s16(x, 8); // x >> 8 + const int16x8_t sum_part = vaddq_s16(x, half); // x + 0x80 + const int16x8_t sum = vaddq_s16(temp, sum_part); + + return vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(sum), 8)); +} + +static inline int16x8_t qvbyte_mul_s16(int16x8_t x, int16x8_t alpha, int16x8_t half) +{ + // t = qRound(x * alpha / 255.0) + + const int16x8_t t = vmulq_s16(x, alpha); // t + return qvdiv_255_s16(t, half); +} + +static inline int16x8_t qvinterpolate_pixel_255(int16x8_t x, int16x8_t a, int16x8_t y, int16x8_t b, int16x8_t half) +{ + // t = x * a + y * b + + const int16x8_t ta = vmulq_s16(x, a); + const int16x8_t tb = vmulq_s16(y, b); + + return qvdiv_255_s16(vaddq_s16(ta, tb), half); +} + +static inline int16x8_t qvsource_over_s16(int16x8_t src16, int16x8_t dst16, int16x8_t half, int16x8_t full) +{ + const int16x4_t alpha16_high = vdup_lane_s16(vget_high_s16(src16), 3); + const int16x4_t alpha16_low = vdup_lane_s16(vget_low_s16(src16), 3); + + const int16x8_t alpha16 = vsubq_s16(full, vcombine_s16(alpha16_low, alpha16_high)); + + return vaddq_s16(src16, qvbyte_mul_s16(dst16, alpha16, half)); +} + +void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + const uint *src = (const uint *) srcPixels; + uint *dst = (uint *) destPixels; + int16x8_t half = vdupq_n_s16(0x80); + int16x8_t full = vdupq_n_s16(0xff); + if (const_alpha == 256) { + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + int32x4_t src32 = vld1q_s32((int32_t *)&src[x]); + if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) { + // all opaque + vst1q_s32((int32_t *)&dst[x], src32); + } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) { + int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]); + + const uint8x16_t src8 = vreinterpretq_u8_s32(src32); + const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32); + + const uint8x8_t src8_low = vget_low_u8(src8); + const uint8x8_t dst8_low = vget_low_u8(dst8); + + const uint8x8_t src8_high = vget_high_u8(src8); + const uint8x8_t dst8_high = vget_high_u8(dst8); + + const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low)); + const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low)); + + const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high)); + const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high)); + + const int16x8_t result16_low = qvsource_over_s16(src16_low, dst16_low, half, full); + const int16x8_t result16_high = qvsource_over_s16(src16_high, dst16_high, half, full); + + const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low)); + const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high)); + + vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high)); + } + } + for (; x<w; ++x) { + uint s = src[x]; + if (s >= 0xff000000) + dst[x] = s; + else if (s != 0) + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } else if (const_alpha != 0) { + const_alpha = (const_alpha * 255) >> 8; + int16x8_t const_alpha16 = vdupq_n_s16(const_alpha); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + if (src[x] | src[x+1] | src[x+2] | src[x+3]) { + int32x4_t src32 = vld1q_s32((int32_t *)&src[x]); + int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]); + + const uint8x16_t src8 = vreinterpretq_u8_s32(src32); + const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32); + + const uint8x8_t src8_low = vget_low_u8(src8); + const uint8x8_t dst8_low = vget_low_u8(dst8); + + const uint8x8_t src8_high = vget_high_u8(src8); + const uint8x8_t dst8_high = vget_high_u8(dst8); + + const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low)); + const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low)); + + const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high)); + const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high)); + + const int16x8_t srcalpha16_low = qvbyte_mul_s16(src16_low, const_alpha16, half); + const int16x8_t srcalpha16_high = qvbyte_mul_s16(src16_high, const_alpha16, half); + + const int16x8_t result16_low = qvsource_over_s16(srcalpha16_low, dst16_low, half, full); + const int16x8_t result16_high = qvsource_over_s16(srcalpha16_high, dst16_high, half, full); + + const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low)); + const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high)); + + vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high)); + } + } + for (; x<w; ++x) { + uint s = src[x]; + if (s != 0) { + s = BYTE_MUL(s, const_alpha); + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } +} + +// qblendfunctions.cpp +void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + if (const_alpha != 256) { + if (const_alpha != 0) { + const uint *src = (const uint *) srcPixels; + uint *dst = (uint *) destPixels; + int16x8_t half = vdupq_n_s16(0x80); + const_alpha = (const_alpha * 255) >> 8; + int one_minus_const_alpha = 255 - const_alpha; + int16x8_t const_alpha16 = vdupq_n_s16(const_alpha); + int16x8_t one_minus_const_alpha16 = vdupq_n_s16(255 - const_alpha); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + int32x4_t src32 = vld1q_s32((int32_t *)&src[x]); + int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]); + + const uint8x16_t src8 = vreinterpretq_u8_s32(src32); + const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32); + + const uint8x8_t src8_low = vget_low_u8(src8); + const uint8x8_t dst8_low = vget_low_u8(dst8); + + const uint8x8_t src8_high = vget_high_u8(src8); + const uint8x8_t dst8_high = vget_high_u8(dst8); + + const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low)); + const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low)); + + const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high)); + const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high)); + + const int16x8_t result16_low = qvinterpolate_pixel_255(src16_low, const_alpha16, dst16_low, one_minus_const_alpha16, half); + const int16x8_t result16_high = qvinterpolate_pixel_255(src16_high, const_alpha16, dst16_high, one_minus_const_alpha16, half); + + const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low)); + const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high)); + + vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high)); + } + for (; x<w; ++x) { + uint s = src[x]; + s = BYTE_MUL(s, const_alpha); + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha); + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } + } else { + qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); + } +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_NEON + diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h new file mode 100644 index 0000000..cb9a0d6 --- /dev/null +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 QDRAWHELPER_NEON_P_H +#define QDRAWHELPER_NEON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qdrawhelper_p.h> + +QT_BEGIN_NAMESPACE + +#ifdef QT_HAVE_NEON + +void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +#endif // QT_HAVE_NEON + +QT_END_NAMESPACE + +#endif // QDRAWHELPER_NEON_P_H diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index ed86f5a..bcc993a 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -310,8 +310,8 @@ QColor QS60StylePrivate::stateColor(const QColor &color, const QStyleOption *opt QColor hsvColor = retColor.toHsv(); int colorSat = hsvColor.saturation(); int colorVal = hsvColor.value(); - colorSat = (colorSat!=0) ? (colorSat>>1) : 128; - colorVal = (colorVal!=0) ? (colorVal>>1) : 128; + colorSat = (colorSat != 0) ? (colorSat >> 1) : 128; + colorVal = (colorVal != 0) ? (colorVal >> 1) : 128; hsvColor.setHsv(hsvColor.hue(), colorSat, colorVal); retColor = hsvColor.toRgb(); } @@ -339,7 +339,7 @@ QColor QS60StylePrivate::lighterColor(const QColor &baseColor) bool QS60StylePrivate::drawsOwnThemeBackground(const QWidget *widget) { - return qobject_cast<const QDialog *> (widget); + return (widget ? (widget->windowType() == Qt::Dialog) : false); } QFont QS60StylePrivate::s60Font( @@ -372,7 +372,6 @@ void QS60StylePrivate::clearCaches(CacheClearReason reason) case CC_LayoutChange: // when layout changes, the colors remain in cache, but graphics and fonts can change m_mappedFontsCache.clear(); - deleteBackground(); QPixmapCache::clear(); break; case CC_ThemeChange: @@ -400,10 +399,10 @@ QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const if (!cachedColorExists) { const int frameCornerWidth = pixelMetric(PM_Custom_FrameCornerWidth); const int frameCornerHeight = pixelMetric(PM_Custom_FrameCornerHeight); - Q_ASSERT(2*frameCornerWidth<32); - Q_ASSERT(2*frameCornerHeight<32); + Q_ASSERT(2 * frameCornerWidth < 32); + Q_ASSERT(2 * frameCornerHeight < 32); - const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32,32)).toImage(); + const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32, 32)).toImage(); Q_ASSERT(frameImage.bytesPerLine() > 0); if (frameImage.isNull()) return Qt::black; @@ -418,14 +417,14 @@ QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const int skips = 0; int estimations = 0; - const int topBorderLastPixel = frameCornerHeight*frameImage.width()-1; - const int bottomBorderFirstPixel = frameImage.width()*frameImage.height()-frameCornerHeight*frameImage.width()-1; - const int rightBorderFirstPixel = frameImage.width()-frameCornerWidth; + const int topBorderLastPixel = frameCornerHeight*frameImage.width() - 1; + const int bottomBorderFirstPixel = frameImage.width() * frameImage.height() - frameCornerHeight*frameImage.width() - 1; + const int rightBorderFirstPixel = frameImage.width() - frameCornerWidth; const int leftBorderLastPixel = frameCornerWidth; while ((skips + estimations) < pixels) { - if ((skips+estimations) > topBorderLastPixel && - (skips+estimations) < bottomBorderFirstPixel) { + if ((skips + estimations) > topBorderLastPixel && + (skips + estimations) < bottomBorderFirstPixel) { for (int rowIndex = 0; rowIndex < frameImage.width(); rowIndex++) { if (rowIndex > leftBorderLastPixel && rowIndex < rightBorderFirstPixel) { @@ -530,18 +529,18 @@ void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start, endRect = startRect.translated(rect.width() - startRect.width(), 0); middleRect.adjust(startRect.width(), 0, -startRect.width(), 0); if (startRect.bottomRight().x() > endRect.topLeft().x()) { - const int overlap = (startRect.bottomRight().x() - endRect.topLeft().x())>>1; - startRect.setWidth(startRect.width()-overlap); - endRect.adjust(overlap,0,0,0); + const int overlap = (startRect.bottomRight().x() - endRect.topLeft().x()) >> 1; + startRect.setWidth(startRect.width() - overlap); + endRect.adjust(overlap, 0, 0, 0); } } else { startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height())); endRect = startRect.translated(0, rect.height() - startRect.height()); middleRect.adjust(0, startRect.height(), 0, -startRect.height()); if (startRect.topRight().y() > endRect.bottomLeft().y()) { - const int overlap = (startRect.topRight().y() - endRect.bottomLeft().y())>>1; - startRect.setHeight(startRect.height()-overlap); - endRect.adjust(0,overlap,0,0); + const int overlap = (startRect.topRight().y() - endRect.bottomLeft().y()) >> 1; + startRect.setHeight(startRect.height() - overlap); + endRect.adjust(0, overlap, 0, 0); } } @@ -809,13 +808,13 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag case QS60StyleEnums::SP_QgnGrafTabActiveL: //Returned QSize for tabs must not be square, but narrow rectangle with width:height //ratio of 1:2 for horizontal tab bars (and 2:1 for vertical ones). - result.setWidth(result.height()>>1); + result.setWidth(result.height() >> 1); break; case QS60StyleEnums::SP_QgnGrafNsliderEndLeft: case QS60StyleEnums::SP_QgnGrafNsliderEndRight: case QS60StyleEnums::SP_QgnGrafNsliderMiddle: - result.setWidth(result.height()>>1); + result.setWidth(result.height() >> 1); break; case QS60StyleEnums::SP_QgnGrafNsliderMarker: @@ -992,10 +991,11 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom buttonOption.QStyleOption::operator=(*cmb); const int maxHeight = cmbxFrame.height(); const int maxWidth = cmbxFrame.width() - cmbxEditField.width(); - const int topLeftPoint = direction ? cmbxEditField.right()+1 : cmbxEditField.left()+1-maxWidth; + const int topLeftPoint = direction ? + (cmbxEditField.right() + 1) : (cmbxEditField.left() + 1 - maxWidth); const QRect buttonRect(topLeftPoint, cmbxEditField.top(), maxWidth, maxHeight); buttonOption.rect = buttonRect; - buttonOption.state = cmb->state & (State_Enabled | State_MouseOver); + buttonOption.state = cmb->state; drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget); // draw label background - label itself is drawn separately @@ -1381,9 +1381,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, const QModelIndex index = vopt->index; //todo: Draw cell background only once - for the first cell. QStyleOptionViewItemV4 voptAdj2 = voptAdj; - const QModelIndex indexFirst = itemView->model()->index(0,0); + const QModelIndex indexFirst = itemView->model()->index(0, 0); const QModelIndex indexLast = itemView->model()->index( - itemView->model()->rowCount()-1,itemView->model()->columnCount()-1); + itemView->model()->rowCount() - 1, itemView->model()->columnCount() -1); if (itemView->viewport()) voptAdj2.rect = QRect( itemView->visualRect(indexFirst).topLeft(), itemView->visualRect(indexLast).bottomRight()).intersect(itemView->viewport()->rect()); @@ -1571,16 +1571,16 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, f.setPointSizeF(f.pointSizeF() * KTabFontMul); painter->setFont(f); - if (option->state & QStyle::State_Selected){ + const bool selected = optionTab.state & State_Selected; + if (selected) optionTab.palette.setColor(QPalette::Active, QPalette::WindowText, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option)); - } const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::RoundedWest || optionTab.shape == QTabBar::TriangularEast || optionTab.shape == QTabBar::TriangularWest; - const bool selected = optionTab.state & State_Selected; + if (verticalTabs) { painter->save(); int newX, newY, newRotation; @@ -1618,12 +1618,12 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QPixmap tabIcon = optionTab.icon.pixmap(iconSize, (optionTab.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); if (tab->text.isEmpty()) - painter->drawPixmap(tr.center().x() - (tabIcon.height() >>1), - tr.center().y() - (tabIcon.height() >>1), + painter->drawPixmap(tr.center().x() - (tabIcon.height() >> 1), + tr.center().y() - (tabIcon.height() >> 1), tabIcon); else painter->drawPixmap(tr.left() + tabOverlap, - tr.center().y() - (tabIcon.height() >>1), + tr.center().y() - (tabIcon.height() >> 1), tabIcon); tr.setLeft(tr.left() + iconSize.width() + 4); } @@ -1652,7 +1652,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, if (optionProgressBar->orientation == Qt::Horizontal) { progressRect.setWidth(int(progressRect.width() * progressFactor)); if(optionProgressBar->direction == Qt::RightToLeft) - progressRect.translate(optionProgressBar->rect.width()-progressRect.width(),0); + progressRect.translate(optionProgressBar->rect.width()-progressRect.width(), 0); progressRect.adjust(1, 0, -1, 0); } else { progressRect.adjust(0, 1, 0, -1); @@ -1718,18 +1718,18 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem); optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth)); optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight)); - const int moveByX = optionCheckBox.rect.width()+vSpacing; + const int moveByX = optionCheckBox.rect.width() + vSpacing; if (optionMenuItem.direction == Qt::LeftToRight) { - textRect.translate(moveByX,0); + textRect.translate(moveByX, 0); iconRect.translate(moveByX, 0); - iconRect.setWidth(iconRect.width()+vSpacing); - textRect.setWidth(textRect.width()-moveByX-vSpacing); - optionCheckBox.rect.translate(vSpacing/2, hSpacing/2); + iconRect.setWidth(iconRect.width() + vSpacing); + textRect.setWidth(textRect.width() - moveByX - vSpacing); + optionCheckBox.rect.translate(vSpacing >> 1, hSpacing >> 1); } else { - textRect.setWidth(textRect.width()-moveByX); - iconRect.setWidth(iconRect.width()+vSpacing); - iconRect.translate(-optionCheckBox.rect.width()-vSpacing, 0); - optionCheckBox.rect.translate(textRect.width()+iconRect.width(),0); + textRect.setWidth(textRect.width() - moveByX); + iconRect.setWidth(iconRect.width() + vSpacing); + iconRect.translate(-optionCheckBox.rect.width() - vSpacing, 0); + optionCheckBox.rect.translate(textRect.width() + iconRect.width(), 0); } drawPrimitive(PE_IndicatorMenuCheckMark, &optionCheckBox, painter, widget); } @@ -1740,9 +1740,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, if (itemWithIcon) { drawItemPixmap(painter, iconRect, text_flags, pix); if (optionMenuItem.direction == Qt::LeftToRight) - textRect.translate(vSpacing,0); + textRect.translate(vSpacing, 0); else - textRect.translate(-vSpacing,0); + textRect.translate(-vSpacing, 0); textRect.setWidth(textRect.width()-vSpacing); } @@ -1750,7 +1750,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, if (drawSubMenuIndicator) { QStyleOptionMenuItem arrowOptions; arrowOptions.QStyleOption::operator=(*menuItem); - const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget)>>1) + + const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget) >> 1) + pixelMetric(QStyle::PM_LayoutVerticalSpacing, option, widget); if (optionMenuItem.direction == Qt::LeftToRight) arrowOptions.rect.setLeft(textRect.right()); @@ -1795,8 +1795,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, painter->save(); QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header)); const int penWidth = (header->orientation == Qt::Horizontal) ? - linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth) - : linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth); + linePen.width() + QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth) + : linePen.width() + QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth); linePen.setWidth(penWidth); painter->setPen(linePen); if (header->orientation == Qt::Horizontal){ @@ -1815,7 +1815,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, //Make cornerButton slightly smaller so that it is not on top of table border graphic. QStyleOptionHeader subopt = *header; const int borderTweak = - QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth)>>1; + QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1; if (subopt.direction == Qt::LeftToRight) subopt.rect.adjust(borderTweak, borderTweak, 0, -borderTweak); else @@ -1908,9 +1908,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, } else { const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); if (option->direction == Qt::LeftToRight) - headerRect.adjust(-2*frameWidth, 0, 0, 0); + headerRect.adjust(-2 * frameWidth, 0, 0, 0); else - headerRect.adjust(0, 0, 2*frameWidth, 0); + headerRect.adjust(0, 0, 2 * frameWidth, 0); } if (option->palette.brush(QPalette::Button).color() == Qt::transparent) QS60StylePrivate::drawSkinElement( @@ -2033,7 +2033,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti QRect tickRect = option->rect; const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth); // adjust tickmark rect to exclude frame border - tickRect.adjust(0,-frameBorderWidth,0,-frameBorderWidth); + tickRect.adjust(0, -frameBorderWidth, 0, -frameBorderWidth); QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd; QS60StylePrivate::drawSkinPart(skinPart, painter, tickRect, (flags | QS60StylePrivate::SF_ColorSkinned)); @@ -2045,7 +2045,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_IndicatorRadioButton: { QRect buttonRect = option->rect; //there is empty (a. 33%) space in svg graphics for radiobutton - const qreal reduceWidth = (qreal)buttonRect.width()/3.0; + const qreal reduceWidth = (qreal)buttonRect.width() / 3.0; const qreal rectWidth = (qreal)option->rect.width() != 0 ? option->rect.width() : 1.0; // Try to occupy the full area const qreal scaler = 1 + (reduceWidth/rectWidth); @@ -2108,27 +2108,28 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_IndicatorSpinDown: case PE_IndicatorSpinUp: if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { - QStyleOptionSpinBox optionSpinBox = *spinBox; - if (QS60StylePrivate::canDrawThemeBackground(optionSpinBox.palette.base())) { + if (QS60StylePrivate::canDrawThemeBackground(spinBox->palette.base())) { + QStyleOptionSpinBox optionSpinBox = *spinBox; const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ? QS60StyleEnums::SP_QgnGrafScrollArrowUp : QS60StyleEnums::SP_QgnGrafScrollArrowDown; - const int adjustment = qMin(optionSpinBox.rect.width(), optionSpinBox.rect.height())/6; - optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment ); - QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect,flags); + const int iconMargin = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1; + optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin ); + QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect, flags); } else { commonStyleDraws = true; } } +#endif //QT_NO_SPINBOX #ifndef QT_NO_COMBOBOX - else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) { + if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) { if (QS60StylePrivate::canDrawThemeBackground( option->palette.base())) { // We want to draw down arrow here for comboboxes as well. + QStyleOptionFrame optionsComboBox = *cmb; const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown; - QStyleOptionFrame comboBox = *cmb; - const int adjustment = qMin(comboBox.rect.width(), comboBox.rect.height())/6; - comboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment ); - QS60StylePrivate::drawSkinPart(part, painter, comboBox.rect,flags); + const int iconMargin = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1; + optionsComboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin ); + QS60StylePrivate::drawSkinPart(part, painter, optionsComboBox.rect, flags); } else { commonStyleDraws = true; } @@ -2146,12 +2147,11 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti // We want to draw down arrow here for comboboxes as well. QStyleOptionFrame comboBox = *cmb; const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); - comboBox.rect.adjust(0,frameWidth,0,-frameWidth); + comboBox.rect.adjust(0, frameWidth, 0, -frameWidth); QCommonStyle::drawPrimitive(element, &comboBox, painter, widget); } #endif //QT_NO_COMBOBOX break; -#endif //QT_NO_SPINBOX case PE_Widget: if (QS60StylePrivate::drawsOwnThemeBackground(widget) #ifndef QT_NO_COMBOBOX @@ -2161,7 +2161,10 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti || qobject_cast<const QMenu *> (widget) #endif //QT_NO_MENU ) { - if (QS60StylePrivate::canDrawThemeBackground(option->palette.base())) + //Need extra check since dialogs have their own theme background + if (QS60StylePrivate::canDrawThemeBackground(option->palette.base()) && + option->palette.window().texture().cacheKey() == + QS60StylePrivate::m_themePalette->window().texture().cacheKey()) QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_OptionsMenu, painter, option->rect, flags); else commonStyleDraws = true; @@ -2338,22 +2341,22 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, case CT_ToolButton: sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); //FIXME properly - style should calculate the location of border frame-part - sz += QSize(2*pixelMetric(PM_ButtonMargin), 2*pixelMetric(PM_ButtonMargin)); + sz += QSize(2 * pixelMetric(PM_ButtonMargin), 2 * pixelMetric(PM_ButtonMargin)); if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) if (toolBtn->subControls & SC_ToolButtonMenu) - sz += QSize(pixelMetric(PM_MenuButtonIndicator),0); + sz += QSize(pixelMetric(PM_MenuButtonIndicator), 0); break; case CT_PushButton: sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); //FIXME properly - style should calculate the location of border frame-part - sz += QSize(2*pixelMetric(PM_ButtonMargin), 2*pixelMetric(PM_ButtonMargin)); + sz += QSize(2 * pixelMetric(PM_ButtonMargin), 2 * pixelMetric(PM_ButtonMargin)); if (const QAbstractButton *buttonWidget = (qobject_cast<const QAbstractButton *>(widget))) if (buttonWidget->isCheckable()) sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0); break; case CT_LineEdit: if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) - sz += QSize(2*f->lineWidth, 4*f->lineWidth); + sz += QSize(2 * f->lineWidth, 4 * f->lineWidth); break; case CT_TabBarTab: { @@ -2368,7 +2371,7 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, if (QS60StylePrivate::isTouchSupported()) //Make itemview easier to use in touch devices //QCommonStyle does not adjust height with horizontal margin, it only adjusts width - sz.setHeight(sz.height() + 2*pixelMetric(QStyle::PM_FocusFrameVMargin)); + sz.setHeight(sz.height() + 2 * pixelMetric(QStyle::PM_FocusFrameVMargin)); break; default: sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); @@ -2384,10 +2387,10 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w int retValue = -1; switch (sh) { case SH_Table_GridLineColor: - retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors,2,0).rgba()); + retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 2, 0).rgba()); break; case SH_GroupBox_TextLabelColor: - retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors,6,0).rgba()); + retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0).rgba()); break; case SH_ScrollBar_ScrollWhenPointerLeavesControl: retValue = true; @@ -2469,7 +2472,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple sliderlen = (qint64(scrollbarOption->pageStep) * maxlen) / (range + scrollbarOption->pageStep); const int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbarOption, widget); - if (sliderlen < slidermin || range > (INT_MAX>>1)) + if (sliderlen < slidermin || range > (INT_MAX >> 1)) sliderlen = slidermin; if (sliderlen > maxlen) sliderlen = maxlen; @@ -2520,39 +2523,40 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; const int buttonMargin = spinbox->frame ? 2 : 0; - const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize) + 2*buttonMargin; + const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize) + 2 * buttonMargin; QSize buttonSize; buttonSize.setHeight(qMax(8, spinbox->rect.height() - frameThickness)); - buttonSize.setWidth(buttonWidth); + //width should at least be equal to height + buttonSize.setWidth(qMax(buttonSize.height(), buttonWidth)); buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); const int y = frameThickness + spinbox->rect.y(); - const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - 2*buttonSize.width(); + const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - 2 * buttonSize.width(); switch (scontrol) { case SC_SpinBoxUp: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return QRect(); - ret = QRect(x, y, buttonWidth, buttonSize.height()); + ret = QRect(x, y, buttonSize.width(), buttonSize.height()); break; case SC_SpinBoxDown: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return QRect(); - ret = QRect(x+buttonSize.width(), y, buttonWidth, buttonSize.height()); + ret = QRect(x + buttonSize.width(), y, buttonSize.width(), buttonSize.height()); break; case SC_SpinBoxEditField: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) ret = QRect( frameThickness, frameThickness, - spinbox->rect.width() - 2*frameThickness, - spinbox->rect.height() - 2*frameThickness); + spinbox->rect.width() - 2 * frameThickness, + spinbox->rect.height() - 2 * frameThickness); else ret = QRect( frameThickness, frameThickness, x - frameThickness, - spinbox->rect.height() - 2*frameThickness); + spinbox->rect.height() - 2 * frameThickness); break; case SC_SpinBoxFrame: ret = spinbox->rect; @@ -2568,29 +2572,29 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple ret = cmb->rect; const int width = cmb->rect.width(); const int height = cmb->rect.height(); + const int buttonIconSize = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize); const int buttonMargin = cmb->frame ? 2 : 0; // lets use spinbox frame here as well, as no combobox specific value available. const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0; - const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize); + const int buttonWidth = qMax(cmb->rect.height(), buttonIconSize); + const int xposMod = (cmb->rect.x()) + width - buttonMargin - buttonWidth; + const int ypos = cmb->rect.y(); QSize buttonSize; - buttonSize.setHeight(qMax(8, (cmb->rect.height()>>1) - frameThickness)); //minimum of 8 pixels - buttonSize.setWidth(buttonWidth+2*buttonMargin); + buttonSize.setWidth(buttonWidth + 2 * buttonMargin); + buttonSize.setHeight(qMax(8, (cmb->rect.height() >> 1) - frameThickness)); //buttons should be squares buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); switch (scontrol) { case SC_ComboBoxArrow: - ret.setRect( - ret.x() + ret.width() - buttonMargin - buttonWidth, - ret.y() + buttonMargin, - buttonWidth, - height - 2*buttonMargin); + ret.setRect(xposMod, ypos + buttonMargin, buttonWidth, height - 2 * buttonMargin); break; case SC_ComboBoxEditField: { - ret.setRect( - ret.x() + frameThickness, - ret.y() + frameThickness, - ret.width() - 2*frameThickness - buttonSize.width(), - ret.height() - 2*frameThickness); + const int withFrameX = cmb->rect.x() + cmb->rect.width() - frameThickness - buttonSize.width(); + ret = QRect( + frameThickness, + frameThickness, + withFrameX - frameThickness, + cmb->rect.height() - 2 * frameThickness); } break; default: @@ -2607,7 +2611,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple //slightly indent text and boxes, so that dialog border does not mess with them. const int horizontalSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing); - ret.adjust(2,horizontalSpacing-3,0,0); + ret.adjust(2, horizontalSpacing - 3, 0, 0); } break; case SC_GroupBoxFrame: { @@ -2615,7 +2619,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple const int tbHeight = textBox.height(); ret.translate(0, -ret.y()); // include title to within the groupBox frame - ret.setHeight(ret.height()+tbHeight); + ret.setHeight(ret.height() + tbHeight); if (widget && ret.bottom() > widget->rect().bottom()) ret.setBottom(widget->rect().bottom()); } @@ -2627,7 +2631,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple break; case CC_ToolButton: if (const QStyleOptionToolButton *toolButton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { - const int indicatorRect = pixelMetric(PM_MenuButtonIndicator) + 2*pixelMetric(PM_ButtonMargin); + const int indicatorRect = pixelMetric(PM_MenuButtonIndicator) + 2 * pixelMetric(PM_ButtonMargin); const int border = pixelMetric(PM_ButtonMargin) + pixelMetric(PM_DefaultFrameWidth); ret = toolButton->rect; const bool popup = (toolButton->features & @@ -2665,13 +2669,13 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con // in S60 the input text box doesn't start from line Edit's TL, but // a bit indented. QRect lineEditRect = opt->rect; - const int adjustment = opt->rect.height()>>2; - lineEditRect.adjust(adjustment,0,0,0); + const int adjustment = opt->rect.height() >> 2; + lineEditRect.adjust(adjustment, 0, 0, 0); ret = lineEditRect; } break; case SE_TabBarTearIndicator: - ret = QRect(0,0,0,0); + ret = QRect(0, 0, 0, 0); break; case SE_TabWidgetTabBar: if (const QStyleOptionTabWidgetFrame *optionTab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { @@ -2693,12 +2697,12 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con // make sure that gain does not set the rect outside of widget boundaries if (twf->direction == Qt::RightToLeft) { if ((ret.left() - gain) < widget->rect().left()) - gain = widget->rect().left()-ret.left(); - ret.adjust(-gain,0,0,0); + gain = widget->rect().left() - ret.left(); + ret.adjust(-gain, 0, 0, 0); } else { if ((ret.right() + gain) > widget->rect().right()) - gain = widget->rect().right()-ret.right(); - ret.adjust(0,0,gain,0); + gain = widget->rect().right() - ret.right(); + ret.adjust(0, 0, gain, 0); } } break; @@ -2706,8 +2710,8 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con default: { if (widget) { if ((ret.bottom() + gain) > widget->rect().bottom()) - gain = widget->rect().bottom()-ret.bottom(); - ret.adjust(0,0,0,gain); + gain = widget->rect().bottom() - ret.bottom(); + ret.adjust(0, 0, 0, gain); } break; } @@ -2733,7 +2737,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing); //const int horizontalSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing); const int checkBoxRectWidth = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget).width(); - ret.adjust(-checkBoxRectWidth-verticalSpacing,0,-checkBoxRectWidth-verticalSpacing,0); + ret.adjust(-checkBoxRectWidth - verticalSpacing, 0, -checkBoxRectWidth - verticalSpacing, 0); } } else if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; @@ -2758,9 +2762,9 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){ // submenu indicator is very small, so lets halve the rect if (menuItem->direction == Qt::LeftToRight) - ret.adjust(0,0,-(indicatorWidth >> 1),0); + ret.adjust(0, 0, -(indicatorWidth >> 1), 0); else - ret.adjust((indicatorWidth >> 1),0,0,0); + ret.adjust((indicatorWidth >> 1), 0, 0, 0); } } } @@ -2784,14 +2788,14 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con const int itemHeight = opt->rect.height(); int heightOffset = 0; if (indicatorHeight < itemHeight) - heightOffset = ((itemHeight - indicatorHeight)>>1); + heightOffset = ((itemHeight - indicatorHeight) >> 1); if (checkBoxOnly) { // Move rect and make it slightly smaller, so that // a) highlight border does not cross the rect // b) in s60 list checkbox is smaller than normal checkbox //todo; magic three - ret.setRect(opt->rect.left()+3, opt->rect.top() + heightOffset, - indicatorWidth-3, indicatorHeight-3); + ret.setRect(opt->rect.left() + 3, opt->rect.top() + heightOffset, + indicatorWidth - 3, indicatorHeight - 3); } else { ret.setRect(opt->rect.right() - indicatorWidth - spacing, opt->rect.top() + heightOffset, indicatorWidth, indicatorHeight); @@ -2955,7 +2959,7 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { const int iconDimension = QS60StylePrivate::pixelMetric(QStyle::PM_ToolBarIconSize); - const QRect iconSize = (!option) ? QRect(0,0,iconDimension,iconDimension) : option->rect; + const QRect iconSize = (!option) ? QRect(0, 0, iconDimension, iconDimension) : option->rect; QS60StyleEnums::SkinParts part; QS60StylePrivate::SkinElementFlags adjustedFlags; if (option) diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 13ac301..fb9665a 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -1133,9 +1133,21 @@ QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, Skin QPixmap QS60StylePrivate::backgroundTexture() { + bool createNewBackground = false; if (!m_background) { + createNewBackground = true; + } else { + //if background brush does not match screensize, re-create it + if (m_background->width() != S60->screenWidthInPixels || + m_background->height() != S60->screenHeightInPixels) { + delete m_background; + createNewBackground = true; + } + } + + if (createNewBackground) { QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, - QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), 0, SkinElementFlags()); + QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), 0, SkinElementFlags()); m_background = new QPixmap(background); } return *m_background; @@ -1143,8 +1155,7 @@ QPixmap QS60StylePrivate::backgroundTexture() QSize QS60StylePrivate::screenSize() { - const TSize screenSize = QS60Data::screenDevice()->SizeInPixels(); - return QSize(screenSize.iWidth, screenSize.iHeight); + return QSize(S60->screenWidthInPixels, S60->screenHeightInPixels); } QS60Style::QS60Style() diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 8b40931..aff3ac0 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -1065,7 +1065,7 @@ QRect QRenderRule::boxRect(const QRect& cr, int flags) const r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]); } } - if (!hasNativeBorder() && (flags & Border)) { + if (hasBorder() && (flags & Border)) { const int *b = border()->borders; r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]); } diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index f96f66b..f523226 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1938,7 +1938,11 @@ void QTextControlPrivate::focusEvent(QFocusEvent *e) emit q->updateRequest(q->selectionRect()); if (e->gotFocus()) { #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && e->reason() == Qt::PopupFocusReason)) { + if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason +#ifdef Q_OS_SYMBIAN + || e->reason() == Qt::ActiveWindowFocusReason +#endif + ))) { #endif cursorOn = (interactionFlags & Qt::TextSelectableByKeyboard); if (interactionFlags & Qt::TextEditable) { diff --git a/src/gui/util/qsystemtrayicon_p.h b/src/gui/util/qsystemtrayicon_p.h index 86de366..029a259 100644 --- a/src/gui/util/qsystemtrayicon_p.h +++ b/src/gui/util/qsystemtrayicon_p.h @@ -94,6 +94,7 @@ public: class QBalloonTip : public QWidget { + Q_OBJECT public: static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, const QString& msg, QSystemTrayIcon *trayIcon, diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index c036c32..e26d5c3 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -1180,12 +1180,10 @@ static int getKeyboardAutoRepeatRate() { TTimeIntervalMicroSeconds32 time; S60->wsSession().GetKeyboardRepeatRate(initialTime, time); ret = time.Int() / 1000; // msecs -#elif defined(Q_OS_WIN) +#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) DWORD time; if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0) != FALSE) ret = static_cast<int>(1000 / static_cast<int>(time)); // msecs -#else -#pragma message("Using default guesstimated value for keyboard repeat rate") #endif return ret; // msecs } diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 15dcda2..573b2b5 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1761,7 +1761,11 @@ void QLineEdit::focusInEvent(QFocusEvent *e) d->clickCausedFocus = 1; } #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason)){ + if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && ( e->reason() == Qt::PopupFocusReason +#ifdef Q_OS_SYMBIAN + || e->reason() == Qt::ActiveWindowFocusReason +#endif + ))) { #endif d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); QStyleOptionFrameV2 opt; diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index 5e7d06e..a3624d6 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -765,7 +765,7 @@ void QPlainTextEditPrivate::init(const QString &txt) QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); - QObject::connect(control, SIGNAL(textChanged(const QString &)), q, SLOT(updateMicroFocus())); + QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus())); // set a null page size initially to avoid any relayouting until the textedit // is shown. relayoutDocument() will take care of setting the page size to the diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp index 63fac2a..5d8f134 100644 --- a/src/gui/widgets/qtextedit.cpp +++ b/src/gui/widgets/qtextedit.cpp @@ -158,7 +158,7 @@ void QTextEditPrivate::init(const QString &html) QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); - QObject::connect(control, SIGNAL(textChanged(const QString &)), q, SLOT(updateMicroFocus())); + QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus())); QTextDocument *doc = control->document(); // set a null page size initially to avoid any relayouting until the textedit diff --git a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp index 9645fa8..f58f5be 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp @@ -403,6 +403,7 @@ void QAudioDeviceInfoInternal::updateLists() QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) { + QList<QByteArray> allDevices; QList<QByteArray> devices; QByteArray filter; @@ -430,6 +431,7 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) if((name != NULL) && (descr != NULL) && ((io == NULL) || (io == filter))) { QString deviceName = QLatin1String(name); QString deviceDescription = QLatin1String(descr); + allDevices.append(deviceName.toLocal8Bit().constData()); if(deviceDescription.contains(QLatin1String("Default Audio Device"))) devices.append(deviceName.toLocal8Bit().constData()); } @@ -457,6 +459,9 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) if (idx > 0) devices.append("default"); #endif + if (devices.size() == 0 && allDevices.size() > 0) + return allDevices; + return devices; } diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index b7f9ffd..f50a547 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -153,6 +153,14 @@ WAVEHDR* QAudioInputPrivate::allocateBlocks(int size, int count) void QAudioInputPrivate::freeBlocks(WAVEHDR* blockArray) { + WAVEHDR* blocks = blockArray; + + int count = buffer_size/period_size; + + for(int i = 0; i < count; i++) { + waveInUnprepareHeader(hWaveIn,&blocks[i], sizeof(WAVEHDR)); + blocks+=sizeof(WAVEHDR); + } HeapFree(GetProcessHeap(), 0, blockArray); } @@ -222,11 +230,6 @@ bool QAudioInputPrivate::open() } else { period_size = buffer_size/5; } -#ifdef Q_OS_WINCE - // For wince reduce size to 40ms for buffer size and 20ms period - buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.04; - period_size = buffer_size/2; -#endif timeStamp.restart(); elapsedTimeOffset = 0; wfx.nSamplesPerSec = settings.frequency(); @@ -317,7 +320,7 @@ void QAudioInputPrivate::close() deviceState = QAudio::StoppedState; int count = 0; - while(!finished && count < 100) { + while(!finished && count < 500) { count++; Sleep(10); } @@ -349,9 +352,10 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) char* p = data; qint64 l = 0; qint64 written = 0; + while(!done) { // Read in some audio data - if(waveBlocks[header].dwBytesRecorded > 0) { + if(waveBlocks[header].dwBytesRecorded > 0 && waveBlocks[header].dwFlags & WHDR_DONE) { if(pullMode) { l = audioSource->write(waveBlocks[header].lpData, waveBlocks[header].dwBytesRecorded); @@ -394,6 +398,9 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) //no data, not ready yet, next time return 0; } + + waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); + EnterCriticalSection(&waveInCriticalSection); waveFreeBlockCount++; LeaveCriticalSection(&waveInCriticalSection); @@ -401,17 +408,22 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) waveBlocks[header].dwFlags = 0L; result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); if(result != MMSYSERR_NOERROR) { + result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result); - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); + errorState = QAudio::IOError; + EnterCriticalSection(&waveInCriticalSection); + waveFreeBlockCount--; + LeaveCriticalSection(&waveInCriticalSection); + return 0; } result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR)); if(result != MMSYSERR_NOERROR) { qWarning("QAudioInput: failed to setup block %d,err=%d",header,result); - errorState = QAudio::OpenError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); + errorState = QAudio::IOError; + EnterCriticalSection(&waveInCriticalSection); + waveFreeBlockCount--; + LeaveCriticalSection(&waveInCriticalSection); + return 0; } header++; if(header >= buffer_size/period_size) diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index 2cfc472..02c8cfe 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -147,6 +147,14 @@ WAVEHDR* QAudioOutputPrivate::allocateBlocks(int size, int count) void QAudioOutputPrivate::freeBlocks(WAVEHDR* blockArray) { + WAVEHDR* blocks = blockArray; + + int count = buffer_size/period_size; + + for(int i = 0; i < count; i++) { + waveOutUnprepareHeader(hWaveOut,&blocks[i], sizeof(WAVEHDR)); + blocks+=sizeof(WAVEHDR); + } HeapFree(GetProcessHeap(), 0, blockArray); } diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 8a8f483..d28d5f3 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -170,13 +170,15 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.append(qShaderSnippets[MainVertexShader]); source.append(qShaderSnippets[PositionOnlyVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, context, this); - vertexShader->compileSourceCode(source); + if (!vertexShader->compileSourceCode(source)) + qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); fragShader = new QGLShader(QGLShader::Fragment, context, this); - fragShader->compileSourceCode(source); + if (!fragShader->compileSourceCode(source)) + qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); simpleShaderProg = new QGLShaderProgram(context, this); simpleShaderProg->addShader(vertexShader); @@ -193,13 +195,15 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); source.append(qShaderSnippets[UntransformedPositionVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, context, this); - vertexShader->compileSourceCode(source); + if (!vertexShader->compileSourceCode(source)) + qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ImageSrcFragmentShader]); fragShader = new QGLShader(QGLShader::Fragment, context, this); - fragShader->compileSourceCode(source); + if (!fragShader->compileSourceCode(source)) + qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); blitShaderProg = new QGLShaderProgram(context, this); blitShaderProg->addShader(vertexShader); @@ -234,84 +238,95 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS } } - QByteArray source; - source.append(qShaderSnippets[prog.mainFragShader]); - source.append(qShaderSnippets[prog.srcPixelFragShader]); - if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) - source.append(prog.customStageSource); - if (prog.compositionFragShader) - source.append(qShaderSnippets[prog.compositionFragShader]); - if (prog.maskFragShader) - source.append(qShaderSnippets[prog.maskFragShader]); - QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); - fragShader->compileSourceCode(source); - - source.clear(); - source.append(qShaderSnippets[prog.mainVertexShader]); - source.append(qShaderSnippets[prog.positionVertexShader]); - QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); - vertexShader->compileSourceCode(source); + QGLShader *vertexShader = 0; + QGLShader *fragShader = 0; + QGLEngineShaderProg *newProg = 0; + bool success = false; + + do { + QByteArray source; + source.append(qShaderSnippets[prog.mainFragShader]); + source.append(qShaderSnippets[prog.srcPixelFragShader]); + if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) + source.append(prog.customStageSource); + if (prog.compositionFragShader) + source.append(qShaderSnippets[prog.compositionFragShader]); + if (prog.maskFragShader) + source.append(qShaderSnippets[prog.maskFragShader]); + fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); + QByteArray description; +#if defined(QT_DEBUG) + // Name the shader for easier debugging + description.append("Fragment shader: main="); + description.append(snippetNameStr(prog.mainFragShader)); + description.append(", srcPixel="); + description.append(snippetNameStr(prog.srcPixelFragShader)); + if (prog.compositionFragShader) { + description.append(", composition="); + description.append(snippetNameStr(prog.compositionFragShader)); + } + if (prog.maskFragShader) { + description.append(", mask="); + description.append(snippetNameStr(prog.maskFragShader)); + } + fragShader->setObjectName(QString::fromLatin1(description)); +#endif + if (!fragShader->compileSourceCode(source)) { + qWarning() << "Warning:" << description << "failed to compile!"; + break; + } + source.clear(); + source.append(qShaderSnippets[prog.mainVertexShader]); + source.append(qShaderSnippets[prog.positionVertexShader]); + vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); #if defined(QT_DEBUG) - // Name the shaders for easier debugging - QByteArray description; - description.append("Fragment shader: main="); - description.append(snippetNameStr(prog.mainFragShader)); - description.append(", srcPixel="); - description.append(snippetNameStr(prog.srcPixelFragShader)); - if (prog.compositionFragShader) { - description.append(", composition="); - description.append(snippetNameStr(prog.compositionFragShader)); - } - if (prog.maskFragShader) { - description.append(", mask="); - description.append(snippetNameStr(prog.maskFragShader)); - } - fragShader->setObjectName(QString::fromLatin1(description)); - - description.clear(); - description.append("Vertex shader: main="); - description.append(snippetNameStr(prog.mainVertexShader)); - description.append(", position="); - description.append(snippetNameStr(prog.positionVertexShader)); - vertexShader->setObjectName(QString::fromLatin1(description)); + // Name the shader for easier debugging + description.clear(); + description.append("Vertex shader: main="); + description.append(snippetNameStr(prog.mainVertexShader)); + description.append(", position="); + description.append(snippetNameStr(prog.positionVertexShader)); + vertexShader->setObjectName(QString::fromLatin1(description)); #endif + if (!vertexShader->compileSourceCode(source)) { + qWarning() << "Warning:" << description << "failed to compile!"; + break; + } - QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog); - - // If the shader program's not found in the cache, create it now. - newProg->program = new QGLShaderProgram(ctxGuard.context(), this); - newProg->program->addShader(vertexShader); - newProg->program->addShader(fragShader); - - // We have to bind the vertex attribute names before the program is linked: - newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - if (newProg->useTextureCoords) - newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - if (newProg->useOpacityAttribute) - newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); - - newProg->program->link(); - if (!newProg->program->isLinked()) { - QLatin1String none("none"); - QLatin1String br("\n"); - QString error; - error = QLatin1String("Shader program failed to link,") + newProg = new QGLEngineShaderProg(prog); + + // If the shader program's not found in the cache, create it now. + newProg->program = new QGLShaderProgram(ctxGuard.context(), this); + newProg->program->addShader(vertexShader); + newProg->program->addShader(fragShader); + + // We have to bind the vertex attribute names before the program is linked: + newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + if (newProg->useTextureCoords) + newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); + if (newProg->useOpacityAttribute) + newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); + + newProg->program->link(); + if (!newProg->program->isLinked()) { + QLatin1String none("none"); + QLatin1String br("\n"); + QString error; + error = QLatin1String("Shader program failed to link,") #if defined(QT_DEBUG) - + br - + QLatin1String(" Shaders Used:") + br - + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br - + QLatin1String(vertexShader->sourceCode()) + br - + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br - + QLatin1String(fragShader->sourceCode()) + br + + br + + QLatin1String(" Shaders Used:") + br + + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br + + QLatin1String(vertexShader->sourceCode()) + br + + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br + + QLatin1String(fragShader->sourceCode()) + br #endif - + QLatin1String(" Error Log:\n") - + QLatin1String(" ") + newProg->program->log(); - qWarning() << error; - delete newProg; // Deletes the QGLShaderProgram in it's destructor - newProg = 0; - } - else { + + QLatin1String(" Error Log:\n") + + QLatin1String(" ") + newProg->program->log(); + qWarning() << error; + break; + } if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to @@ -323,6 +338,22 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS } cachedPrograms.insert(0, newProg); + + success = true; + } while (false); + + // Clean up everything if we weren't successful + if (!success) { + if (newProg) { + delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders + newProg = 0; + } + else { + if (vertexShader) + delete vertexShader; + if (fragShader) + delete fragShader; + } } return newProg; @@ -362,8 +393,11 @@ QGLEngineShaderManager::~QGLEngineShaderManager() removeCustomStage(); } -uint QGLEngineShaderManager::getUniformLocation(Uniform id) +GLuint QGLEngineShaderManager::getUniformLocation(Uniform id) { + if (!currentShaderProg) + return 0; + QVector<uint> &uniformLocations = currentShaderProg->uniformLocations; if (uniformLocations.isEmpty()) uniformLocations.fill(GLuint(-1), NumUniforms); @@ -394,9 +428,9 @@ uint QGLEngineShaderManager::getUniformLocation(Uniform id) } -void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform) +void QGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType) { - Q_UNUSED(transform); // Currently ignored + Q_UNUSED(transformType); // Currently ignored } void QGLEngineShaderManager::setDirty() @@ -406,6 +440,7 @@ void QGLEngineShaderManager::setDirty() void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) { + Q_ASSERT(style != Qt::NoBrush); if (srcPixelType == PixelSrcType(style)) return; @@ -467,7 +502,10 @@ void QGLEngineShaderManager::removeCustomStage() QGLShaderProgram* QGLEngineShaderManager::currentProgram() { - return currentShaderProg->program; + if (currentShaderProg) + return currentShaderProg->program; + else + return simpleProgram(); } QGLShaderProgram* QGLEngineShaderManager::simpleProgram() diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 50c1432..1ec4cdc 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -454,7 +454,7 @@ public: // There are optimisations we can do, depending on the brush transform: // 1) May not have to apply perspective-correction // 2) Can use lower precision for matrix - void optimiseForBrushTransform(const QTransform &transform); + void optimiseForBrushTransform(QTransform::TransformationType transformType); void setSrcPixelType(Qt::BrushStyle); void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images void setOpacityMode(OpacityMode); @@ -463,7 +463,7 @@ public: void setCustomStage(QGLCustomShaderStage* stage); void removeCustomStage(); - uint getUniformLocation(Uniform id); + GLuint getUniformLocation(Uniform id); void setDirty(); // someone has manually changed the current shader program bool useCorrectShaderProg(); // returns true if the shader program needed to be changed diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 2407979..46de124 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -99,12 +99,15 @@ static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\ opacity = opacityArray; \ }"; +// NOTE: We let GL do the perspective correction so texture lookups in the fragment +// shader are also perspective corrected. static const char* const qglslPositionOnlyVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - uniform highp mat4 pmvMatrix;\ + attribute highp vec2 vertexCoordsArray;\ + uniform highp mat3 pmvMatrix;\ void setPosition(void)\ {\ - gl_Position = pmvMatrix * vertexCoordsArray;\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \ }"; static const char* const qglslUntransformedPositionVertexShader = "\ @@ -116,20 +119,19 @@ static const char* const qglslUntransformedPositionVertexShader = "\ // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 static const char* const qglslPositionWithPatternBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray; \ - uniform highp mat4 pmvMatrix; \ + attribute highp vec2 vertexCoordsArray; \ + uniform highp mat3 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 patternTexCoords; \ void setPosition(void) { \ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \ }"; @@ -147,20 +149,19 @@ static const char* const qglslPatternBrushSrcFragmentShader = "\ // Linear Gradient Brush static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray; \ - uniform highp mat4 pmvMatrix; \ + attribute highp vec2 vertexCoordsArray; \ + uniform highp mat3 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec3 linearData; \ uniform highp mat3 brushTransform; \ varying mediump float index; \ void setPosition() { \ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \ }"; @@ -178,20 +179,19 @@ static const char* const qglslLinearGradientBrushSrcFragmentShader = "\ // Conical Gradient Brush static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - uniform highp mat4 pmvMatrix;\ + attribute highp vec2 vertexCoordsArray;\ + uniform highp mat3 pmvMatrix;\ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 A; \ void setPosition(void)\ {\ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ A = hTexCoords.xy * invertedHTexCoordsZ; \ }"; @@ -215,8 +215,8 @@ static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\ // Radial Gradient Brush static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - uniform highp mat4 pmvMatrix;\ + attribute highp vec2 vertexCoordsArray;\ + uniform highp mat3 pmvMatrix;\ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ uniform highp vec2 fmp; \ @@ -224,13 +224,12 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ varying highp vec2 A; \ void setPosition(void) \ {\ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ A = hTexCoords.xy * invertedHTexCoordsZ; \ b = 2.0 * dot(A, fmp); \ }"; @@ -253,20 +252,19 @@ static const char* const qglslRadialGradientBrushSrcFragmentShader = "\ // Texture Brush static const char* const qglslPositionWithTextureBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray; \ - uniform highp mat4 pmvMatrix; \ + attribute highp vec2 vertexCoordsArray; \ + uniform highp mat3 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 textureCoords; \ void setPosition(void) { \ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \ }"; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index fb9bcb4..d3a9547 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -358,10 +358,10 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? - if (id != GLuint(-1) && id == lastTexture) + if (id != GLuint(-1) && id == lastTextureUsed) return; - lastTexture = id; + lastTextureUsed = id; if (smoothPixmapTransform) { glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -386,19 +386,28 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity) } -void QGL2PaintEngineExPrivate::setBrush(const QBrush* brush) +void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush) { + if (qbrush_fast_equals(currentBrush, brush)) + return; + + const Qt::BrushStyle newStyle = qbrush_style(brush); + Q_ASSERT(newStyle != Qt::NoBrush); + currentBrush = brush; - brushTextureDirty = true; - brushUniformsDirty = true; - if (currentBrush->style() == Qt::TexturePattern - && qHasPixmapTexture(*brush) && brush->texture().isQBitmap()) + brushUniformsDirty = true; // All brushes have at least one uniform + + if (newStyle > Qt::SolidPattern) + brushTextureDirty = true; + + if (currentBrush.style() == Qt::TexturePattern + && qHasPixmapTexture(brush) && brush.texture().isQBitmap()) { shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern); } else { - shaderManager->setSrcPixelType(currentBrush->style()); + shaderManager->setSrcPixelType(newStyle); } - shaderManager->optimiseForBrushTransform(currentBrush->transform()); + shaderManager->optimiseForBrushTransform(currentBrush.transform().type()); } @@ -420,7 +429,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() { Q_Q(QGL2PaintEngineEx); // qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()"); - Qt::BrushStyle style = currentBrush->style(); + Qt::BrushStyle style = currentBrush.style(); if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) { // Get the image data for the pattern @@ -433,7 +442,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { // Gradiant brush: All the gradiants use the same texture - const QGradient* g = currentBrush->gradient(); + const QGradient* g = currentBrush.gradient(); // We apply global opacity in the fragment shaders, so we always pass 1.0 // for opacity to the cache. @@ -450,7 +459,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform); } else if (style == Qt::TexturePattern) { - const QPixmap& texPixmap = currentBrush->texture(); + const QPixmap& texPixmap = currentBrush.texture(); glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); QGLTexture *tex = ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); @@ -464,15 +473,15 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() void QGL2PaintEngineExPrivate::updateBrushUniforms() { // qDebug("QGL2PaintEngineExPrivate::updateBrushUniforms()"); - Qt::BrushStyle style = currentBrush->style(); + Qt::BrushStyle style = currentBrush.style(); if (style == Qt::NoBrush) return; - QTransform brushQTransform = currentBrush->transform(); + QTransform brushQTransform = currentBrush.transform(); if (style == Qt::SolidPattern) { - QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); + QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col); } else { @@ -480,7 +489,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QPointF translationPoint; if (style <= Qt::DiagCrossPattern) { - QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); + QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); @@ -488,7 +497,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::LinearGradientPattern) { - const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient()); + const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient()); QPointF realStart = g->start(); QPointF realFinal = g->finalStop(); @@ -508,7 +517,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::ConicalGradientPattern) { - const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient()); + const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush.gradient()); translationPoint = g->center(); GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0; @@ -519,7 +528,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::RadialGradientPattern) { - const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient()); + const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient()); QPointF realCenter = g->center(); QPointF realFocal = g->focalPoint(); qreal realRadius = g->radius(); @@ -537,10 +546,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::TexturePattern) { - const QPixmap& texPixmap = currentBrush->texture(); + const QPixmap& texPixmap = currentBrush.texture(); - if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) { - QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); + if (qHasPixmapTexture(currentBrush) && currentBrush.texture().isQBitmap()) { + QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } @@ -561,7 +570,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QTransform gl_to_qt(1, 0, 0, -1, 0, height); QTransform inv_matrix; if (style == Qt::TexturePattern && textureInvertedY == -1) - inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush->texture().height()) * brushQTransform * matrix).inverted() * translate; + inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush.texture().height()) * brushQTransform * matrix).inverted() * translate; else inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate; @@ -577,37 +586,43 @@ void QGL2PaintEngineExPrivate::updateMatrix() { // qDebug("QGL2PaintEngineExPrivate::updateMatrix()"); - // We set up the 4x4 transformation matrix on the vertex shaders to - // be the equivalent of glOrtho(0, w, h, 0, -1, 1) * transform: + const QTransform& transform = q->state()->matrix; + + // The projection matrix converts from Qt's coordinate system to GL's coordinate system + // * GL's viewport is 2x2, Qt's is width x height + // * GL has +y -> -y going from bottom -> top, Qt is the other way round + // * GL has [0,0] in the center, Qt has it in the top-left // - // | 2/width 0 0 -1 | | m11 m21 0 dx | - // | 0 -2/height 0 1 | | m12 m22 0 dy | - // | 0 0 -1 0 | * | 0 0 1 0 | - // | 0 0 0 1 | | m13 m23 0 m33 | + // This results in the Projection matrix below, which is multiplied by the painter's + // transformation matrix, as shown below: // - // We expand out the multiplication to save the cost of a full 4x4 - // matrix multiplication as most of the components are trivial. - const QTransform& transform = q->state()->matrix; + // Projection Matrix Painter Transform + // ------------------------------------------------ ------------------------ + // | 2.0 / width | 0.0 | -1.0 | | m11 | m21 | dx | + // | 0.0 | -2.0 / height | 1.0 | * | m12 | m22 | dy | + // | 0.0 | 0.0 | 1.0 | | m13 | m23 | m33 | + // ------------------------------------------------ ------------------------ + // + // NOTE: The resultant matrix is also transposed, as GL expects column-major matracies - qreal wfactor = 2.0 / width; - qreal hfactor = -2.0 / height; - - pmvMatrix[0][0] = wfactor * transform.m11() - transform.m13(); - pmvMatrix[0][1] = hfactor * transform.m12() + transform.m13(); - pmvMatrix[0][2] = 0.0; - pmvMatrix[0][3] = transform.m13(); - pmvMatrix[1][0] = wfactor * transform.m21() - transform.m23(); - pmvMatrix[1][1] = hfactor * transform.m22() + transform.m23(); - pmvMatrix[1][2] = 0.0; - pmvMatrix[1][3] = transform.m23(); - pmvMatrix[2][0] = 0.0; - pmvMatrix[2][1] = 0.0; - pmvMatrix[2][2] = -1.0; - pmvMatrix[2][3] = 0.0; - pmvMatrix[3][0] = wfactor * transform.dx() - transform.m33(); - pmvMatrix[3][1] = hfactor * transform.dy() + transform.m33(); - pmvMatrix[3][2] = 0.0; - pmvMatrix[3][3] = transform.m33(); + const GLfloat wfactor = 2.0f / width; + const GLfloat hfactor = -2.0f / height; + + if (addOffset) { + pmvMatrix[2][0] = (wfactor * (transform.dx() + 0.49f)) - transform.m33(); + pmvMatrix[2][1] = (hfactor * (transform.dy() + 0.49f)) + transform.m33(); + } else { + pmvMatrix[2][0] = (wfactor * transform.dx()) - transform.m33(); + pmvMatrix[2][1] = (hfactor * transform.dy()) + transform.m33(); + } + + pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13(); + pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23(); + pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13(); + pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23(); + pmvMatrix[0][2] = transform.m13(); + pmvMatrix[1][2] = transform.m23(); + pmvMatrix[2][2] = transform.m33(); // 1/10000 == 0.0001, so we have good enough res to cover curves // that span the entire widget... @@ -694,7 +709,14 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect) void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern) { // Setup for texture drawing + currentBrush = noBrush; shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); + + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + if (prepareForDraw(opaque)) shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); @@ -749,7 +771,7 @@ void QGL2PaintEngineEx::beginNativePainting() Q_UNUSED(ctx); #endif - d->lastTexture = GLuint(-1); + d->lastTextureUsed = GLuint(-1); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); d->resetGLState(); @@ -776,12 +798,6 @@ void QGL2PaintEngineEx::endNativePainting() d->needsSync = true; } -const QGLContext *QGL2PaintEngineEx::context() -{ - Q_D(QGL2PaintEngineEx); - return d->ctx; -} - void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) { if (newMode == mode) @@ -792,7 +808,7 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); glDisableVertexAttribArray(QT_OPACITY_ATTR); - lastTexture = GLuint(-1); + lastTextureUsed = GLuint(-1); } if (newMode == TextDrawingMode) { @@ -840,13 +856,14 @@ struct QGL2PEVectorPathCache qreal iscale; }; -void qopengl2paintengine_cleanup_vectorpath(QPaintEngineEx *engine, void *data) +void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data) { QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data; #ifdef QT_OPENGL_CACHE_AS_VBOS - QGL2PaintEngineExPrivate *d = QGL2PaintEngineExPrivate::getData((QGL2PaintEngineEx *) engine); - d->unusedVBOSToClean << c->vbo; + Q_ASSERT(engine->type() == QPaintEngine::OpenGL2); + static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo; #else + Q_UNUSED(engine); qFree(c->vertices); #endif delete c; @@ -857,6 +874,16 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) { transferMode(BrushDrawingMode); + const QOpenGL2PaintEngineState *s = q->state(); + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && + (qbrush_style(currentBrush) == Qt::SolidPattern) && + !multisamplingAlwaysEnabled; + + if (addOffset != newAddOffset) { + addOffset = newAddOffset; + matrixDirty = true; + } + // Might need to call updateMatrix to re-calculate inverseScale if (matrixDirty) updateMatrix(); @@ -866,7 +893,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) // Check to see if there's any hints if (path.shape() == QVectorPath::RectangleHint) { QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); composite(rect); } else if (path.isConvex()) { @@ -892,7 +919,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) } else { cache = new QGL2PEVectorPathCache; cache->vertexCount = 0; - data = const_cast<QVectorPath &>(path).addCacheData(q, cache, qopengl2paintengine_cleanup_vectorpath); + data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath); } // Flatten the path at the current scale factor and fill it into the cache struct. @@ -914,7 +941,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) #endif } - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); #ifdef QT_OPENGL_CACHE_AS_VBOS glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); @@ -933,7 +960,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) path.makeCacheable(); vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale, false); - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); } @@ -958,7 +985,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); } - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); if (inRenderText) prepareDepthRangeForRenderText(); @@ -1155,10 +1182,10 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) : QGLEngineShaderManager::NoOpacity; if (stateHasOpacity && (mode != ImageDrawingMode)) { // Using a brush - bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) && - (currentBrush->style() <= Qt::DiagCrossPattern); + bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) && + (currentBrush.style() <= Qt::DiagCrossPattern); - if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern) + if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern) opacityMode = QGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader } } @@ -1268,31 +1295,14 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) { Q_D(QGL2PaintEngineEx); - Qt::BrushStyle style = qbrush_style(brush); - if (style == Qt::NoBrush) + if (qbrush_style(brush) == Qt::NoBrush) return; + if (!d->inRenderText) ensureActive(); - QOpenGL2PaintEngineState *s = state(); - bool doOffset = !(s->renderHints & QPainter::Antialiasing) && - (style == Qt::SolidPattern) && - !d->multisamplingAlwaysEnabled; - - if (doOffset) { - d->temporaryTransform = s->matrix; - QTransform tx = QTransform::fromTranslate(.49, .49); - s->matrix = s->matrix * tx; - d->matrixDirty = true; - } - - d->setBrush(&brush); + d->setBrush(brush); d->fill(path); - - if (doOffset) { - s->matrix = d->temporaryTransform; - d->matrixDirty = true; - } } extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp @@ -1302,9 +1312,8 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) { Q_D(QGL2PaintEngineEx); - Qt::PenStyle penStyle = qpen_style(pen); const QBrush &penBrush = qpen_brush(pen); - if (penStyle == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) + if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) return; QOpenGL2PaintEngineState *s = state(); @@ -1315,45 +1324,47 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) } ensureActive(); + d->setBrush(penBrush); + d->stroke(path, pen); +} - bool doOffset = !(s->renderHints & QPainter::Antialiasing) && !d->multisamplingAlwaysEnabled; - if (doOffset) { - d->temporaryTransform = s->matrix; - QTransform tx = QTransform::fromTranslate(0.49, .49); - s->matrix = s->matrix * tx; - d->matrixDirty = true; +void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen) +{ + const QOpenGL2PaintEngineState *s = q->state(); + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !multisamplingAlwaysEnabled; + if (addOffset != newAddOffset) { + addOffset = newAddOffset; + matrixDirty = true; } - bool opaque = penBrush.isOpaque() && s->opacity > 0.99; - d->setBrush(&penBrush); - d->transferMode(BrushDrawingMode); + const Qt::PenStyle penStyle = qpen_style(pen); + const QBrush &penBrush = qpen_brush(pen); + const bool opaque = penBrush.isOpaque() && s->opacity > 0.99; + + transferMode(BrushDrawingMode); // updateMatrix() is responsible for setting the inverse scale on // the strokers, so we need to call it here and not wait for // prepareForDraw() down below. - d->updateMatrix(); + updateMatrix(); if (penStyle == Qt::SolidLine) { - d->stroker.process(path, pen); + stroker.process(path, pen); } else { // Some sort of dash - d->dasher.process(path, pen); + dasher.process(path, pen); - QVectorPath dashStroke(d->dasher.points(), - d->dasher.elementCount(), - d->dasher.elementTypes()); - d->stroker.process(dashStroke, pen); + QVectorPath dashStroke(dasher.points(), + dasher.elementCount(), + dasher.elementTypes()); + stroker.process(dashStroke, pen); } - - QGLContext *ctx = d->ctx; - Q_UNUSED(ctx); - if (opaque) { - d->prepareForDraw(opaque); + prepareForDraw(opaque); glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, d->stroker.vertices()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, d->stroker.vertexCount() / 2); + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, stroker.vertices()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2); // QBrush b(Qt::green); // d->setBrush(&b); @@ -1371,30 +1382,25 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) : width; if (pen.isCosmetic()) - extra = extra * d->inverseScale; + extra = extra * inverseScale; QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra); - d->fillStencilWithVertexArray(d->stroker.vertices(), d->stroker.vertexCount() / 2, + fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2, 0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode); glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); // Pass when any bit is set, replace stencil value with 0 glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); - d->prepareForDraw(false); + prepareForDraw(false); // Stencil the brush onto the dest buffer - d->composite(bounds); + composite(bounds); glStencilMask(0); - d->updateClipScissorTest(); - } - - if (doOffset) { - s->matrix = d->temporaryTransform; - d->matrixDirty = true; + updateClipScissorTest(); } } @@ -1434,7 +1440,7 @@ void QGL2PaintEngineEx::renderHintsChanged() #endif Q_D(QGL2PaintEngineEx); - d->lastTexture = GLuint(-1); + d->lastTextureUsed = GLuint(-1); d->brushTextureDirty = true; // qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!"); } @@ -1603,8 +1609,13 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr) glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data()); + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + QBrush pensBrush = q->state()->pen.brush(); - setBrush(&pensBrush); + setBrush(pensBrush); if (inRenderText) prepareDepthRangeForRenderText(); @@ -1649,7 +1660,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly q->state()->opacity = 1; opacityUniformDirty = true; pensBrush = Qt::white; - setBrush(&pensBrush); + setBrush(pensBrush); } compositionModeDirty = false; // I can handle this myself, thank you very much @@ -1670,7 +1681,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly q->state()->opacity = oldOpacity; opacityUniformDirty = true; pensBrush = q->state()->pen.brush(); - setBrush(&pensBrush); + setBrush(pensBrush); } compositionModeDirty = false; @@ -1700,20 +1711,31 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) { + Q_D(QGL2PaintEngineEx); // Use fallback for extended composition modes. if (state()->composition_mode > QPainter::CompositionMode_Plus) { QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints); return; } - Q_D(QGL2PaintEngineEx); + ensureActive(); + d->drawPixmaps(drawingData, dataCount, pixmap, hints); +} + +void QGL2PaintEngineExPrivate::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) +{ GLfloat dx = 1.0f / pixmap.size().width(); GLfloat dy = 1.0f / pixmap.size().height(); - d->vertexCoordinateArray.clear(); - d->textureCoordinateArray.clear(); - d->opacityArray.reset(); + vertexCoordinateArray.clear(); + textureCoordinateArray.clear(); + opacityArray.reset(); + + if (addOffset) { + addOffset = false; + matrixDirty = true; + } bool allOpaque = true; @@ -1730,31 +1752,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c); QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c); - d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy, drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy); - d->textureCoordinateArray.lineToArray(src.right, src.bottom); - d->textureCoordinateArray.lineToArray(src.right, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.bottom); - d->textureCoordinateArray.lineToArray(src.right, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.top); + textureCoordinateArray.lineToArray(src.left, src.top); + textureCoordinateArray.lineToArray(src.left, src.top); + textureCoordinateArray.lineToArray(src.left, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.bottom); - qreal opacity = drawingData[i].opacity * state()->opacity; - d->opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; + qreal opacity = drawingData[i].opacity * q->state()->opacity; + opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; allOpaque &= (opacity >= 0.99f); } - ensureActive(); - - QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption @@ -1762,27 +1781,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d if (texture->options & QGLContext::InvertedYBindOption) { // Flip texture y-coordinate. - QGLPoint *data = d->textureCoordinateArray.data(); + QGLPoint *data = textureCoordinateArray.data(); for (int i = 0; i < 6 * dataCount; ++i) data[i].y = 1 - data[i].y; } - d->transferMode(ImageArrayDrawingMode); + transferMode(ImageArrayDrawingMode); bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque; - d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, - state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); + updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); // Setup for texture drawing - d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); - if (d->prepareForDraw(isOpaque)) - d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); + currentBrush = noBrush; + shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); + if (prepareForDraw(isOpaque)) + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); if (isBitmap) { - QColor col = qt_premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity); - d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::PatternColor), col); + QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount); @@ -1814,7 +1834,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->compositionModeDirty = true; d->opacityUniformDirty = true; d->needsSync = true; - d->use_system_clip = !systemClip().isEmpty(); + d->useSystemClip = !systemClip().isEmpty(); + d->currentBrush = QBrush(); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); d->stencilClean = true; @@ -1934,12 +1955,12 @@ void QGL2PaintEngineExPrivate::updateClipScissorTest() #else QRect bounds = q->state()->rectangleClip; if (!q->state()->clipEnabled) { - if (use_system_clip) + if (useSystemClip) bounds = systemClip.boundingRect(); else bounds = QRect(0, 0, width, height); } else { - if (use_system_clip) + if (useSystemClip) bounds = bounds.intersected(systemClip.boundingRect()); else bounds = bounds.intersected(QRect(0, 0, width, height)); @@ -1994,6 +2015,11 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) { transferMode(BrushDrawingMode); + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + if (matrixDirty) updateMatrix(); @@ -2093,7 +2119,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) switch (op) { case Qt::NoClip: - if (d->use_system_clip) { + if (d->useSystemClip) { state()->clipTestEnabled = true; state()->currentClip = 1; } else { @@ -2165,13 +2191,13 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->clipChanged = true; if (systemClip.isEmpty()) { - use_system_clip = false; + useSystemClip = false; } else { if (q->paintDevice()->devType() == QInternal::Widget && currentClipWidget) { QWidgetPrivate *widgetPrivate = qt_widget_private(currentClipWidget->window()); - use_system_clip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; + useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; } else { - use_system_clip = true; + useSystemClip = true; } } @@ -2181,19 +2207,19 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->currentClip = 1; maxClip = 1; - q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); + q->state()->rectangleClip = useSystemClip ? systemClip.boundingRect() : QRect(0, 0, width, height); updateClipScissorTest(); if (systemClip.rectCount() == 1) { if (systemClip.boundingRect() == QRect(0, 0, width, height)) - use_system_clip = false; + useSystemClip = false; #ifndef QT_GL_NO_SCISSOR_TEST // scissoring takes care of the system clip return; #endif } - if (use_system_clip) { + if (useSystemClip) { clearClip(0); QPainterPath path; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 77ca3a8..c94c4f4 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -105,13 +105,8 @@ public: ~QGL2PaintEngineEx(); bool begin(QPaintDevice *device); - bool end(); - void ensureActive(); - - virtual void fill(const QVectorPath &path, const QBrush &brush); - virtual void stroke(const QVectorPath &path, const QPen &pen); - virtual void clip(const QVectorPath &path, Qt::ClipOperation op); + bool end(); virtual void clipEnabledChanged(); virtual void penChanged(); @@ -122,20 +117,21 @@ public: virtual void renderHintsChanged(); virtual void transformChanged(); - + 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 drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); - virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); - virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); + virtual void fill(const QVectorPath &path, const QBrush &brush); + virtual void stroke(const QVectorPath &path, const QPen &pen); + virtual void clip(const QVectorPath &path, Qt::ClipOperation op); - virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); Type type() const { return OpenGL2; } - void setState(QPainterState *s); - QPainterState *createState(QPainterState *orig) const; + virtual void setState(QPainterState *s); + virtual QPainterState *createState(QPainterState *orig) const; inline QOpenGL2PaintEngineState *state() { return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state()); } @@ -146,8 +142,6 @@ public: void beginNativePainting(); void endNativePainting(); - const QGLContext* context(); - QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); void setRenderTextActive(bool); @@ -169,11 +163,12 @@ public: QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) : q(q_ptr), + shaderManager(0), width(0), height(0), ctx(0), - currentBrush(0), + useSystemClip(true), + addOffset(false), inverseScale(1), - shaderManager(0), inRenderText(false) { } @@ -185,45 +180,62 @@ public: void updateCompositionMode(); void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1); - void setBrush(const QBrush* brush); - - void transferMode(EngineMode newMode); void resetGLState(); - // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points: + // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points, + // however writeClip can also be thought of as en entry point as it does similar things. 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 drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); void drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, const QTextItemInt &ti); + // draws whatever is in the vertex array: void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive); void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) { drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive); } - // ^ draws whatever is in the vertex array + // Composites the bounding rect onto dest buffer: void composite(const QGLRect& boundingRect); - // ^ Composites the bounding rect onto dest buffer + // Calls drawVertexArrays to render into stencil buffer: void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode); void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(), vertexArray.boundingRect(), useWindingFill ? WindingFillMode : OddEvenFillMode); } - // ^ Calls drawVertexArrays to render into stencil buffer - - bool prepareForDraw(bool srcPixelsAreOpaque); - // ^ returns whether the current program changed or not + void setBrush(const QBrush& brush); + void transferMode(EngineMode newMode); + bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed inline void useSimpleShader(); + inline GLuint location(const QGLEngineShaderManager::Uniform uniform) { + return shaderManager->getUniformLocation(uniform); + } + void prepareDepthRangeForRenderText(); void restoreDepthRangeForRenderText(); + void clearClip(uint value); + void writeClip(const QVectorPath &path, uint value); + void resetClipIfNeeded(); + + void updateClipScissorTest(); + void setScissor(const QRect &rect); + void regenerateClip(); + void systemStateChanged(); + + static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; } static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); } + static void cleanupVectorPath(QPaintEngineEx *engine, void *data); + QGL2PaintEngineEx* q; + QGLEngineShaderManager* shaderManager; QGLPaintDevice* device; int width, height; QGLContext *ctx; @@ -240,41 +252,25 @@ public: bool opacityUniformDirty; bool stencilClean; // Has the stencil not been used for clipping so far? + bool useSystemClip; QRegion dirtyStencilRegion; QRect currentScissorBounds; uint maxClip; - const QBrush* currentBrush; // May not be the state's brush! - - GLfloat inverseScale; + QBrush currentBrush; // May not be the state's brush! + const QBrush noBrush; QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QDataBuffer<GLfloat> opacityArray; - GLfloat staticVertexCoordinateArray[8]; GLfloat staticTextureCoordinateArray[8]; - GLfloat pmvMatrix[4][4]; - - QGLEngineShaderManager* shaderManager; - - void clearClip(uint value); - void writeClip(const QVectorPath &path, uint value); - void resetClipIfNeeded(); - - void updateClipScissorTest(); - void setScissor(const QRect &rect); - void regenerateClip(); - void systemStateChanged(); - uint use_system_clip : 1; - - uint location(QGLEngineShaderManager::Uniform uniform) - { - return shaderManager->getUniformLocation(uniform); - } + bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix + GLfloat pmvMatrix[3][3]; + GLfloat inverseScale; - GLuint lastTexture; + GLuint lastTextureUsed; bool needsSync; bool inRenderText; @@ -286,7 +282,6 @@ public: QTriangulatingStroker stroker; QDashedStrokeProcessor dasher; - QTransform temporaryTransform; QScopedPointer<QPixmapFilter> convolutionFilter; QScopedPointer<QPixmapFilter> colorizeFilter; diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp index 6082f49..395b8a3 100644 --- a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp +++ b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp @@ -62,8 +62,14 @@ void QTriangulatingStroker::endCapOrJoinClosed(const qreal *start, const qreal * endCap(cur); } int count = m_vertices.size(); - m_vertices.add(m_vertices.at(count-2)); - m_vertices.add(m_vertices.at(count-1)); + + // Copy the (x, y) values because QDataBuffer::add(const float& t) + // may resize the buffer, which will leave t pointing at the + // previous buffer's memory region if we don't copy first. + float x = m_vertices.at(count-2); + float y = m_vertices.at(count-1); + m_vertices.add(x); + m_vertices.add(y); } diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index b4191dc..f9737a56 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -2275,6 +2275,42 @@ void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value \overload Sets the uniform variable at \a location in the current context + to a 2x2 matrix \a value. The matrix elements must be specified + in column-major order. + + \sa setAttributeValue() + \since 4.6.2 +*/ +void QGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2]) +{ + Q_D(QGLShaderProgram); + Q_UNUSED(d); + if (location != -1) + glUniformMatrix2fv(location, 1, GL_FALSE, value[0]); +} + +/*! + \overload + + Sets the uniform variable at \a location in the current context + to a 3x3 matrix \a value. The matrix elements must be specified + in column-major order. + + \sa setAttributeValue() + \since 4.6.2 +*/ +void QGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3]) +{ + Q_D(QGLShaderProgram); + Q_UNUSED(d); + if (location != -1) + glUniformMatrix3fv(location, 1, GL_FALSE, value[0]); +} + +/*! + \overload + + Sets the uniform variable at \a location in the current context to a 4x4 matrix \a value. The matrix elements must be specified in column-major order. @@ -2288,6 +2324,37 @@ void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4]) glUniformMatrix4fv(location, 1, GL_FALSE, value[0]); } + +/*! + \overload + + Sets the uniform variable called \a name in the current context + to a 2x2 matrix \a value. The matrix elements must be specified + in column-major order. + + \sa setAttributeValue() + \since 4.6.2 +*/ +void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2]) +{ + setUniformValue(uniformLocation(name), value); +} + +/*! + \overload + + Sets the uniform variable called \a name in the current context + to a 3x3 matrix \a value. The matrix elements must be specified + in column-major order. + + \sa setAttributeValue() + \since 4.6.2 +*/ +void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3]) +{ + setUniformValue(uniformLocation(name), value); +} + /*! \overload diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h index deeaee2..4eb80dd 100644 --- a/src/opengl/qglshaderprogram.h +++ b/src/opengl/qglshaderprogram.h @@ -216,6 +216,8 @@ public: void setUniformValue(int location, const QMatrix4x2& value); void setUniformValue(int location, const QMatrix4x3& value); void setUniformValue(int location, const QMatrix4x4& value); + void setUniformValue(int location, const GLfloat value[2][2]); + void setUniformValue(int location, const GLfloat value[3][3]); void setUniformValue(int location, const GLfloat value[4][4]); void setUniformValue(int location, const QTransform& value); @@ -242,6 +244,8 @@ public: void setUniformValue(const char *name, const QMatrix4x2& value); void setUniformValue(const char *name, const QMatrix4x3& value); void setUniformValue(const char *name, const QMatrix4x4& value); + void setUniformValue(const char *name, const GLfloat value[2][2]); + void setUniformValue(const char *name, const GLfloat value[3][3]); void setUniformValue(const char *name, const GLfloat value[4][4]); void setUniformValue(const char *name, const QTransform& value); diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index ed7fdff..8dae02a 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -4522,6 +4522,12 @@ typedef QHash<QFontEngine*, QGLGlyphHash*> QGLFontGlyphHash; typedef QHash<quint64, QGLFontTexture*> QGLFontTexHash; typedef QHash<const QGLContext*, QGLFontGlyphHash*> QGLContextHash; +static inline void qt_delete_glyph_hash(QGLGlyphHash *hash) +{ + qDeleteAll(*hash); + delete hash; +} + class QGLGlyphCache : public QObject { Q_OBJECT @@ -4562,7 +4568,7 @@ void QGLGlyphCache::fontEngineDestroyed(QObject *o) if (font_cache->find(fe) != font_cache->end()) { ctx = keys.at(i); QGLGlyphHash *cache = font_cache->take(fe); - delete cache; + qt_delete_glyph_hash(cache); break; } } @@ -4599,7 +4605,7 @@ void QGLGlyphCache::cleanupContext(const QGLContext *ctx) QList<QFontEngine *> keys = font_cache->keys(); for (int i=0; i < keys.size(); ++i) { QFontEngine *fe = keys.at(i); - delete font_cache->take(fe); + qt_delete_glyph_hash(font_cache->take(fe)); quint64 font_key = (reinterpret_cast<quint64>(ctx) << 32) | reinterpret_cast<quint64>(fe); QGLFontTexture *font_tex = qt_font_textures.take(font_key); if (font_tex) { @@ -4640,7 +4646,9 @@ void QGLGlyphCache::cleanCache() QList<const QGLContext *> keys = qt_context_cache.keys(); for (int i=0; i < keys.size(); ++i) { QGLFontGlyphHash *font_cache = qt_context_cache.value(keys.at(i)); - qDeleteAll(*font_cache); + QGLFontGlyphHash::Iterator it = font_cache->begin(); + for (; it != font_cache->end(); ++it) + qt_delete_glyph_hash(it.value()); font_cache->clear(); } qDeleteAll(qt_context_cache); diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 4e1d50d..92c990b 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -341,22 +341,11 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull()) { if (external_format == GL_RGB) { - QImage tx = m_source.convertToFormat(QImage::Format_RGB32); - - QVector<uchar> pixelData(w * h * 3); - uchar *p = &pixelData[0]; - QRgb *src = (QRgb *)tx.bits(); - - for (int i = 0; i < w * h; ++i) { - *p++ = qRed(*src); - *p++ = qGreen(*src); - *p++ = qBlue(*src); - ++src; - } + const QImage tx = m_source.convertToFormat(QImage::Format_RGB888); glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - GL_UNSIGNED_BYTE, &pixelData[0]); + GL_UNSIGNED_BYTE, tx.bits()); } else { const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 4744eb6..bb26d29 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1063,7 +1063,7 @@ static inline bool setIntOption(const QStringList &arguments, const QString &var static inline QColor colorFromName(const QString &name) { - QRegExp rx("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])"); + QRegExp rx(QLatin1String("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")); rx.setCaseSensitivity(Qt::CaseInsensitive); if (rx.exactMatch(name)) { Q_ASSERT(rx.captureCount() == 4); @@ -1278,7 +1278,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec) #ifdef QT_NO_DIRECTFB_WM result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); #elif (Q_DIRECTFB_VERSION >= 0x010000) - result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); + IDirectFBSurface *layerSurface; + if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) { + result = layerSurface->GetSize(layerSurface, &w, &h); + layerSurface->Release(layerSurface); + } + if (w <= 0 || h <= 0) { + result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); + } #else qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n" "query the size of the primary surface in windowed mode. You have to specify\n" diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index c95b63c..dee0e52 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -54,6 +54,10 @@ QT_BEGIN_NAMESPACE #define Q_TRANSPARENT 0x00ffffff +// avoid going through QImage::scanLine() which calls detach +#define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl) + + /* Incremental image decoder for GIF image format. @@ -135,7 +139,7 @@ private: int frame; bool out_of_bounds; bool digress; - void nextY(QImage *image); + void nextY(unsigned char *bits, int bpl); void disposePrevious(QImage *image); }; @@ -232,6 +236,10 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, // CompuServe Incorporated. GIF(sm) is a Service Mark property of // CompuServe Incorporated." + image->detach(); + int bpl = image->bytesPerLine(); + unsigned char *bits = image->bits(); + #define LM(l, m) (((m)<<8)|l) digress = false; const int initial = length; @@ -335,7 +343,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; if (image->isNull()) { (*image) = QImage(swidth, sheight, format); - memset(image->bits(), 0, image->byteCount()); + bpl = image->bytesPerLine(); + bits = image->bits(); + memset(bits, 0, image->byteCount()); // ### size of the upcoming frame, should rather // be known before decoding it. @@ -393,11 +403,13 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, backingstore = QImage(qMax(backingstore.width(), w), qMax(backingstore.height(), h), QImage::Format_RGB32); - memset(image->bits(), 0, image->byteCount()); + memset(bits, 0, image->byteCount()); } + const int dest_bpl = backingstore.bytesPerLine(); + unsigned char *dest_data = backingstore.bits(); for (int ln=0; ln<h; ln++) { - memcpy(backingstore.scanLine(ln), - image->scanLine(t+ln)+l, w*sizeof(QRgb)); + memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln), + FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb)); } } @@ -470,14 +482,14 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, if (needfirst) { firstcode=oldcode=code; if (!out_of_bounds && image->height() > y && firstcode!=trans_index) - ((QRgb*)image->scanLine(y))[x] = color(firstcode); + ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode); x++; if (x>=swidth) out_of_bounds = true; needfirst=false; if (x>=left+width) { x=left; out_of_bounds = left>=swidth || y>=sheight; - nextY(image); + nextY(bits, bpl); } } else { incode=code; @@ -515,7 +527,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, const QRgb *map = lcmap ? localcmap : globalcmap; QRgb *line = 0; if (!out_of_bounds && h > y) - line = (QRgb*)image->scanLine(y); + line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); while (sp>stack) { const uchar index = *(--sp); if (!out_of_bounds && h > y && index!=trans_index) { @@ -529,9 +541,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, if (x>=left+width) { x=left; out_of_bounds = left>=swidth || y>=sheight; - nextY(image); + nextY(bits, bpl); if (!out_of_bounds && h > y) - line = (QRgb*)image->scanLine(y); + line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); } } } @@ -644,7 +656,7 @@ void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb co } } -void QGIFFormat::nextY(QImage *image) +void QGIFFormat::nextY(unsigned char *bits, int bpl) { int my; switch (interlace) { @@ -660,7 +672,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } @@ -689,7 +701,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } @@ -713,7 +725,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 54bbcda..11608ef 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -84,15 +84,12 @@ class QImageSmoothScaler public: QImageSmoothScaler(const int w, const int h, const QImage &src); QImageSmoothScaler(const int srcWidth, const int srcHeight, - const char *parameters); + const int dstWidth, const int dstHeight); virtual ~QImageSmoothScaler(void); QImage scale(); -protected: - int scaledWidth(void) const; - private: QImageSmoothScalerPrivate *d; virtual QRgb *scanLine(const int line = 0, const QImage *src = 0); @@ -123,33 +120,9 @@ QImageSmoothScaler::QImageSmoothScaler(const int w, const int h, } QImageSmoothScaler::QImageSmoothScaler(const int srcWidth, const int srcHeight, - const char *parameters) + const int dstWidth, const int dstHeight) { - char sModeStr[1024]; - int t1; - int t2; - int dstWidth; - int dstHeight; - - sModeStr[0] = '\0'; - d = new QImageSmoothScalerPrivate; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400 - sscanf_s(parameters, "Scale( %i, %i, %1023s )", &dstWidth, &dstHeight, sModeStr, sizeof(sModeStr)); -#else - sscanf(parameters, "Scale( %i, %i, %s )", &dstWidth, &dstHeight, sModeStr); -#endif - QString sModeQStr = QString::fromLatin1(sModeStr); - - t1 = srcWidth * dstHeight; - t2 = srcHeight * dstWidth; - - if (((sModeQStr == QLatin1String("ScaleMin")) && (t1 > t2)) || ((sModeQStr == QLatin1String("ScaleMax")) && (t2 < t2))) { - dstHeight = t2 / srcWidth; - } else if (sModeQStr != QLatin1String("ScaleFree")) { - dstWidth = t1 / srcHeight; - } - d->setup(srcWidth, srcHeight, dstWidth, dstHeight, 0); } @@ -164,11 +137,6 @@ void QImageSmoothScalerPrivate::setup(const int srcWidth, const int srcHeight, hasAlpha = hasAlphaChannel; } -int QImageSmoothScaler::scaledWidth() const -{ - return d->cols; -} - QImageSmoothScaler::~QImageSmoothScaler() { delete d; @@ -467,20 +435,18 @@ QImage QImageSmoothScaler::scale() class jpegSmoothScaler : public QImageSmoothScaler { public: - jpegSmoothScaler(struct jpeg_decompress_struct *info, const char *params): - QImageSmoothScaler(info->output_width, info->output_height, params) + jpegSmoothScaler(struct jpeg_decompress_struct *info, const QSize& dstSize, const QRect& clipRect) + : QImageSmoothScaler(clipRect.width(), clipRect.height(), + dstSize.width(), dstSize.height()) { - cinfo = info; - cols24Bit = scaledWidth() * 3; - - cacheHeight = 1; - imageCache = QImage( info->output_width, cacheHeight, QImage::Format_RGB32 ); + cinfo = info; + clip = clipRect; + imageCache = QImage(info->output_width, 1, QImage::Format_RGB32); } private: - int cols24Bit; + QRect clip; QImage imageCache; - int cacheHeight; struct jpeg_decompress_struct *cinfo; QRgb *scanLine(const int line = 0, const QImage *src = 0) @@ -492,33 +458,42 @@ private: Q_UNUSED(src); uchar* data = imageCache.bits(); + + // Read ahead if we haven't reached the first clipped scanline yet. + while (int(cinfo->output_scanline) < clip.y() && + cinfo->output_scanline < cinfo->output_height) + jpeg_read_scanlines(cinfo, &data, 1); + + // Read the next scanline. We assume that "line" + // will never be >= clip.height(). jpeg_read_scanlines(cinfo, &data, 1); - out = (QRgb*)imageCache.scanLine(0); + if (cinfo->output_scanline == cinfo->output_height) + jpeg_finish_decompress(cinfo); + + out = ((QRgb*)data) + clip.x(); // // The smooth scale algorithm only works on 32-bit images; // convert from (8|24) bits to 32. // if (cinfo->output_components == 1) { - in = (uchar*)out + scaledWidth(); - for (uint i = scaledWidth(); i--; ) { - in--; + in = data + clip.right(); + for (int i = clip.width(); i--; ) { out[i] = qRgb(*in, *in, *in); + in--; } - } else if (cinfo->out_color_space == JCS_CMYK) { - int cols32Bit = scaledWidth() * 4; - in = (uchar*)out + cols32Bit; - for (uint i = scaledWidth(); i--; ) { - in -= 4; - int k = in[3]; - out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255); - //out[i] = qRgb(in[0], in[1], in[2]); - } - } else { - in = (uchar*)out + cols24Bit; - for (uint i = scaledWidth(); i--; ) { - in -= 3; + } else if (cinfo->out_color_space == JCS_CMYK) { + in = data + clip.right() * 4; + for (int i = clip.width(); i--; ) { + int k = in[3]; + out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255); + in -= 4; + } + } else { + in = data + clip.right() * 3; + for (int i = clip.width(); i--; ) { out[i] = qRgb(in[0], in[1], in[2]); + in -= 3; } } @@ -637,18 +612,6 @@ inline my_jpeg_source_mgr::my_jpeg_source_mgr(QIODevice *device) } -static void scaleSize(int &reqW, int &reqH, int imgW, int imgH, Qt::AspectRatioMode mode) -{ - if (mode == Qt::IgnoreAspectRatio) - return; - int t1 = imgW * reqH; - int t2 = reqW * imgH; - if ((mode == Qt::KeepAspectRatio && (t1 > t2)) || (mode == Qt::KeepAspectRatioByExpanding && (t1 < t2))) - reqH = t2 / imgW; - else - reqW = t1 / imgH; -} - static bool read_jpeg_size(QIODevice *device, int &w, int &h) { bool rt = false; @@ -729,7 +692,7 @@ static bool read_jpeg_format(QIODevice *device, QImage::Format &format) } static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, - bool dummy = false) + const QSize& size) { QImage::Format format; switch (info->output_components) { @@ -744,13 +707,8 @@ static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, return false; // unsupported format } - const QSize size(info->output_width, info->output_height); if (dest->size() != size || dest->format() != format) { - static uchar dummyImage[1]; - if (dummy) // Create QImage but don't read the pixels - *dest = QImage(dummyImage, size.width(), size.height(), format); - else - *dest = QImage(size, format); + *dest = QImage(size, format); if (format == QImage::Format_Indexed8) { dest->setColorCount(256); @@ -763,13 +721,9 @@ static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, } static bool read_jpeg_image(QIODevice *device, QImage *outImage, - const QByteArray ¶meters, QSize scaledSize, - int inQuality ) + QSize scaledSize, QRect scaledClipRect, + QRect clipRect, int inQuality ) { -#ifdef QT_NO_IMAGE_SMOOTHSCALE - Q_UNUSED( scaledSize ); -#endif - struct jpeg_decompress_struct cinfo; struct my_jpeg_source_mgr *iod_src = new my_jpeg_source_mgr(device); @@ -794,18 +748,53 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage, if (quality < 0) quality = 75; - QString params = QString::fromLatin1(parameters); - params.simplified(); - int sWidth = 0, sHeight = 0; - char sModeStr[1024] = ""; - Qt::AspectRatioMode sMode; + // If possible, merge the scaledClipRect into either scaledSize + // or clipRect to avoid doing a separate scaled clipping pass. + // Best results are achieved by clipping before scaling, not after. + if (!scaledClipRect.isEmpty()) { + if (scaledSize.isEmpty() && clipRect.isEmpty()) { + // No clipping or scaling before final clip. + clipRect = scaledClipRect; + scaledClipRect = QRect(); + } else if (scaledSize.isEmpty()) { + // Clipping, but no scaling: combine the clip regions. + scaledClipRect.translate(clipRect.topLeft()); + clipRect = scaledClipRect.intersected(clipRect); + scaledClipRect = QRect(); + } else if (clipRect.isEmpty()) { + // No clipping, but scaling: if we can map back to an + // integer pixel boundary, then clip before scaling. + if ((cinfo.image_width % scaledSize.width()) == 0 && + (cinfo.image_height % scaledSize.height()) == 0) { + int x = scaledClipRect.x() * cinfo.image_width / + scaledSize.width(); + int y = scaledClipRect.y() * cinfo.image_height / + scaledSize.height(); + int width = (scaledClipRect.right() + 1) * + cinfo.image_width / scaledSize.width() - x; + int height = (scaledClipRect.bottom() + 1) * + cinfo.image_height / scaledSize.height() - y; + clipRect = QRect(x, y, width, height); + scaledSize = scaledClipRect.size(); + scaledClipRect = QRect(); + } + } else { + // Clipping and scaling: too difficult to figure out, + // and not a likely use case, so do it the long way. + } + } -#ifndef QT_NO_IMAGE_SMOOTHSCALE - // If high quality not required, shrink image during decompression - if (scaledSize.isValid() && !scaledSize.isEmpty() && quality < HIGH_QUALITY_THRESHOLD - && !params.contains(QLatin1String("GetHeaderInformation")) ) { - cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(), - cinfo.image_width / scaledSize.height()); + // Determine the scale factor to pass to libjpeg for quick downscaling. + if (!scaledSize.isEmpty()) { + if (clipRect.isEmpty()) { + cinfo.scale_denom = + qMin(cinfo.image_width / scaledSize.width(), + cinfo.image_height / scaledSize.height()); + } else { + cinfo.scale_denom = + qMin(clipRect.width() / scaledSize.width(), + clipRect.height() / scaledSize.height()); + } if (cinfo.scale_denom < 2) { cinfo.scale_denom = 1; } else if (cinfo.scale_denom < 4) { @@ -816,9 +805,19 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage, cinfo.scale_denom = 8; } cinfo.scale_num = 1; + if (!clipRect.isEmpty()) { + // Correct the scale factor so that we clip accurately. + // It is recommended that the clip rectangle be aligned + // on an 8-pixel boundary for best performance. + while (cinfo.scale_denom > 1 && + ((clipRect.x() % cinfo.scale_denom) != 0 || + (clipRect.y() % cinfo.scale_denom) != 0 || + (clipRect.width() % cinfo.scale_denom) != 0 || + (clipRect.height() % cinfo.scale_denom) != 0)) { + cinfo.scale_denom /= 2; + } + } } -#endif - // If high quality not required, use fast decompression if( quality < HIGH_QUALITY_THRESHOLD ) { @@ -826,132 +825,102 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage, cinfo.do_fancy_upsampling = FALSE; } + (void) jpeg_calc_output_dimensions(&cinfo); - (void) jpeg_start_decompress(&cinfo); + // Determine the clip region to extract. + QRect imageRect(0, 0, cinfo.output_width, cinfo.output_height); + QRect clip; + if (clipRect.isEmpty()) { + clip = imageRect; + } else if (cinfo.scale_denom == 1) { + clip = clipRect.intersected(imageRect); + } else { + // The scale factor was corrected above to ensure that + // we don't miss pixels when we scale the clip rectangle. + clip = QRect(clipRect.x() / int(cinfo.scale_denom), + clipRect.y() / int(cinfo.scale_denom), + clipRect.width() / int(cinfo.scale_denom), + clipRect.height() / int(cinfo.scale_denom)); + clip = clip.intersected(imageRect); + } - if (params.contains(QLatin1String("GetHeaderInformation"))) { - if (!ensureValidImage(outImage, &cinfo, true)) - longjmp(jerr.setjmp_buffer, 1); - } else if (params.contains(QLatin1String("Scale"))) { -#if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE) - sscanf_s(params.toLatin1().data(), "Scale(%i, %i, %1023s)", - &sWidth, &sHeight, sModeStr, sizeof(sModeStr)); -#else - sscanf(params.toLatin1().data(), "Scale(%i, %i, %1023s)", - &sWidth, &sHeight, sModeStr); -#endif +#ifndef QT_NO_IMAGE_SMOOTHSCALE + if (scaledSize.isValid() && scaledSize != clip.size() + && quality >= HIGH_QUALITY_THRESHOLD) { - QString sModeQStr(QString::fromLatin1(sModeStr)); - if (sModeQStr == QLatin1String("IgnoreAspectRatio")) { - sMode = Qt::IgnoreAspectRatio; - } else if (sModeQStr == QLatin1String("KeepAspectRatio")) { - sMode = Qt::KeepAspectRatio; - } else if (sModeQStr == QLatin1String("KeepAspectRatioByExpanding")) { - sMode = Qt::KeepAspectRatioByExpanding; - } else { - qDebug("read_jpeg_image: invalid aspect ratio mode \"%s\", see QImage::AspectRatioMode documentation", sModeStr); - sMode = Qt::KeepAspectRatio; - } + (void) jpeg_start_decompress(&cinfo); -// qDebug("Parameters ask to scale the image to %i x %i AspectRatioMode: %s", sWidth, sHeight, sModeStr); - scaleSize(sWidth, sHeight, cinfo.output_width, cinfo.output_height, sMode); -// qDebug("Scaling the jpeg to %i x %i", sWidth, sHeight, sModeStr); - - if (cinfo.output_components == 3 || cinfo.output_components == 4) { - if (outImage->size() != QSize(sWidth, sHeight) || outImage->format() != QImage::Format_RGB32) - *outImage = QImage(sWidth, sHeight, QImage::Format_RGB32); - } else if (cinfo.output_components == 1) { - if (outImage->size() != QSize(sWidth, sHeight) || outImage->format() != QImage::Format_Indexed8) - *outImage = QImage(sWidth, sHeight, QImage::Format_Indexed8); - outImage->setColorCount(256); - for (int i = 0; i < 256; ++i) - outImage->setColor(i, qRgb(i,i,i)); - } else { - // Unsupported format - } - if (outImage->isNull()) + jpegSmoothScaler scaler(&cinfo, scaledSize, clip); + *outImage = scaler.scale(); + } else +#endif + { + // Allocate memory for the clipped QImage. + if (!ensureValidImage(outImage, &cinfo, clip.size())) longjmp(jerr.setjmp_buffer, 1); - if (!outImage->isNull()) { - QImage tmpImage(cinfo.output_width, 1, QImage::Format_RGB32); - uchar* inData = tmpImage.bits(); - uchar* outData = outImage->bits(); - int out_bpl = outImage->bytesPerLine(); + // Avoid memcpy() overhead if grayscale with no clipping. + bool quickGray = (cinfo.output_components == 1 && + clip == imageRect); + if (!quickGray) { + // Ask the jpeg library to allocate a temporary row. + // The library will automatically delete it for us later. + // The libjpeg docs say we should do this before calling + // jpeg_start_decompress(). We can't use "new" here + // because we are inside the setjmp() block and an error + // in the jpeg input stream would cause a memory leak. + JSAMPARRAY rows = (cinfo.mem->alloc_sarray) + ((j_common_ptr)&cinfo, JPOOL_IMAGE, + cinfo.output_width * cinfo.output_components, 1); + + (void) jpeg_start_decompress(&cinfo); + while (cinfo.output_scanline < cinfo.output_height) { - int outputLine = sHeight * cinfo.output_scanline / cinfo.output_height; - (void) jpeg_read_scanlines(&cinfo, &inData, 1); + int y = int(cinfo.output_scanline) - clip.y(); + if (y >= clip.height()) + break; // We've read the entire clip region, so abort. + + (void) jpeg_read_scanlines(&cinfo, rows, 1); + + if (y < 0) + continue; // Haven't reached the starting line yet. + if (cinfo.output_components == 3) { - uchar *in = inData; - QRgb *out = (QRgb*)outData + outputLine * out_bpl; - for (uint i=0; i<cinfo.output_width; i++) { -// ### Only scaling down an image works, I don't think scaling up will work at the moment -// ### An idea I have to make this a smooth scale is to progressively add the pixel values up -// When scaling down, multiple values are being over drawn in to the output buffer. -// Instead, a weighting based on the distance the line or pixel is from the output pixel determines -// the weight of it when added to the output buffer. At present it is a non-smooth scale which is -// inefficently implemented, it still uncompresses all the jpeg, an optimization for progressive -// jpegs could be made if scaling by say 50% or some other special cases - out[sWidth * i / cinfo.output_width] = qRgb(in[0], in[1], in[2]); + // Expand 24->32 bpp. + uchar *in = rows[0] + clip.x() * 3; + QRgb *out = (QRgb*)outImage->scanLine(y); + for (int i = 0; i < clip.width(); ++i) { + *out++ = qRgb(in[0], in[1], in[2]); in += 3; } - } else { -// ### Need to test the case where the jpeg is grayscale, need some black and white jpegs to test -// this code. (also only scales down and probably won't scale to a larger size) - uchar *in = inData; - uchar *out = outData + outputLine*out_bpl; - for (uint i=0; i<cinfo.output_width; i++) { - out[sWidth * i / cinfo.output_width] = in[i]; + } else if (cinfo.out_color_space == JCS_CMYK) { + // Convert CMYK->RGB. + uchar *in = rows[0] + clip.x() * 4; + QRgb *out = (QRgb*)outImage->scanLine(y); + for (int i = 0; i < clip.width(); ++i) { + int k = in[3]; + *out++ = qRgb(k * in[0] / 255, k * in[1] / 255, + k * in[2] / 255); + in += 4; } + } else if (cinfo.output_components == 1) { + // Grayscale. + memcpy(outImage->scanLine(y), + rows[0] + clip.x(), clip.width()); } } - (void) jpeg_finish_decompress(&cinfo); - } -#ifndef QT_NO_IMAGE_SMOOTHSCALE - } else if (scaledSize.isValid() && scaledSize != QSize(cinfo.output_width, cinfo.output_height) - && quality >= HIGH_QUALITY_THRESHOLD) { - - jpegSmoothScaler scaler(&cinfo, QString().sprintf("Scale( %d, %d, ScaleFree )", - scaledSize.width(), - scaledSize.height()).toLatin1().data()); - *outImage = scaler.scale(); -#endif - } else { - if (!ensureValidImage(outImage, &cinfo)) - longjmp(jerr.setjmp_buffer, 1); - - uchar* data = outImage->bits(); - int bpl = outImage->bytesPerLine(); - while (cinfo.output_scanline < cinfo.output_height) { - uchar *d = data + cinfo.output_scanline * bpl; - (void) jpeg_read_scanlines(&cinfo, - &d, - 1); + } else { + // Load unclipped grayscale data directly into the QImage. + (void) jpeg_start_decompress(&cinfo); + while (cinfo.output_scanline < cinfo.output_height) { + uchar *row = outImage->scanLine(cinfo.output_scanline); + (void) jpeg_read_scanlines(&cinfo, &row, 1); + } } - (void) jpeg_finish_decompress(&cinfo); - if (cinfo.output_components == 3) { - // Expand 24->32 bpp. - for (uint j=0; j<cinfo.output_height; j++) { - uchar *in = outImage->scanLine(j) + cinfo.output_width * 3; - QRgb *out = (QRgb*)outImage->scanLine(j); + if (cinfo.output_scanline == cinfo.output_height) + (void) jpeg_finish_decompress(&cinfo); - for (uint i=cinfo.output_width; i--;) { - in-=3; - out[i] = qRgb(in[0], in[1], in[2]); - } - } - } else if (cinfo.out_color_space == JCS_CMYK) { - for (uint j = 0; j < cinfo.output_height; ++j) { - uchar *in = outImage->scanLine(j) + cinfo.output_width * 4; - QRgb *out = (QRgb*)outImage->scanLine(j); - - for (uint i = cinfo.output_width; i--; ) { - in-=4; - int k = in[3]; - out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255); - } - } - } if (cinfo.density_unit == 1) { outImage->setDotsPerMeterX(int(100. * cinfo.X_density / 2.54)); outImage->setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54)); @@ -960,13 +929,15 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage, outImage->setDotsPerMeterY(int(100. * cinfo.Y_density)); } - if (scaledSize.isValid() && scaledSize != QSize(cinfo.output_width, cinfo.output_height)) + if (scaledSize.isValid() && scaledSize != clip.size()) *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::FastTransformation); } } jpeg_destroy_decompress(&cinfo); delete iod_src; + if (!scaledClipRect.isEmpty()) + *outImage = outImage->copy(scaledClipRect); return !outImage->isNull(); } @@ -1224,7 +1195,7 @@ bool QJpegHandler::read(QImage *image) { if (!canRead()) return false; - return read_jpeg_image(device(), image, parameters, scaledSize, quality); + return read_jpeg_image(device(), image, scaledSize, scaledClipRect, clipRect, quality); } bool QJpegHandler::write(const QImage &image) @@ -1235,9 +1206,9 @@ bool QJpegHandler::write(const QImage &image) bool QJpegHandler::supportsOption(ImageOption option) const { return option == Quality -#ifndef QT_NO_IMAGE_SMOOTHSCALE || option == ScaledSize -#endif + || option == ScaledClipRect + || option == ClipRect || option == Size || option == ImageFormat; } @@ -1246,10 +1217,12 @@ QVariant QJpegHandler::option(ImageOption option) const { if (option == Quality) { return quality; -#ifndef QT_NO_IMAGE_SMOOTHSCALE } else if (option == ScaledSize) { return scaledSize; -#endif + } else if (option == ScaledClipRect) { + return scaledClipRect; + } else if (option == ClipRect) { + return clipRect; } else if (option == Size) { if (canRead() && !device()->isSequential()) { qint64 pos = device()->pos(); @@ -1276,10 +1249,12 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value) { if (option == Quality) quality = value.toInt(); -#ifndef QT_NO_IMAGE_SMOOTHSCALE else if ( option == ScaledSize ) scaledSize = value.toSize(); -#endif + else if ( option == ScaledClipRect ) + scaledClipRect = value.toRect(); + else if ( option == ClipRect ) + clipRect = value.toRect(); } QByteArray QJpegHandler::name() const diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.h b/src/plugins/imageformats/jpeg/qjpeghandler.h index 654c078..6870cd6 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.h +++ b/src/plugins/imageformats/jpeg/qjpeghandler.h @@ -44,6 +44,7 @@ #include <QtGui/qimageiohandler.h> #include <QtCore/QSize> +#include <QtCore/QRect> QT_BEGIN_NAMESPACE @@ -66,8 +67,9 @@ public: private: int quality; - QByteArray parameters; QSize scaledSize; + QRect scaledClipRect; + QRect clipRect; }; QT_END_NAMESPACE diff --git a/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pro b/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pro index 9687908..691cce1 100644 --- a/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pro +++ b/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pro @@ -3,7 +3,7 @@ TEMPLATE = subdirs # We just want to export the sqlite3 binaries for Symbian for platforms that do not have them. symbian { - !exists($${EPOCROOT}epoc32/release/armv5/lib/sqlite3.dso) { + !symbian_no_export_sqlite:!exists($${EPOCROOT}epoc32/release/armv5/lib/sqlite3.dso) { BLD_INF_RULES.prj_exports += ":zip SQLite3_v9.2.zip" } } diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index d50e85f..7a629d7 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -2503,7 +2503,7 @@ EXPORTS ?cacheMode@QMovie@@QAE?AW4CacheMode@1@XZ @ 2502 NONAME ; enum QMovie::CacheMode QMovie::cacheMode(void) ?cacheMode@QMovie@@QBE?AW4CacheMode@1@XZ @ 2503 NONAME ; enum QMovie::CacheMode QMovie::cacheMode(void) const ?cacheStatistics@QFont@@SAXXZ @ 2504 NONAME ; void QFont::cacheStatistics(void) - ?cacheType@QTextureGlyphCache@@QBE?AW4Type@QFontEngineGlyphCache@@XZ @ 2505 NONAME ; enum QFontEngineGlyphCache::Type QTextureGlyphCache::cacheType(void) const + ?cacheType@QTextureGlyphCache@@QBE?AW4Type@QFontEngineGlyphCache@@XZ @ 2505 NONAME ABSENT ; enum QFontEngineGlyphCache::Type QTextureGlyphCache::cacheType(void) const ?calcEffectiveOpacity@QGraphicsItemPrivate@@QBEMXZ @ 2506 NONAME ; float QGraphicsItemPrivate::calcEffectiveOpacity(void) const ?calculateTabWidth@QTextEngine@@QBE?AUQFixed@@HU2@@Z @ 2507 NONAME ; struct QFixed QTextEngine::calculateTabWidth(int, struct QFixed) const ?calendarPopup@QDateTimeEdit@@QBE_NXZ @ 2508 NONAME ; bool QDateTimeEdit::calendarPopup(void) const @@ -4299,7 +4299,7 @@ EXPORTS ?expandingDirections@QSpacerItem@@UBE?AV?$QFlags@W4Orientation@Qt@@@@XZ @ 4298 NONAME ; class QFlags<enum Qt::Orientation> QSpacerItem::expandingDirections(void) const ?expandingDirections@QWidgetItem@@UBE?AV?$QFlags@W4Orientation@Qt@@@@XZ @ 4299 NONAME ; class QFlags<enum Qt::Orientation> QWidgetItem::expandingDirections(void) const ?expandsOnDoubleClick@QTreeView@@QBE_NXZ @ 4300 NONAME ; bool QTreeView::expandsOnDoubleClick(void) const - ?expireGlyphCache@QFontEngine@@AAEXXZ @ 4301 NONAME ; void QFontEngine::expireGlyphCache(void) + ?expireGlyphCache@QFontEngine@@AAEXXZ @ 4301 NONAME ABSENT ; void QFontEngine::expireGlyphCache(void) ?extension@QDialog@@QBEPAVQWidget@@XZ @ 4302 NONAME ; class QWidget * QDialog::extension(void) const ?extension@QGraphicsEllipseItem@@MBE?AVQVariant@@ABV2@@Z @ 4303 NONAME ; class QVariant QGraphicsEllipseItem::extension(class QVariant const &) const ?extension@QGraphicsItem@@MBE?AVQVariant@@ABV2@@Z @ 4304 NONAME ; class QVariant QGraphicsItem::extension(class QVariant const &) const @@ -4933,8 +4933,8 @@ EXPORTS ?globalY@QMouseEvent@@QBEHXZ @ 4932 NONAME ; int QMouseEvent::globalY(void) const ?globalY@QTabletEvent@@QBEHXZ @ 4933 NONAME ; int QTabletEvent::globalY(void) const ?globalY@QWheelEvent@@QBEHXZ @ 4934 NONAME ; int QWheelEvent::globalY(void) const - ?glyphCache@QFontEngine@@QBEPAVQFontEngineGlyphCache@@PAXABVQTransform@@@Z @ 4935 NONAME ; class QFontEngineGlyphCache * QFontEngine::glyphCache(void *, class QTransform const &) const - ?glyphCache@QFontEngine@@QBEPAVQFontEngineGlyphCache@@W4Type@2@ABVQTransform@@@Z @ 4936 NONAME ; class QFontEngineGlyphCache * QFontEngine::glyphCache(enum QFontEngineGlyphCache::Type, class QTransform const &) const + ?glyphCache@QFontEngine@@QBEPAVQFontEngineGlyphCache@@PAXABVQTransform@@@Z @ 4935 NONAME ABSENT ; class QFontEngineGlyphCache * QFontEngine::glyphCache(void *, class QTransform const &) const + ?glyphCache@QFontEngine@@QBEPAVQFontEngineGlyphCache@@W4Type@2@ABVQTransform@@@Z @ 4936 NONAME ABSENT ; class QFontEngineGlyphCache * QFontEngine::glyphCache(enum QFontEngineGlyphCache::Type, class QTransform const &) const ?glyphCount@QFontEngine@@UBEHXZ @ 4937 NONAME ; int QFontEngine::glyphCount(void) const ?glyphMargin@QTextureGlyphCache@@UBEHXZ @ 4938 NONAME ; int QTextureGlyphCache::glyphMargin(void) const ?gotFocus@QFocusEvent@@QBE_NXZ @ 4939 NONAME ; bool QFocusEvent::gotFocus(void) const @@ -9103,7 +9103,7 @@ EXPORTS ?setGestureCancelPolicy@QGesture@@QAEXW4GestureCancelPolicy@1@@Z @ 9102 NONAME ; void QGesture::setGestureCancelPolicy(enum QGesture::GestureCancelPolicy) ?setGlobalStrut@QApplication@@SAXABVQSize@@@Z @ 9103 NONAME ; void QApplication::setGlobalStrut(class QSize const &) ?setGlyphCache@QFontEngine@@QAEXPAXPAVQFontEngineGlyphCache@@@Z @ 9104 NONAME ; void QFontEngine::setGlyphCache(void *, class QFontEngineGlyphCache *) - ?setGlyphCache@QFontEngine@@QAEXW4Type@QFontEngineGlyphCache@@PAV3@@Z @ 9105 NONAME ; void QFontEngine::setGlyphCache(enum QFontEngineGlyphCache::Type, class QFontEngineGlyphCache *) + ?setGlyphCache@QFontEngine@@QAEXW4Type@QFontEngineGlyphCache@@PAV3@@Z @ 9105 NONAME ABSENT ; void QFontEngine::setGlyphCache(enum QFontEngineGlyphCache::Type, class QFontEngineGlyphCache *) ?setGraphicsEffect@QGraphicsItem@@QAEXPAVQGraphicsEffect@@@Z @ 9106 NONAME ; void QGraphicsItem::setGraphicsEffect(class QGraphicsEffect *) ?setGraphicsEffect@QWidget@@QAEXPAVQGraphicsEffect@@@Z @ 9107 NONAME ; void QWidget::setGraphicsEffect(class QGraphicsEffect *) ?setGraphicsEffectSource@QGraphicsEffectPrivate@@QAEXPAVQGraphicsEffectSource@@@Z @ 9108 NONAME ; void QGraphicsEffectPrivate::setGraphicsEffectSource(class QGraphicsEffectSource *) @@ -12522,4 +12522,7 @@ EXPORTS ?addCacheData@QVectorPath@@QBEPAUCacheEntry@1@PAVQPaintEngineEx@@PAXP6AX01@Z@Z @ 12521 NONAME ; struct QVectorPath::CacheEntry * QVectorPath::addCacheData(class QPaintEngineEx *, void *, void (*)(class QPaintEngineEx *, void *)) const ?discardUpdateRequest@QGraphicsItemPrivate@@QBE_N_N00@Z @ 12522 NONAME ; bool QGraphicsItemPrivate::discardUpdateRequest(bool, bool, bool) const ?makeCacheable@QVectorPath@@QBEXXZ @ 12523 NONAME ; void QVectorPath::makeCacheable(void) const + ??0Tab@QTextOption@@QAE@ABU01@@Z @ 12524 NONAME ; QTextOption::Tab::Tab(struct QTextOption::Tab const &) + ?effectiveBoundingRect@QGraphicsItemPrivate@@QBE?AVQRectF@@ABV2@@Z @ 12525 NONAME ; class QRectF QGraphicsItemPrivate::effectiveBoundingRect(class QRectF const &) const + ?glyphCache@QFontEngine@@QBEPAVQFontEngineGlyphCache@@PAXW4Type@2@ABVQTransform@@@Z @ 12526 NONAME ; class QFontEngineGlyphCache * QFontEngine::glyphCache(void *, enum QFontEngineGlyphCache::Type, class QTransform const &) const diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby index 41eb562..f24ac4b 100644 --- a/src/s60installs/qt.iby +++ b/src/s60installs/qt.iby @@ -90,27 +90,27 @@ file=ABI_DIR\BUILD_DIR\qts60plugin_5_0.dll SHARED_LIB_DIR\qts60plugin_5_0.dll S60_APP_RESOURCE(s60main) // imageformats stubs -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qjpeg.qtplugin resource\qt\plugins\imageformats\qjpeg.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qmng.qtplugin resource\qt\plugins\imageformats\qmng.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qsvg.qtplugin resource\qt\plugins\imageformats\qsvg.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qtiff.qtplugin resource\qt\plugins\imageformats\qtiff.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qjpeg.qtplugin resource\qt\plugins\imageformats\qjpeg.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qmng.qtplugin resource\qt\plugins\imageformats\qmng.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qsvg.qtplugin resource\qt\plugins\imageformats\qsvg.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qtiff.qtplugin resource\qt\plugins\imageformats\qtiff.qtplugin // codecs stubs -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qcncodecs.qtplugin resource\qt\plugins\codecs\qcncodecs.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qjpcodecs.qtplugin resource\qt\plugins\codecs\qjpcodecs.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qkrcodecs.qtplugin resource\qt\plugins\codecs\qkrcodecs.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qtwcodecs.qtplugin resource\qt\plugins\codecs\qtwcodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qcncodecs.qtplugin resource\qt\plugins\codecs\qcncodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qjpcodecs.qtplugin resource\qt\plugins\codecs\qjpcodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qkrcodecs.qtplugin resource\qt\plugins\codecs\qkrcodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qtwcodecs.qtplugin resource\qt\plugins\codecs\qtwcodecs.qtplugin // iconengines stubs -data=\epoc32\winscw\c\resource\qt\plugins\iconengines\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin // Phonon MMF backend -data=\epoc32\winscw\c\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin // graphicssystems -data=\epoc32\winscw\c\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin // Stub sis file data=ZSYSTEM\install\qt.sis System\Install\qt.sis diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 37adfa9..e024396 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -105,10 +105,6 @@ symbian: { qtlibraries.sources += QtDeclarative.dll } - contains(QT_CONFIG, webkit): { - qtlibraries.sources += QtWebKit.dll - } - graphicssystems_plugins.path = c:$$QT_PLUGINS_BASE_DIR/graphicssystems contains(QT_CONFIG, openvg) { qtlibraries.sources += QtOpenVG.dll @@ -117,4 +113,9 @@ symbian: { BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" BLD_INF_RULES.prj_exports += "qtdemoapps.iby $$CORE_APP_LAYER_IBY_EXPORT_PATH(qtdemoapps.iby)" + PLUGIN_STUBS = $$files(qmakepluginstubs/*) + for(STUB, PLUGIN_STUBS) { + STUB_FILENAME = $$basename(STUB) + BLD_INF_RULES.prj_exports += "qmakepluginstubs/$${STUB_FILENAME} /epoc32/data/qt/qtlibspluginstubs/$${STUB_FILENAME}" + } } diff --git a/src/s60main/qts60main.cpp b/src/s60main/qts60main.cpp index 725b17c..8923fb9 100644 --- a/src/s60main/qts60main.cpp +++ b/src/s60main/qts60main.cpp @@ -6,35 +6,33 @@ ** ** This file is part of the Symbian application wrapper 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_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -54,7 +52,7 @@ GLDEF_C TInt E32Main() { CTrapCleanup *cleanupStack = q_check_ptr(CTrapCleanup::New()); TInt err = 0; - TRAP(err, QtMainWrapper()); + TRAP(err, err = QtMainWrapper()); delete cleanupStack; return err; diff --git a/src/s60main/qts60main_mcrt0.cpp b/src/s60main/qts60main_mcrt0.cpp index edc2fb8..b9a720b 100644 --- a/src/s60main/qts60main_mcrt0.cpp +++ b/src/s60main/qts60main_mcrt0.cpp @@ -6,35 +6,33 @@ ** ** This file is part of the Symbian application wrapper 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_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: ** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. ** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index ac220bd..21c947b 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -2864,14 +2864,8 @@ static QSvgNode *createPolygonNode(QSvgNode *parent, const QChar *s = pointsStr.constData(); QVector<qreal> points = parseNumbersList(s); QPolygonF poly(points.count()/2); - int i = 0; - QVector<qreal>::const_iterator itr = points.constBegin(); - while (itr != points.constEnd()) { - qreal one = *itr; ++itr; - qreal two = *itr; ++itr; - poly[i] = QPointF(one, two); - ++i; - } + for (int i = 0; i < poly.size(); ++i) + poly[i] = QPointF(points.at(2 * i), points.at(2 * i + 1)); QSvgNode *polygon = new QSvgPolygon(parent, poly); return polygon; } @@ -2886,14 +2880,8 @@ static QSvgNode *createPolylineNode(QSvgNode *parent, const QChar *s = pointsStr.constData(); QVector<qreal> points = parseNumbersList(s); QPolygonF poly(points.count()/2); - int i = 0; - QVector<qreal>::const_iterator itr = points.constBegin(); - while (itr != points.constEnd()) { - qreal one = *itr; ++itr; - qreal two = *itr; ++itr; - poly[i] = QPointF(one, two); - ++i; - } + for (int i = 0; i < poly.size(); ++i) + poly[i] = QPointF(points.at(2 * i), points.at(2 * i + 1)); QSvgNode *line = new QSvgPolyline(parent, poly); return line; diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 0a87412..27ec3bd 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -3063,11 +3063,11 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing() Aspects of the parsing behavior can be adapted using setFeature() and setProperty(). + \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0 + QXmlSimpleReader is not reentrant. If you want to use the class in threaded code, lock the code using QXmlSimpleReader with a locking mechanism, such as a QMutex. - - \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0 */ static inline bool is_S(QChar ch) diff --git a/src/xmlpatterns/api/api.pri b/src/xmlpatterns/api/api.pri index 9fcc2f5..a0adf75 100644 --- a/src/xmlpatterns/api/api.pri +++ b/src/xmlpatterns/api/api.pri @@ -1,59 +1,57 @@ -HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \ - $$PWD/qabstractmessagehandler.h \ - $$PWD/qabstracturiresolver.h \ - $$PWD/qabstractxmlnodemodel.h \ - $$PWD/qabstractxmlnodemodel_p.h \ - $$PWD/qabstractxmlpullprovider_p.h \ - $$PWD/qabstractxmlreceiver.h \ - $$PWD/qabstractxmlreceiver_p.h \ - $$PWD/qdeviceresourceloader_p.h \ - $$PWD/qiodevicedelegate_p.h \ - $$PWD/qnetworkaccessdelegator_p.h \ - $$PWD/qpullbridge_p.h \ - $$PWD/qresourcedelegator_p.h \ - $$PWD/qsimplexmlnodemodel.h \ - $$PWD/qsourcelocation.h \ - $$PWD/quriloader_p.h \ - $$PWD/qvariableloader_p.h \ - $$PWD/qxmlformatter.h \ - $$PWD/qxmlname.h \ - $$PWD/qxmlnamepool.h \ - $$PWD/qxmlquery.h \ - $$PWD/qxmlquery_p.h \ - $$PWD/qxmlresultitems.h \ - $$PWD/qxmlresultitems_p.h \ - $$PWD/qxmlschema.h \ - $$PWD/qxmlschema_p.h \ - $$PWD/qxmlschemavalidator.h \ - $$PWD/qxmlschemavalidator_p.h \ - $$PWD/qxmlserializer.h \ - $$PWD/qxmlserializer_p.h \ - $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler_p.h \ - $$PWD/../../../tools/xmlpatterns/qcoloroutput_p.h - -SOURCES += $$PWD/qvariableloader.cpp \ - $$PWD/qabstractmessagehandler.cpp \ - $$PWD/qabstracturiresolver.cpp \ - $$PWD/qabstractxmlnodemodel.cpp \ - $$PWD/qabstractxmlpullprovider.cpp \ - $$PWD/qabstractxmlreceiver.cpp \ - $$PWD/qiodevicedelegate.cpp \ - $$PWD/qnetworkaccessdelegator.cpp \ - $$PWD/qpullbridge.cpp \ - $$PWD/qresourcedelegator.cpp \ - $$PWD/qsimplexmlnodemodel.cpp \ - $$PWD/qsourcelocation.cpp \ - $$PWD/quriloader.cpp \ - $$PWD/qxmlformatter.cpp \ - $$PWD/qxmlname.cpp \ - $$PWD/qxmlnamepool.cpp \ - $$PWD/qxmlquery.cpp \ - $$PWD/qxmlresultitems.cpp \ - $$PWD/qxmlschema.cpp \ - $$PWD/qxmlschema_p.cpp \ - $$PWD/qxmlschemavalidator.cpp \ - $$PWD/qxmlserializer.cpp \ - $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler.cpp \ - $$PWD/../../../tools/xmlpatterns/qcoloroutput.cpp - -INCLUDEPATH += $$PWD/../../../tools/xmlpatterns/ +HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \ + $$PWD/qabstractmessagehandler.h \ + $$PWD/qabstracturiresolver.h \ + $$PWD/qabstractxmlnodemodel.h \ + $$PWD/qabstractxmlnodemodel_p.h \ + $$PWD/qabstractxmlpullprovider_p.h \ + $$PWD/qabstractxmlreceiver.h \ + $$PWD/qabstractxmlreceiver_p.h \ + $$PWD/qdeviceresourceloader_p.h \ + $$PWD/qiodevicedelegate_p.h \ + $$PWD/qnetworkaccessdelegator_p.h \ + $$PWD/qpullbridge_p.h \ + $$PWD/qresourcedelegator_p.h \ + $$PWD/qsimplexmlnodemodel.h \ + $$PWD/qsourcelocation.h \ + $$PWD/quriloader_p.h \ + $$PWD/qvariableloader_p.h \ + $$PWD/qxmlformatter.h \ + $$PWD/qxmlname.h \ + $$PWD/qxmlnamepool.h \ + $$PWD/qxmlquery.h \ + $$PWD/qxmlquery_p.h \ + $$PWD/qxmlresultitems.h \ + $$PWD/qxmlresultitems_p.h \ + $$PWD/qxmlschema.h \ + $$PWD/qxmlschema_p.h \ + $$PWD/qxmlschemavalidator.h \ + $$PWD/qxmlschemavalidator_p.h \ + $$PWD/qxmlserializer.h \ + $$PWD/qxmlserializer_p.h \ + $$PWD/qcoloringmessagehandler_p.h \ + $$PWD/qcoloroutput_p.h \ + $$PWD/qxmlpatternistcli_p.h +SOURCES += $$PWD/qvariableloader.cpp \ + $$PWD/qabstractmessagehandler.cpp \ + $$PWD/qabstracturiresolver.cpp \ + $$PWD/qabstractxmlnodemodel.cpp \ + $$PWD/qabstractxmlpullprovider.cpp \ + $$PWD/qabstractxmlreceiver.cpp \ + $$PWD/qiodevicedelegate.cpp \ + $$PWD/qnetworkaccessdelegator.cpp \ + $$PWD/qpullbridge.cpp \ + $$PWD/qresourcedelegator.cpp \ + $$PWD/qsimplexmlnodemodel.cpp \ + $$PWD/qsourcelocation.cpp \ + $$PWD/quriloader.cpp \ + $$PWD/qxmlformatter.cpp \ + $$PWD/qxmlname.cpp \ + $$PWD/qxmlnamepool.cpp \ + $$PWD/qxmlquery.cpp \ + $$PWD/qxmlresultitems.cpp \ + $$PWD/qxmlschema.cpp \ + $$PWD/qxmlschema_p.cpp \ + $$PWD/qxmlschemavalidator.cpp \ + $$PWD/qxmlserializer.cpp \ + $$PWD/qcoloringmessagehandler.cpp \ + $$PWD/qcoloroutput.cpp diff --git a/src/xmlpatterns/api/qcoloringmessagehandler.cpp b/src/xmlpatterns/api/qcoloringmessagehandler.cpp new file mode 100644 index 0000000..7d3eb6f --- /dev/null +++ b/src/xmlpatterns/api/qcoloringmessagehandler.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 <QXmlStreamReader> + +#include "qcoloringmessagehandler_p.h" +#include "qxmlpatternistcli_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ColoringMessageHandler::ColoringMessageHandler(QObject *parent) : QAbstractMessageHandler(parent) +{ + m_classToColor.insert(QLatin1String("XQuery-data"), Data); + m_classToColor.insert(QLatin1String("XQuery-expression"), Keyword); + m_classToColor.insert(QLatin1String("XQuery-function"), Keyword); + m_classToColor.insert(QLatin1String("XQuery-keyword"), Keyword); + m_classToColor.insert(QLatin1String("XQuery-type"), Keyword); + m_classToColor.insert(QLatin1String("XQuery-uri"), Data); + m_classToColor.insert(QLatin1String("XQuery-filepath"), Data); + + /* If you're tuning the colors, take it easy laddie. Take into account: + * + * - Get over your own taste, there's others too on this planet + * - Make sure it works well on black & white + * - Make sure it works well on white & black + */ + insertMapping(Location, CyanForeground); + insertMapping(ErrorCode, RedForeground); + insertMapping(Keyword, BlueForeground); + insertMapping(Data, BlueForeground); + insertMapping(RunningText, DefaultColor); +} + +void ColoringMessageHandler::handleMessage(QtMsgType type, + const QString &description, + const QUrl &identifier, + const QSourceLocation &sourceLocation) +{ + const bool hasLine = sourceLocation.line() != -1; + + switch(type) + { + case QtWarningMsg: + { + if(hasLine) + { + writeUncolored(QXmlPatternistCLI::tr("Warning in %1, at line %2, column %3: %4").arg(QString::fromLatin1(sourceLocation.uri().toEncoded()), + QString::number(sourceLocation.line()), + QString::number(sourceLocation.column()), + colorifyDescription(description))); + } + else + { + writeUncolored(QXmlPatternistCLI::tr("Warning in %1: %2").arg(QString::fromLatin1(sourceLocation.uri().toEncoded()), + colorifyDescription(description))); + } + + break; + } + case QtFatalMsg: + { + const QString errorCode(identifier.fragment()); + Q_ASSERT(!errorCode.isEmpty()); + QUrl uri(identifier); + uri.setFragment(QString()); + + QString location; + + if(sourceLocation.isNull()) + location = QXmlPatternistCLI::tr("Unknown location"); + else + location = QString::fromLatin1(sourceLocation.uri().toEncoded()); + + QString errorId; + /* If it's a standard error code, we don't want to output the + * whole URI. */ + if(uri.toString() == QLatin1String("http://www.w3.org/2005/xqt-errors")) + errorId = errorCode; + else + errorId = QString::fromLatin1(identifier.toEncoded()); + + if(hasLine) + { + writeUncolored(QXmlPatternistCLI::tr("Error %1 in %2, at line %3, column %4: %5").arg(colorify(errorId, ErrorCode), + colorify(location, Location), + colorify(QString::number(sourceLocation.line()), Location), + colorify(QString::number(sourceLocation.column()), Location), + colorifyDescription(description))); + } + else + { + writeUncolored(QXmlPatternistCLI::tr("Error %1 in %2: %3").arg(colorify(errorId, ErrorCode), + colorify(location, Location), + colorifyDescription(description))); + } + break; + } + case QtCriticalMsg: + /* Fallthrough. */ + case QtDebugMsg: + { + Q_ASSERT_X(false, Q_FUNC_INFO, + "message() is not supposed to receive QtCriticalMsg or QtDebugMsg."); + return; + } + } +} + +QString ColoringMessageHandler::colorifyDescription(const QString &in) const +{ + QXmlStreamReader reader(in); + QString result; + result.reserve(in.size()); + ColorType currentColor = RunningText; + + while(!reader.atEnd()) + { + reader.readNext(); + + switch(reader.tokenType()) + { + case QXmlStreamReader::StartElement: + { + if(reader.name() == QLatin1String("span")) + { + Q_ASSERT(m_classToColor.contains(reader.attributes().value(QLatin1String("class")).toString())); + currentColor = m_classToColor.value(reader.attributes().value(QLatin1String("class")).toString()); + } + + continue; + } + case QXmlStreamReader::Characters: + { + result.append(colorify(reader.text().toString(), currentColor)); + continue; + } + case QXmlStreamReader::EndElement: + { + currentColor = RunningText; + continue; + } + /* Fallthrough, */ + case QXmlStreamReader::StartDocument: + /* Fallthrough, */ + case QXmlStreamReader::EndDocument: + continue; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, + "Unexpected node."); + } + } + + Q_ASSERT_X(!reader.hasError(), Q_FUNC_INFO, + "The output from Patternist must be well-formed."); + return result; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qcoloringmessagehandler_p.h b/src/xmlpatterns/api/qcoloringmessagehandler_p.h new file mode 100644 index 0000000..3e8d18b --- /dev/null +++ b/src/xmlpatterns/api/qcoloringmessagehandler_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the XMLPatterns 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef Patternist_ColoringMessageHandler_h +#define Patternist_ColoringMessageHandler_h + +#include <QHash> + +#include "qcoloroutput_p.h" +#include "qabstractmessagehandler.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class ColoringMessageHandler : public QAbstractMessageHandler + , private ColorOutput + { + public: + ColoringMessageHandler(QObject *parent = 0); + + protected: + virtual void handleMessage(QtMsgType type, + const QString &description, + const QUrl &identifier, + const QSourceLocation &sourceLocation); + + private: + QString colorifyDescription(const QString &in) const; + + enum ColorType + { + RunningText, + Location, + ErrorCode, + Keyword, + Data + }; + + QHash<QString, ColorType> m_classToColor; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qcoloroutput.cpp b/src/xmlpatterns/api/qcoloroutput.cpp new file mode 100644 index 0000000..4f27fd5 --- /dev/null +++ b/src/xmlpatterns/api/qcoloroutput.cpp @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtXmlPatterns 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 <QFile> +#include <QHash> +#include <QTextCodec> + +#include "qcoloroutput_p.h" + +// TODO: rename insertMapping() to insertColorMapping() +// TODO: Use a smart pointer for managing ColorOutputPrivate *d; +// TODO: break out the C++ example into a snippet file + +/* This include must appear here, because if it appears at the beginning of the file for + * instance, it breaks build -- "qglobal.h:628: error: template with + * C linkage" -- on Mac OS X 10.4. */ +#ifndef Q_OS_WIN +#include <unistd.h> +#endif + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +namespace QPatternist +{ + class ColorOutputPrivate + { + public: + ColorOutputPrivate() : currentColorID(-1) + + { + /* - QIODevice::Unbuffered because we want it to appear when the user actually calls, performance + * is considered of lower priority. + */ + m_out.open(stderr, QIODevice::WriteOnly | QIODevice::Unbuffered); + + coloringEnabled = isColoringPossible(); + } + + ColorOutput::ColorMapping colorMapping; + int currentColorID; + bool coloringEnabled; + + static const char *const foregrounds[]; + static const char *const backgrounds[]; + + inline void write(const QString &msg) + { + m_out.write(msg.toLocal8Bit()); + } + + static QString escapeCode(const QString &in) + { + QString result; + result.append(QChar(0x1B)); + result.append(QLatin1Char('[')); + result.append(in); + result.append(QLatin1Char('m')); + return result; + } + + private: + QFile m_out; + + /*! + Returns true if it's suitable to send colored output to \c stderr. + */ + inline bool isColoringPossible() const + { +# if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) + /* Windows doesn't at all support ANSI escape codes, unless + * the user install a "device driver". See the Wikipedia links in the + * class documentation for details. */ + return false; +# else + /* We use QFile::handle() to get the file descriptor. It's a bit unsure + * whether it's 2 on all platforms and in all cases, so hopefully this layer + * of abstraction helps handle such cases. */ + return isatty(m_out.handle()); +# endif + } + }; +} + +const char *const ColorOutputPrivate::foregrounds[] = +{ + "0;30", + "0;34", + "0;32", + "0;36", + "0;31", + "0;35", + "0;33", + "0;37", + "1;30", + "1;34", + "1;32", + "1;36", + "1;31", + "1;35", + "1;33", + "1;37" +}; + +const char *const ColorOutputPrivate::backgrounds[] = +{ + "0;40", + "0;44", + "0;42", + "0;46", + "0;41", + "0;45", + "0;43" +}; + +/*! + \since 4.4 + \nonreentrant + \brief Outputs colored messages to \c stderr. + \internal + + ColorOutput is a convenience class for outputting messages to \c stderr + using color escape codes, as mandated in ECMA-48. ColorOutput will only + color output when it is detected to be suitable. For instance, if \c stderr is + detected to be attached to a file instead of a TTY, no coloring will be done. + + ColorOutput does its best attempt. but it is generally undefined what coloring + or effect the various coloring flags has. It depends strongly on what terminal + software that is being used. + + When using `echo -e 'my escape sequence'`, \033 works as an initiator but not + when printing from a C++ program, despite having escaped the backslash. + That's why we below use characters with value 0x1B. + + It can be convenient to subclass ColorOutput with a private scope, such that the + functions are directly available in the class using it. + + \section1 Usage + + To output messages, call write() or writeUncolored(). write() takes as second + argument an integer, which ColorOutput uses as a lookup key to find the color + it should color the text in. The mapping from keys to colors is done using + insertMapping(). Typically this is used by having enums for the various kinds + of messages, which subsequently are registered. + + \code + enum MyMessage + { + Error, + Important + }; + + ColorOutput output; + output.insertMapping(Error, ColorOutput::RedForeground); + output.insertMapping(Import, ColorOutput::BlueForeground); + + output.write("This is important", Important); + output.write("Jack, I'm only the selected official!", Error); + \endcode + + \sa {http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html} {Bash Prompt HOWTO, 6.1. Colours} + {http://linuxgazette.net/issue51/livingston-blade.html} {Linux Gazette, Tweaking Eterm, Edward Livingston-Blade} + {http://www.ecma-international.org/publications/standards/Ecma-048.htm} {Standard ECMA-48, Control Functions for Coded Character Sets, ECMA International}, + {http://en.wikipedia.org/wiki/ANSI_escape_code} {Wikipedia, ANSI escape code} + {http://linuxgazette.net/issue65/padala.html} {Linux Gazette, So You Like Color!, Pradeep Padala} + */ + +/*! + \enum ColorOutput::ColorCode + + \value DefaultColor ColorOutput performs no coloring. This typically means black on white + or white on black, depending on the settings of the user's terminal. + */ + +/*! + Sets the color mapping to be \a cMapping. + + Negative values are disallowed. + + \sa colorMapping(), insertMapping() + */ +void ColorOutput::setColorMapping(const ColorMapping &cMapping) +{ + d->colorMapping = cMapping; +} + +/*! + Returns the color mappings in use. + + \sa setColorMapping(), insertMapping() + */ +ColorOutput::ColorMapping ColorOutput::colorMapping() const +{ + return d->colorMapping; +} + +/*! + Constructs a ColorOutput instance, ready for use. + */ +ColorOutput::ColorOutput() : d(new ColorOutputPrivate()) +{ +} + +/*! + Destructs this ColorOutput instance. + */ +ColorOutput::~ColorOutput() +{ + delete d; +} + +/*! + Sends \a message to \c stderr, using the color looked up in colorMapping() using \a colorID. + + If \a color isn't available in colorMapping(), result and behavior is undefined. + + If \a colorID is 0, which is the default value, the previously used coloring is used. ColorOutput + is initialized to not color at all. + + If \a message is empty, effects are undefined. + + \a message will be printed as is. For instance, no line endings will be inserted. + */ +void ColorOutput::write(const QString &message, int colorID) +{ + d->write(colorify(message, colorID)); +} + +/*! + Writes \a message to \c stderr as if for instance + QTextStream would have been used, and adds a line ending at the end. + + This function can be practical to use such that one can use ColorOutput for all forms of writing. + */ +void ColorOutput::writeUncolored(const QString &message) +{ + d->write(message + QLatin1Char('\n')); +} + +/*! + Treats \a message and \a colorID identically to write(), but instead of writing + \a message to \c stderr, it is prepared for being written to \c stderr, but is then + returned. + + This is useful when the colored string is inserted into a translated string(dividing + the string into several small strings prevents proper translation). + */ +QString ColorOutput::colorify(const QString &message, int colorID) const +{ + Q_ASSERT_X(colorID == -1 || d->colorMapping.contains(colorID), Q_FUNC_INFO, + qPrintable(QString::fromLatin1("There is no color registered by id %1").arg(colorID))); + Q_ASSERT_X(!message.isEmpty(), Q_FUNC_INFO, "It makes no sense to attempt to print an empty string."); + + if(colorID != -1) + d->currentColorID = colorID; + + if(d->coloringEnabled && colorID != -1) + { + const int color(d->colorMapping.value(colorID)); + + /* If DefaultColor is set, we don't want to color it. */ + if(color & DefaultColor) + return message; + + const int foregroundCode = (int(color) & ForegroundMask) >> ForegroundShift; + const int backgroundCode = (int(color) & BackgroundMask) >> BackgroundShift; + QString finalMessage; + bool closureNeeded = false; + + if(foregroundCode) + { + finalMessage.append(ColorOutputPrivate::escapeCode(QLatin1String(ColorOutputPrivate::foregrounds[foregroundCode - 1]))); + closureNeeded = true; + } + + if(backgroundCode) + { + finalMessage.append(ColorOutputPrivate::escapeCode(QLatin1String(ColorOutputPrivate::backgrounds[backgroundCode - 1]))); + closureNeeded = true; + } + + finalMessage.append(message); + + if(closureNeeded) + { + finalMessage.append(QChar(0x1B)); + finalMessage.append(QLatin1String("[0m")); + } + + return finalMessage; + } + else + return message; +} + +/*! + Adds a color mapping from \a colorID to \a colorCode, for this ColorOutput instance. + + This is a convenience function for creating a ColorOutput::ColorMapping instance and + calling setColorMapping(). + + \sa colorMapping(), setColorMapping() + */ +void ColorOutput::insertMapping(int colorID, const ColorCode colorCode) +{ + d->colorMapping.insert(colorID, colorCode); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qcoloroutput_p.h b/src/xmlpatterns/api/qcoloroutput_p.h new file mode 100644 index 0000000..1917ec7 --- /dev/null +++ b/src/xmlpatterns/api/qcoloroutput_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the XMLPatterns 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef Patternist_ColorOutput_h +#define Patternist_ColorOutput_h + +#include <QtCore/QtGlobal> +#include <QtCore/QHash> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class ColorOutputPrivate; + + class ColorOutput + { + enum + { + ForegroundShift = 10, + BackgroundShift = 20, + SpecialShift = 20, + ForegroundMask = ((1 << ForegroundShift) - 1) << ForegroundShift, + BackgroundMask = ((1 << BackgroundShift) - 1) << BackgroundShift + }; + + public: + enum ColorCodeComponent + { + BlackForeground = 1 << ForegroundShift, + BlueForeground = 2 << ForegroundShift, + GreenForeground = 3 << ForegroundShift, + CyanForeground = 4 << ForegroundShift, + RedForeground = 5 << ForegroundShift, + PurpleForeground = 6 << ForegroundShift, + BrownForeground = 7 << ForegroundShift, + LightGrayForeground = 8 << ForegroundShift, + DarkGrayForeground = 9 << ForegroundShift, + LightBlueForeground = 10 << ForegroundShift, + LightGreenForeground = 11 << ForegroundShift, + LightCyanForeground = 12 << ForegroundShift, + LightRedForeground = 13 << ForegroundShift, + LightPurpleForeground = 14 << ForegroundShift, + YellowForeground = 15 << ForegroundShift, + WhiteForeground = 16 << ForegroundShift, + + BlackBackground = 1 << BackgroundShift, + BlueBackground = 2 << BackgroundShift, + GreenBackground = 3 << BackgroundShift, + CyanBackground = 4 << BackgroundShift, + RedBackground = 5 << BackgroundShift, + PurpleBackground = 6 << BackgroundShift, + BrownBackground = 7 << BackgroundShift, + DefaultColor = 1 << SpecialShift + }; + + typedef QFlags<ColorCodeComponent> ColorCode; + typedef QHash<int, ColorCode> ColorMapping; + + ColorOutput(); + ~ColorOutput(); + + void setColorMapping(const ColorMapping &cMapping); + ColorMapping colorMapping() const; + void insertMapping(int colorID, const ColorCode colorCode); + + void writeUncolored(const QString &message); + void write(const QString &message, int color = -1); + QString colorify(const QString &message, int color = -1) const; + + private: + ColorOutputPrivate *d; + Q_DISABLE_COPY(ColorOutput) + }; +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(QPatternist::ColorOutput::ColorCode) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlpatternistcli_p.h b/src/xmlpatterns/api/qxmlpatternistcli_p.h new file mode 100644 index 0000000..072e4aa --- /dev/null +++ b/src/xmlpatterns/api/qxmlpatternistcli_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the XMLPatterns 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef Patternist_Cli_h +#define Patternist_Cli_h + +#include <QCoreApplication> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlPatternistCLI +{ +public: + Q_DECLARE_TR_FUNCTIONS(QXmlPatternistCLI) +private: + inline QXmlPatternistCLI(); + Q_DISABLE_COPY(QXmlPatternistCLI) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/xmlpatterns.pro b/src/xmlpatterns/xmlpatterns.pro index 1df497d..a224762 100644 --- a/src/xmlpatterns/xmlpatterns.pro +++ b/src/xmlpatterns/xmlpatterns.pro @@ -1,15 +1,14 @@ -TARGET = QtXmlPatterns -QPRO_PWD = $$PWD -QT = core network -DEFINES += QT_BUILD_XMLPATTERNS_LIB QT_NO_USING_NAMESPACE +TARGET = QtXmlPatterns +QPRO_PWD = $$PWD +QT = core \ + network +DEFINES += QT_BUILD_XMLPATTERNS_LIB \ + QT_NO_USING_NAMESPACE win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x61000000 - -unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtNetwork - +unix:QMAKE_PKGCONFIG_REQUIRES = QtCore \ + QtNetwork include(../qbase.pri) - PRECOMPILED_HEADER = ../corelib/global/qt_pch.h - include($$PWD/common.pri) include($$PWD/acceltree/acceltree.pri) include($$PWD/api/api.pri) @@ -25,14 +24,13 @@ include($$PWD/schema/schema.pri) include($$PWD/type/type.pri) include($$PWD/utils/utils.pri) include($$PWD/qobjectmodel/qobjectmodel.pri, "", true) +wince*:# The Microsoft MIPS compiler crashes if /Og is specified +: -wince*: { - # The Microsoft MIPS compiler crashes if /Og is specified - # -O2/1 expands to /Og plus additional arguments. - contains(DEFINES, MIPS): { - QMAKE_CXXFLAGS_RELEASE ~= s/-O2/-Oi -Ot -Oy -Ob2/ - QMAKE_CXXFLAGS_RELEASE ~= s/-O1/-Os -Oy -Ob2/ - } +# -O2/1 expands to /Og plus additional arguments. +contains(DEFINES, MIPS): { + QMAKE_CXXFLAGS_RELEASE ~= s/-O2/-Oi -Ot -Oy -Ob2/ + QMAKE_CXXFLAGS_RELEASE ~= s/-O1/-Os -Oy -Ob2/ } - -symbian:TARGET.UID3=0x2001E62B +symbian:TARGET.UID3 = 0x2001E62B +HEADERS += |