summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJanne Koskinen <janne.p.koskinen@digia.com>2009-12-23 13:34:35 (GMT)
committerJanne Koskinen <janne.p.koskinen@digia.com>2009-12-23 13:34:35 (GMT)
commitc0a4c266deeb867069b65b158ded3f7b9becfebf (patch)
tree3641277e204e22b0490f8d03f19b158c7e81cf96 /src
parent01cf310d21b17d8f57911ae194eaa0ca2472d155 (diff)
parent5f7b681661d8067b3fd954f04b7a25d833f5c92a (diff)
downloadQt-c0a4c266deeb867069b65b158ded3f7b9becfebf.zip
Qt-c0a4c266deeb867069b65b158ded3f7b9becfebf.tar.gz
Qt-c0a4c266deeb867069b65b158ded3f7b9becfebf.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt-s60-public into 4.6
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c4
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp3
-rw-r--r--src/3rdparty/webkit/VERSION2
-rw-r--r--src/3rdparty/webkit/WebCore/ChangeLog13
-rw-r--r--src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.cpp5
-rw-r--r--src/3rdparty/webkit/WebCore/svg/graphics/SVGImage.h2
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebinspector.cpp5
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp56
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebview.h5
-rw-r--r--src/3rdparty/webkit/WebKit/qt/ChangeLog50
-rw-r--r--src/activeqt/container/qaxbase.cpp2
-rw-r--r--src/corelib/io/qfileinfo.cpp2
-rw-r--r--src/corelib/io/qresource.cpp2
-rw-r--r--src/corelib/kernel/qobject.cpp15
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm9
-rw-r--r--src/gui/kernel/qwidget_mac.mm6
-rw-r--r--src/gui/painting/painting.pri2
-rw-r--r--src/gui/styles/qs60style.cpp8
-rw-r--r--src/gui/styles/qs60style_s60.cpp17
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp2
-rw-r--r--src/network/access/qnetworkreply.cpp2
-rw-r--r--src/network/kernel/qhostinfo.cpp297
-rw-r--r--src/network/kernel/qhostinfo_p.h148
-rw-r--r--src/network/kernel/qhostinfo_win.cpp6
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp191
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h66
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp58
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h2
-rw-r--r--src/opengl/qglshaderprogram.cpp67
-rw-r--r--src/opengl/qglshaderprogram.h4
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp407
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.h4
-rw-r--r--src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pro2
-rw-r--r--src/svg/qsvghandler.cpp20
-rw-r--r--src/xmlpatterns/api/api.pri116
-rw-r--r--src/xmlpatterns/api/qcoloringmessagehandler.cpp198
-rw-r--r--src/xmlpatterns/api/qcoloringmessagehandler_p.h98
-rw-r--r--src/xmlpatterns/api/qcoloroutput.cpp348
-rw-r--r--src/xmlpatterns/api/qcoloroutput_p.h133
-rw-r--r--src/xmlpatterns/api/qxmlpatternistcli_p.h74
-rw-r--r--src/xmlpatterns/xmlpatterns.pro34
41 files changed, 1801 insertions, 684 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/VERSION b/src/3rdparty/webkit/VERSION
index 62acbdf..e6813a1 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
+ de77f8ee69c434bde9306c8f407ee2e443a00188
diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog
index 4f6146f..c60a5d4 100644
--- a/src/3rdparty/webkit/WebCore/ChangeLog
+++ b/src/3rdparty/webkit/WebCore/ChangeLog
@@ -1,3 +1,16 @@
+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/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..35f6e0c 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
@@ -3080,7 +3080,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 +3089,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 +3156,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 +3165,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 +3250,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..37d527fa 100644
--- a/src/3rdparty/webkit/WebKit/qt/ChangeLog
+++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog
@@ -1,3 +1,53 @@
+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/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
index 3795f56..ed7ac29 100644
--- a/src/activeqt/container/qaxbase.cpp
+++ b/src/activeqt/container/qaxbase.cpp
@@ -909,7 +909,7 @@ QAxMetaObject *QAxBase::internalMetaObject() const
\property QAxBase::control
\brief the name of the COM object wrapped by this QAxBase object.
- Setting this property initilializes the COM object. Any COM object
+ Setting this property initializes the COM object. Any COM object
previously set is shut down.
The most efficient way to set this property is by using the
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/qresource.cpp b/src/corelib/io/qresource.cpp
index 5c543d4..a061ad1 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -273,7 +273,7 @@ QResourcePrivate::load(const QString &file)
QString cleaned = cleanPath(file);
for(int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
- const int node = res->findNode(cleaned);
+ const int node = res->findNode(cleaned, locale);
if(node != -1) {
if(related.isEmpty()) {
container = res->isContainer(node);
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 4370ee0..305ec4f 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -578,12 +578,13 @@ int QMetaCallEvent::placeMetaCall(QObject *object)
protected functions connectNotify() and disconnectNotify() make
it possible to track connections.
- QObjects organize themselves in object trees. When you create a
- QObject with another object as parent, the object will
- automatically add itself to the parent's children() list. The
- parent takes ownership of the object; i.e., it will automatically
- delete its children in its destructor. You can look for an object
- by name and optionally type using findChild() or findChildren().
+ QObjects organize themselves in \l {Object Trees and Object
+ Ownership} {object trees}. When you create a QObject with another
+ object as parent, the object will automatically add itself to the
+ parent's children() list. The parent takes ownership of the
+ object; i.e., it will automatically delete its children in its
+ destructor. You can look for an object by name and optionally type
+ using findChild() or findChildren().
Every object has an objectName() and its class name can be found
via the corresponding metaObject() (see QMetaObject::className()).
@@ -682,7 +683,7 @@ int QMetaCallEvent::placeMetaCall(QObject *object)
\l{Writing Source Code for Translation} document.
\sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
- {Object Trees and Object Ownership}
+ \sa {Object Trees and Object Ownership}
*/
/*!
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_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 0b1e79a..a6cc9c7 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -383,7 +383,7 @@ neon {
DEFINES += QT_HAVE_NEON
HEADERS += painting/qdrawhelper_neon_p.h
SOURCES += painting/qdrawhelper_neon.cpp
- QMAKE.CXXFLAGS *= -mfpu=neon
+ QMAKE_CXXFLAGS *= -mfpu=neon
}
contains(QT_CONFIG, zlib) {
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index ed86f5a..e370ed0 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -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:
@@ -2161,7 +2160,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;
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/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index a59cd48..e26d5c3 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -1180,7 +1180,7 @@ static int getKeyboardAutoRepeatRate() {
TTimeIntervalMicroSeconds32 time;
S60->wsSession().GetKeyboardRepeatRate(initialTime, time);
ret = time.Int() / 1000; // msecs
-#elif defined(Q_OS_WIN) and !defined(Q_OS_WINCE)
+#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
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 9ab4057..e6ca367 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -171,7 +171,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
\value UnknownProxyError an unknown proxy-related error
was detected
- \value UnknownContentError an unknonwn error related to
+ \value UnknownContentError an unknown error related to
the remote content was detected
\value ProtocolFailure a breakdown in protocol was
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 98a39cd..e77a425 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -60,11 +60,9 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QHostInfoAgent, theAgent)
-void QHostInfoAgent::staticCleanup()
-{
- theAgent()->cleanup();
-}
+#ifndef QT_NO_THREAD
+Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
+#endif
//#define QHOSTINFO_DEBUG
@@ -143,6 +141,9 @@ static QBasicAtomicInt theIdCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
\snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 4
+ \note There is no guarantee on the order the signals will be emitted
+ if you start multiple requests with lookupHost().
+
\sa abortHostLookup(), addresses(), error(), fromName()
*/
int QHostInfo::lookupHost(const QString &name, QObject *receiver,
@@ -159,38 +160,32 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
qRegisterMetaType<QHostInfo>("QHostInfo");
-#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
- QWindowsSockInit bust; // makes sure WSAStartup was callled
-#endif
-
- QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
- result.data()->autoDelete = false;
- QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
- receiver, member);
- int id = result.data()->lookupId = theIdCounter.fetchAndAddRelaxed(1);
+ int id = theIdCounter.fetchAndAddRelaxed(1); // generate unique ID
if (name.isEmpty()) {
- QHostInfo info(id);
- info.setError(QHostInfo::HostNotFound);
- info.setErrorString(QObject::tr("No host name given"));
- QMetaObject::invokeMethod(result.data(), "emitResultsReady", Qt::QueuedConnection,
- Q_ARG(QHostInfo, info));
- result.take()->autoDelete = true;
+ QHostInfo hostInfo(id);
+ hostInfo.setError(QHostInfo::HostNotFound);
+ hostInfo.setErrorString(QObject::tr("No host name given"));
+ QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
+ QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
+ receiver, member, Qt::QueuedConnection);
+ result.data()->emitResultsReady(hostInfo);
return id;
}
- QHostInfoAgent *agent = theAgent();
- agent->addHostName(name, result.take());
-
-#if !defined QT_NO_THREAD
- if (!agent->isRunning())
- agent->start();
+#ifdef QT_NO_THREAD
+ QHostInfo hostInfo = QHostInfoAgent::fromName(name);
+ hostInfo.setLookupId(id);
+ QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
+ QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
+ receiver, member, Qt::QueuedConnection);
+ result.data()->emitResultsReady(hostInfo);
#else
-// if (!agent->isRunning())
- agent->run();
-// else
-// agent->wakeOne();
+ QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id);
+ QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection);
+ theHostInfoLookupManager()->scheduleLookup(runnable);
#endif
+
return id;
}
@@ -201,8 +196,12 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
*/
void QHostInfo::abortHostLookup(int id)
{
- QHostInfoAgent *agent = theAgent();
- agent->abortLookup(id);
+#ifndef QT_NO_THREAD
+ theHostInfoLookupManager()->abortLookup(id);
+#else
+ // we cannot abort if it was non threaded.. the result signal has already been posted
+ Q_UNUSED(id);
+#endif
}
/*!
@@ -228,70 +227,6 @@ QHostInfo QHostInfo::fromName(const QString &name)
}
/*!
- \internal
- Pops a query off the queries list, performs a blocking call to
- QHostInfoAgent::lookupHost(), and emits the resultsReady()
- signal. This process repeats until the queries list is empty.
-*/
-void QHostInfoAgent::run()
-{
-#ifndef QT_NO_THREAD
- // Dont' allow thread termination during event delivery, but allow it
- // during the actual blocking host lookup stage.
- setTerminationEnabled(false);
- forever
-#endif
- {
- QHostInfoQuery *query;
- {
-#ifndef QT_NO_THREAD
- // the queries list is shared between threads. lock all
- // access to it.
- QMutexLocker locker(&mutex);
- if (!quit && queries.isEmpty())
- cond.wait(&mutex);
- if (quit) {
- // Reset the quit variable in case QCoreApplication is
- // destroyed and recreated.
- quit = false;
- break;
- }
- if (queries.isEmpty())
- continue;
-#else
- if (queries.isEmpty())
- return;
-#endif
- query = queries.takeFirst();
- pendingQueryId = query->object->lookupId;
- }
-
-#if defined(QHOSTINFO_DEBUG)
- qDebug("QHostInfoAgent::run(%p): looking up \"%s\"", this,
- query->hostName.toLatin1().constData());
-#endif
-
-#ifndef QT_NO_THREAD
- // Start query - allow termination at this point, but not outside. We
- // don't want to all termination during event delivery, but we don't
- // want the lookup to prevent the app from quitting (the agent
- // destructor terminates the thread).
- setTerminationEnabled(true);
-#endif
- QHostInfo info = fromName(query->hostName);
-#ifndef QT_NO_THREAD
- setTerminationEnabled(false);
-#endif
-
- int id = query->object->lookupId;
- info.setLookupId(id);
- if (pendingQueryId == id)
- query->object->emitResultsReady(info);
- delete query;
- }
-}
-
-/*!
\enum QHostInfo::HostInfoError
This enum describes the various errors that can occur when trying
@@ -467,4 +402,174 @@ void QHostInfo::setErrorString(const QString &str)
\sa hostName()
*/
+#ifndef QT_NO_THREAD
+QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i)
+{
+ setAutoDelete(true);
+}
+
+// the QHostInfoLookupManager will at some point call this via a QThreadPool
+void QHostInfoRunnable::run()
+{
+ QHostInfoLookupManager *manager = theHostInfoLookupManager();
+ // check aborted
+ if (manager->wasAborted(id)) {
+ manager->lookupFinished(this);
+ return;
+ }
+
+ // check cache
+ // FIXME
+
+ // if not in cache: OS lookup
+ QHostInfo hostInfo = QHostInfoAgent::fromName(toBeLookedUp);
+
+ // save to cache
+ // FIXME
+
+ // check aborted again
+ if (manager->wasAborted(id)) {
+ manager->lookupFinished(this);
+ return;
+ }
+
+ // signal emission
+ hostInfo.setLookupId(id);
+ resultEmitter.emitResultsReady(hostInfo);
+
+ manager->lookupFinished(this);
+
+ // thread goes back to QThreadPool
+}
+
+QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), wasDeleted(false)
+{
+ moveToThread(QCoreApplicationPrivate::mainThread());
+ threadPool.setMaxThreadCount(5); // do 5 DNS lookups in parallel
+}
+
+QHostInfoLookupManager::~QHostInfoLookupManager()
+{
+ wasDeleted = true;
+}
+
+void QHostInfoLookupManager::work()
+{
+ if (wasDeleted)
+ return;
+
+ // goals of this function:
+ // - launch new lookups via the thread pool
+ // - make sure only one lookup per host/IP is in progress
+
+ QMutexLocker locker(&mutex);
+
+ if (!finishedLookups.isEmpty()) {
+ // remove ID from aborted if it is in there
+ for (int i = 0; i < finishedLookups.length(); i++) {
+ abortedLookups.removeAll(finishedLookups.at(i)->id);
+ }
+
+ finishedLookups.clear();
+ }
+
+ if (!postponedLookups.isEmpty()) {
+ // try to start the postponed ones
+
+ QMutableListIterator<QHostInfoRunnable*> iterator(postponedLookups);
+ while (iterator.hasNext()) {
+ QHostInfoRunnable* postponed = iterator.next();
+
+ // check if none of the postponed hostnames is currently running
+ bool alreadyRunning = false;
+ for (int i = 0; i < currentLookups.length(); i++) {
+ if (currentLookups.at(i)->toBeLookedUp == postponed->toBeLookedUp) {
+ alreadyRunning = true;
+ break;
+ }
+ }
+ if (!alreadyRunning) {
+ iterator.remove();
+ scheduledLookups.prepend(postponed); // prepend! we want to finish it ASAP
+ }
+ }
+ }
+
+ if (!scheduledLookups.isEmpty()) {
+ // try to start the new ones
+ QMutableListIterator<QHostInfoRunnable*> iterator(scheduledLookups);
+ while (iterator.hasNext()) {
+ QHostInfoRunnable *scheduled = iterator.next();
+
+ // check if a lookup for this host is already running, then postpone
+ for (int i = 0; i < currentLookups.size(); i++) {
+ if (currentLookups.at(i)->toBeLookedUp == scheduled->toBeLookedUp) {
+ iterator.remove();
+ postponedLookups.append(scheduled);
+ scheduled = 0;
+ break;
+ }
+ }
+
+ if (scheduled && threadPool.tryStart(scheduled)) {
+ // runnable now running in new thread, track this in currentLookups
+ iterator.remove();
+ currentLookups.append(scheduled);
+ } else if (scheduled) {
+ // wanted to start, but could not because thread pool is busy
+ break;
+ } else {
+ // was postponed, continue iterating
+ continue;
+ }
+ };
+ }
+}
+
+// called by QHostInfo
+void QHostInfoLookupManager::scheduleLookup(QHostInfoRunnable *r)
+{
+ if (wasDeleted)
+ return;
+
+ QMutexLocker locker(&this->mutex);
+ scheduledLookups.enqueue(r);
+ work();
+}
+
+// called by QHostInfo
+void QHostInfoLookupManager::abortLookup(int id)
+{
+ if (wasDeleted)
+ return;
+
+ QMutexLocker locker(&this->mutex);
+ if (!abortedLookups.contains(id))
+ abortedLookups.append(id);
+}
+
+// called from QHostInfoRunnable
+bool QHostInfoLookupManager::wasAborted(int id)
+{
+ if (wasDeleted)
+ return true;
+
+ QMutexLocker locker(&this->mutex);
+ return abortedLookups.contains(id);
+}
+
+// called from QHostInfoRunnable
+void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r)
+{
+ if (wasDeleted)
+ return;
+
+ QMutexLocker locker(&this->mutex);
+ currentLookups.removeOne(r);
+ finishedLookups.append(r);
+ work();
+}
+
+#endif // QT_NO_THREAD
+
QT_END_NAMESPACE
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index afd3570..643bb73 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -61,17 +61,17 @@
#include "QtCore/qobject.h"
#include "QtCore/qpointer.h"
-#if !defined QT_NO_THREAD
+#ifndef QT_NO_THREAD
#include "QtCore/qthread.h"
-# define QHostInfoAgentBase QThread
-#else
-# define QHostInfoAgentBase QObject
+#include "QtCore/qthreadpool.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qrunnable.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qqueue.h"
#endif
QT_BEGIN_NAMESPACE
-static const int QHOSTINFO_THREAD_WAIT = 250; // ms
-
class QHostInfoResult : public QObject
{
Q_OBJECT
@@ -79,102 +79,18 @@ public Q_SLOTS:
inline void emitResultsReady(const QHostInfo &info)
{
emit resultsReady(info);
- if (autoDelete)
- delete this;
}
Q_SIGNALS:
- void resultsReady(const QHostInfo &info);
-
-public:
- int lookupId;
- bool autoDelete;
+ void resultsReady(const QHostInfo info);
};
-struct QHostInfoQuery
-{
- inline QHostInfoQuery() : object(0) {}
- inline ~QHostInfoQuery() { delete object; }
- inline QHostInfoQuery(const QString &name, QHostInfoResult *result)
- : hostName(name), object(result) {}
-
- QString hostName;
- QHostInfoResult *object;
-};
-
-class QHostInfoAgent : public QHostInfoAgentBase
+// needs to be QObject because fromName calls tr()
+class QHostInfoAgent : public QObject
{
Q_OBJECT
public:
- inline QHostInfoAgent()
- {
- // There is a chance that there will be two instances of
- // QHostInfoAgent if two threads try to get Q_GLOBAL_STATIC
- // object at the same time. The second object will be deleted
- // immediately before anyone uses it, but we need to be
- // careful about what we do in the constructor.
- static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
- if (done.testAndSetRelaxed(0, 1))
- qAddPostRoutine(staticCleanup);
- moveToThread(QCoreApplicationPrivate::mainThread());
- quit = false;
- pendingQueryId = -1;
- }
- inline ~QHostInfoAgent()
- { cleanup(); }
-
- void run();
static QHostInfo fromName(const QString &hostName);
-
- inline void addHostName(const QString &name, QHostInfoResult *result)
- {
- QMutexLocker locker(&mutex);
- queries << new QHostInfoQuery(name, result);
- cond.wakeOne();
- }
-
- inline void abortLookup(int id)
- {
- QMutexLocker locker(&mutex);
- for (int i = 0; i < queries.size(); ++i) {
- QHostInfoResult *result = queries.at(i)->object;
- if (result->lookupId == id) {
- result->disconnect();
- delete queries.takeAt(i);
- return;
- }
- }
- if (pendingQueryId == id)
- pendingQueryId = -1;
- }
-
- static void staticCleanup();
-
-public Q_SLOTS:
- inline void cleanup()
- {
- {
- QMutexLocker locker(&mutex);
- qDeleteAll(queries);
- queries.clear();
- quit = true;
- cond.wakeOne();
- }
-#ifndef QT_NO_THREAD
- if (!wait(QHOSTINFO_THREAD_WAIT)) {
- terminate();
- // Don't wait forever; see QTBUG-5296.
- wait(QHOSTINFO_THREAD_WAIT);
- }
-#endif
- }
-
-private:
- QList<QHostInfoQuery *> queries;
- QMutex mutex;
- QWaitCondition cond;
- volatile bool quit;
- int pendingQueryId;
};
class QHostInfoPrivate
@@ -194,6 +110,52 @@ public:
int lookupId;
};
+#ifndef QT_NO_THREAD
+// the following classes are used for the (normal) case: We use multiple threads to lookup DNS
+
+class QHostInfoRunnable : public QRunnable
+{
+public:
+ QHostInfoRunnable (QString hn, int i);
+ void run();
+
+ QString toBeLookedUp;
+ int id;
+ QHostInfoResult resultEmitter;
+};
+
+class QHostInfoLookupManager : public QObject
+{
+ Q_OBJECT
+public:
+ QHostInfoLookupManager();
+ ~QHostInfoLookupManager();
+
+ void work();
+
+ // called from QHostInfo
+ void scheduleLookup(QHostInfoRunnable *r);
+ void abortLookup(int id);
+
+ // called from QHostInfoRunnable
+ void lookupFinished(QHostInfoRunnable *r);
+ bool wasAborted(int id);
+
+protected:
+ QList<QHostInfoRunnable*> currentLookups; // in progress
+ QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
+ QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
+ QList<QHostInfoRunnable*> finishedLookups; // recently finished
+ QList<int> abortedLookups; // ids of aborted lookups
+
+ QThreadPool threadPool;
+
+ QMutex mutex;
+
+ bool wasDeleted;
+};
+#endif
+
QT_END_NAMESPACE
#endif // QHOSTINFO_P_H
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index 720aaa5..727a8b0 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -105,11 +105,7 @@ static void resolveLibrary()
#include <qmutex.h>
QMutex qPrivCEMutex;
#endif
-/*
- Performs a blocking call to gethostbyname or getaddrinfo, stores
- the results in a QHostInfo structure and emits the
- resultsReady() signal.
-*/
+
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
#if defined(Q_OS_WINCE)
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 1187c2d..9d545b9 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;
@@ -364,6 +395,9 @@ QGLEngineShaderManager::~QGLEngineShaderManager()
uint QGLEngineShaderManager::getUniformLocation(Uniform id)
{
+ if (!currentShaderProg)
+ return 0;
+
QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
if (uniformLocations.isEmpty())
uniformLocations.fill(GLuint(-1), NumUniforms);
@@ -468,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/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 8ca2fd4..f52ed92 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -583,37 +583,37 @@ 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:
- //
- // | 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 |
- //
- // 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;
- 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();
+ // 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
+ //
+ // This results in the Projection matrix below, which is multiplied by the painter's
+ // transformation matrix, as shown below:
+ //
+ // 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
+
+ const GLfloat wfactor = 2.0f / width;
+ const GLfloat hfactor = -2.0f / height;
+
+ pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13();
+ pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23();
+ pmvMatrix[2][0] = (wfactor * transform.dx() ) - transform.m33();
+ pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13();
+ pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23();
+ pmvMatrix[2][1] = (hfactor * transform.dy() ) + transform.m33();
+ 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...
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 33ce24d..f1ec6e6 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -254,7 +254,7 @@ public:
GLfloat staticVertexCoordinateArray[8];
GLfloat staticTextureCoordinateArray[8];
- GLfloat pmvMatrix[4][4];
+ GLfloat pmvMatrix[3][3];
QGLEngineShaderManager* shaderManager;
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/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 &parameters, 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/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/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 +=