From ab56759cefbcf2072ac777f0d897e561f5a3c8af Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 1 Apr 2009 13:53:02 +0200 Subject: don't display warning message when calling checksdk -list checksdk -list now displays the list of available SDK without yielding the warning message "No SDK specified: Defaulting to ...". Reviewed-by: mauricek --- tools/checksdk/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/checksdk/main.cpp b/tools/checksdk/main.cpp index 1d4b616..717f5c9 100644 --- a/tools/checksdk/main.cpp +++ b/tools/checksdk/main.cpp @@ -97,12 +97,6 @@ int main(int argc, char **argv) } } - // Check for SDK Name, otherwise use Windows Mobile as default - if (sdkName.isEmpty()) { - qWarning("No SDK specified: Defaulting to Windows Mobile 5.0 Pocket PC SDK"); - sdkName = QString::fromLatin1("Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"); - } - CeSdkHandler handler; if (!handler.parse()) { qWarning("Could not find any installed SDK, aborting!"); @@ -118,6 +112,12 @@ int main(int argc, char **argv) return 0; } + // Check for SDK Name, otherwise use Windows Mobile as default + if (sdkName.isEmpty()) { + qWarning("No SDK specified: Defaulting to Windows Mobile 5.0 Pocket PC SDK"); + sdkName = QString::fromLatin1("Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"); + } + // finally find the given SDK and prompt out the environment to be set for (QList::iterator it = list.begin(); it != list.end(); ++it ) { if (sdkName == it->name()) { -- cgit v0.12 From 38b5bff2fab59e965aba59b4f121a7c8945e4d75 Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Mon, 6 Apr 2009 12:39:13 +0200 Subject: Doc - Clarified that button style on X11 platforms may depend on the desktop environment. Task-number: 250338 Reviewed-by: Jens Bache-Wiig --- src/gui/widgets/qdialogbuttonbox.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 246da95..4a95292 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -752,7 +752,8 @@ QDialogButtonBox::~QDialogButtonBox() \value KdeLayout Use a policy appropriate for applications on KDE. \value GnomeLayout Use a policy appropriate for applications on GNOME. - The button layout is specified by the \l{style()}{current style}. + The button layout is specified by the \l{style()}{current style}. However, + on the X11 platform, it may be influenced by the desktop environment. */ /*! -- cgit v0.12 From 1a125061f201bb7ee746f1eddc0604cd85a6545c Mon Sep 17 00:00:00 2001 From: jasplin Date: Mon, 6 Apr 2009 12:43:53 +0200 Subject: Corrected typo. Reviewed-by: jasplin --- dist/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/README b/dist/README index 110be1c..38b3a1c 100644 --- a/dist/README +++ b/dist/README @@ -114,7 +114,7 @@ HOW TO REPORT A BUG If you think you have found a bug in Qt, we would like to hear about it so that we can fix it. Before reporting a bug, please check http://qtsoftware.com/developer/faqs/ and -http://qtsoftware.com/products/appdev/platform/platforms/ to see if the to see if +http://qtsoftware.com/products/appdev/platform/platforms/ to see if the issue is already known. Always include the following information in your bug report: the name -- cgit v0.12 From 73f5131793d52d93b18a40d36599e063f18246e9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 6 Apr 2009 11:18:34 +0200 Subject: Install the animation.mng file. Otherwise, for people who install Qt (everyone outside Nokia), the animation file isn't present. Reviewed-by: Trust Me BT: yes --- examples/widgets/movie/movie.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/widgets/movie/movie.pro b/examples/widgets/movie/movie.pro index b5f0a7a..1c7cbae 100644 --- a/examples/widgets/movie/movie.pro +++ b/examples/widgets/movie/movie.pro @@ -4,6 +4,6 @@ SOURCES = main.cpp \ # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/movie -sources.files = $$SOURCES $$HEADERS $$RESOURCES movie.pro movies +sources.files = $$SOURCES $$HEADERS $$RESOURCES movie.pro animation.mng sources.path = $$[QT_INSTALL_EXAMPLES]/widgets/movie INSTALLS += target sources -- cgit v0.12 From 5bb504a78cad5e38cd522785a37898f4e88cd272 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 6 Apr 2009 13:16:39 +0200 Subject: Rename these files to have lowercase .txt extension. mkdist doesn't case-insensitive comparison. Reviewed-by: TrustMe BT: yes --- FAQ | 18 ------------------ FAQ.txt | 18 ++++++++++++++++++ LGPL_EXCEPTION.TXT | 3 --- LGPL_EXCEPTION.txt | 3 +++ 4 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 FAQ create mode 100644 FAQ.txt delete mode 100644 LGPL_EXCEPTION.TXT create mode 100644 LGPL_EXCEPTION.txt diff --git a/FAQ b/FAQ deleted file mode 100644 index c243e5c..0000000 --- a/FAQ +++ /dev/null @@ -1,18 +0,0 @@ -This is a list of Frequently Asked Questions regarding Qt Release 4.5.0. - -Q: I'm using a Unix system and I downloaded the Zip package. However, when I try -to run the configure script, I get the following error message: -"bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory" -A: The problem here is converting files from Windows style line endings (CRLF) -to Unix style line endings (LF). To avoid this problem, uncompress the file -again and give the option "-a" to unzip, which will then add the correct line -endings. - -Q: I'm running Windows XP and I downloaded the qt-win-eval-4.5.0-vs2008.exe -version of Qt. However, when I try to run the examples I get an error saying: -"The application failed to start because the application configuration is -incorrect. Reinstalling the application may fix this problem.". I reinstalled -the package but the error persists. What am I doing wrong? -A: The problem is an incorrect version of the CRT. Visual studio requires CRT90 -while Windows XP comes with CRT80. To solve this problem, please install the -2008 CRT redistributable package from Microsoft. diff --git a/FAQ.txt b/FAQ.txt new file mode 100644 index 0000000..c243e5c --- /dev/null +++ b/FAQ.txt @@ -0,0 +1,18 @@ +This is a list of Frequently Asked Questions regarding Qt Release 4.5.0. + +Q: I'm using a Unix system and I downloaded the Zip package. However, when I try +to run the configure script, I get the following error message: +"bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory" +A: The problem here is converting files from Windows style line endings (CRLF) +to Unix style line endings (LF). To avoid this problem, uncompress the file +again and give the option "-a" to unzip, which will then add the correct line +endings. + +Q: I'm running Windows XP and I downloaded the qt-win-eval-4.5.0-vs2008.exe +version of Qt. However, when I try to run the examples I get an error saying: +"The application failed to start because the application configuration is +incorrect. Reinstalling the application may fix this problem.". I reinstalled +the package but the error persists. What am I doing wrong? +A: The problem is an incorrect version of the CRT. Visual studio requires CRT90 +while Windows XP comes with CRT80. To solve this problem, please install the +2008 CRT redistributable package from Microsoft. diff --git a/LGPL_EXCEPTION.TXT b/LGPL_EXCEPTION.TXT deleted file mode 100644 index 8d0f85e..0000000 --- a/LGPL_EXCEPTION.TXT +++ /dev/null @@ -1,3 +0,0 @@ -Nokia Qt LGPL Exception version 1.0 - -As a special exception to the GNU Lesser General Public License version 2.1, the object code form of a "work that uses the Library" may incorporate material from a header file that is part of the Library. You may distribute such object code under terms of your choice, provided that the incorporated material (i) does not exceed more than 5% of the total size of the Library; and (ii) is limited to numerical parameters, data structure layouts, accessors, macros, inline functions and templates. \ No newline at end of file diff --git a/LGPL_EXCEPTION.txt b/LGPL_EXCEPTION.txt new file mode 100644 index 0000000..8d0f85e --- /dev/null +++ b/LGPL_EXCEPTION.txt @@ -0,0 +1,3 @@ +Nokia Qt LGPL Exception version 1.0 + +As a special exception to the GNU Lesser General Public License version 2.1, the object code form of a "work that uses the Library" may incorporate material from a header file that is part of the Library. You may distribute such object code under terms of your choice, provided that the incorporated material (i) does not exceed more than 5% of the total size of the Library; and (ii) is limited to numerical parameters, data structure layouts, accessors, macros, inline functions and templates. \ No newline at end of file -- cgit v0.12 From cf65dea821a2ba796bb1f32c80de6b9db224dff5 Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Mon, 6 Apr 2009 13:15:00 +0200 Subject: Doc - Mentioned what the default filters are for QFileSystemModel::filter(). Task-number: 250285 Reviewed-by: Benjamin Poulain --- src/gui/dialogs/qfilesystemmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index c7b3137..012d3a1 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -1430,7 +1430,10 @@ void QFileSystemModel::setFilter(QDir::Filters filters) } /*! - Returns the filter specification for the directory model. + Returns the filter specified for the directory model. + + If a filter has not been set, the default filter is QDir::AllEntries | + QDir::NoDotAndDotDot | QDir::AllDirs. \sa QDir::Filters */ -- cgit v0.12 From e27743bdeda7aa3cb42f2d81a521121f8ee04eae Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Wed, 25 Feb 2009 12:18:28 +0100 Subject: Fixes: Optimize QGraphicsView::itemUpdated. Task: - RevBy: Andreas AutoTest: - Details: Accumulate the parentToItem transform as we iterate instead of creating it from bottom-up each time. --- src/gui/graphicsview/qgraphicsview.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2f7f57a..9b0e12d 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -804,10 +804,17 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) if (item->isClipped()) { // Minimize unnecessary redraw. QGraphicsItem *p = item; + QTransform xform; + QGraphicsItem *lastTransformItem = 0; while ((p = p->d_ptr->parent)) { if (p->flags() & QGraphicsItem::ItemClipsChildrenToShape) { - updateRect &= p->itemTransform(item).mapRect(p->boundingRect()); - if (updateRect.isNull()) + if (!lastTransformItem) + xform = item->itemTransform(p); + else + xform *= lastTransformItem->itemTransform(p); + lastTransformItem = p; + updateRect &= xform.inverted().mapRect(p->boundingRect()); + if (updateRect.isEmpty()) return; } @@ -815,7 +822,7 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) break; } - if (updateRect.isNull()) + if (updateRect.isEmpty()) return; } -- cgit v0.12 From be6be8c73929f2ddee9a02f59db05c3ba453a63e Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 26 Feb 2009 14:49:47 +0100 Subject: Fixes: Optimize QGraphicsViewPrivate::updateRect()/updateRegion(). Details: Those cut-offs are extremely important. After few seconds interaction with the iphone demo, updateRect() was called approx. 3000 times with an empty rect. Then imagine what happens when having e.g. FullViewportUpdate. We do q->viewport()->update() JUST FOR FUN! --- src/gui/graphicsview/qgraphicsview.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 9b0e12d..aa5f069 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -928,6 +928,9 @@ void QGraphicsViewPrivate::updateAll() void QGraphicsViewPrivate::updateRegion(const QRegion &r) { + if (r.isEmpty()) + return; + Q_Q(QGraphicsView); // Rect intersects viewport - update everything? @@ -976,6 +979,9 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) void QGraphicsViewPrivate::updateRect(const QRect &r) { + if (r.isEmpty()) + return; + Q_Q(QGraphicsView); // Rect intersects viewport - update everything? -- cgit v0.12 From e9fa8ba1ad0b0b2d3363fb33635071677f42b983 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 26 Feb 2009 15:00:08 +0100 Subject: Fixes: Cleanup calls to QGraphicsViewPrivate::updateRect()/updateRegion() Details: Checking for QRect::isNull() was wrong in the first place, and checking for isEmpty()/isNull() is overhead after 4a491a84aeba68279927597a261522dcc23bb3ff. --- src/gui/graphicsview/qgraphicsview.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index aa5f069..b92c886 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -829,17 +829,10 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) // Map the rect to view coordinates. QRect vr = viewport->rect(); - if (!item->d_ptr->hasBoundingRegionGranularity) { - QRect r = mapToViewRect(item, updateRect) & vr; - if (r.isNull()) - return; - this->updateRect(r); - } else { - QRegion r = mapToViewRegion(item, updateRect) & vr; - if (r.isEmpty()) - return; - updateRegion(r); - } + if (!item->d_ptr->hasBoundingRegionGranularity) + this->updateRect(mapToViewRect(item, updateRect) & vr); + else + updateRegion(mapToViewRegion(item, updateRect) & vr); } void QGraphicsViewPrivate::updateLater() @@ -863,9 +856,7 @@ void QGraphicsViewPrivate::_q_updateLaterSlot() for (int i = 0; i < dirtyItems.size(); ++i) { const QGraphicsItem *item = dirtyItems.at(i); QTransform x = item->sceneTransform() * viewTransform; - QRect viewRect = x.mapRect(item->boundingRect()).toAlignedRect() & vr; - if (!viewRect.isNull()) - updateRect(viewRect); + updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); } dirtyRectCount += dirtyRects.size(); -- cgit v0.12 From 8a2ebc96220f50be3a9c382c32d7eaab89921ff7 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 26 Feb 2009 15:47:04 +0100 Subject: Fixes: Use QRect::isEmpty() rather than isNull() if possible. RevBy: Andreas Details: Note that isNull() implies isEmpty(), but it only catches the cases where width and height is 0. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 83a7e67..b982393 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3757,7 +3757,7 @@ bool QGraphicsItemPrivate::isProxyWidget() const */ void QGraphicsItem::update(const QRectF &rect) { - if (d_ptr->dirty) + if (d_ptr->dirty || (rect.isEmpty() && !rect.isNull())) return; if (d_ptr->scene && isVisible()) { if (CacheMode(d_ptr->cacheMode) != NoCache) { diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ff46e2e..9b06945 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3455,7 +3455,7 @@ QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const void QGraphicsScene::update(const QRectF &rect) { Q_D(QGraphicsScene); - if (d->updateAll) + if (d->updateAll || (rect.isEmpty() && !rect.isNull())) return; // Check if anyone's connected; if not, we can send updates directly to diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index b92c886..f88918f 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -862,7 +862,7 @@ void QGraphicsViewPrivate::_q_updateLaterSlot() dirtyRectCount += dirtyRects.size(); bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate; - if ((dirtyRectCount > 0 || !dirtyBoundingRect.isNull()) && !fullUpdatePending && !noUpdate) { + if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) { if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) { @@ -3284,7 +3284,7 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event) } // Update old rubberband - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isNull()) { + if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isEmpty()) { if (d->viewportUpdateMode != FullViewportUpdate) viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); else @@ -3466,7 +3466,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) QPainter painter(viewport()); QTransform original = painter.worldTransform(); #ifndef QT_NO_RUBBERBAND - if (d->rubberBanding && !d->rubberBandRect.isNull()) + if (d->rubberBanding && !d->rubberBandRect.isEmpty()) painter.save(); #endif // Set up render hints @@ -3561,7 +3561,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) #ifndef QT_NO_RUBBERBAND // Rubberband - if (d->rubberBanding && !d->rubberBandRect.isNull()) { + if (d->rubberBanding && !d->rubberBandRect.isEmpty()) { painter.restore(); QStyleOptionRubberBand option; option.initFrom(viewport()); @@ -3645,7 +3645,7 @@ void QGraphicsView::scrollContentsBy(int dx, int dy) #ifndef QT_NO_RUBBERBAND // Update old rubberband - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isNull()) { + if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isEmpty()) { if (d->viewportUpdateMode != FullViewportUpdate) viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); else -- cgit v0.12 From eda77b7c410a59d1b77c263994679452613d9d0b Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 27 Feb 2009 16:00:55 +0100 Subject: Fixes: Small optimization: reduce calls to QTransform::type(). Task: none RevBy: Ariya Hidayat AutoTest: Still pass. Details: QTransform::type() is cached, so only the first call to it should be expensive. However, it is not inlined so there's an overhead involved (especially when these functions are called a gazillion times). --- src/gui/painting/qtransform.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index c70208c..c120143 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1222,7 +1222,8 @@ static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &pol */ QPolygonF QTransform::map(const QPolygonF &a) const { - if (type() >= QTransform::TxProject) + TransformationType t = type(); + if (t >= QTransform::TxProject) return mapProjective(*this, a); int size = a.size(); @@ -1231,7 +1232,6 @@ QPolygonF QTransform::map(const QPolygonF &a) const const QPointF *da = a.constData(); QPointF *dp = p.data(); - TransformationType t = type(); for(i = 0; i < size; ++i) { MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp); } @@ -1249,7 +1249,8 @@ QPolygonF QTransform::map(const QPolygonF &a) const */ QPolygon QTransform::map(const QPolygon &a) const { - if (type() >= QTransform::TxProject) + TransformationType t = type(); + if (t >= QTransform::TxProject) return mapProjective(*this, QPolygonF(a)).toPolygon(); int size = a.size(); @@ -1258,7 +1259,6 @@ QPolygon QTransform::map(const QPolygon &a) const const QPoint *da = a.constData(); QPoint *dp = p.data(); - TransformationType t = type(); for(i = 0; i < size; ++i) { qreal nx = 0, ny = 0; MAP(da[i].xp, da[i].yp, nx, ny); @@ -2061,10 +2061,11 @@ QTransform::operator QVariant() const Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale) { - if (transform.type() <= QTransform::TxTranslate) { + const QTransform::TransformationType type = transform.type(); + if (type <= QTransform::TxTranslate) { *scale = 1; return true; - } else if (transform.type() == QTransform::TxScale) { + } else if (type == QTransform::TxScale) { const qreal xScale = qAbs(transform.m11()); const qreal yScale = qAbs(transform.m22()); *scale = qMax(xScale, yScale); @@ -2076,7 +2077,7 @@ bool qt_scaleForTransform(const QTransform &transform, qreal *scale) const qreal yScale = transform.m12() * transform.m12() + transform.m22() * transform.m22(); *scale = qSqrt(qMax(xScale, yScale)); - return transform.type() == QTransform::TxRotate && qFuzzyCompare(xScale, yScale); + return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale); } QT_END_NAMESPACE -- cgit v0.12 From b4456f8775c36bcb2ceef9ca1a00c7765f1d2735 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 27 Feb 2009 18:10:08 +0100 Subject: Fixes: Get rid of a gazillion calls to QTransform::operator*=. Details: Be a little bit smarter before doing *= :) --- src/gui/graphicsview/qgraphicsitem.cpp | 38 +++++++++++++++++++++------------ src/gui/graphicsview/qgraphicsscene.cpp | 5 +++-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b982393..bb95543 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2511,10 +2511,10 @@ QTransform QGraphicsItem::sceneTransform() const QTransform m; if (d_ptr->hasTransform) { m = transform(); - m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); - } else { - // ### ? QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()) - m.translate(d_ptr->pos.x(), d_ptr->pos.y()); + if (!d_ptr->pos.isNull()) + m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); + } else if (!d_ptr->pos.isNull()) { + m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); } // Combine with parent and add to cache. @@ -2639,6 +2639,8 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co if (ok) *ok = true; const QPointF &itemPos = d_ptr->pos; + if (itemPos.isNull()) + return d_ptr->hasTransform ? transform() : QTransform(); if (d_ptr->hasTransform) return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y()); return QTransform::fromTranslate(itemPos.x(), itemPos.y()); @@ -2649,7 +2651,8 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co const QPointF &otherPos = other->d_ptr->pos; if (other->d_ptr->hasTransform) { QTransform otherToParent = other->transform(); - otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y()); + if (!otherPos.isNull()) + otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y()); return otherToParent.inverted(ok); } else { if (ok) @@ -2674,11 +2677,11 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y()); if (hasTr) - itemToParent = transform() * itemToParent; + itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent; QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y()); if (otherHasTr) - otherToParent = other->transform() * otherToParent; + otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent; return itemToParent * otherToParent.inverted(ok); } @@ -2718,7 +2721,8 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co const QGraphicsItemPrivate *pd = p->d_ptr; if (pd->hasTransform) x *= p->transform(); - x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y()); + if (!pd->pos.isNull()) + x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y()); } while ((p = p->d_ptr->parent) && p != root); if (parentOfOther) return x.inverted(ok); @@ -2995,7 +2999,9 @@ QRectF QGraphicsItem::childrenBoundingRect() const QRectF childRect; foreach (QGraphicsItem *child, children()) { QPointF childPos = child->pos(); - QTransform matrix = child->transform() * QTransform::fromTranslate(childPos.x(), childPos.y()); + QTransform matrix = child->transform(); + if (!childPos.isNull()) + matrix *= QTransform::fromTranslate(childPos.x(), childPos.y()); childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect()); } return childRect; @@ -8544,13 +8550,17 @@ void QGraphicsItemGroup::addToGroup(QGraphicsItem *item) QTransform oldSceneMatrix = item->sceneTransform(); item->setPos(mapFromItem(item, 0, 0)); item->setParentItem(this); - item->setTransform(oldSceneMatrix - * sceneTransform().inverted() - * QTransform::fromTranslate(-item->x(), -item->y())); + QTransform newItemTransform(oldSceneMatrix); + newItemTransform *= sceneTransform().inverted(); + if (!item->pos().isNull()) + newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y()); + item->setTransform(newItemTransform); item->d_func()->setIsMemberOfGroup(true); prepareGeometryChange(); - d->itemsBoundingRect |= (item->transform() * QTransform::fromTranslate(item->x(), item->y())) - .mapRect(item->boundingRect() | item->childrenBoundingRect()); + QTransform itemTransform(item->transform()); + if (!item->pos().isNull()) + itemTransform *= QTransform::fromTranslate(item->x(), item->y()); + d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect()); update(); } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9b06945..b509507 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4772,8 +4772,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) { // Construct an item-to-pixmap transform. QPointF p = deviceRect.topLeft(); - QTransform itemToPixmap = QTransform::fromTranslate(-p.x(), -p.y()); - itemToPixmap = painter->worldTransform() * itemToPixmap; + QTransform itemToPixmap = painter->worldTransform(); + if (!p.isNull()) + itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y()); // Map the item's logical expose to pixmap coordinates. QRegion pixmapExposed = scrollExposure; -- cgit v0.12 From fac3c7b73ba2c6b39332445ae00b2fe26a578913 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 2 Mar 2009 10:34:50 +0100 Subject: Fixes: Optimization: Important cut-offs for QTransform. Task: none RevBy: Samuel AutoTest: Still pass Details: Please do not perform (potentially expensive) calculations just for fun :) --- src/gui/painting/qtransform.cpp | 29 ++++++++++++++++++++++++++--- src/gui/painting/qtransform.h | 8 ++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index c120143..fa808d0 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -399,6 +399,9 @@ QTransform QTransform::inverted(bool *invertible) const */ QTransform & QTransform::translate(qreal dx, qreal dy) { + if (dx == 0 && dy == 0) + return *this; + switch(type()) { case TxNone: affine._dx = dx; @@ -435,7 +438,10 @@ QTransform & QTransform::translate(qreal dx, qreal dy) QTransform QTransform::fromTranslate(qreal dx, qreal dy) { QTransform transform(1, 0, 0, 1, dx, dy); - transform.m_dirty = TxTranslate; + if (dx == 0 && dy == 0) + transform.m_dirty = TxNone; + else + transform.m_dirty = TxTranslate; return transform; } @@ -447,6 +453,9 @@ QTransform QTransform::fromTranslate(qreal dx, qreal dy) */ QTransform & QTransform::scale(qreal sx, qreal sy) { + if (sx == 1 && sy == 1) + return *this; + switch(type()) { case TxNone: case TxTranslate: @@ -481,7 +490,10 @@ QTransform & QTransform::scale(qreal sx, qreal sy) QTransform QTransform::fromScale(qreal sx, qreal sy) { QTransform transform(sx, 0, 0, sy, 0, 0); - transform.m_dirty = TxScale; + if (sx == 1 && sy == 1) + transform.m_dirty = TxNone; + else + transform.m_dirty = TxScale; return transform; } @@ -544,6 +556,9 @@ const qreal inv_dist_to_plane = 1. / 1024.; */ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) { + if (a == 0) + return *this; + qreal sina = 0; qreal cosa = 0; if (a == 90. || a == -270.) @@ -715,7 +730,15 @@ bool QTransform::operator!=(const QTransform &o) const */ QTransform & QTransform::operator*=(const QTransform &o) { - TransformationType t = qMax(type(), o.type()); + const TransformationType otherType = o.type(); + if (otherType == TxNone) + return *this; + + const TransformationType thisType = type(); + if (thisType == TxNone) + return operator=(o); + + TransformationType t = qMax(thisType, otherType); switch(t) { case TxNone: break; diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index de7ebcd..c76409b 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -257,6 +257,8 @@ inline qreal QTransform::dy() const inline QTransform &QTransform::operator*=(qreal num) { + if (num == 1.) + return *this; affine._m11 *= num; affine._m12 *= num; m_13 *= num; @@ -271,11 +273,15 @@ inline QTransform &QTransform::operator*=(qreal num) } inline QTransform &QTransform::operator/=(qreal div) { + if (div == 0) + return *this; div = 1/div; return operator*=(div); } inline QTransform &QTransform::operator+=(qreal num) { + if (num == 0) + return *this; affine._m11 += num; affine._m12 += num; m_13 += num; @@ -290,6 +296,8 @@ inline QTransform &QTransform::operator+=(qreal num) } inline QTransform &QTransform::operator-=(qreal num) { + if (num == 0) + return *this; affine._m11 -= num; affine._m12 -= num; m_13 -= num; -- cgit v0.12 From ab130a0019fadeff4622778ca9f8b3e630da14da Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 2 Mar 2009 16:22:20 +0100 Subject: Fixes: Speed up QGrahicsItemPrivate::effectiveOpacity(). RevBy: Andreas AutoTest: tst_QGraphicsItem::opacity still passes --- src/gui/graphicsview/qgraphicsitem.cpp | 12 +++++++++++- src/gui/graphicsview/qgraphicsitem_p.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index bb95543..cda1bd1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1862,6 +1862,9 @@ qreal QGraphicsItem::opacity() const */ qreal QGraphicsItem::effectiveOpacity() const { + if (!d_ptr->hasEffectiveOpacity) + return qreal(1.0); + QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity); return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble()); } @@ -3680,7 +3683,14 @@ void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity) } // Set this item's resolved opacity. - setExtra(ExtraEffectiveOpacity, myEffectiveOpacity); + if (qFuzzyCompare(myEffectiveOpacity, qreal(1.0))) { + // Opaque, unset effective opacity. + hasEffectiveOpacity = 0; + unsetExtra(ExtraEffectiveOpacity); + } else { + hasEffectiveOpacity = 1; + setExtra(ExtraEffectiveOpacity, myEffectiveOpacity); + } // Resolve children always. for (int i = 0; i < children.size(); ++i) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 07f6958..98fe6ed 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -133,6 +133,7 @@ public: hasBoundingRegionGranularity(0), flags(0), hasOpacity(0), + hasEffectiveOpacity(0), isWidget(0), dirty(0), dirtyChildren(0), @@ -262,6 +263,7 @@ public: // New 32 bytes quint32 hasOpacity : 1; + quint32 hasEffectiveOpacity : 1; quint32 isWidget : 1; quint32 dirty : 1; quint32 dirtyChildren : 1; -- cgit v0.12 From 7f50f45da0ad4a9eedd3ad7d8a82f719f7f8dd73 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Tue, 3 Mar 2009 13:06:05 +0100 Subject: Fixes: Optimize: QGraphicsItem::clipPath. RevBy: Andreas AutoTest: Still pass --- src/gui/graphicsview/qgraphicsitem.cpp | 46 +++++++++++----------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index cda1bd1..8b37648 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3143,48 +3143,32 @@ QPainterPath QGraphicsItem::clipPath() const // Start with the item's bounding rect. clip.addRect(boundingRect()); - bool clipAway = false; if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // Make list of parents up to the farthest ancestor that clips its - // children to its shape. - QVarLengthArray clippingAncestors; - const QGraphicsItem *parent = parentItem(); - const QGraphicsItem *clipOwner = 0; - do { + const QGraphicsItem *parent = this; + const QGraphicsItem *lastParent = this; + + // Intersect any in-between clips starting at the top and moving downwards. + while ((parent = parent->d_ptr->parent)) { if (parent->d_ptr->flags & ItemClipsChildrenToShape) { - clippingAncestors.append(parent); - clipOwner = parent; + // Map clip to the current parent and intersect with its shape. + clip = (lastParent->itemTransform(parent).map(clip)).intersected(parent->shape()); + if (clip.isEmpty()) + return clip; + lastParent = parent; } - } while ((parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) && (parent = parent->parentItem())); - - // Start with the topmost clip. - QPainterPath parentClip = clipOwner->shape(); - // Intersect any in-between clips starting at the bottom and moving - // upwards. - for (int i = clippingAncestors.size() - 2; i >= 0; --i) { - const QGraphicsItem *item = clippingAncestors[i]; - // ### what if itemtransform fails - if (clipOwner) - parentClip = clipOwner->itemTransform(item).map(parentClip); - parentClip = parentClip.intersected(item->shape()); - if (parentClip.isEmpty()) { - clip = parentClip; - clipAway = true; + if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) break; - } - clipOwner = item; } - if (!clipAway) { + if (lastParent != this) { + // Map clip back to the item's transform. // ### what if itemtransform fails - clip = clip.intersected(clipOwner->itemTransform(this).map(parentClip)); - if (clip.isEmpty()) - clipAway = true; + clip = lastParent->itemTransform(this).map(clip); } } - if (!clipAway && d->flags & ItemClipsToShape) + if (d->flags & ItemClipsToShape) clip = clip.intersected(shape()); return clip; -- cgit v0.12 From b67dffcccea9166918ac93c281d87fd5eb3baf84 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Tue, 3 Mar 2009 13:30:33 +0100 Subject: Fixes: Small optimization in QGraphicsItem::clipPath(). RevBy: Andreas Details: Use QPainterPath::addRect() rather than addPolygon() and closeSubPath(). --- src/gui/graphicsview/qgraphicsitem.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 8b37648..fa77fd9 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3259,8 +3259,8 @@ bool QGraphicsItem::collidesWithPath(const QPainterPath &path, Qt::ItemSelection return false; } - QRectF rectA = _q_adjustedRect(boundingRect()); - QRectF rectB = _q_adjustedRect(path.controlPointRect()); + const QRectF rectA = _q_adjustedRect(boundingRect()); + const QRectF rectB = _q_adjustedRect(path.controlPointRect()); if (!rectA.intersects(rectB)) { // This we can determine efficiently. If the two rects neither // intersect nor contain eachother, then the two items do not collide. @@ -3269,12 +3269,11 @@ bool QGraphicsItem::collidesWithPath(const QPainterPath &path, Qt::ItemSelection // For further testing, we need this item's shape or bounding rect. QPainterPath thisShape; - if (mode == Qt::IntersectsItemShape || mode == Qt::ContainsItemShape) { + if (mode == Qt::IntersectsItemShape || mode == Qt::ContainsItemShape) thisShape = (isClipped() && !d_ptr->localCollisionHack) ? clipPath() : shape(); - } else { - thisShape.addPolygon(_q_adjustedRect(boundingRect())); - thisShape.closeSubpath(); - } + else + thisShape.addRect(rectA); + if (thisShape == QPainterPath()) { // Empty shape? No collision. return false; -- cgit v0.12 From d74f1a91b05b943c1a8ae7847de6ee50b2093b89 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 3 Mar 2009 17:08:30 +0100 Subject: Fixes: Be a bit more smarter when calling setGeometry from itemChange RevBy: bnilsen AutoTest: Bench Details : if we come from setPosHelper (so itemChange) we don't need to do all the stuff regarding the size in setGeometry because the size doesn't change. I remove two calls to fullUpdateHelper and update() because prepareGeometryChange already call updateHelper and setPosHelper call fullUpdaterHelper too so we don't need to call them inside setGeometry. We can only call prepareGeometryChange only if we don't come from setPos. --- src/gui/graphicsview/qgraphicsitem.cpp | 6 +-- src/gui/graphicsview/qgraphicsitem_p.h | 2 +- src/gui/graphicsview/qgraphicswidget.cpp | 58 ++++++++++++--------- src/gui/graphicsview/qgraphicswidget_p.h | 2 + .../benchmarks/qgraphicswidget/qgraphicswidget.pro | 6 +++ .../qgraphicswidget/tst_qgraphicswidget.cpp | 60 ++++++++++++++++++++++ 6 files changed, 105 insertions(+), 29 deletions(-) create mode 100644 tests/benchmarks/qgraphicswidget/qgraphicswidget.pro create mode 100644 tests/benchmarks/qgraphicswidget/tst_qgraphicswidget.cpp diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fa77fd9..443cc8c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2352,7 +2352,7 @@ QPointF QGraphicsItem::scenePos() const the item is also updated; otherwise it is not updated before and after the change. */ -void QGraphicsItemPrivate::setPosHelper(const QPointF &pos, bool update) +void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) { Q_Q(QGraphicsItem); if (this->pos == pos) @@ -2364,7 +2364,7 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos, bool update) return; // Update and repositition. - if (scene && update) { + if (scene) { fullUpdateHelper(true); q->prepareGeometryChange(); } @@ -2387,7 +2387,7 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos, bool update) */ void QGraphicsItem::setPos(const QPointF &pos) { - d_ptr->setPosHelper(pos, /* update = */ true); + d_ptr->setPosHelper(pos); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 98fe6ed..7deae52 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -158,7 +158,7 @@ public: virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; static bool movableAncestorIsSelected(const QGraphicsItem *item); - void setPosHelper(const QPointF &pos, bool update); + void setPosHelper(const QPointF &pos); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); void updateHelper(const QRectF &rect = QRectF(), bool force = false); diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 64ec0e7..7f02fb9 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -366,32 +366,33 @@ void QGraphicsWidget::resize(const QSizeF &size) void QGraphicsWidget::setGeometry(const QRectF &rect) { QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func(); - const QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr; - setAttribute(Qt::WA_Resized); - QRectF newGeom = rect; - newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize)) - .boundedTo(effectiveSizeHint(Qt::MaximumSize))); - if (newGeom == d->geom) - return; - - // Update and prepare to change the geometry (remove from index). - if (wd->scene) { - if (rect.topLeft() != d->geom.topLeft()) - wd->fullUpdateHelper(true); - else - update(); - } - prepareGeometryChange(); - - // setPos triggers ItemPositionChange, which can adjust position + QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr; + QRectF newGeom; QPointF oldPos = d->geom.topLeft(); - wd->inSetGeometry = 1; - wd->setPosHelper(newGeom.topLeft(), /* update = */ false); - wd->inSetGeometry = 0; - newGeom.moveTopLeft(pos()); - - if (newGeom == d->geom) - return; + if (!wd->inSetPos) { + setAttribute(Qt::WA_Resized); + newGeom = rect; + newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize)) + .boundedTo(effectiveSizeHint(Qt::MaximumSize))); + if (newGeom == d->geom) + return; + + // setPos triggers ItemPositionChange, which can adjust position + wd->inSetGeometry = 1; + wd->setPosHelper(newGeom.topLeft()); + wd->inSetGeometry = 0; + newGeom.moveTopLeft(pos()); + + if (newGeom == d->geom) + return; + + // Update and prepare to change the geometry (remove from index) if the size has changed. + if (wd->scene) { + if (rect.topLeft() == d->geom.topLeft()) { + prepareGeometryChange(); + } + } + } // Update the layout item geometry bool moved = oldPos != pos(); @@ -401,6 +402,11 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) event.setOldPos(oldPos); event.setNewPos(pos()); QApplication::sendEvent(this, &event); + if (wd->inSetPos) { + //set the new pos + d->geom.moveTopLeft(pos()); + return; + } } QSizeF oldSize = size(); QGraphicsLayoutItem::setGeometry(newGeom); @@ -1016,9 +1022,11 @@ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant & break; case ItemPositionHasChanged: if (!d->inSetGeometry) { + d->inSetPos = 1; // Ensure setGeometry is called (avoid recursion when setPos is // called from within setGeometry). setGeometry(QRectF(pos(), size())); + d->inSetPos = 0 ; } break; case ItemParentChange: { diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h index 455a129..53eaa31 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.h +++ b/src/gui/graphicsview/qgraphicswidget_p.h @@ -86,6 +86,7 @@ public: inheritedFontResolveMask(0), inSetGeometry(0), polished(0), + inSetPos(0), focusPolicy(Qt::NoFocus), focusNext(0), focusPrev(0), @@ -195,6 +196,7 @@ public: quint32 attributes : 10; quint32 inSetGeometry : 1; quint32 polished: 1; + quint32 inSetPos : 1; // Focus Qt::FocusPolicy focusPolicy; diff --git a/tests/benchmarks/qgraphicswidget/qgraphicswidget.pro b/tests/benchmarks/qgraphicswidget/qgraphicswidget.pro new file mode 100644 index 0000000..f1ec54e --- /dev/null +++ b/tests/benchmarks/qgraphicswidget/qgraphicswidget.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qgraphicswidget +TEMPLATE = app +# Input +SOURCES += tst_qgraphicswidget.cpp diff --git a/tests/benchmarks/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/benchmarks/qgraphicswidget/tst_qgraphicswidget.cpp new file mode 100644 index 0000000..97837e2 --- /dev/null +++ b/tests/benchmarks/qgraphicswidget/tst_qgraphicswidget.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +****************************************************************************/ + +#include +#include +#include +#include +#include +//TESTED_FILES= + +class tst_QGraphicsWidget : public QObject +{ + Q_OBJECT + +public: + tst_QGraphicsWidget(); + virtual ~tst_QGraphicsWidget(); + +public slots: + void init(); + void cleanup(); + +private slots: + void move(); +}; + +tst_QGraphicsWidget::tst_QGraphicsWidget() +{ +} + +tst_QGraphicsWidget::~tst_QGraphicsWidget() +{ +} + +void tst_QGraphicsWidget::init() +{ +} + +void tst_QGraphicsWidget::cleanup() +{ +} + +void tst_QGraphicsWidget::move() +{ + QGraphicsScene scene; + QGraphicsWidget *widget = new QGraphicsWidget(); + scene.addItem(widget); + QGraphicsView view(&scene); + view.show(); + QBENCHMARK { + widget->setPos(qrand(),qrand()); + } +} + +QTEST_MAIN(tst_QGraphicsWidget) +#include "tst_qgraphicswidget.moc" -- cgit v0.12 From 0985805ab3c7de5b15c115a98afb15944b6d93b9 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Mon, 9 Mar 2009 14:33:02 +0100 Subject: Fixes: Don't fill the pixmap because we will copy the cache into it. RevBy: bnilsen AutoTest: All pass + plasma ok --- src/gui/graphicsview/qgraphicsscene.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b509507..8a67d24 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4736,11 +4736,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size()) { QPoint diff = newCacheIndent - deviceData->cacheIndent; QPixmap newPix(deviceRect.size()); - // ### Investigate removing this fill (test with Plasma and - // graphicssystem raster). - newPix.fill(Qt::transparent); if (!pix.isNull()) { QPainter newPixPainter(&newPix); + newPixPainter.setCompositionMode(QPainter::CompositionMode_Source); newPixPainter.drawPixmap(-diff, pix); newPixPainter.end(); } -- cgit v0.12 From 4556bcbd40c8feb7185aae7da5f0686f12d87565 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Wed, 11 Mar 2009 17:24:41 +0100 Subject: Fixes: Optimization: Cache QGraphicsItem::clipPath(). RevBy: Alexis AutoTest: Still pass Details: No-brainer. --- src/gui/graphicsview/qgraphicsitem.cpp | 46 ++++++++++++++++++++++++++++------ src/gui/graphicsview/qgraphicsitem_p.h | 14 +++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 443cc8c..5b997f4 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -631,6 +631,7 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch case QGraphicsItem::ItemClipsChildrenToShape: flag = AncestorClipsChildren; enabled = flags & QGraphicsItem::ItemClipsChildrenToShape; + invalidateCachedClipPathRecursively(/*childrenOnly=*/true); break; case QGraphicsItem::ItemIgnoresTransformations: flag = AncestorIgnoresTransformations; @@ -1270,6 +1271,9 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->updateAncestorFlag(ItemClipsChildrenToShape); } + if ((flags & ItemClipsToShape) != (oldFlags & ItemClipsToShape)) + d_ptr->invalidateCachedClipPath(); + if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) { // Item children clipping changes. Propagate the ancestor flag to // all children. @@ -3136,10 +3140,15 @@ bool QGraphicsItem::isClipped() const QPainterPath QGraphicsItem::clipPath() const { Q_D(const QGraphicsItem); - QPainterPath clip; - if (!isClipped()) - return clip; + if (!d->dirtyClipPath) + return d->cachedClipPath; + + if (!isClipped()) { + d_ptr->setCachedClipPath(QPainterPath()); + return d->cachedClipPath; + } + QPainterPath clip; // Start with the item's bounding rect. clip.addRect(boundingRect()); @@ -3150,15 +3159,27 @@ QPainterPath QGraphicsItem::clipPath() const // Intersect any in-between clips starting at the top and moving downwards. while ((parent = parent->d_ptr->parent)) { if (parent->d_ptr->flags & ItemClipsChildrenToShape) { - // Map clip to the current parent and intersect with its shape. - clip = (lastParent->itemTransform(parent).map(clip)).intersected(parent->shape()); - if (clip.isEmpty()) + // Map clip to the current parent and intersect with its shape/clipPath + clip = lastParent->itemTransform(parent).map(clip); + if (!parent->d_ptr->dirtyClipPath) { + clip = clip.intersected(parent->d_ptr->cachedClipPath); + if (!(parent->d_ptr->flags & ItemClipsToShape)) + clip = clip.intersected(parent->shape()); + } else { + clip = clip.intersected(parent->shape()); + } + + if (clip.isEmpty()) { + d_ptr->setCachedClipPath(clip); return clip; + } lastParent = parent; } - if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) + if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + || !parent->d_ptr->dirtyClipPath) { break; + } } if (lastParent != this) { @@ -3171,6 +3192,7 @@ QPainterPath QGraphicsItem::clipPath() const if (d->flags & ItemClipsToShape) clip = clip.intersected(shape()); + d_ptr->setCachedClipPath(clip); return clip; } @@ -3726,6 +3748,15 @@ void QGraphicsItemPrivate::removeExtraItemCache() unsetExtra(ExtraCacheData); } +void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly) +{ + if (!childrenOnly) + invalidateCachedClipPath(); + // ### Return if this item doesn't clip its children? + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->invalidateCachedClipPathRecursively(false); +} + /*! \internal @@ -5505,6 +5536,7 @@ void QGraphicsItem::prepareGeometryChange() QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); scenePrivate->removeFromIndex(this); + d_ptr->invalidateCachedClipPathRecursively(); } } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 7deae52..1e2c09b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -138,6 +138,7 @@ public: dirty(0), dirtyChildren(0), localCollisionHack(0), + dirtyClipPath(1), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -234,6 +235,18 @@ public: QGraphicsItemCache *extraItemCache() const; void removeExtraItemCache(); + inline void setCachedClipPath(const QPainterPath &path) + { + cachedClipPath = path; + dirtyClipPath = 0; + } + + inline void invalidateCachedClipPath() + { dirtyClipPath = 1; } + + void invalidateCachedClipPathRecursively(bool childrenOnly = false); + + QPainterPath cachedClipPath; QPointF pos; qreal z; QGraphicsScene *scene; @@ -268,6 +281,7 @@ public: quint32 dirty : 1; quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; + quint32 dirtyClipPath : 1; // Optional stacking order int globalStackingOrder; -- cgit v0.12 From f4547b98b52bfc95fb0c14ec58df204cfcec0db2 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 3 Apr 2009 14:19:12 +0200 Subject: Fixes: Cleanup/Optimize QGraphicsView::findItems. RevBy: Alexis AutoTest: Still pass Details: findItems() does almost exactly the same as QGraphicsView::items, the only difference is that it checks whether we are about to redraw all items. Next step is to optimize the items_helper functions. The patch does also include a fix for ::items/childItems_helper(const QPainterPath ...); it didn't take Qt::Intersects/ContainsItemBoundingRect into account (in the same fashion as we do in the other helper functions). --- src/gui/graphicsview/qgraphicsscene.cpp | 80 ++++++++++++++++----- src/gui/graphicsview/qgraphicsview.cpp | 122 ++++++++------------------------ src/gui/graphicsview/qgraphicsview_p.h | 7 +- 3 files changed, 94 insertions(+), 115 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8a67d24..3db8e35 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1487,21 +1487,46 @@ QList QGraphicsScenePrivate::items_helper(const QPainterPath &p Qt::SortOrder order) const { QList items; + const QRectF pathRect = _q_adjustedRect(path.controlPointRect()); + // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItemsInRect(_q_adjustedRect(path.controlPointRect()))) { + foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) { // Find the item's scene transform in a clever way. QTransform x = item->sceneTransform(); - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - QPainterPath mappedPath = xinv.map(path); - if (itemCollidesWithPath(item, mappedPath, mode)) { + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + QRectF br = _q_adjustedRect(item->boundingRect()); + if (mode >= Qt::ContainsItemBoundingRect) { + // Path contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { items << item; - if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) - childItems_helper(&items, item, mappedPath, mode); + keep = true; + } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } } } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + childItems_helper(&items, item, xinv.map(path), mode); + } } if (order != Qt::SortOrder(-1)) @@ -1629,29 +1654,46 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, Qt::ItemSelectionMode mode) const { bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - QPainterPath intersectedPath = !parentClip ? path : path.intersected(parent->shape()); - if (intersectedPath.isEmpty()) + QRectF pathRect = _q_adjustedRect(path.boundingRect()); + QRectF r = !parentClip ? pathRect : pathRect.intersected(_q_adjustedRect(parent->boundingRect())); + if (r.isEmpty()) return; QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; // Skip invisible items. if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity(), qreal(0.0))) continue; - QTransform x = item->sceneTransform(); - - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - QPainterPath mappedPath = xinv.map(path); - if (itemCollidesWithPath(item, mappedPath, mode)) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + QRectF br = _q_adjustedRect(item->boundingRect()); + bool keep = false; + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { items->append(item); - if (!item->d_ptr->children.isEmpty()) - childItems_helper(items, item, mappedPath, mode); + keep = true; } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { + if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children that clip children. + childItems_helper(items, item, item->mapFromParent(path), mode); } } } diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index f88918f..c421417 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1029,103 +1029,40 @@ void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array extern QPainterPath qt_regionToPath(const QRegion ®ion); -QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, - const QTransform &worldTransform, - bool *allItems) const +QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const { Q_Q(const QGraphicsView); - QList itemList; - QSet tmp; - bool simpleTransform = worldTransform.type() <= QTransform::TxScale; - - QPainterPath path = qt_regionToPath(exposedRegion); - *allItems = path.contains(q->mapFromScene(scene->d_func()->growingItemsBoundingRect).boundingRect()); - QList exposedRects; - QList exposedPolys; - - // Transform the exposed viewport rects to scene rects or polygons - foreach (const QRect &rect, exposedRegion.rects()) { - QPolygonF exposedPoly = q->mapToScene(rect.adjusted(-1, -1, 1, 1)); - QRectF exposedRect = exposedPoly.boundingRect(); - if (!simpleTransform) - exposedPolys << exposedPoly; - exposedRects << exposedRect; - } - - // Find which items need to be drawn. - if (*allItems) { + const QPainterPath exposedPath(qt_regionToPath(exposedRegion)); + const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); + + if (exposedScenePath.contains(scene->d_func()->growingItemsBoundingRect)) { + Q_ASSERT(allItems); + *allItems = true; + // All items are guaranteed within the exposed region, don't bother using the index. - foreach (QGraphicsItem *item, scene->items()) { + QList itemList(scene->items()); + int i = 0; + while (i < itemList.size()) { // But we only want to include items that are visible - if (item->isVisible()) - itemList << item; - } - } else if (simpleTransform) { - // Simple rect lookups will do. - if (exposedRects.size() > 1) { - foreach (const QRectF &rect, exposedRects) { - foreach (QGraphicsItem *item, scene->d_func()->items_helper(rect, Qt::IntersectsItemBoundingRect, Qt::SortOrder(-1) /* don't sort */)) { - if (!tmp.contains(item)) { - tmp << item; - itemList << item; - } - } - } - } else { - itemList += scene->d_func()->items_helper(exposedRects[0], Qt::IntersectsItemBoundingRect, Qt::SortOrder(-1) /* don't sort */); - } - } else { - // Polygon lookup is necessary. - if (exposedRects.size() > 1) { - foreach (const QPolygonF &poly, exposedPolys) { - foreach (QGraphicsItem *item, scene->d_func()->items_helper(poly, Qt::IntersectsItemBoundingRect, Qt::SortOrder(-1) /* don't sort */)) { - if (!tmp.contains(item)) { - tmp << item; - itemList << item; - } - } - } - } else { - itemList += scene->d_func()->items_helper(exposedPolys[0], Qt::IntersectsItemBoundingRect, Qt::SortOrder(-1) /* don't sort */); + if (!itemList.at(i)->isVisible()) + itemList.removeAt(i); + else + ++i; } - } - // Check for items that ignore inherited transformations, and add them if - // necessary. - QRectF untr = scene->d_func()->largestUntransformableItem; - if (!*allItems && !untr.isNull()) { - // Map the largest untransformable item subtree boundingrect from view - // to scene coordinates, and use this to expand all exposed rects in - // search for untransformable items. - QRectF ltri = matrix.inverted().mapRect(untr); - ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); - - foreach (const QRect &rect, exposedRegion.rects()) { - QRectF exposed = q->mapToScene(rect.adjusted(-1, -1, 1, 1)).boundingRect(); - exposed.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); - - foreach (QGraphicsItem *item, scene->d_func()->estimateItemsInRect(exposed)) { - if (item->d_ptr->itemIsUntransformable()) { - if (!tmp.contains(item)) { - QPainterPath rectPath; - rectPath.addRect(rect); - QPainterPath path = item->deviceTransform(q->viewportTransform()).inverted().map(rectPath); - if (item->collidesWithPath(path, Qt::IntersectsItemBoundingRect)) { - itemList << item; - tmp << item; - } - } - } - } - } + // Sort the items. + QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled); + return itemList; } - tmp.clear(); - // Sort the items. - QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, - scene->d_func()->sortCacheEnabled); + if (scene->d_func()->largestUntransformableItem.isNull()) { + return scene->d_func()->items_helper(exposedScenePath, + Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder); + } - return itemList; + // NB! Path must be in viewport coordinates. + return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); } void QGraphicsViewPrivate::generateStyleOptions(const QList &itemList, @@ -2228,7 +2165,8 @@ QList QGraphicsView::items() const certainly room for improvement. */ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &path, - Qt::ItemSelectionMode mode) const + Qt::ItemSelectionMode mode, + Qt::SortOrder order) const { Q_Q(const QGraphicsView); @@ -2278,8 +2216,8 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat } // ### Insertion sort would be faster. - QGraphicsScenePrivate::sortItems(&result, Qt::AscendingOrder, - scene->d_func()->sortCacheEnabled); + if (order != Qt::SortOrder(-1)) + QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled); return result; } @@ -3485,7 +3423,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Find all exposed items bool allItems = false; - QList itemList = d->findItems(exposedRegion, viewTransform, &allItems); + QList itemList = d->findItems(exposedRegion, &allItems); #ifdef QGRAPHICSVIEW_DEBUG int exposedTime = stopWatch.elapsed(); diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 2109673..a76279e 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -85,7 +85,8 @@ public: qint64 verticalScroll() const; QList itemsInArea(const QPainterPath &path, - Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; + Qt::ItemSelectionMode mode = Qt::IntersectsItemShape, + Qt::SortOrder = Qt::AscendingOrder) const; QPointF mousePressItemPoint; QPointF mousePressScenePoint; @@ -172,9 +173,7 @@ public: void updateRegion(const QRegion ®ion); bool updateSceneSlotReimplementedChecked; - QList findItems(const QRegion &exposedRegion, - const QTransform &worldTransform, - bool *allItems) const; + QList findItems(const QRegion &exposedRegion, bool *allItems) const; void generateStyleOptions(const QList &itemList, QGraphicsItem **itemArray, -- cgit v0.12 From 4020327503eaefae42da4bd6e71125b6972ac97f Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 3 Apr 2009 14:43:11 +0200 Subject: Add a cut-off for simple rectangle lookups. Make sure we use the rect-variation of QGraphicsScene's item lookup functions if the view has a simple transform and a simple expose region. Reviewed-by: Bjoern Erik Nilsen --- src/gui/graphicsview/qgraphicsview.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c421417..9191fc5 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1056,6 +1056,11 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg } if (scene->d_func()->largestUntransformableItem.isNull()) { + if (exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale) { + return scene->d_func()->items_helper(exposedScenePath.controlPointRect(), + Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder); + } return scene->d_func()->items_helper(exposedScenePath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); -- cgit v0.12 From 4d019e66fb62d6f25627144539abd7f59413abee Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Tue, 17 Mar 2009 11:42:07 +0100 Subject: Fixes: Only use the parent's cached clip path if it is clipped. RevBy: TrustMe Details: ...otherwise it'll be empty and too much will be clipped away. --- src/gui/graphicsview/qgraphicsitem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5b997f4..a3a12e7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3157,11 +3157,12 @@ QPainterPath QGraphicsItem::clipPath() const const QGraphicsItem *lastParent = this; // Intersect any in-between clips starting at the top and moving downwards. + bool foundValidClipPath = false; while ((parent = parent->d_ptr->parent)) { if (parent->d_ptr->flags & ItemClipsChildrenToShape) { // Map clip to the current parent and intersect with its shape/clipPath clip = lastParent->itemTransform(parent).map(clip); - if (!parent->d_ptr->dirtyClipPath) { + if ((foundValidClipPath = !parent->d_ptr->dirtyClipPath && parent->isClipped())) { clip = clip.intersected(parent->d_ptr->cachedClipPath); if (!(parent->d_ptr->flags & ItemClipsToShape)) clip = clip.intersected(parent->shape()); @@ -3177,7 +3178,7 @@ QPainterPath QGraphicsItem::clipPath() const } if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - || !parent->d_ptr->dirtyClipPath) { + || foundValidClipPath) { break; } } -- cgit v0.12 From bd4b177e051852f0fb94df9c0ee2e512478e0d38 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Wed, 18 Mar 2009 13:27:16 +0100 Subject: Fixes: Get rid of lots of calls to qFuzzyCompare. RevBy: Olivier AutoTest: Still pass. Details: Items usually don't have effective opacity, i.e. it is 1.0, so don't bother doing fuzzy compare if that's the case. --- src/gui/graphicsview/qgraphicsitem_p.h | 6 ++++++ src/gui/graphicsview/qgraphicsscene.cpp | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 1e2c09b..df07b87 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -246,6 +246,12 @@ public: void invalidateCachedClipPathRecursively(bool childrenOnly = false); + inline bool isInvisible() const + { + return !visible || (hasEffectiveOpacity + && qFuzzyCompare(q_func()->effectiveOpacity() + 1.0, qreal(1.0))); + } + QPainterPath cachedClipPath; QPointF pos; qreal z; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3db8e35..1422184 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1552,7 +1552,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, continue; // Skip invisible items and all their children. - if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity(), qreal(0.0))) + if (item->d_ptr->isInvisible()) continue; // ### _q_adjustedRect is only needed because QRectF::intersects, @@ -1612,7 +1612,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, continue; // Skip invisible items. - if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity() + 1, qreal(1.0))) + if (item->d_ptr->isInvisible()) continue; // ### _q_adjustedRect is only needed because QRectF::intersects, @@ -1666,7 +1666,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, continue; // Skip invisible items. - if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity(), qreal(0.0))) + if (item->d_ptr->isInvisible()) continue; // ### _q_adjustedRect is only needed because QRectF::intersects, -- cgit v0.12 From 5910dbe6e7a024301d431102703f9abe323ebd13 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 19 Mar 2009 15:31:56 +0100 Subject: Fixes: Compile on funky scratchbox ARM compiler. --- src/gui/graphicsview/qgraphicsitem_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index df07b87..98e7c13 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -249,7 +249,7 @@ public: inline bool isInvisible() const { return !visible || (hasEffectiveOpacity - && qFuzzyCompare(q_func()->effectiveOpacity() + 1.0, qreal(1.0))); + && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0))); } QPainterPath cachedClipPath; -- cgit v0.12 From c1909321a486621ef196dd4bb3cf354406d86d46 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 20 Mar 2009 18:06:05 +0100 Subject: Fixes: Clever invalidating of the cached clip path. RevBy: Andreas AutoTest: still pass Details: Adds emptyClipPath bit, a cut-off to test if the item has an empty clip path (i.e., is clipped away). Also adds code for invalidating the cache from inside setPos(). --- src/gui/graphicsview/qgraphicsitem.cpp | 124 ++++++++++++++++++++++++++++++--- src/gui/graphicsview/qgraphicsitem_p.h | 18 ++++- 2 files changed, 129 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a3a12e7..badc41e 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2368,15 +2368,18 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) return; // Update and repositition. + inSetPosHelper = 1; if (scene) { fullUpdateHelper(true); q->prepareGeometryChange(); } this->pos = newPos; invalidateSceneTransformCache(); + updateCachedClipPathFromSetPosHelper(); // Send post-notification. q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos); + inSetPosHelper = 0; } /*! @@ -3141,7 +3144,7 @@ QPainterPath QGraphicsItem::clipPath() const { Q_D(const QGraphicsItem); if (!d->dirtyClipPath) - return d->cachedClipPath; + return d->emptyClipPath ? QPainterPath() : d->cachedClipPath; if (!isClipped()) { d_ptr->setCachedClipPath(QPainterPath()); @@ -3163,6 +3166,13 @@ QPainterPath QGraphicsItem::clipPath() const // Map clip to the current parent and intersect with its shape/clipPath clip = lastParent->itemTransform(parent).map(clip); if ((foundValidClipPath = !parent->d_ptr->dirtyClipPath && parent->isClipped())) { + if (parent->d_ptr->emptyClipPath) { + if (d_ptr->flags & ItemClipsChildrenToShape) + d_ptr->setEmptyCachedClipPathRecursively(); + else + d_ptr->setEmptyCachedClipPath(); + return QPainterPath(); + } clip = clip.intersected(parent->d_ptr->cachedClipPath); if (!(parent->d_ptr->flags & ItemClipsToShape)) clip = clip.intersected(parent->shape()); @@ -3171,7 +3181,10 @@ QPainterPath QGraphicsItem::clipPath() const } if (clip.isEmpty()) { - d_ptr->setCachedClipPath(clip); + if (d_ptr->flags & ItemClipsChildrenToShape) + d_ptr->setEmptyCachedClipPathRecursively(); + else + d_ptr->setEmptyCachedClipPath(); return clip; } lastParent = parent; @@ -3749,13 +3762,95 @@ void QGraphicsItemPrivate::removeExtraItemCache() unsetExtra(ExtraCacheData); } -void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly) +void QGraphicsItemPrivate::setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect) +{ + setEmptyCachedClipPath(); + + const bool checkRect = !emptyIfOutsideThisRect.isNull() + && !(flags & QGraphicsItem::ItemClipsChildrenToShape); + for (int i = 0; i < children.size(); ++i) { + if (!checkRect) { + children.at(i)->d_ptr->setEmptyCachedClipPathRecursively(); + continue; + } + + QGraphicsItem *child = children.at(i); + const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect); + if (rect.intersects(child->boundingRect())) + child->d_ptr->invalidateCachedClipPathRecursively(false, rect); + else + child->d_ptr->setEmptyCachedClipPathRecursively(rect); + } +} + +void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly, const QRectF &emptyIfOutsideThisRect) { if (!childrenOnly) invalidateCachedClipPath(); - // ### Return if this item doesn't clip its children? - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->invalidateCachedClipPathRecursively(false); + + const bool checkRect = !emptyIfOutsideThisRect.isNull(); + for (int i = 0; i < children.size(); ++i) { + if (!checkRect) { + children.at(i)->d_ptr->invalidateCachedClipPathRecursively(false); + continue; + } + + QGraphicsItem *child = children.at(i); + const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect); + if (rect.intersects(child->boundingRect())) + child->d_ptr->invalidateCachedClipPathRecursively(false, rect); + else + child->d_ptr->setEmptyCachedClipPathRecursively(rect); + } +} + +void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper() +{ + Q_ASSERT(inSetPosHelper); + + if (!(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) + return; // Not clipped by any ancestor. + + // Find closest clip ancestor. + QGraphicsItem *clipParent = parent; + while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) + clipParent = clipParent->d_ptr->parent; + + Q_ASSERT(clipParent); + Q_Q(QGraphicsItem); + + // From here everything is calculated in clip parent's coordinates. + const QTransform thisToParentTransform(q->itemTransform(clipParent)); + const QRectF parentBoundingRect(clipParent->boundingRect()); + const QRectF thisBoundingRect(thisToParentTransform.mapRect(q->boundingRect())); + + if (!parentBoundingRect.intersects(thisBoundingRect)) { + // Item is moved outside the clip parent's bounding rect, + // i.e. it is fully clipped and the clip path is empty. + if (flags & QGraphicsItem::ItemClipsChildrenToShape) + setEmptyCachedClipPathRecursively(); + else + setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentBoundingRect)); + return; + } + + const QPainterPath parentClip(clipParent->isClipped() ? clipParent->clipPath() : clipParent->shape()); + if (parentClip.contains(thisBoundingRect)) + return; // Item is inside the clip parent's shape. No update required. + + const QRectF parentClipRect(parentClip.controlPointRect()); + if (!parentClipRect.intersects(thisBoundingRect)) { + // Item is moved outside the clip parent's shape, + // i.e. it is fully clipped and the clip path is empty. + if (flags & QGraphicsItem::ItemClipsChildrenToShape) + setEmptyCachedClipPathRecursively(); + else + setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentClipRect)); + } else { + // Item is partially inside the clip parent's shape, + // i.e. the cached clip path must be invalidated. + invalidateCachedClipPathRecursively(false, thisToParentTransform.inverted().mapRect(parentClipRect)); + } } /*! @@ -5532,13 +5627,20 @@ void QGraphicsItem::removeFromIndex() */ void QGraphicsItem::prepareGeometryChange() { - if (d_ptr->scene) { - d_ptr->updateHelper(); + if (!d_ptr->scene) + return; + + d_ptr->updateHelper(); + QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); + scenePrivate->removeFromIndex(this); - QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->removeFromIndex(this); + if (d_ptr->inSetPosHelper) + return; + + if (d_ptr->flags & ItemClipsChildrenToShape) d_ptr->invalidateCachedClipPathRecursively(); - } + else + d_ptr->invalidateCachedClipPath(); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 98e7c13..f5c3505 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -139,6 +139,8 @@ public: dirtyChildren(0), localCollisionHack(0), dirtyClipPath(1), + emptyClipPath(0), + inSetPosHelper(0), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -239,12 +241,22 @@ public: { cachedClipPath = path; dirtyClipPath = 0; + emptyClipPath = 0; } + inline void setEmptyCachedClipPath() + { + emptyClipPath = 1; + dirtyClipPath = 0; + } + + void setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect = QRectF()); + inline void invalidateCachedClipPath() - { dirtyClipPath = 1; } + { /*static int count = 0 ;qWarning("%i", ++count);*/ dirtyClipPath = 1; emptyClipPath = 0; } - void invalidateCachedClipPathRecursively(bool childrenOnly = false); + void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); + void updateCachedClipPathFromSetPosHelper(); inline bool isInvisible() const { @@ -288,6 +300,8 @@ public: quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; quint32 dirtyClipPath : 1; + quint32 emptyClipPath : 1; + quint32 inSetPosHelper : 1; // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 95fa7a93bc840e0f49ee30e76abb2b4f8579c997 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 23 Mar 2009 15:54:30 +0100 Subject: Fixes: Optimization: Clip path is empty if the bounding rect is empty. RevBy: TrustMe --- src/gui/graphicsview/qgraphicsitem.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index badc41e..75b6cf1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3151,9 +3151,18 @@ QPainterPath QGraphicsItem::clipPath() const return d->cachedClipPath; } + const QRectF thisBoundingRect(boundingRect()); + if (thisBoundingRect.isEmpty()) { + if (d_ptr->flags & ItemClipsChildrenToShape) + d_ptr->setEmptyCachedClipPathRecursively(); + else + d_ptr->setEmptyCachedClipPath(); + return QPainterPath(); + } + QPainterPath clip; // Start with the item's bounding rect. - clip.addRect(boundingRect()); + clip.addRect(thisBoundingRect); if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { const QGraphicsItem *parent = this; -- cgit v0.12 From deccc867b244fbc52ca58e21623febbc27310b05 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 23 Mar 2009 19:37:41 +0100 Subject: Fixes: Don't bother processing items that are clipped away. RevBy: Andreas --- src/gui/graphicsview/qgraphicsitem_p.h | 3 + src/gui/graphicsview/qgraphicsscene.cpp | 116 ++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 52 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index f5c3505..3e4c269 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -264,6 +264,9 @@ public: && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0))); } + inline bool isClippedAway() const + { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } + QPainterPath cachedClipPath; QPointF pos; qreal z; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 1422184..f32fe71 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1539,12 +1539,14 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, const QRectF &rect, Qt::ItemSelectionMode mode) const { - QPainterPath path; bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; QRectF r = !parentClip ? _q_adjustedRect(rect) : _q_adjustedRect(rect).intersected(_q_adjustedRect(parent->boundingRect())); if (r.isEmpty()) return; + QPainterPath path; QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); @@ -1555,28 +1557,30 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, if (item->d_ptr->isInvisible()) continue; - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); - QRectF mbr = item->mapRectToParent(br); bool keep = false; - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { - items->append(item); - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(rect, mbr)) { - if (path == QPainterPath()) - path.addRect(rect); - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + QRectF br = _q_adjustedRect(item->boundingRect()); + QRectF mbr = item->mapRectToParent(br); + if (mode >= Qt::ContainsItemBoundingRect) { + // Rect intersects/contains item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) + || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { items->append(item); keep = true; } + } else { + // Rect intersects/contains item's shape + if (QRectF_intersects(rect, mbr)) { + if (path == QPainterPath()) + path.addRect(rect); + if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } } } @@ -1598,13 +1602,15 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, const QPolygonF &polygon, Qt::ItemSelectionMode mode) const { - QPainterPath path; bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; QRectF polyRect = _q_adjustedRect(polygon.boundingRect()); QRectF r = !parentClip ? polyRect : polyRect.intersected(_q_adjustedRect(parent->boundingRect())); if (r.isEmpty()) return; + QPainterPath path; QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); @@ -1615,29 +1621,31 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, if (item->d_ptr->isInvisible()) continue; - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); bool keep = false; - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + QRectF br = _q_adjustedRect(item->boundingRect()); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect if (path == QPainterPath()) path.addPolygon(polygon); - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { items->append(item); keep = true; } + } else { + // Polygon contains/intersects item's shape + if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { + if (path == QPainterPath()) + path.addPolygon(polygon); + if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } } } @@ -1654,6 +1662,8 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, Qt::ItemSelectionMode mode) const { bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; QRectF pathRect = _q_adjustedRect(path.boundingRect()); QRectF r = !parentClip ? pathRect : pathRect.intersected(_q_adjustedRect(parent->boundingRect())); if (r.isEmpty()) @@ -1669,25 +1679,27 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, if (item->d_ptr->isInvisible()) continue; - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); bool keep = false; - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + QRectF br = _q_adjustedRect(item->boundingRect()); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { items->append(item); keep = true; } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { + if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } } } -- cgit v0.12 From 0d959a6c402ea3a3a55d7076d453d4bdbf8dce8e Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Tue, 24 Mar 2009 15:50:26 +0100 Subject: Fixes: Discard update requests if possible. AutoTest: Still pass. Details: Update requests can be discarded if the item itself is clipped away and the item clips all its children to shape. This cut-off is extremely effective (and aggressive:)) --- src/gui/graphicsview/qgraphicsitem.cpp | 54 ++++++++++++++++++++++------------ src/gui/graphicsview/qgraphicsitem_p.h | 9 ++++-- src/gui/graphicsview/qgraphicsview.cpp | 2 ++ 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 75b6cf1..a5d6021 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1063,7 +1063,7 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) qVariantSetValue(variant, this); d_ptr->parent->itemChange(ItemChildAddedChange, variant); if (!implicitUpdate) - d_ptr->updateHelper(); + d_ptr->updateHelper(QRectF(), false, true); // Inherit ancestor flags from the new parent. d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); @@ -1092,7 +1092,7 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) if (!d_ptr->enabled && !d_ptr->explicitlyDisabled) d_ptr->setEnabledHelper(true, /* explicit = */ false); - d_ptr->updateHelper(); + d_ptr->updateHelper(QRectF(), false, true); } if (d_ptr->scene) { @@ -1236,7 +1236,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) int geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); bool fullUpdate = (flags & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); if (fullUpdate) - d_ptr->fullUpdateHelper(); + d_ptr->fullUpdateHelper(false, true); // Keep the old flags to compare the diff. GraphicsItemFlags oldFlags = this->flags(); @@ -1281,7 +1281,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) } // ### Why updateHelper? - d_ptr->updateHelper(); + d_ptr->updateHelper(QRectF(), false, true); // Notify change. itemChange(ItemFlagsHaveChanged, quint32(flags)); @@ -2369,13 +2369,13 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) // Update and repositition. inSetPosHelper = 1; + updateCachedClipPathFromSetPosHelper(newPos); if (scene) { fullUpdateHelper(true); q->prepareGeometryChange(); } this->pos = newPos; invalidateSceneTransformCache(); - updateCachedClipPathFromSetPosHelper(); // Send post-notification. q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos); @@ -2771,7 +2771,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) return; // Update and set the new transformation. - d_ptr->fullUpdateHelper(true); + d_ptr->fullUpdateHelper(true, true); prepareGeometryChange(); d_ptr->hasTransform = !newTransform.isIdentity(); d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); @@ -2817,7 +2817,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) return; // Update and set the new transformation. - d_ptr->fullUpdateHelper(true); + d_ptr->fullUpdateHelper(true, true); prepareGeometryChange(); d_ptr->hasTransform = !newTransform.isIdentity(); d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); @@ -3626,7 +3626,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) only case where the item's background should be marked as dirty even when the item isn't visible. */ -void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force) +void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath) { // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. @@ -3634,6 +3634,8 @@ void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force) return; if (!scene || (scene && scene->d_func()->updateAll && scene->d_func()->hasSceneRect)) return; + if (!force && !maybeDirtyClipPath && discardUpdateRequest()) + return; if (scene && (visible || force)) { if (rect.isNull()) dirty = 1; @@ -3646,17 +3648,19 @@ void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force) Propagates updates to \a item and all its children. */ -void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly) +void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath) { + if (!maybeDirtyClipPath && discardUpdateRequest()) + return; // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. if (!scene || (scene && scene->d_func()->updateAll && scene->d_func()->hasSceneRect)) return; if (!childrenOnly && !dirty) - updateHelper(); + updateHelper(QRectF(), false, maybeDirtyClipPath); if (children.isEmpty() || dirtyChildren) return; - if (flags & QGraphicsItem::ItemClipsChildrenToShape) { + if (flags & QGraphicsItem::ItemClipsChildrenToShape || children.isEmpty()) { // ### mark all children dirty? // Unnecessary to update children as well. return; @@ -3683,7 +3687,7 @@ void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly) } } foreach (QGraphicsItem *child, children) - child->d_ptr->fullUpdateHelper(); + child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath); dirtyChildren = 1; } @@ -3813,23 +3817,35 @@ void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly } } -void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper() +void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &newPos) { Q_ASSERT(inSetPosHelper); if (!(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) return; // Not clipped by any ancestor. - // Find closest clip ancestor. + // Find closest clip ancestor and transform. + Q_Q(QGraphicsItem); + QTransform thisToParentTransform = hasTransform + ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y()) + : QTransform::fromTranslate(newPos.x(), newPos.y()); QGraphicsItem *clipParent = parent; - while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) + while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { + if (clipParent->d_ptr->hasTransform) + thisToParentTransform *= clipParent->transform(); + if (!clipParent->d_ptr->pos.isNull()) { + thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(), + clipParent->d_ptr->pos.y()); + } clipParent = clipParent->d_ptr->parent; + } + // thisToParentTransform is now the same as q->itemTransform(clipParent), except + // that the new position (which is not yet set on the item) is taken into account. Q_ASSERT(clipParent); - Q_Q(QGraphicsItem); + Q_ASSERT(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); // From here everything is calculated in clip parent's coordinates. - const QTransform thisToParentTransform(q->itemTransform(clipParent)); const QRectF parentBoundingRect(clipParent->boundingRect()); const QRectF thisBoundingRect(thisToParentTransform.mapRect(q->boundingRect())); @@ -3894,6 +3910,8 @@ void QGraphicsItem::update(const QRectF &rect) { if (d_ptr->dirty || (rect.isEmpty() && !rect.isNull())) return; + if (d_ptr->discardUpdateRequest()) + return; if (d_ptr->scene && isVisible()) { if (CacheMode(d_ptr->cacheMode) != NoCache) { QGraphicsItemCache *cache = d_ptr->extraItemCache(); @@ -5639,7 +5657,7 @@ void QGraphicsItem::prepareGeometryChange() if (!d_ptr->scene) return; - d_ptr->updateHelper(); + d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); scenePrivate->removeFromIndex(this); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 3e4c269..dabbe53 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -164,8 +164,8 @@ public: void setPosHelper(const QPointF &pos); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); - void updateHelper(const QRectF &rect = QRectF(), bool force = false); - void fullUpdateHelper(bool childrenOnly = false); + void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false); + void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false); void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); void invalidateSceneTransformCache(); @@ -256,7 +256,7 @@ public: { /*static int count = 0 ;qWarning("%i", ++count);*/ dirtyClipPath = 1; emptyClipPath = 0; } void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); - void updateCachedClipPathFromSetPosHelper(); + void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); inline bool isInvisible() const { @@ -267,6 +267,9 @@ public: inline bool isClippedAway() const { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } + inline bool discardUpdateRequest() const + { return ((flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty()) && isClippedAway(); } + QPainterPath cachedClipPath; QPointF pos; qreal z; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 9191fc5..43263da 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -855,6 +855,8 @@ void QGraphicsViewPrivate::_q_updateLaterSlot() const QList &dirtyItems = scene->d_func()->dirtyItems; for (int i = 0; i < dirtyItems.size(); ++i) { const QGraphicsItem *item = dirtyItems.at(i); + if (item->d_ptr->discardUpdateRequest()) + continue; QTransform x = item->sceneTransform() * viewTransform; updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); } -- cgit v0.12 From 9ed299a3edba92791e1c5af64b8fd9c9fe74c0ea Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Wed, 25 Mar 2009 12:38:35 +0100 Subject: Fixes: Optimize QGraphicsViewPrivate::itemUpdated. AutoTest: Still pass Details: Get rid of QTransform::inverted()/operator*= and do nothing if the item clips all its children and the update rect is outside the bounding rect. --- src/gui/graphicsview/qgraphicsview.cpp | 40 ++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 43263da..4db2257 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -801,38 +801,36 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) updateLater(); QRectF updateRect = rect; - if (item->isClipped()) { + if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) { + updateRect &= item->boundingRect(); + if (updateRect.isEmpty()) + return; + } + + QGraphicsItem *clipItem = item; + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { // Minimize unnecessary redraw. - QGraphicsItem *p = item; - QTransform xform; - QGraphicsItem *lastTransformItem = 0; - while ((p = p->d_ptr->parent)) { - if (p->flags() & QGraphicsItem::ItemClipsChildrenToShape) { - if (!lastTransformItem) - xform = item->itemTransform(p); - else - xform *= lastTransformItem->itemTransform(p); - lastTransformItem = p; - updateRect &= xform.inverted().mapRect(p->boundingRect()); + QGraphicsItem *parent = item; + while ((parent = parent->d_ptr->parent)) { + if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { + // Map update rect to the current parent and itersect with its bounding rect. + updateRect = clipItem->itemTransform(parent).mapRect(updateRect) & parent->boundingRect(); if (updateRect.isEmpty()) return; + clipItem = parent; } - if (!(p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) + if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) break; } - - if (updateRect.isEmpty()) - return; } - // Map the rect to view coordinates. - QRect vr = viewport->rect(); - + // Map update rect from clipItem coordinates to view coordinates. + Q_ASSERT(clipItem); if (!item->d_ptr->hasBoundingRegionGranularity) - this->updateRect(mapToViewRect(item, updateRect) & vr); + this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect()); else - updateRegion(mapToViewRegion(item, updateRect) & vr); + updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect()); } void QGraphicsViewPrivate::updateLater() -- cgit v0.12 From a914eb155e085ba0efa5b95154bf7345d4be7cd7 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Wed, 25 Mar 2009 13:41:10 +0100 Subject: Fixes: Minimize QVariant constr/destr in setPosHelper. RevBy: TrustMe --- src/gui/graphicsview/qgraphicsitem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a5d6021..396fdbd 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2363,7 +2363,8 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) return; // Notify the item that the position is changing. - QPointF newPos = q->itemChange(QGraphicsItem::ItemPositionChange, pos).toPointF(); + const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos)); + QPointF newPos = newPosVariant.toPointF(); if (newPos == this->pos) return; @@ -2378,7 +2379,7 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) invalidateSceneTransformCache(); // Send post-notification. - q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos); + q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); inSetPosHelper = 0; } -- cgit v0.12 From 5564ef89f46fe96aa0b22b888a9a8ba053eea6c7 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 26 Mar 2009 16:48:48 +0100 Subject: Fixes: Don't check the force boolean. Details: It's clipped away regardless. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 396fdbd..c691206 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3635,7 +3635,7 @@ void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool may return; if (!scene || (scene && scene->d_func()->updateAll && scene->d_func()->hasSceneRect)) return; - if (!force && !maybeDirtyClipPath && discardUpdateRequest()) + if (!maybeDirtyClipPath && discardUpdateRequest()) return; if (scene && (visible || force)) { if (rect.isNull()) -- cgit v0.12 From 15098c5ec73db5de8ca724f744a1484f888ed271 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 26 Mar 2009 17:05:59 +0100 Subject: Fixes: Do not update children if not required. AutoTest: Still pass --- src/gui/graphicsview/qgraphicsitem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c691206..b4f36de 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1583,9 +1583,10 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Update children with explicitly = false. + const bool updateChildren = update && !(flags & QGraphicsItem::ItemClipsChildrenToShape); foreach (QGraphicsItem *child, children) { if (!newVisible || !child->d_ptr->explicitlyHidden) - child->d_ptr->setVisibleHelper(newVisible, false); + child->d_ptr->setVisibleHelper(newVisible, false, updateChildren); } // Enable subfocus -- cgit v0.12 From d85835580463f88df6a71d27d2577739e5366f68 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Thu, 26 Mar 2009 17:16:36 +0100 Subject: Fixes: Don't bother updating hidden items. AutoTest: Still pass --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b4f36de..327b352 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3652,7 +3652,7 @@ void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool may */ void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath) { - if (!maybeDirtyClipPath && discardUpdateRequest()) + if (!visible || (!maybeDirtyClipPath && discardUpdateRequest())) return; // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f32fe71..e13a767 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5174,6 +5174,9 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) d->resetDirtyItemsLater(); } + if (!item->isVisible()) + return; // Hiding an item won't effect the largestUntransformableItem/sceneRect. + // Update d->largestUntransformableItem by mapping this item's bounding // rect back to the topmost untransformable item's untransformed // coordinate system (which sort of equals the 1:1 coordinate system of an -- cgit v0.12 From 23c73210fc79055f4bac44de0e43f9917f8d0e7f Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Tue, 24 Mar 2009 15:50:26 +0100 Subject: Fixes: Discard update requests if possible. AutoTest: Still pass. Details: Update requests can be discarded if the item itself is clipped away and the item clips all its children to shape. This cut-off is extremely effective (and aggressive:)) --- src/gui/graphicsview/qgraphicsitem.cpp | 39 +++++++++++++++++++++++++--------- src/gui/graphicsview/qgraphicsitem_p.h | 6 ++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 327b352..23787a7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1102,10 +1102,7 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) } // Resolve opacity. - if (QGraphicsItem *p = d_ptr->parent) - d_ptr->resolveEffectiveOpacity(p->effectiveOpacity()); - else - d_ptr->resolveEffectiveOpacity(1.0); + d_ptr->updateEffectiveOpacity(); // Resolve depth. d_ptr->resolveDepth(parent ? parent->d_ptr->depth : -1); @@ -1246,12 +1243,8 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) // Reresolve effective opacity if the opacity flags change. static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren; - if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask)) { - if (QGraphicsItem *p = d_ptr->parent) - d_ptr->resolveEffectiveOpacity(p->effectiveOpacity()); - else - d_ptr->resolveEffectiveOpacity(1.0); - } + if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask)) + d_ptr->updateEffectiveOpacity(); if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) { // Clear focus on the item if it has focus when the focusable flag @@ -3693,6 +3686,32 @@ void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyCl dirtyChildren = 1; } +static inline bool allChildrenCombineOpacity(QGraphicsItem *parent) +{ + Q_ASSERT(parent); + if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + return false; + + const QList children(parent->childItems()); + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity) + return false; + } + return true; +} + +void QGraphicsItemPrivate::updateEffectiveOpacity() +{ + Q_Q(QGraphicsItem); + if (parent) { + resolveEffectiveOpacity(parent->effectiveOpacity()); + parent->d_ptr->allChildrenCombineOpacity = ::allChildrenCombineOpacity(parent); + } else { + resolveEffectiveOpacity(1.0); + } + allChildrenCombineOpacity = ::allChildrenCombineOpacity(q); +} + /*! \internal diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index dabbe53..c795915 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -141,6 +141,7 @@ public: dirtyClipPath(1), emptyClipPath(0), inSetPosHelper(0), + allChildrenCombineOpacity(1), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -166,6 +167,7 @@ public: void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false); void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false); + void updateEffectiveOpacity(); void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); void invalidateSceneTransformCache(); @@ -264,6 +266,9 @@ public: && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0))); } + inline bool childrenCombineOpacity() const + { return allChildrenCombineOpacity || children.isEmpty(); } + inline bool isClippedAway() const { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } @@ -308,6 +313,7 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; + quint32 allChildrenCombineOpacity : 1; // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 73ce29e6bc09651a4e70b5e61c36d56e568905c7 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 27 Mar 2009 18:53:02 +0100 Subject: Fixes: Simplify the cut-offs and be more agressive :-) AutoTest: Still pass. Details: It's easier to read and understand the code now. --- src/gui/graphicsview/qgraphicsitem.cpp | 84 ++++++++++++++++++++-------------- src/gui/graphicsview/qgraphicsitem_p.h | 21 ++++++--- src/gui/graphicsview/qgraphicsview.cpp | 5 +- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 23787a7..d27d3cd 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3613,6 +3613,24 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) /*! \internal + Returns true if we can discard an update request; otherwise false. +*/ +bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, + bool ignoreVisibleBit, + bool ignoreDirtyBit) const +{ + // No scene, or if the scene is updating everything, means we have nothing + // to do. The only exception is if the scene tracks the growing scene rect. + return (!visible && !ignoreVisibleBit) + || (dirty && !ignoreDirtyBit) + || !scene + || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) + || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) + || (childrenCombineOpacity() && isFullyTransparent()); +} + +/*! + \internal Asks the scene to mark this item's scene rect as dirty, requesting a redraw. This does not invalidate any cache. @@ -3625,17 +3643,12 @@ void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool may { // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. - if (dirty) - return; - if (!scene || (scene && scene->d_func()->updateAll && scene->d_func()->hasSceneRect)) + if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force)) return; - if (!maybeDirtyClipPath && discardUpdateRequest()) - return; - if (scene && (visible || force)) { - if (rect.isNull()) - dirty = 1; - scene->itemUpdated(q_ptr, rect); - } + + if (rect.isNull()) + dirty = 1; + scene->itemUpdated(q_ptr, rect); } /*! @@ -3645,21 +3658,23 @@ void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool may */ void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath) { - if (!visible || (!maybeDirtyClipPath && discardUpdateRequest())) - return; - // No scene, or if the scene is updating everything, means we have nothing - // to do. The only exception is if the scene tracks the growing scene rect. - if (!scene || (scene && scene->d_func()->updateAll && scene->d_func()->hasSceneRect)) - return; - if (!childrenOnly && !dirty) - updateHelper(QRectF(), false, maybeDirtyClipPath); - if (children.isEmpty() || dirtyChildren) + if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, + /*ignoreVisibleBit=*/false, + /*ignoreDirtyBit=*/true)) { return; - if (flags & QGraphicsItem::ItemClipsChildrenToShape || children.isEmpty()) { - // ### mark all children dirty? + } + + if (!childrenOnly && !dirty) { + // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath). + dirty = 1; + scene->itemUpdated(q_ptr, QRectF()); + } + + if (dirtyChildren || childrenClippedToShape()) { // Unnecessary to update children as well. return; } + if (ancestorFlags & AncestorClipsChildren) { Q_Q(QGraphicsItem); // Check if we can avoid updating all children. @@ -3929,22 +3944,23 @@ bool QGraphicsItemPrivate::isProxyWidget() const */ void QGraphicsItem::update(const QRectF &rect) { - if (d_ptr->dirty || (rect.isEmpty() && !rect.isNull())) + if ((rect.isEmpty() && !rect.isNull()) || d_ptr->discardUpdateRequest()) return; - if (d_ptr->discardUpdateRequest()) - return; - if (d_ptr->scene && isVisible()) { - if (CacheMode(d_ptr->cacheMode) != NoCache) { - QGraphicsItemCache *cache = d_ptr->extraItemCache(); - if (rect.isNull()) { - cache->allExposed = true; - cache->exposed.clear(); - } else { - cache->exposed.append(rect); - } + + if (CacheMode(d_ptr->cacheMode) != NoCache) { + QGraphicsItemCache *cache = d_ptr->extraItemCache(); + if (rect.isNull()) { + cache->allExposed = true; + cache->exposed.clear(); + } else { + cache->exposed.append(rect); } - d_ptr->updateHelper(rect); } + + // Effectively the same as updateHelper(rect); + if (rect.isNull()) + d_ptr->dirty = 1; + d_ptr->scene->itemUpdated(this, rect); } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c795915..a5871a7 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -165,6 +165,9 @@ public: void setPosHelper(const QPointF &pos); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); + bool discardUpdateRequest(bool ignoreClipping = false, + bool ignoreVisibleBit = false, + bool ignoreDirtyBit = false) const; void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false); void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false); void updateEffectiveOpacity(); @@ -260,11 +263,8 @@ public: void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); - inline bool isInvisible() const - { - return !visible || (hasEffectiveOpacity - && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0))); - } + inline bool isFullyTransparent() const + { return hasEffectiveOpacity && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0)); } inline bool childrenCombineOpacity() const { return allChildrenCombineOpacity || children.isEmpty(); } @@ -272,8 +272,15 @@ public: inline bool isClippedAway() const { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } - inline bool discardUpdateRequest() const - { return ((flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty()) && isClippedAway(); } + inline bool childrenClippedToShape() const + { return (flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty(); } + + inline bool isInvisible() const + { + return !visible + || (childrenClippedToShape() && isClippedAway()) + || (childrenCombineOpacity() && isFullyTransparent()); + } QPainterPath cachedClipPath; QPointF pos; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 4db2257..f0d360a 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -853,8 +853,11 @@ void QGraphicsViewPrivate::_q_updateLaterSlot() const QList &dirtyItems = scene->d_func()->dirtyItems; for (int i = 0; i < dirtyItems.size(); ++i) { const QGraphicsItem *item = dirtyItems.at(i); - if (item->d_ptr->discardUpdateRequest()) + if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false, + /*ignoreVisibleBit=*/false, + /*ignoreDirtyBit=*/true)) { continue; + } QTransform x = item->sceneTransform() * viewTransform; updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); } -- cgit v0.12 From 30d01c387179160c8c418ecedfb4506a55d282e8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 27 Mar 2009 22:17:10 +0100 Subject: Optimise QGraphicsScene/View::items(const QPointF &pos) Implement specialized (and more efficient versions) of item_helper() and child_helper() that test for QPointF in the scene. --- src/gui/graphicsview/qgraphicsscene.cpp | 94 ++++++++++++++++++++++++++++----- src/gui/graphicsview/qgraphicsscene_p.h | 4 ++ src/gui/graphicsview/qgraphicsview.cpp | 4 +- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e13a767..b4dc62c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1358,6 +1358,48 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } + +QList QGraphicsScenePrivate::items_helper(const QPointF &pos) const +{ + QList items; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + QRectF adjustedRect = QRectF(pos, QSize(1,1)); + foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + QRectF br = _q_adjustedRect(item->boundingRect()); + // Rect intersects/contains item's shape + if (QRectF_intersects(adjustedRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (item->contains(xinv.map(pos))) { + items << item; + keep = true; + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + childItems_helper(&items, item, xinv.map(pos)); + } + } + + sortItems(&items, Qt::AscendingOrder, sortCacheEnabled); + return items; +} + QList QGraphicsScenePrivate::items_helper(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order) const @@ -1392,7 +1434,7 @@ QList QGraphicsScenePrivate::items_helper(const QRectF &rect, bool ok; QTransform xinv = x.inverted(&ok); if (ok) { - if (path == QPainterPath()) + if (path.isEmpty()) path.addRect(rect); if (itemCollidesWithPath(item, xinv.map(path), mode)) { items << item; @@ -1536,6 +1578,42 @@ QList QGraphicsScenePrivate::items_helper(const QPainterPath &p void QGraphicsScenePrivate::childItems_helper(QList *items, const QGraphicsItem *parent, + const QPointF &pos) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + // ### is this needed? + if (parentClip && !parent->boundingRect().contains(pos)) + return; + + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items and all their children. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + if (item->contains(item->mapFromParent(pos))) { + items->append(item); + keep = true; + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) + // Recurse into children. + childItems_helper(items, item, item->mapFromParent(pos)); + } +} + + +void QGraphicsScenePrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, const QRectF &rect, Qt::ItemSelectionMode mode) const { @@ -1597,6 +1675,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, } } + void QGraphicsScenePrivate::childItems_helper(QList *items, const QGraphicsItem *parent, const QPolygonF &polygon, @@ -2380,17 +2459,8 @@ QList QGraphicsScene::items() const */ QList QGraphicsScene::items(const QPointF &pos) const { - QList itemsAtPoint; - - // Find all items within a 1x1 rect area starting at pos. This can be - // inefficient for scenes that use small coordinates (like unity - // coordinates), or for detailed graphs. ### The index should support - // fetching items at a pos to avoid this limitation. - foreach (QGraphicsItem *item, items(QRectF(pos, QSizeF(1, 1)), Qt::IntersectsItemBoundingRect)) { - if (item->contains(item->mapFromScene(pos))) - itemsAtPoint << item; - } - return itemsAtPoint; + Q_D(const QGraphicsScene); + return d->items_helper(pos); } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 9c165d1..befbbd8 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -197,6 +197,7 @@ public: void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; + QList items_helper(const QPointF &pos) const; QList items_helper(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order) const; @@ -208,6 +209,9 @@ public: Qt::SortOrder order) const; void childItems_helper(QList *items, const QGraphicsItem *parent, + const QPointF &pos) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, const QRectF &rect, Qt::ItemSelectionMode mode) const; void childItems_helper(QList *items, diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index f0d360a..ba9cdbf 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2251,9 +2251,9 @@ QList QGraphicsView::items(const QPoint &pos) const if (d->scene->d_func()->largestUntransformableItem.isNull()) { if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { QTransform xinv = viewportTransform().inverted(); - return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1))); + return d->scene->items(xinv.map(pos)); } - return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2)); + return d->scene->items(mapToScene(pos)); } QPainterPath path; -- cgit v0.12 From bc3d96a902d16a9bb358c05de9f6bfede3594731 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 27 Mar 2009 22:18:47 +0100 Subject: Optimise QPainterPath::contains(QPointF) We can shortcut quite some calculations for the common case by first checking whether the point is contained in the control point rect. --- src/gui/painting/qpainterpath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 70036e1..e1f5eea 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1725,7 +1725,7 @@ static void qt_painterpath_isect_curve(const QBezier &bezier, const QPointF &pt, */ bool QPainterPath::contains(const QPointF &pt) const { - if (isEmpty()) + if (isEmpty() || !controlPointRect().contains(pt)) return false; QPainterPathData *d = d_func(); -- cgit v0.12 From d516e5fbed3a7eac20229ead34221c732f85cdb6 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Tue, 31 Mar 2009 14:58:15 +0200 Subject: Fixes: Minimize QVariant overhead related to QGraphicsItem::itemChange. RevBy: Andreas AutoTest: included --- src/gui/graphicsview/qgraphicsitem.cpp | 70 ++++++++++++++------------ src/gui/graphicsview/qgraphicsscene.cpp | 24 +++++---- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 18 +++++++ 3 files changed, 69 insertions(+), 43 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index d27d3cd..11a03b6 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1024,9 +1024,8 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) } if (parent == d_ptr->parent) return; - QVariant variant; - qVariantSetValue(variant, parent); - parent = qVariantValue(itemChange(ItemParentChange, variant)); + const QVariant newParentVariant(itemChange(ItemParentChange, qVariantFromValue(parent))); + parent = qVariantValue(newParentVariant); if (parent == d_ptr->parent) return; @@ -1041,11 +1040,11 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) // We anticipate geometry changes prepareGeometryChange(); + const QVariant thisPointerVariant(qVariantFromValue(this)); if (d_ptr->parent) { // Remove from current parent qt_graphicsitem_removeChild(this, &d_ptr->parent->d_func()->children); - qVariantSetValue(variant, this); - d_ptr->parent->itemChange(ItemChildRemovedChange, variant); + d_ptr->parent->itemChange(ItemChildRemovedChange, thisPointerVariant); } if ((d_ptr->parent = parent)) { @@ -1060,8 +1059,7 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) } d_ptr->parent->d_func()->children << this; - qVariantSetValue(variant, this); - d_ptr->parent->itemChange(ItemChildAddedChange, variant); + d_ptr->parent->itemChange(ItemChildAddedChange, thisPointerVariant); if (!implicitUpdate) d_ptr->updateHelper(QRectF(), false, true); @@ -1111,7 +1109,7 @@ void QGraphicsItem::setParentItem(QGraphicsItem *parent) d_ptr->invalidateSceneTransformCache(); // Deliver post-change notification - itemChange(QGraphicsItem::ItemParentHasChanged, qVariantFromValue(parent)); + itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); } /*! @@ -1372,9 +1370,9 @@ QString QGraphicsItem::toolTip() const */ void QGraphicsItem::setToolTip(const QString &toolTip) { - QString newCursor = itemChange(ItemToolTipChange, toolTip).toString(); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTip); - itemChange(ItemToolTipHasChanged, toolTip); + const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip)); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString()); + itemChange(ItemToolTipHasChanged, toolTipVariant); } #endif // QT_NO_TOOLTIP @@ -1416,9 +1414,8 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - QCursor newCursor = qVariantValue(itemChange(ItemCursorChange, - qVariantFromValue(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, newCursor); + const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue(cursor))); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue(cursorVariant)); d_ptr->hasCursor = 1; if (d_ptr->scene) { foreach (QGraphicsView *view, d_ptr->scene->views()) { @@ -1435,7 +1432,7 @@ void QGraphicsItem::setCursor(const QCursor &cursor) } } } - itemChange(ItemCursorHasChanged, qVariantFromValue(newCursor)); + itemChange(ItemCursorHasChanged, cursorVariant); } /*! @@ -1529,7 +1526,9 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo return; // Modify the property. - newVisible = q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, quint32(newVisible)).toBool(); + const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, + quint32(newVisible))); + newVisible = newVisibleVariant.toBool(); if (visible == quint32(newVisible)) return; visible = newVisible; @@ -1591,7 +1590,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, quint32(visible)); + q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant); } /*! @@ -1697,7 +1696,9 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Modify the property. - enabled = q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, quint32(newEnabled)).toBool(); + const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, + quint32(newEnabled))); + enabled = newEnabledVariant.toBool(); // Schedule redraw. if (update) @@ -1709,7 +1710,7 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, quint32(enabled)); + q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); } /*! @@ -1796,7 +1797,8 @@ void QGraphicsItem::setSelected(bool selected) selected = false; if (d_ptr->selected == selected) return; - bool newSelected = itemChange(ItemSelectedChange, quint32(selected)).toBool(); + const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected))); + bool newSelected = newSelectedVariant.toBool(); if (d_ptr->selected == newSelected) return; d_ptr->selected = newSelected; @@ -1816,7 +1818,7 @@ void QGraphicsItem::setSelected(bool selected) } // Deliver post-change notification. - itemChange(QGraphicsItem::ItemSelectedHasChanged, quint32(d_ptr->selected)); + itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant); } /*! @@ -1892,7 +1894,8 @@ qreal QGraphicsItem::effectiveOpacity() const void QGraphicsItem::setOpacity(qreal opacity) { // Notify change. - qreal newOpacity = itemChange(ItemOpacityChange, double(opacity)).toDouble(); + const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); + qreal newOpacity = newOpacityVariant.toDouble(); // Normalize. newOpacity = qBound(0.0, newOpacity, 1.0); @@ -2759,9 +2762,9 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) return; // Notify the item that the matrix is changing. - QVariant variant; - qVariantSetValue(variant, newTransform.toAffine()); - newTransform = QTransform(qVariantValue(itemChange(ItemMatrixChange, variant))); + QVariant newTransformVariant(itemChange(ItemMatrixChange, + qVariantFromValue(newTransform.toAffine()))); + newTransform = QTransform(qVariantValue(newTransformVariant)); if (oldTransform == newTransform) return; @@ -2773,7 +2776,9 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->invalidateSceneTransformCache(); // Send post-notification. - itemChange(ItemTransformHasChanged, newTransform); + // NB! We have to change the value from QMatrix to QTransform. + qVariantSetValue(newTransformVariant, newTransform); + itemChange(ItemTransformHasChanged, newTransformVariant); } /*! @@ -2805,9 +2810,9 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) return; // Notify the item that the transformation matrix is changing. - QVariant variant; - qVariantSetValue(variant, newTransform); - newTransform = qVariantValue(itemChange(ItemTransformChange, variant)); + const QVariant newTransformVariant(itemChange(ItemTransformChange, + qVariantFromValue(newTransform))); + newTransform = qVariantValue(newTransformVariant); if (oldTransform == newTransform) return; @@ -2819,7 +2824,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) d_ptr->invalidateSceneTransformCache(); // Send post-notification. - itemChange(ItemTransformHasChanged, newTransform); + itemChange(ItemTransformHasChanged, newTransformVariant); } /*! @@ -2967,7 +2972,8 @@ qreal QGraphicsItem::zValue() const */ void QGraphicsItem::setZValue(qreal z) { - qreal newZ = qreal(itemChange(ItemZValueChange, double(z)).toDouble()); + const QVariant newZVariant(itemChange(ItemZValueChange, double(z))); + qreal newZ = qreal(newZVariant.toDouble()); if (newZ == d_ptr->z) return; d_ptr->z = z; @@ -2979,7 +2985,7 @@ void QGraphicsItem::setZValue(qreal z) d_ptr->scene->d_func()->invalidateSortCache(); } - itemChange(ItemZValueHasChanged, double(newZ)); + itemChange(ItemZValueHasChanged, newZVariant); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b4dc62c..bcc329e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -632,10 +632,11 @@ void QGraphicsScenePrivate::_q_updateLater() */ void QGraphicsScenePrivate::_q_polishItems() { + const QVariant booleanTrueVariant(true); foreach (QGraphicsItem *item, unpolishedItems) { if (!item->d_ptr->explicitlyHidden) { - item->itemChange(QGraphicsItem::ItemVisibleChange, true); - item->itemChange(QGraphicsItem::ItemVisibleHasChanged, true); + item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); + item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); } if (item->isWidget()) { QEvent event(QEvent::Polish); @@ -691,9 +692,8 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) Q_Q(QGraphicsScene); if (QGraphicsItem *parent = item->d_func()->parent) { - QVariant variant; - qVariantSetValue(variant, item); - parent->itemChange(QGraphicsItem::ItemChildRemovedChange, variant); + parent->itemChange(QGraphicsItem::ItemChildRemovedChange, + qVariantFromValue(item)); parent->d_func()->children.removeAll(item); } @@ -2847,8 +2847,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. - QGraphicsScene *targetScene = qVariantValue(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue(this))); + const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue(this))); + QGraphicsScene *targetScene = qVariantValue(newSceneVariant); if (targetScene != this) { if (targetScene && item->scene() != targetScene) targetScene->addItem(item); @@ -2942,7 +2943,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue(this)); + item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); } /*! @@ -3206,8 +3207,9 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. - QGraphicsScene *targetScene = qVariantValue(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue(0))); + const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue(0))); + QGraphicsScene *targetScene = qVariantValue(newSceneVariant); if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; @@ -3305,7 +3307,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue(0)); + item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); } /*! diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 0f2d671..ad0dc97 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -3934,8 +3934,26 @@ void tst_QGraphicsItem::itemChange() tester.itemSceneChangeTargetScene = 0; tester.itemChangeReturnValue = QVariant(); scene.removeItem(&tester); + ++changeCount; // ItemSceneChange + ++changeCount; // ItemSceneHasChanged QCOMPARE(tester.scene(), (QGraphicsScene *)0); } + { + // ItemToolTipChange/ItemToolTipHasChanged + const QString toolTip(QLatin1String("I'm soo cool")); + const QString overridenToolTip(QLatin1String("No, you are not soo cool")); + tester.itemChangeReturnValue = overridenToolTip; + tester.setToolTip(toolTip); + ++changeCount; // ItemToolTipChange + ++changeCount; // ItemToolTipHasChanged + QCOMPARE(tester.changes.size(), changeCount); + QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange); + QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip); + QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged); + QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip); + QCOMPARE(tester.toolTip(), overridenToolTip); + tester.itemChangeReturnValue = QVariant(); + } } class EventFilterTesterItem : public QGraphicsLineItem -- cgit v0.12 From 79799ec4788692d44862832d85f80953d386cb27 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Wed, 1 Apr 2009 11:25:01 +0200 Subject: Fixes: Partially revert 9b0af2395c84a6895a5ce6368f151d4ec00c8755 RevBy: Andreas AutoTest: tst_QGraphicsView::itemAt2 pass again Details: A QPoint in the view has to be mapped to a pixel in the scene, otherwise it won't be possible to e.g. click on items that are smaller than a pixel. So...we have to optimize the hit-testing code in another way --- src/gui/graphicsview/qgraphicsview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index ba9cdbf..f0d360a 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2251,9 +2251,9 @@ QList QGraphicsView::items(const QPoint &pos) const if (d->scene->d_func()->largestUntransformableItem.isNull()) { if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { QTransform xinv = viewportTransform().inverted(); - return d->scene->items(xinv.map(pos)); + return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1))); } - return d->scene->items(mapToScene(pos)); + return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2)); } QPainterPath path; -- cgit v0.12 From 32767aa5699937a3737b9515f4f82acc04ccdfcd Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 3 Apr 2009 11:47:59 +0200 Subject: Fixes: Optimize the way we adjust rectangles. RevBy: Olivier AutoTest: Still pass --- src/gui/graphicsview/qgraphicsitem.cpp | 39 ++++++++--------- src/gui/graphicsview/qgraphicsscene.cpp | 76 +++++++++++++++++++++------------ 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 11a03b6..8478561 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -528,25 +528,22 @@ QT_BEGIN_NAMESPACE // QRectF::intersects() returns false always if either the source or target // rectangle's width or height are 0. This works around that problem. -static QRectF _q_adjustedRect(const QRectF &rect) -{ - static const qreal p = (qreal)0.00001; - QRectF r = rect; - if (!r.width()) - r.adjust(-p, 0, p, 0); - if (!r.height()) - r.adjust(0, -p, 0, p); - return r; +static inline void _q_adjustRect(QRectF *rect) +{ + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(-0.00001, 0, 0.00001, 0); + if (!rect->height()) + rect->adjust(0, -0.00001, 0, 0.00001); } -static QRect _q_adjustedRect(const QRect &rect) +static inline void _q_adjustRect(QRect *rect) { - QRect r = rect; - if (!r.width()) - r.adjust(0, 0, 1, 0); - if (!r.height()) - r.adjust(0, 0, 0, 1); - return r; + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(0, 0, 1, 0); + if (!rect->height()) + rect->adjust(0, 0, 0, 1); } /* @@ -3305,8 +3302,10 @@ bool QGraphicsItem::collidesWithPath(const QPainterPath &path, Qt::ItemSelection return false; } - const QRectF rectA = _q_adjustedRect(boundingRect()); - const QRectF rectB = _q_adjustedRect(path.controlPointRect()); + QRectF rectA(boundingRect()); + _q_adjustRect(&rectA); + QRectF rectB(path.controlPointRect()); + _q_adjustRect(&rectB); if (!rectA.intersects(rectB)) { // This we can determine efficiently. If the two rects neither // intersect nor contain eachother, then the two items do not collide. @@ -3489,7 +3488,9 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c // into the bitmap, converts the result to a QRegion and scales the region // back to device space with inverse granularity. qreal granularity = boundingRegionGranularity(); - QRect deviceRect = _q_adjustedRect(itemToDeviceTransform.mapRect(boundingRect()).toRect()); + QRectF adjustedMappedBoundingRect(itemToDeviceTransform.mapRect(boundingRect())); + _q_adjustRect(&adjustedMappedBoundingRect); + QRect deviceRect = adjustedMappedBoundingRect.toRect(); if (granularity == 0.0) return QRegion(deviceRect); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bcc329e..a5fec69 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -292,15 +292,21 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) // QRectF::intersects() returns false always if either the source or target // rectangle's width or height are 0. This works around that problem. -static QRectF _q_adjustedRect(const QRectF &rect) +static inline void _q_adjustRect(QRectF *rect) { - static const qreal p = (qreal)0.00001; - QRectF r = rect; - if (!r.width()) - r.adjust(-p, 0, p, 0); - if (!r.height()) - r.adjust(0, -p, 0, p); - return r; + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(-0.00001, 0, 0.00001, 0); + if (!rect->height()) + rect->adjust(0, -0.00001, 0, 0.00001); +} + +static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->boundingRect()); + _q_adjustRect(&boundingRect); + return boundingRect; } static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) @@ -1374,7 +1380,7 @@ QList QGraphicsScenePrivate::items_helper(const QPointF &pos) c // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); // Rect intersects/contains item's shape if (QRectF_intersects(adjustedRect, x.mapRect(br))) { bool ok; @@ -1410,7 +1416,8 @@ QList QGraphicsScenePrivate::items_helper(const QRectF &rect, // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. - QRectF adjustedRect = _q_adjustedRect(rect); + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { // Find the item's scene transform in a clever way. QTransform x = item->sceneTransform(); @@ -1419,7 +1426,7 @@ QList QGraphicsScenePrivate::items_helper(const QRectF &rect, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Rect intersects/contains item's bounding rect QRectF mbr = x.mapRect(br); @@ -1471,7 +1478,8 @@ QList QGraphicsScenePrivate::items_helper(const QPolygonF &poly { QList items; - QRectF polyRect = _q_adjustedRect(polygon.boundingRect()); + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); QPainterPath path; // The index returns a rough estimate of what items are inside the rect. @@ -1484,7 +1492,7 @@ QList QGraphicsScenePrivate::items_helper(const QPolygonF &poly // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Polygon contains/intersects item's bounding rect if (path == QPainterPath()) @@ -1529,7 +1537,8 @@ QList QGraphicsScenePrivate::items_helper(const QPainterPath &p Qt::SortOrder order) const { QList items; - const QRectF pathRect = _q_adjustedRect(path.controlPointRect()); + QRectF pathRect(path.controlPointRect()); + _q_adjustRect(&pathRect); // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. @@ -1541,7 +1550,7 @@ QList QGraphicsScenePrivate::items_helper(const QPainterPath &p // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Path contains/intersects item's bounding rect if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) @@ -1620,7 +1629,9 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF r = !parentClip ? _q_adjustedRect(rect) : _q_adjustedRect(rect).intersected(_q_adjustedRect(parent->boundingRect())); + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); if (r.isEmpty()) return; @@ -1640,7 +1651,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); QRectF mbr = item->mapRectToParent(br); if (mode >= Qt::ContainsItemBoundingRect) { // Rect intersects/contains item's bounding rect @@ -1684,8 +1695,9 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF polyRect = _q_adjustedRect(polygon.boundingRect()); - QRectF r = !parentClip ? polyRect : polyRect.intersected(_q_adjustedRect(parent->boundingRect())); + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); + QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); if (r.isEmpty()) return; @@ -1705,7 +1717,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Polygon contains/intersects item's bounding rect if (path == QPainterPath()) @@ -1743,8 +1755,9 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF pathRect = _q_adjustedRect(path.boundingRect()); - QRectF r = !parentClip ? pathRect : pathRect.intersected(_q_adjustedRect(parent->boundingRect())); + QRectF pathRect(path.boundingRect()); + _q_adjustRect(&pathRect); + QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); if (r.isEmpty()) return; @@ -1763,7 +1776,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Polygon contains/intersects item's bounding rect if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) @@ -4690,7 +4703,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte // Item's (local) bounding rect QRectF brect = item->boundingRect(); - if (_q_adjustedRect(brect).isEmpty()) + QRectF adjustedBrect(brect); + _q_adjustRect(&adjustedBrect); + if (adjustedBrect.isEmpty()) return; // Fetch the off-screen transparent buffer and exposed area info. @@ -5232,9 +5247,12 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) update(item->sceneBoundingRect()); } else { // ### Remove _q_adjustedRects(). - QRectF boundingRect = _q_adjustedRect(item->boundingRect()); - if (!rect.isNull()) - boundingRect &= _q_adjustedRect(rect); + QRectF boundingRect(adjustedItemBoundingRect(item)); + if (!rect.isNull()) { + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + boundingRect &= adjustedRect; + } // Update each view directly. for (int i = 0; i < d->views.size(); ++i) @@ -5264,7 +5282,9 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) // defined scene rect. if (!d->hasSceneRect) { QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect; - d->growingItemsBoundingRect |= _q_adjustedRect(item->sceneBoundingRect()); + QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect()); + _q_adjustRect(&adjustedItemSceneBoundingRect); + d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect; if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect) emit sceneRectChanged(d->growingItemsBoundingRect); } -- cgit v0.12 From 3dc62362f3380fa653bc1225ce06e5e4cefa745a Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 3 Apr 2009 16:39:58 +0200 Subject: Fixes: We have to adjust the item's bounding rect. RevBy: Andreas AutoTest: Still pass Details: QRectF::intersects does not work with flat rectangles, so we cannot intersect the bounding rect without adjusting it first. --- src/gui/graphicsview/qgraphicsview.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index f0d360a..c4297df 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -790,6 +790,19 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); } +// QRectF::intersects() returns false always if either the source or target +// rectangle's width or height are 0. This works around that problem. +static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->boundingRect()); + if (!boundingRect.width()) + boundingRect.adjust(-0.00001, 0, 0.00001, 0); + if (!boundingRect.height()) + boundingRect.adjust(0, -0.00001, 0, 0.00001); + return boundingRect; +} + /*! \internal */ @@ -802,7 +815,7 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) QRectF updateRect = rect; if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) { - updateRect &= item->boundingRect(); + updateRect &= adjustedItemBoundingRect(item); if (updateRect.isEmpty()) return; } @@ -814,7 +827,8 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) while ((parent = parent->d_ptr->parent)) { if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { // Map update rect to the current parent and itersect with its bounding rect. - updateRect = clipItem->itemTransform(parent).mapRect(updateRect) & parent->boundingRect(); + updateRect = clipItem->itemTransform(parent).mapRect(updateRect) + & adjustedItemBoundingRect(parent); if (updateRect.isEmpty()) return; clipItem = parent; -- cgit v0.12 From 416fd77e653d089b7832002a68d5b7725fa492db Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 3 Apr 2009 16:52:10 +0200 Subject: Fixes: Wrong adjustment of rect added in 0aa2ef27249dc8e782c2942340776bb19de80a0d RevBy: TrustMe AutoTest: tst_QGraphicsItem::boundingRegion() pass again Details: The original code adjusted the QRect version of a mapped bounding rect, wheras my patch adjusted a mapped bounding rect (QRectF) and then converted it to a QRect. --- src/gui/graphicsview/qgraphicsitem.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 8478561..9d320b7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3488,9 +3488,8 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c // into the bitmap, converts the result to a QRegion and scales the region // back to device space with inverse granularity. qreal granularity = boundingRegionGranularity(); - QRectF adjustedMappedBoundingRect(itemToDeviceTransform.mapRect(boundingRect())); - _q_adjustRect(&adjustedMappedBoundingRect); - QRect deviceRect = adjustedMappedBoundingRect.toRect(); + QRect deviceRect = itemToDeviceTransform.mapRect(boundingRect()).toRect(); + _q_adjustRect(&deviceRect); if (granularity == 0.0) return QRegion(deviceRect); -- cgit v0.12 From cc18633fe45d599bfeac2a8b2737d155f1dd5564 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 6 Apr 2009 13:31:02 +0200 Subject: Fixup update rect regression by adjusting expose rectangles. This change shows a limitation in Graphics View caused by QPen's default width being 0 (cosmetic), while Graphics View actually does not support cosmetic pens at all. Because items are at risk of drawing lines that poke 1 pixel outside their bounding rect, QGraphicsView must look for items that are up to one pixel larger than their bounding rect mapped to viewport coordinates. Furthermore, mapToScene(QRect) forces us to adjust the input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight() (etc) when mapping the rectangle to a polygon (which is _wrong_). Since this behavior has been there since 4.2, we don't want to fix it in a 4.5 patch release... The only _proper_ fix to this problem is for the view to know the item's "adjust" in device coordinates, allowing items to use cosmetic pens freely. Fex, we could introduce QGraphicsItem::viewportMargins() or so. Added an autotest to ensure this doesn't break again. Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsview.cpp | 42 ++++++++++++++---- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 61 ++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c4297df..418638f 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1046,13 +1046,24 @@ void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array extern QPainterPath qt_regionToPath(const QRegion ®ion); +/*! + ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the + input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight() + (etc) when mapping the rectangle to a polygon (which is _wrong_). In + addition, as QGraphicsItem::boundingRect() is defined in logical space, + but the default pen for QPainter is cosmetic with a width of 0, QPainter + is at risk of painting 1 pixel outside the bounding rect. Therefore we + must search for items with an adjustment of (-1, -1, 1, 1). +*/ QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const { Q_Q(const QGraphicsView); - const QPainterPath exposedPath(qt_regionToPath(exposedRegion)); - const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); - if (exposedScenePath.contains(scene->d_func()->growingItemsBoundingRect)) { + // Step 1) If all items are contained within the expose region, then + // return a list of all visible items. + const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 2, 2)) + .boundingRect(); + if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) { Q_ASSERT(allItems); *allItems = true; @@ -1072,12 +1083,27 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg return itemList; } + // Step 2) If the expose region is a simple rect and the view is only + // translated or scaled, search for items using + // QGraphicsScene::items(QRectF). + bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull() + && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale); + if (simpleRectLookup) { + return scene->d_func()->items_helper(exposedRegionSceneBounds, + Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder); + } + + // If the region is complex or the view has a complex transform, adjust + // the expose region, convert it to a path, and then search for items + // using QGraphicsScene::items(QPainterPath); + QRegion adjustedRegion; + foreach (const QRect &r, exposedRegion.rects()) + adjustedRegion += r.adjusted(-1, -1, 1, 1); + + const QPainterPath exposedPath(qt_regionToPath(adjustedRegion)); if (scene->d_func()->largestUntransformableItem.isNull()) { - if (exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale) { - return scene->d_func()->items_helper(exposedScenePath.controlPointRect(), - Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder); - } + const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); return scene->d_func()->items_helper(exposedScenePath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 4368e76..412c6c5 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -155,6 +155,8 @@ private slots: void fitInView(); void itemsAtPoint(); void itemsInRect(); + void itemsInRect_cosmeticAdjust_data(); + void itemsInRect_cosmeticAdjust(); void itemsInPoly(); void itemsInPath(); void itemAt(); @@ -1310,6 +1312,65 @@ void tst_QGraphicsView::itemsInRect() QCOMPARE(items.takeFirst()->zValue(), qreal(3)); } +class CountPaintItem : public QGraphicsRectItem +{ +public: + int numPaints; + + CountPaintItem(const QRectF &rect) + : QGraphicsRectItem(rect), numPaints(0) + { } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) + { + ++numPaints; + QGraphicsRectItem::paint(painter, option, widget); + } +}; + +void tst_QGraphicsView::itemsInRect_cosmeticAdjust_data() +{ + QTest::addColumn("updateRect"); + QTest::addColumn("numPaints"); + + QTest::newRow("nil") << QRect() << 1; + QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1; + QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1; + QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1; + QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1; + QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 0; + QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 0; + QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 0; + QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 0; +} + +void tst_QGraphicsView::itemsInRect_cosmeticAdjust() +{ + QFETCH(QRect, updateRect); + QFETCH(int, numPaints); + + QGraphicsScene scene(-100, -100, 200, 200); + CountPaintItem *rect = new CountPaintItem(QRectF(-50, -50, 100, 100)); + scene.addItem(rect); + + QGraphicsView view(&scene); + view.setFrameStyle(0); + view.resize(300, 300); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(125); + + rect->numPaints = 0; + if (updateRect.isNull()) + view.viewport()->update(); + else + view.viewport()->update(updateRect); + qApp->processEvents(); + QCOMPARE(rect->numPaints, numPaints); +} + void tst_QGraphicsView::itemsInPoly() { QGraphicsScene scene; -- cgit v0.12 From f06c4f2d7378b40a0a184393a8986032d5a700ee Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Mon, 6 Apr 2009 14:17:15 +0200 Subject: BT: Fix combobox background color regression There was a regression in the background color for QComboBox popups. This should resolve it. It essentially tells the system to stay off the system palette while QGtkStyle is used. We will introduce a cleaner style hint for this in 4.6. Reviewed-by: nrc --- src/gui/kernel/qapplication_x11.cpp | 6 ++++-- src/gui/styles/gtksymbols.cpp | 8 +------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 10fb886..b1270bc 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -1362,8 +1362,10 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue); } - QApplicationPrivate::setSystemPalette(pal); - + // QGtkStyle sets it's own system palette + if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) { + QApplicationPrivate::setSystemPalette(pal); + } QColor::setAllowX11ColorNames(allowX11ColorNames); } diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index 8123d32..f7af8f8 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -504,13 +504,6 @@ static QPalette gtkWidgetPalette(const QString >kWidgetName) pal.setBrush(QPalette::Disabled, QPalette::WindowText, disabledTextColor); pal.setBrush(QPalette::All, QPalette::ButtonText, textColor); pal.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledTextColor); - if (gtkWidgetName == QLS("GtkMenu")) { - // This really applies to the combo box rendering since - // QComboBox copies the palette from a QMenu - GdkColor gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; - QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); - pal.setBrush(QPalette::Base, bgColor); - } return pal; } @@ -528,6 +521,7 @@ void QGtk::applyCustomPaletteHash() GdkColor gdkBg = QGtk::gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL]; QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); menuPal.setBrush(QPalette::Base, bgColor); + menuPal.setBrush(QPalette::Window, bgColor); qApp->setPalette(menuPal, "QMenu"); QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar")); -- cgit v0.12 From b8dcae1572651774085024ddf4cb02e4a954bcd7 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 6 Apr 2009 14:29:02 +0200 Subject: compile for systems without Qt3Support Reviewed-by: joerg QTest::newRow only accepts char* and without Qt3Support there is no implicit cast available. --- tests/auto/qpainter/tst_qpainter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index a4c768d..fb8df2e 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -3629,7 +3629,7 @@ void tst_QPainter::drawImage_data() QString("srcFormat %1, dstFormat %2, odd x: %3, odd width: %4") .arg(srcFormat).arg(dstFormat).arg(odd_x).arg(odd_width); - QTest::newRow(description) << (10 + odd_x) << 10 << (20 + odd_width) << 20 + QTest::newRow(qPrintable(description)) << (10 + odd_x) << 10 << (20 + odd_width) << 20 << QImage::Format(srcFormat) << QImage::Format(dstFormat); } -- cgit v0.12 From 6ce4a3b66e2b31f80d1a2d09a4c4087f88a7a9e8 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 6 Apr 2009 14:42:31 +0200 Subject: remove dead code Reviewed-by: jbache --- tests/auto/qmenubar/tst_qmenubar.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/auto/qmenubar/tst_qmenubar.cpp b/tests/auto/qmenubar/tst_qmenubar.cpp index 277e15c..e0a9f42 100644 --- a/tests/auto/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/qmenubar/tst_qmenubar.cpp @@ -1337,7 +1337,6 @@ tst_QMenuBar::allowActiveAndDisabled() // disabled menu items are added QMenu fileMenu("&File"); - QAction disabledAction() ; // Task 241043 : check that second menu is activated // if all items are disabled QAction *act = fileMenu.addAction("Disabled"); -- cgit v0.12 From e517ecc9025b68179c67a383791eefbedfee0543 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 6 Apr 2009 15:07:58 +0200 Subject: compile Reviewed-by: thartman function declaration was missing arguments as done in the other testcases in 831d2742b7c41924f052acd81620e8bfc58afde7 --- tests/auto/qsqlthread/tst_qsqlthread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qsqlthread/tst_qsqlthread.cpp b/tests/auto/qsqlthread/tst_qsqlthread.cpp index d871be4..8b8fc65 100644 --- a/tests/auto/qsqlthread/tst_qsqlthread.cpp +++ b/tests/auto/qsqlthread/tst_qsqlthread.cpp @@ -70,7 +70,7 @@ public: void recreateTestTables(); void repopulateTestTables(); - void generic_data(); + void generic_data(const QString &engine=QString()); tst_Databases dbs; public slots: -- cgit v0.12 From 1d3706f2b66ba5fbb586e532fc29852f55d81c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 6 Apr 2009 15:57:22 +0200 Subject: Update WebKit from code.staikos.net/srv/git/webkit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using branch origin/qtwebkit-4.5 (f72c14123c593dc9d649d25b7186334bba0026b5) Changes in WebKit since the last update: ++ b/WebCore/ChangeLog 2009-04-06 Tor Arne Vestbø Reviewed by Simon Hausmann. [Qt] Don't show and hide the platformPluginWidget, as it's our QWebView * plugins/mac/PluginViewMac.cpp: (WebCore::PluginView::show): (WebCore::PluginView::hide): (WebCore::PluginView::setParentVisible): 2009-04-06 Mike Belshe Reviewed by Eric Seidel. HTMLCanvasElement crash when ImageBuffer creation fails. https://bugs.webkit.org/show_bug.cgi?id=23212 Check for NULL before using the ImageBuffer as we might be low on memory and creation may have failed. Test case creation blocked by: https://bugs.webkit.org/show_bug.cgi?id=25055 * html/HTMLCanvasElement.cpp: (WebCore::HTMLCanvasElement::createImageBuffer): 2009-04-05 Erik L. Bunce Reviewed by Simon Hausmann. https://bugs.webkit.org/show_bug.cgi?id=25050 Fix an assert failure when dropping an 'empty' text/uri-list on a QWebView. * platform/qt/DragDataQt.cpp: (WebCore::DragData::asURL): ++ b/WebKitTools/ChangeLog 2009-03-31 Adam Roben Make resolve-ChangeLogs -f work when the working tree has spaces in its path Reviewed by Mark Rowe and David Kilzer. * Scripts/resolve-ChangeLogs: (sub fixMergedChangeLogs): Quote the path to resolve-ChangeLogs in case it contains spaces. 2009-03-17 David Kilzer resolve-ChangeLogs should not die on unmerged non-ChangeLog files Reviewed by Adam Roben. Fixes the following bug in resolve-ChangeLogs: Use of uninitialized value in -e at ./WebKitTools/Scripts/resolve-ChangeLogs line 132. Died at ./WebKitTools/Scripts/resolve-ChangeLogs line 164. * Scripts/resolve-ChangeLogs: (findUnmergedChangeLogs): Check the result of findChangeLog() to make sure we don't add undef values to the list of files being returned. 2009-03-11 David Kilzer Bug 24378: resolve-ChangeLogs should use git status or svn status to find and fix unmerged ChangeLogs Reviewed by Adam Roben. * Scripts/resolve-ChangeLogs: If -f|--fix-merged is not passed and no file or directory names are specified on the command-line then try to find unmerged ChangeLog files based on 'svn stat' or 'git diff'. Added global $isGit and $isSVN variables so that isGit() and isSVN() only have to be called once. (findUnmergedChangeLogs): Added. --- src/3rdparty/webkit/VERSION | 2 +- src/3rdparty/webkit/WebCore/ChangeLog | 38 + .../webkit/WebCore/generated/CSSPropertyNames.cpp | 5 +- .../webkit/WebCore/generated/CSSValueKeywords.c | 5 +- src/3rdparty/webkit/WebCore/generated/ColorData.c | 5 +- .../webkit/WebCore/generated/DocTypeStrings.cpp | 5 +- .../webkit/WebCore/generated/HTMLEntityNames.c | 5 +- .../webkit/WebCore/generated/tokenizer.cpp | 2315 ++++++-------------- .../webkit/WebCore/html/HTMLCanvasElement.cpp | 4 + .../webkit/WebCore/platform/qt/DragDataQt.cpp | 6 +- .../webkit/WebCore/plugins/mac/PluginViewMac.cpp | 9 - src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp | 2 +- 12 files changed, 744 insertions(+), 1657 deletions(-) diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index 1ebf6ef..9decb66 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 - 9c6a4a25fe741b43dd64f5dbaeccfb647cb321fb + f72c14123c593dc9d649d25b7186334bba0026b5 diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index e8850f3..d0382f2 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,41 @@ +2009-04-06 Tor Arne Vestbø + + Reviewed by Simon Hausmann. + + [Qt] Don't show and hide the platformPluginWidget, as it's our QWebView + + * plugins/mac/PluginViewMac.cpp: + (WebCore::PluginView::show): + (WebCore::PluginView::hide): + (WebCore::PluginView::setParentVisible): + +2009-04-06 Mike Belshe + + Reviewed by Eric Seidel. + + HTMLCanvasElement crash when ImageBuffer creation fails. + https://bugs.webkit.org/show_bug.cgi?id=23212 + + Check for NULL before using the ImageBuffer as we might + be low on memory and creation may have failed. + + Test case creation blocked by: + https://bugs.webkit.org/show_bug.cgi?id=25055 + + * html/HTMLCanvasElement.cpp: + (WebCore::HTMLCanvasElement::createImageBuffer): + +2009-04-05 Erik L. Bunce + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=25050 + + Fix an assert failure when dropping an 'empty' text/uri-list on a QWebView. + + * platform/qt/DragDataQt.cpp: + (WebCore::DragData::asURL): + 2009-03-27 Zack Rusin Reviewed by Simon Hausmann. diff --git a/src/3rdparty/webkit/WebCore/generated/CSSPropertyNames.cpp b/src/3rdparty/webkit/WebCore/generated/CSSPropertyNames.cpp index 25313ac..ca4ea5a 100644 --- a/src/3rdparty/webkit/WebCore/generated/CSSPropertyNames.cpp +++ b/src/3rdparty/webkit/WebCore/generated/CSSPropertyNames.cpp @@ -1,4 +1,4 @@ -/* ANSI-C code produced by gperf version 3.0.3 */ +/* ANSI-C code produced by gperf version 3.0.2 */ /* Command-line: gperf -a -L ANSI-C -E -C -c -o -t --key-positions='*' -NfindProp -Hhash_prop -Wwordlist_prop -D -s 2 CSSPropertyNames.gperf */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -217,9 +217,6 @@ hash_prop (register const char *str, register unsigned int len) #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif #endif const struct props * findProp (register const char *str, register unsigned int len) diff --git a/src/3rdparty/webkit/WebCore/generated/CSSValueKeywords.c b/src/3rdparty/webkit/WebCore/generated/CSSValueKeywords.c index 5ff0858..d0433e0 100644 --- a/src/3rdparty/webkit/WebCore/generated/CSSValueKeywords.c +++ b/src/3rdparty/webkit/WebCore/generated/CSSValueKeywords.c @@ -1,4 +1,4 @@ -/* ANSI-C code produced by gperf version 3.0.3 */ +/* ANSI-C code produced by gperf version 3.0.2 */ /* Command-line: gperf -L ANSI-C -E -C -n -o -t --key-positions='*' -NfindValue -Hhash_val -Wwordlist_value -D CSSValueKeywords.gperf */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -179,9 +179,6 @@ hash_val (register const char *str, register unsigned int len) #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif #endif const struct css_value * findValue (register const char *str, register unsigned int len) diff --git a/src/3rdparty/webkit/WebCore/generated/ColorData.c b/src/3rdparty/webkit/WebCore/generated/ColorData.c index 478566c..18d9926 100644 --- a/src/3rdparty/webkit/WebCore/generated/ColorData.c +++ b/src/3rdparty/webkit/WebCore/generated/ColorData.c @@ -1,5 +1,5 @@ #include // bogus -/* ANSI-C code produced by gperf version 3.0.3 */ +/* ANSI-C code produced by gperf version 3.0.2 */ /* Command-line: gperf -CDEot -L ANSI-C --key-positions='*' -N findColor -D -s 2 */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -141,9 +141,6 @@ hash (register const char *str, register unsigned int len) #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif #endif const struct NamedColor * findColor (register const char *str, register unsigned int len) diff --git a/src/3rdparty/webkit/WebCore/generated/DocTypeStrings.cpp b/src/3rdparty/webkit/WebCore/generated/DocTypeStrings.cpp index 686629c..ad63b9e 100644 --- a/src/3rdparty/webkit/WebCore/generated/DocTypeStrings.cpp +++ b/src/3rdparty/webkit/WebCore/generated/DocTypeStrings.cpp @@ -1,5 +1,5 @@ #include // bogus -/* ANSI-C code produced by gperf version 3.0.3 */ +/* ANSI-C code produced by gperf version 3.0.2 */ /* Command-line: gperf -CEot -L ANSI-C --key-positions='*' -N findDoctypeEntry -F ,PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -331,9 +331,6 @@ hash (register const char *str, register unsigned int len) #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif #endif const struct PubIDInfo * findDoctypeEntry (register const char *str, register unsigned int len) diff --git a/src/3rdparty/webkit/WebCore/generated/HTMLEntityNames.c b/src/3rdparty/webkit/WebCore/generated/HTMLEntityNames.c index 993e106..470c4cd 100644 --- a/src/3rdparty/webkit/WebCore/generated/HTMLEntityNames.c +++ b/src/3rdparty/webkit/WebCore/generated/HTMLEntityNames.c @@ -1,4 +1,4 @@ -/* ANSI-C code produced by gperf version 3.0.3 */ +/* ANSI-C code produced by gperf version 3.0.2 */ /* Command-line: gperf -a -L ANSI-C -C -G -c -o -t --key-positions='*' -N findEntity -D -s 2 */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -520,9 +520,6 @@ static const short lookup[] = #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif #endif const struct Entity * findEntity (register const char *str, register unsigned int len) diff --git a/src/3rdparty/webkit/WebCore/generated/tokenizer.cpp b/src/3rdparty/webkit/WebCore/generated/tokenizer.cpp index 8462f51..1da1a0b 100644 --- a/src/3rdparty/webkit/WebCore/generated/tokenizer.cpp +++ b/src/3rdparty/webkit/WebCore/generated/tokenizer.cpp @@ -78,42 +78,42 @@ static yyconst flex_int16_t yy_accept[479] = { 0, 0, 0, 0, 0, 0, 0, 69, 67, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 56, - 67, 67, 15, 15, 15, 67, 67, 67, 67, 66, + 67, 67, 67, 67, 15, 15, 15, 67, 67, 66, 15, 15, 15, 65, 15, 2, 0, 0, 0, 14, - 0, 0, 0, 18, 18, 0, 8, 0, 0, 9, - 0, 0, 15, 15, 15, 0, 57, 0, 55, 0, - 0, 56, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 16, 54, 54, 51, 54, 0, 54, 0, 0, - 35, 35, 35, 35, 35, 35, 35, 0, 62, 15, - 0, 0, 15, 15, 0, 15, 15, 15, 7, 6, + 0, 0, 0, 0, 18, 18, 8, 0, 0, 9, + 0, 0, 0, 15, 15, 15, 57, 0, 55, 0, + 0, 56, 0, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 16, 54, 54, 51, 54, 0, 0, + 0, 35, 35, 35, 35, 35, 35, 35, 15, 15, + 7, 62, 15, 0, 0, 15, 15, 0, 15, 6, 5, 15, 15, 15, 15, 0, 0, 0, 14, 0, - 0, 0, 18, 18, 0, 18, 18, 0, 0, 14, - 0, 0, 4, 16, 15, 0, 0, 54, 0, 41, - 54, 37, 39, 54, 52, 43, 54, 42, 50, 54, - 45, 44, 40, 54, 54, 54, 54, 54, 0, 35, - 35, 0, 35, 35, 35, 35, 35, 35, 35, 35, - 15, 15, 16, 15, 15, 63, 63, 15, 15, 12, - 10, 15, 13, 0, 0, 0, 17, 17, 18, 18, - 18, 0, 0, 15, 0, 1, 54, 54, 46, 54, - 53, 16, 47, 54, 54, 54, 3, 35, 35, 35, - - 35, 35, 35, 35, 35, 35, 35, 15, 58, 0, - 63, 63, 63, 62, 15, 11, 0, 0, 0, 18, - 18, 18, 0, 15, 0, 0, 54, 48, 49, 54, - 54, 35, 35, 35, 35, 35, 35, 35, 20, 35, - 15, 64, 63, 63, 63, 63, 0, 0, 0, 0, - 60, 0, 15, 0, 0, 0, 18, 18, 18, 0, - 15, 54, 54, 38, 35, 35, 35, 35, 35, 21, - 35, 35, 15, 64, 63, 63, 63, 63, 63, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, - 0, 15, 0, 0, 17, 17, 18, 18, 0, 15, - - 54, 54, 35, 35, 35, 35, 19, 35, 35, 15, - 64, 63, 63, 63, 63, 63, 63, 0, 59, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 15, 0, 0, 18, 18, 0, 15, 54, 54, 35, - 35, 23, 35, 35, 35, 15, 64, 63, 63, 63, + 0, 0, 18, 18, 18, 0, 18, 0, 0, 14, + 0, 0, 4, 16, 15, 0, 0, 54, 54, 54, + 0, 54, 41, 54, 37, 39, 54, 52, 43, 54, + 42, 50, 54, 45, 44, 40, 54, 54, 0, 35, + 35, 35, 35, 0, 35, 35, 35, 35, 35, 35, + 15, 15, 15, 16, 15, 15, 63, 63, 15, 12, + 10, 15, 13, 0, 0, 0, 17, 18, 18, 18, + 17, 0, 0, 15, 0, 1, 54, 54, 54, 54, + 46, 54, 53, 16, 47, 54, 3, 35, 35, 35, + + 35, 35, 35, 35, 35, 35, 35, 15, 15, 58, + 0, 63, 63, 63, 62, 11, 0, 0, 0, 18, + 18, 18, 0, 15, 0, 0, 54, 54, 54, 48, + 49, 35, 35, 35, 35, 35, 35, 35, 35, 20, + 15, 15, 64, 63, 63, 63, 63, 0, 0, 0, + 0, 60, 0, 0, 0, 0, 18, 18, 18, 0, + 15, 54, 54, 38, 35, 35, 35, 35, 35, 35, + 21, 35, 15, 15, 64, 63, 63, 63, 63, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, + 0, 0, 0, 0, 17, 18, 18, 17, 0, 15, + + 54, 54, 35, 35, 35, 35, 35, 19, 35, 15, + 15, 64, 63, 63, 63, 63, 63, 63, 0, 59, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 18, 0, 15, 54, 54, 35, + 35, 35, 23, 35, 35, 15, 64, 63, 63, 63, 63, 63, 63, 63, 0, 59, 0, 0, 0, 59, 0, 0, 0, 0, 18, 15, 54, 35, 35, 35, 35, 64, 0, 0, 0, 36, 15, 35, 35, 35, @@ -122,7 +122,7 @@ static yyconst flex_int16_t yy_accept[479] = 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 0, 0, 35, 35, 35, 35, 25, 35, - 35, 35, 0, 61, 0, 0, 0, 0, 26, 35, + 35, 35, 0, 0, 0, 61, 0, 0, 26, 35, 35, 35, 35, 27, 35, 0, 0, 0, 0, 31, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 35, 0, 0, 35, 35, 29, 35, 0, 0, 35, @@ -138,909 +138,437 @@ static yyconst flex_int32_t yy_ec[256] = 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 12, 18, 19, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 12, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 12, 54, 12, 55, 56, 12, 57, 58, 59, 60, - - 61, 62, 63, 64, 65, 37, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 12, 84, 1, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85 + 24, 25, 26, 27, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 12, 28, 12, 29, 30, 12, 31, 32, 33, 34, + + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 12, 59, 1, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60 } ; -static yyconst flex_int32_t yy_meta[86] = +static yyconst flex_int32_t yy_meta[61] = { 0, - 1, 2, 3, 4, 4, 5, 6, 7, 6, 6, - 6, 6, 7, 8, 9, 6, 6, 10, 6, 6, - 11, 6, 6, 6, 6, 12, 6, 13, 13, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 6, 14, 13, 13, 13, 13, - 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 6, 6, 6, 14 + 1, 2, 3, 3, 3, 4, 5, 5, 5, 5, + 5, 5, 5, 6, 7, 5, 5, 8, 5, 5, + 9, 5, 5, 5, 5, 10, 5, 11, 5, 11, + 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 5, 5, 5, 11 } ; -static yyconst flex_int16_t yy_base[550] = +static yyconst flex_int16_t yy_base[517] = { 0, - 0, 0, 64, 66, 54, 56, 1407, 6578, 93, 98, - 107, 83, 155, 1376, 77, 1350, 99, 1345, 1328, 207, - 1334, 275, 100, 108, 125, 326, 1315, 1313, 1312, 6578, - 141, 110, 151, 6578, 105, 197, 295, 89, 107, 6578, - 387, 120, 0, 429, 1281, 471, 6578, 117, 532, 6578, - 1283, 269, 137, 176, 281, 574, 283, 1289, 1292, 1246, - 1257, 0, 1221, 249, 135, 282, 276, 153, 91, 169, - 299, 308, 318, 266, 1219, 320, 616, 102, 1246, 348, - 1209, 316, 127, 359, 346, 347, 375, 658, 6578, 208, - 700, 1241, 400, 409, 1220, 397, 327, 761, 6578, 6578, - - 6578, 411, 419, 414, 424, 248, 368, 355, 356, 822, - 883, 0, 1191, 925, 967, 1190, 1028, 381, 421, 464, - 1089, 1150, 6578, 214, 456, 1225, 312, 1151, 1192, 1142, - 442, 1139, 1134, 452, 1131, 1104, 458, 1082, 1060, 358, - 1046, 1028, 1027, 462, 453, 1000, 1253, 469, 1023, 463, - 986, 1295, 492, 486, 500, 484, 502, 513, 969, 1356, - 425, 1417, 1001, 545, 494, 193, 993, 543, 1459, 544, - 554, 558, 555, 508, 398, 1520, 0, 1562, 956, 1623, - 1684, 570, 1745, 563, 993, 6578, 948, 1806, 935, 520, - 921, 498, 914, 546, 1848, 564, 6578, 585, 913, 1909, - - 568, 576, 586, 606, 631, 640, 1951, 2012, 6578, 0, - 203, 924, 907, 694, 2054, 565, 543, 2115, 0, 2157, - 2218, 2279, 2340, 669, 912, 505, 2401, 856, 840, 2443, - 612, 615, 2504, 608, 557, 639, 682, 668, 839, 2546, - 2607, 0, 288, 863, 841, 819, 741, 794, 573, 418, - 6578, 2668, 2710, 620, 2771, 0, 2813, 2874, 2935, 2996, - 3057, 3131, 3173, 3234, 670, 3295, 718, 719, 729, 763, - 684, 3337, 3398, 0, 456, 782, 777, 760, 742, 829, - 649, 834, 3459, 572, 3520, 854, 894, 915, 920, 3581, - 3642, 3684, 593, 3745, 6578, 697, 3806, 3867, 3928, 3989, - - 4050, 4111, 730, 4172, 731, 683, 672, 759, 4214, 4275, - 0, 762, 682, 429, 417, 414, 411, 859, 6578, 650, - 838, 957, 4336, 4397, 607, 926, 988, 4458, 4519, 4580, - 1002, 672, 1010, 4622, 4664, 1042, 752, 4706, 4767, 756, - 4828, 376, 812, 847, 1069, 1033, 0, 387, 6578, 6578, - 6578, 6578, 6578, 6578, 1122, 924, 963, 4870, 1162, 1049, - 1050, 4912, 4973, 678, 1063, 850, 1074, 5005, 1103, 841, - 989, 0, 5062, 5104, 5146, 6578, 1066, 1080, 1081, 1084, - 1108, 1137, 877, 328, 273, 6578, 5188, 5230, 5272, 641, - 1140, 884, 916, 836, 1105, 1161, 5314, 5356, 1233, 1286, - - 1147, 1138, 919, 1206, 1165, 1186, 1141, 1207, 1291, 1263, - 1316, 1345, 1327, 5398, 1086, 1029, 1225, 1133, 258, 1247, - 1248, 1310, 1388, 6578, 1427, 5440, 1449, 5501, 242, 1311, - 1341, 1324, 1326, 173, 1317, 1454, 5562, 1480, 5604, 170, - 1061, 1328, 1355, 1372, 1552, 5646, 5688, 1351, 1374, 1389, - 1409, 5730, 5772, 1419, 1456, 154, 1453, 5814, 5856, 1457, - 112, 897, 793, 5898, 1557, 1418, 109, 1348, 1582, 1550, - 1477, 1481, 1485, 90, 1564, 1458, 39, 6578, 5959, 5964, - 5977, 5982, 5987, 5994, 6004, 6017, 296, 6022, 6032, 6045, - 6059, 651, 6064, 6074, 6079, 6089, 6099, 6103, 571, 6112, - - 6125, 6138, 6152, 6166, 6176, 6186, 6191, 6203, 657, 6217, - 758, 6222, 6234, 6247, 801, 6261, 859, 6266, 6278, 6291, - 6304, 6317, 6330, 1086, 6335, 6348, 1120, 6353, 6365, 6378, - 6391, 6404, 6417, 6430, 6435, 6448, 1216, 6453, 6465, 6478, - 6491, 6504, 6517, 1219, 1220, 6530, 6543, 6553, 6563 + 0, 0, 39, 41, 1573, 1566, 1594, 2399, 62, 71, + 76, 61, 69, 1560, 78, 1559, 89, 1561, 1565, 132, + 1573, 91, 123, 1555, 80, 104, 97, 1554, 1551, 2399, + 85, 176, 175, 2399, 177, 193, 204, 1531, 84, 2399, + 242, 110, 180, 196, 1545, 205, 2399, 113, 277, 2399, + 1547, 72, 221, 133, 206, 234, 181, 1555, 1548, 1530, + 1528, 0, 268, 118, 1515, 221, 60, 240, 92, 230, + 95, 223, 244, 267, 238, 286, 1512, 268, 1521, 279, + 294, 1510, 278, 190, 290, 232, 292, 293, 308, 335, + 2399, 2399, 317, 326, 1516, 351, 336, 356, 366, 2399, + + 2399, 320, 367, 369, 370, 1478, 393, 327, 345, 420, + 455, 398, 1495, 490, 1481, 446, 481, 372, 365, 386, + 525, 560, 2399, 325, 388, 1491, 387, 1477, 595, 1476, + 516, 399, 1475, 34, 1472, 1461, 378, 1438, 1430, 318, + 1429, 1426, 323, 1424, 1423, 1422, 231, 387, 1430, 377, + 1411, 630, 1396, 551, 382, 108, 415, 408, 419, 412, + 586, 436, 665, 1400, 624, 456, 419, 1382, 457, 490, + 491, 625, 492, 1362, 526, 656, 672, 681, 1378, 716, + 707, 527, 723, 561, 1374, 2399, 732, 1346, 767, 437, + 1322, 410, 1312, 445, 1311, 546, 2399, 469, 758, 1303, + + 802, 576, 482, 580, 470, 440, 472, 793, 809, 2399, + 818, 515, 1288, 1273, 853, 552, 1205, 839, 855, 861, + 877, 883, 899, 645, 1227, 483, 905, 921, 612, 1183, + 1168, 609, 927, 943, 626, 517, 628, 508, 629, 1167, + 949, 965, 971, 550, 1167, 1157, 1123, 1006, 1020, 666, + 682, 2399, 1047, 1091, 1006, 1038, 1055, 1063, 1071, 1079, + 632, 1087, 1095, 1105, 539, 1103, 1111, 542, 543, 681, + 1097, 683, 1119, 1127, 1135, 585, 1091, 1083, 1067, 1039, + 721, 752, 772, 1170, 717, 1205, 1184, 1217, 1244, 1258, + 1285, 1320, 984, 1244, 2399, 1276, 1311, 917, 1328, 767, + + 1336, 1344, 733, 1352, 1360, 734, 578, 899, 582, 1395, + 1381, 1397, 623, 853, 822, 794, 793, 760, 807, 2399, + 875, 788, 1432, 1459, 1494, 818, 769, 1440, 1529, 1564, + 1438, 702, 1485, 919, 1520, 1555, 849, 963, 1572, 587, + 1299, 1580, 706, 441, 614, 1615, 1601, 715, 2399, 2399, + 2399, 2399, 2399, 2399, 1473, 839, 856, 1617, 1652, 804, + 852, 1638, 1654, 633, 1480, 871, 1508, 1650, 1542, 644, + 834, 1673, 1679, 1695, 1701, 2399, 1015, 872, 915, 916, + 877, 959, 704, 616, 586, 2399, 1717, 1723, 1739, 1002, + 1148, 514, 961, 989, 990, 1016, 1745, 1761, 1767, 1802, + + 1137, 1008, 1018, 1017, 985, 1129, 878, 1038, 1790, 1806, + 1829, 1211, 1827, 1849, 944, 1057, 1152, 787, 584, 615, + 1196, 918, 1863, 1890, 1279, 2399, 1869, 1867, 516, 1199, + 1154, 943, 1242, 515, 653, 1904, 1906, 1941, 1968, 480, + 945, 1200, 1149, 1214, 1927, 1949, 1947, 1239, 1301, 1207, + 1302, 1974, 1990, 1392, 1267, 411, 1354, 1996, 2012, 1310, + 376, 1241, 1039, 2018, 2034, 1338, 348, 1377, 2040, 1216, + 1391, 1421, 1394, 324, 1226, 1376, 263, 2399, 2075, 2080, + 2091, 2096, 2101, 2110, 2117, 2128, 2137, 2142, 2153, 2165, + 2167, 2176, 2181, 2190, 2195, 2204, 2213, 2225, 2234, 2243, + + 2248, 2260, 2265, 2276, 2281, 2292, 2303, 2314, 2319, 2330, + 2341, 2346, 2357, 2366, 2377, 2386 } ; -static yyconst flex_int16_t yy_def[550] = +static yyconst flex_int16_t yy_def[517] = { 0, 478, 1, 1, 1, 1, 1, 478, 478, 478, 478, 478, 479, 480, 478, 481, 478, 482, 478, 478, 478, - 478, 483, 484, 484, 484, 485, 478, 478, 478, 478, - 484, 484, 484, 478, 484, 478, 478, 478, 479, 478, - 486, 480, 487, 488, 488, 489, 478, 481, 490, 478, - 478, 478, 484, 484, 484, 485, 20, 491, 478, 492, - 478, 20, 493, 493, 493, 493, 493, 493, 493, 493, - 493, 493, 493, 493, 493, 493, 494, 493, 478, 483, - 495, 495, 495, 495, 495, 495, 495, 496, 478, 484, - 497, 478, 484, 484, 498, 484, 484, 484, 478, 478, - - 478, 484, 484, 484, 484, 478, 479, 479, 479, 479, - 486, 499, 488, 488, 500, 488, 114, 501, 501, 501, - 501, 502, 478, 478, 484, 503, 504, 493, 505, 493, - 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, + 478, 483, 484, 478, 485, 485, 485, 478, 478, 478, + 485, 485, 485, 478, 485, 478, 478, 478, 479, 478, + 486, 480, 478, 487, 488, 488, 478, 481, 489, 478, + 478, 478, 484, 485, 485, 485, 20, 490, 478, 491, + 478, 20, 492, 493, 493, 493, 493, 493, 493, 493, + 493, 493, 493, 493, 493, 493, 493, 493, 478, 483, + 494, 495, 495, 495, 495, 495, 495, 495, 485, 485, + 478, 478, 485, 496, 478, 485, 485, 478, 485, 478, + + 478, 485, 485, 485, 485, 478, 479, 479, 479, 479, + 486, 478, 488, 46, 488, 497, 46, 481, 481, 481, + 481, 489, 478, 478, 485, 490, 498, 493, 493, 493, + 499, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 478, 495, - 495, 506, 495, 495, 495, 495, 495, 495, 495, 495, - 484, 98, 478, 484, 484, 507, 478, 484, 98, 484, - 484, 484, 484, 478, 508, 508, 509, 114, 488, 114, - 114, 501, 501, 484, 510, 478, 493, 147, 493, 493, - 493, 493, 493, 493, 147, 493, 478, 495, 495, 160, - - 495, 495, 495, 495, 495, 495, 160, 98, 478, 511, - 512, 478, 478, 513, 98, 484, 478, 514, 515, 114, - 114, 114, 501, 484, 510, 516, 147, 493, 493, 147, - 493, 495, 160, 495, 495, 495, 495, 495, 495, 160, - 98, 517, 518, 478, 478, 478, 519, 519, 520, 521, - 478, 522, 98, 478, 523, 524, 525, 525, 258, 526, - 98, 147, 147, 147, 495, 160, 495, 495, 495, 495, - 495, 160, 98, 527, 528, 478, 478, 478, 478, 478, - 520, 478, 529, 530, 531, 532, 532, 532, 532, 532, - 533, 98, 478, 534, 478, 535, 535, 297, 536, 98, - - 147, 301, 495, 160, 495, 495, 495, 495, 160, 98, - 537, 538, 478, 478, 478, 478, 478, 478, 478, 539, - 539, 539, 539, 540, 541, 541, 541, 541, 542, 543, - 300, 478, 534, 297, 298, 536, 300, 301, 301, 495, - 160, 495, 495, 495, 495, 300, 544, 478, 478, 478, - 478, 478, 478, 478, 539, 539, 539, 323, 541, 541, - 541, 328, 543, 478, 335, 300, 339, 495, 495, 495, - 495, 545, 323, 328, 363, 478, 300, 495, 495, 495, - 495, 495, 495, 495, 495, 478, 323, 328, 363, 300, - 495, 495, 495, 495, 495, 495, 323, 328, 543, 546, - - 495, 495, 495, 495, 495, 495, 495, 495, 539, 541, - 546, 546, 547, 548, 495, 495, 495, 495, 495, 495, - 495, 495, 478, 478, 547, 549, 547, 547, 495, 495, - 495, 495, 495, 495, 495, 547, 428, 547, 428, 495, - 495, 495, 495, 495, 547, 437, 428, 495, 495, 495, - 495, 437, 428, 495, 495, 495, 495, 437, 428, 495, - 495, 495, 495, 437, 547, 495, 495, 495, 547, 495, + 495, 495, 495, 500, 495, 495, 495, 495, 495, 495, + 90, 485, 90, 478, 485, 485, 501, 478, 485, 485, + 485, 485, 485, 478, 479, 110, 478, 114, 488, 114, + 46, 481, 121, 485, 502, 478, 129, 493, 129, 493, + 493, 493, 493, 493, 493, 493, 478, 495, 152, 495, + + 152, 495, 495, 495, 495, 495, 495, 90, 163, 478, + 478, 503, 478, 478, 504, 485, 478, 110, 478, 114, + 180, 46, 121, 485, 502, 498, 129, 189, 493, 493, + 493, 495, 152, 201, 495, 495, 495, 495, 495, 495, + 90, 163, 478, 505, 478, 478, 478, 504, 504, 506, + 507, 478, 508, 478, 110, 478, 114, 180, 46, 121, + 485, 129, 189, 493, 495, 152, 201, 495, 495, 495, + 495, 495, 90, 163, 478, 509, 478, 478, 478, 478, + 478, 506, 478, 510, 507, 511, 504, 504, 504, 504, + 504, 508, 478, 110, 478, 114, 180, 488, 121, 485, + + 129, 189, 495, 152, 201, 495, 495, 495, 495, 485, + 163, 478, 512, 478, 478, 478, 478, 478, 478, 478, + 506, 506, 506, 506, 510, 507, 507, 507, 507, 511, + 291, 478, 110, 488, 180, 121, 485, 493, 189, 495, + 495, 201, 495, 495, 495, 485, 478, 478, 478, 478, + 478, 478, 478, 478, 506, 506, 506, 324, 507, 507, + 507, 329, 291, 478, 488, 485, 493, 495, 495, 495, + 495, 478, 324, 329, 291, 478, 485, 495, 495, 495, + 495, 495, 495, 495, 495, 478, 324, 329, 291, 485, + 495, 495, 495, 495, 495, 495, 324, 329, 291, 513, + + 495, 495, 495, 495, 495, 495, 495, 495, 324, 329, + 513, 411, 514, 515, 495, 495, 495, 495, 495, 495, + 495, 495, 515, 515, 478, 478, 515, 516, 495, 495, + 495, 495, 495, 495, 495, 515, 424, 515, 424, 495, + 495, 495, 495, 495, 424, 515, 439, 495, 495, 495, + 495, 424, 439, 495, 495, 495, 495, 424, 439, 495, + 495, 495, 495, 424, 439, 495, 495, 495, 439, 495, 495, 495, 495, 495, 495, 495, 495, 0, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478 + 478, 478, 478, 478, 478, 478 } ; -static yyconst flex_int16_t yy_nxt[6664] = +static yyconst flex_int16_t yy_nxt[2460] = { 0, 8, 9, 10, 9, 9, 9, 11, 12, 13, 14, 8, 8, 15, 8, 8, 16, 8, 17, 18, 19, - 20, 8, 21, 8, 8, 8, 22, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 24, 23, 23, 23, 23, 23, 23, 25, 23, 23, - 23, 23, 23, 26, 27, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 24, 23, - 23, 23, 23, 23, 23, 25, 23, 23, 23, 23, - 23, 8, 28, 29, 23, 30, 35, 30, 35, 40, - 40, 31, 152, 31, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, 36, 32, 33, 32, 33, 37, 37, - 37, 37, 37, 89, 40, 35, 51, 35, 89, 52, - 31, 89, 31, 89, 92, 93, 92, 93, 106, 40, - 49, 136, 32, 33, 32, 33, 41, 478, 89, 54, - 478, 95, 38, 152, 129, 34, 105, 34, 55, 94, - 89, 103, 56, 91, 89, 129, 106, 148, 91, 136, - 41, 91, 152, 91, 89, 152, 131, 54, 154, 96, - 49, 38, 42, 46, 105, 43, 55, 94, 91, 103, - 152, 102, 44, 44, 44, 44, 44, 44, 129, 89, - 91, 104, 92, 93, 91, 131, 154, 96, 36, 36, - - 36, 36, 36, 137, 91, 135, 129, 152, 46, 102, - 210, 44, 44, 44, 44, 44, 44, 59, 212, 104, - 210, 89, 129, 152, 60, 61, 152, 62, 244, 91, - 92, 92, 137, 135, 63, 63, 64, 65, 66, 63, - 67, 68, 69, 63, 70, 63, 71, 72, 63, 73, - 63, 74, 75, 76, 63, 63, 63, 63, 63, 63, - 77, 91, 78, 63, 63, 64, 65, 66, 63, 67, - 68, 69, 70, 63, 71, 72, 63, 73, 63, 74, - 75, 76, 63, 63, 63, 63, 63, 63, 130, 52, - 174, 63, 80, 144, 89, 152, 37, 37, 37, 37, - - 37, 478, 129, 57, 82, 210, 112, 83, 112, 124, - 84, 152, 125, 276, 85, 86, 130, 87, 174, 129, - 134, 132, 144, 63, 92, 140, 152, 127, 88, 129, - 38, 186, 133, 82, 91, 129, 83, 124, 138, 84, - 89, 125, 85, 86, 139, 87, 98, 141, 134, 132, - 153, 63, 129, 98, 98, 98, 98, 98, 98, 38, - 133, 129, 40, 40, 142, 478, 138, 145, 143, 152, - 39, 129, 139, 129, 157, 40, 141, 156, 192, 153, - 91, 152, 98, 98, 98, 98, 98, 98, 39, 39, - 39, 107, 142, 40, 109, 145, 143, 150, 155, 152, - - 152, 88, 158, 157, 210, 40, 156, 110, 41, 41, - 89, 129, 152, 89, 110, 110, 110, 110, 110, 110, - 164, 41, 89, 478, 89, 150, 155, 89, 152, 152, - 282, 158, 89, 40, 49, 168, 354, 89, 89, 353, - 111, 170, 352, 110, 110, 110, 110, 110, 110, 114, - 91, 41, 172, 91, 351, 165, 114, 114, 114, 114, - 114, 114, 91, 168, 91, 171, 478, 91, 173, 89, - 170, 285, 91, 210, 49, 189, 40, 91, 91, 190, - 172, 313, 115, 165, 184, 114, 114, 114, 114, 114, - 114, 117, 193, 171, 198, 129, 173, 194, 117, 117, - - 117, 117, 117, 117, 189, 129, 129, 209, 190, 91, - 191, 129, 196, 184, 204, 129, 152, 49, 192, 201, - 226, 193, 129, 198, 186, 194, 202, 117, 117, 117, - 117, 117, 117, 48, 48, 48, 118, 152, 191, 152, - 196, 205, 203, 204, 120, 152, 206, 91, 201, 217, - 228, 129, 121, 152, 202, 152, 214, 89, 89, 121, - 121, 121, 121, 121, 121, 164, 152, 209, 89, 205, - 203, 89, 478, 129, 268, 206, 89, 217, 89, 228, - 282, 177, 40, 177, 282, 122, 229, 254, 121, 121, - 121, 121, 121, 121, 98, 231, 91, 91, 91, 129, - - 224, 98, 98, 98, 98, 98, 98, 91, 91, 216, - 152, 91, 234, 232, 229, 254, 91, 129, 91, 282, - 332, 152, 235, 49, 231, 285, 283, 236, 224, 152, - 98, 98, 98, 98, 98, 98, 147, 216, 152, 152, - 234, 237, 232, 147, 147, 147, 147, 147, 147, 332, - 235, 264, 265, 267, 400, 236, 282, 282, 90, 152, - 285, 152, 238, 63, 63, 129, 293, 219, 152, 219, - 237, 239, 147, 147, 147, 147, 147, 147, 160, 264, - 265, 267, 89, 269, 152, 160, 160, 160, 160, 160, - 160, 238, 152, 152, 293, 247, 247, 247, 247, 247, - - 239, 249, 283, 283, 261, 303, 250, 350, 251, 270, - 343, 269, 364, 271, 160, 160, 160, 160, 160, 160, - 162, 152, 91, 152, 376, 152, 308, 162, 162, 162, - 162, 162, 162, 261, 303, 152, 152, 152, 270, 343, - 364, 271, 247, 247, 247, 247, 247, 252, 249, 305, - 115, 306, 376, 250, 308, 251, 162, 162, 162, 162, - 162, 162, 97, 97, 97, 97, 97, 317, 242, 90, - 242, 152, 152, 368, 89, 307, 340, 342, 305, 210, - 306, 169, 152, 152, 152, 316, 344, 349, 169, 169, - 169, 169, 169, 169, 252, 280, 280, 280, 280, 280, - - 366, 478, 315, 307, 340, 342, 478, 314, 251, 152, - 468, 256, 152, 256, 91, 344, 152, 169, 169, 169, - 169, 169, 169, 108, 175, 175, 175, 108, 366, 40, - 280, 280, 280, 280, 280, 318, 318, 318, 318, 318, - 478, 370, 176, 251, 279, 282, 152, 252, 319, 176, - 176, 176, 176, 176, 176, 280, 280, 280, 280, 280, - 318, 318, 318, 318, 318, 152, 278, 90, 251, 274, - 370, 274, 384, 319, 405, 41, 371, 377, 176, 176, - 176, 176, 176, 176, 39, 39, 39, 107, 277, 152, - 109, 283, 152, 129, 152, 280, 280, 280, 280, 280, - - 152, 384, 405, 110, 396, 371, 377, 252, 251, 129, - 110, 110, 110, 110, 110, 110, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 478, 226, 478, 251, - 152, 282, 246, 396, 251, 403, 111, 152, 282, 110, - 110, 110, 110, 110, 110, 178, 404, 252, 467, 245, - 152, 417, 178, 178, 178, 178, 178, 178, 355, 318, - 318, 318, 355, 403, 282, 478, 152, 129, 252, 152, - 282, 356, 152, 252, 129, 404, 467, 283, 115, 285, - 417, 178, 178, 178, 178, 178, 178, 180, 129, 359, - 318, 318, 318, 359, 180, 180, 180, 180, 180, 180, - - 282, 129, 360, 97, 97, 97, 97, 97, 226, 115, - 283, 108, 175, 175, 175, 108, 283, 40, 213, 90, - 385, 163, 152, 180, 180, 180, 180, 180, 180, 116, - 116, 116, 116, 116, 161, 161, 161, 161, 161, 152, - 197, 285, 152, 119, 182, 182, 182, 119, 181, 385, - 90, 478, 478, 129, 40, 181, 181, 181, 181, 181, - 181, 282, 282, 41, 179, 179, 179, 179, 179, 430, - 159, 159, 159, 159, 159, 187, 187, 187, 187, 187, - 129, 129, 152, 90, 181, 181, 181, 181, 181, 181, - 119, 182, 182, 182, 119, 49, 295, 430, 295, 129, - - 448, 40, 285, 285, 199, 199, 199, 199, 199, 183, - 390, 391, 392, 129, 152, 393, 183, 183, 183, 183, - 183, 183, 152, 355, 318, 318, 318, 355, 448, 282, - 311, 429, 311, 152, 152, 129, 356, 152, 390, 152, - 391, 392, 49, 406, 393, 183, 183, 183, 183, 183, - 183, 48, 48, 48, 118, 394, 152, 129, 152, 429, - 432, 152, 120, 359, 318, 318, 318, 359, 395, 401, - 121, 406, 402, 416, 282, 283, 360, 121, 121, 121, - 121, 121, 121, 394, 129, 415, 152, 129, 421, 432, - 152, 152, 129, 152, 152, 129, 419, 395, 401, 407, - - 152, 402, 416, 122, 129, 408, 121, 121, 121, 121, - 121, 121, 188, 415, 152, 285, 421, 420, 152, 188, - 188, 188, 188, 188, 188, 419, 347, 407, 347, 372, - 386, 372, 386, 408, 286, 286, 286, 286, 286, 152, - 127, 418, 422, 115, 115, 167, 420, 251, 188, 188, - 188, 188, 188, 188, 146, 146, 146, 146, 146, 152, - 152, 163, 152, 149, 326, 361, 361, 361, 326, 431, - 418, 422, 129, 195, 129, 282, 433, 57, 152, 434, - 195, 195, 195, 195, 195, 195, 252, 411, 411, 411, - 411, 411, 321, 357, 357, 357, 321, 431, 282, 77, - - 152, 152, 59, 412, 127, 433, 129, 123, 434, 195, - 195, 195, 195, 195, 195, 200, 285, 411, 411, 411, - 411, 411, 200, 200, 200, 200, 200, 200, 423, 423, - 423, 423, 423, 412, 115, 101, 100, 435, 99, 414, - 79, 424, 440, 58, 283, 444, 478, 478, 478, 478, - 478, 200, 200, 200, 200, 200, 200, 159, 159, 159, - 159, 159, 478, 152, 152, 57, 435, 442, 441, 414, - 152, 440, 443, 50, 444, 449, 207, 152, 471, 152, - 426, 152, 454, 207, 207, 207, 207, 207, 207, 423, - 423, 423, 423, 423, 152, 442, 450, 441, 414, 47, - - 443, 152, 424, 449, 152, 455, 478, 471, 152, 152, - 451, 454, 207, 207, 207, 207, 207, 207, 161, 161, - 161, 161, 161, 478, 450, 152, 478, 152, 423, 423, - 423, 423, 423, 456, 455, 478, 460, 208, 451, 478, - 457, 424, 152, 478, 208, 208, 208, 208, 208, 208, - 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, - 478, 456, 152, 424, 461, 470, 478, 478, 424, 457, - 478, 152, 152, 208, 208, 208, 208, 208, 208, 215, - 426, 423, 423, 423, 423, 423, 215, 215, 215, 215, - 215, 215, 461, 470, 424, 478, 478, 478, 463, 478, - - 462, 466, 426, 477, 478, 478, 152, 426, 473, 152, - 152, 152, 474, 478, 475, 215, 215, 215, 215, 215, - 215, 108, 175, 175, 175, 108, 463, 40, 462, 466, - 152, 477, 478, 426, 152, 478, 478, 473, 152, 478, - 218, 474, 478, 475, 478, 478, 478, 218, 218, 218, - 218, 218, 218, 423, 423, 423, 423, 423, 438, 438, - 438, 438, 438, 478, 478, 478, 424, 478, 478, 478, - 478, 424, 478, 41, 478, 478, 218, 218, 218, 218, - 218, 218, 220, 445, 445, 445, 445, 445, 472, 220, - 220, 220, 220, 220, 220, 478, 424, 478, 478, 478, - - 478, 478, 476, 152, 478, 426, 478, 478, 478, 478, - 426, 478, 478, 478, 478, 478, 472, 152, 220, 220, - 220, 220, 220, 220, 179, 179, 179, 179, 179, 478, - 476, 478, 478, 478, 478, 426, 478, 478, 478, 478, - 478, 478, 478, 221, 478, 478, 478, 478, 478, 478, - 221, 221, 221, 221, 221, 221, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 221, - 221, 221, 221, 221, 221, 116, 116, 116, 116, 116, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 222, 478, 478, 478, 478, 478, - 478, 222, 222, 222, 222, 222, 222, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 222, 222, 222, 222, 222, 222, 119, 182, 182, 182, - 119, 478, 478, 478, 478, 478, 478, 40, 478, 478, - 478, 478, 478, 478, 478, 223, 478, 478, 478, 478, - 478, 478, 223, 223, 223, 223, 223, 223, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 49, 478, - - 478, 223, 223, 223, 223, 223, 223, 187, 187, 187, - 187, 187, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 227, 478, 478, 478, - 478, 478, 478, 227, 227, 227, 227, 227, 227, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 227, 227, 227, 227, 227, 227, 230, 478, - 478, 478, 478, 478, 478, 230, 230, 230, 230, 230, - 230, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 230, 230, 230, 230, 230, 230, - 199, 199, 199, 199, 199, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 233, - 478, 478, 478, 478, 478, 478, 233, 233, 233, 233, - 233, 233, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 233, 233, 233, 233, 233, - 233, 240, 478, 478, 478, 478, 478, 478, 240, 240, - 240, 240, 240, 240, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 240, 240, 240, - 240, 240, 240, 161, 161, 161, 161, 161, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 241, 478, 478, 478, 478, 478, 478, 241, - 241, 241, 241, 241, 241, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 241, 241, - 241, 241, 241, 241, 253, 478, 478, 478, 478, 478, - 478, 253, 253, 253, 253, 253, 253, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 253, 253, 253, 253, 253, 253, 108, 175, 175, 175, - 108, 478, 40, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 255, 478, 478, 478, 478, - 478, 478, 255, 255, 255, 255, 255, 255, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 41, 478, - 478, 255, 255, 255, 255, 255, 255, 257, 478, 478, - 478, 478, 478, 478, 257, 257, 257, 257, 257, 257, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 257, 257, 257, 257, 257, 257, 179, - 179, 179, 179, 179, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 258, 478, - 478, 478, 478, 478, 478, 258, 258, 258, 258, 258, - 258, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 258, 258, 258, 258, 258, 258, - 116, 116, 116, 116, 116, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 259, - - 478, 478, 478, 478, 478, 478, 259, 259, 259, 259, - 259, 259, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 259, 259, 259, 259, 259, - 259, 119, 182, 182, 182, 119, 478, 478, 478, 478, - 478, 478, 40, 478, 478, 478, 478, 478, 478, 478, - 260, 478, 478, 478, 478, 478, 478, 260, 260, 260, - 260, 260, 260, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 49, 478, 478, 260, 260, 260, 260, - - 260, 260, 187, 187, 187, 187, 187, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 262, 478, 478, 478, 478, 478, 478, 262, 262, - 262, 262, 262, 262, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 262, 262, 262, - 262, 262, 262, 263, 478, 478, 478, 478, 478, 478, - 263, 263, 263, 263, 263, 263, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 263, - - 263, 263, 263, 263, 263, 199, 199, 199, 199, 199, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 266, 478, 478, 478, 478, 478, - 478, 266, 266, 266, 266, 266, 266, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 266, 266, 266, 266, 266, 266, 272, 478, 478, 478, - 478, 478, 478, 272, 272, 272, 272, 272, 272, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 272, 272, 272, 272, 272, 272, 161, 161, - 161, 161, 161, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 273, 478, 478, - 478, 478, 478, 478, 273, 273, 273, 273, 273, 273, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 273, 273, 273, 273, 273, 273, 280, - 280, 280, 280, 286, 478, 288, 478, 478, 478, 478, - 288, 288, 289, 478, 478, 478, 478, 478, 290, 478, - 478, 478, 478, 478, 478, 290, 290, 290, 290, 290, - - 290, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 291, 478, 478, 290, 290, 290, 290, 290, 290, - 292, 478, 478, 478, 478, 478, 478, 292, 292, 292, - 292, 292, 292, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 292, 292, 292, 292, - 292, 292, 108, 175, 175, 175, 108, 478, 40, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 294, 478, 478, 478, 478, 478, 478, 294, 294, - - 294, 294, 294, 294, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 41, 478, 478, 294, 294, 294, - 294, 294, 294, 296, 478, 478, 478, 478, 478, 478, - 296, 296, 296, 296, 296, 296, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 115, 478, 478, 296, - 296, 296, 296, 296, 296, 179, 179, 179, 179, 179, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 297, 478, 478, 478, 478, 478, - - 478, 297, 297, 297, 297, 297, 297, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 115, 478, 478, - 297, 297, 297, 297, 297, 297, 116, 116, 116, 116, - 116, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 298, 478, 478, 478, 478, - 478, 478, 298, 298, 298, 298, 298, 298, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 298, 298, 298, 298, 298, 298, 119, 182, 182, - - 182, 119, 478, 478, 478, 478, 478, 478, 40, 478, - 478, 478, 478, 478, 478, 478, 299, 478, 478, 478, - 478, 478, 478, 299, 299, 299, 299, 299, 299, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 49, - 478, 478, 299, 299, 299, 299, 299, 299, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 90, 478, 478, - 478, 478, 478, 478, 90, 90, 90, 90, 90, 90, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 300, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 90, 90, 90, 90, 90, 90, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 300, 187, 187, 187, 187, 187, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 301, 478, 478, 478, 478, 478, 478, 301, 301, - 301, 301, 301, 301, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 301, 301, 301, - 301, 301, 301, 302, 478, 478, 478, 478, 478, 478, - - 302, 302, 302, 302, 302, 302, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 302, - 302, 302, 302, 302, 302, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 128, 478, 478, 478, 478, 478, - 478, 128, 128, 128, 128, 128, 128, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 128, 128, 128, 128, 128, 128, 199, 199, 199, 199, - - 199, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 304, 478, 478, 478, 478, - 478, 478, 304, 304, 304, 304, 304, 304, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 304, 304, 304, 304, 304, 304, 309, 478, 478, - 478, 478, 478, 478, 309, 309, 309, 309, 309, 309, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 309, 309, 309, 309, 309, 309, 161, - - 161, 161, 161, 161, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 310, 478, - 478, 478, 478, 478, 478, 310, 310, 310, 310, 310, - 310, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 310, 310, 310, 310, 310, 310, - 281, 281, 281, 320, 478, 478, 322, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 323, - 478, 478, 478, 478, 478, 478, 323, 323, 323, 323, - 323, 323, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 324, 478, 478, 323, 323, 323, 323, 323, - 323, 284, 284, 284, 325, 478, 478, 478, 478, 478, - 478, 478, 327, 478, 478, 478, 478, 478, 478, 478, - 328, 478, 478, 478, 478, 478, 478, 328, 328, 328, - 328, 328, 328, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 329, 478, 478, 328, 328, 328, 328, - 328, 328, 286, 286, 286, 286, 286, 478, 478, 478, - 478, 478, 478, 478, 478, 251, 478, 478, 478, 478, - - 478, 330, 478, 478, 478, 478, 478, 478, 330, 330, - 330, 330, 330, 330, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 252, 478, 478, 330, 330, 330, - 330, 330, 330, 280, 280, 280, 280, 286, 478, 288, - 478, 478, 478, 478, 288, 288, 289, 478, 478, 478, - 478, 478, 290, 478, 478, 478, 478, 478, 478, 290, - 290, 290, 290, 290, 290, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 291, 478, 478, 290, 290, - - 290, 290, 290, 290, 331, 478, 478, 478, 478, 478, - 478, 331, 331, 331, 331, 331, 331, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 331, 331, 331, 331, 331, 331, 108, 175, 175, 175, - 108, 478, 40, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 333, 478, 478, 478, 478, - 478, 478, 333, 333, 333, 333, 333, 333, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 41, 478, - - 478, 333, 333, 333, 333, 333, 333, 179, 179, 179, - 179, 179, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 334, 478, 478, 478, - 478, 478, 478, 334, 334, 334, 334, 334, 334, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 115, - 478, 478, 334, 334, 334, 334, 334, 334, 116, 116, - 116, 116, 116, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 335, 478, 478, - 478, 478, 478, 478, 335, 335, 335, 335, 335, 335, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 335, 335, 335, 335, 335, 335, 119, - 182, 182, 182, 119, 478, 478, 478, 478, 478, 478, - 40, 478, 478, 478, 478, 478, 478, 478, 336, 478, - 478, 478, 478, 478, 478, 336, 336, 336, 336, 336, - 336, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 49, 478, 478, 336, 336, 336, 336, 336, 336, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 337, 478, 478, 90, - 478, 478, 478, 478, 478, 478, 90, 90, 90, 90, - 90, 90, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 90, 90, 90, 90, 90, - 90, 187, 187, 187, 187, 187, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 338, 478, 478, 478, 478, 478, 478, 338, 338, 338, - 338, 338, 338, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 338, 338, 338, 338, - 338, 338, 146, 146, 146, 146, 146, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 339, 478, 478, 478, 478, 478, 478, 339, 339, - 339, 339, 339, 339, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 339, 339, 339, - 339, 339, 339, 199, 199, 199, 199, 199, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 341, 478, 478, 478, 478, 478, 478, 341, - - 341, 341, 341, 341, 341, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 341, 341, - 341, 341, 341, 341, 345, 478, 478, 478, 478, 478, - 478, 345, 345, 345, 345, 345, 345, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 345, 345, 345, 345, 345, 345, 161, 161, 161, 161, - 161, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 346, 478, 478, 478, 478, - - 478, 478, 346, 346, 346, 346, 346, 346, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 346, 346, 346, 346, 346, 346, 321, 357, 357, - 357, 321, 478, 282, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 358, 478, 478, 478, - 478, 478, 478, 358, 358, 358, 358, 358, 358, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 283, - 478, 478, 358, 358, 358, 358, 358, 358, 281, 281, - - 281, 320, 478, 478, 322, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 323, 478, 478, - 478, 478, 478, 478, 323, 323, 323, 323, 323, 323, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 324, 478, 478, 323, 323, 323, 323, 323, 323, 326, - 361, 361, 361, 326, 478, 478, 478, 478, 478, 478, - 282, 478, 478, 478, 478, 478, 478, 478, 362, 478, - 478, 478, 478, 478, 478, 362, 362, 362, 362, 362, - 362, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 285, 478, 478, 362, 362, 362, 362, 362, 362, - 284, 284, 284, 325, 478, 478, 478, 478, 478, 478, - 478, 327, 478, 478, 478, 478, 478, 478, 478, 328, - 478, 478, 478, 478, 478, 478, 328, 328, 328, 328, - 328, 328, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 329, 478, 478, 328, 328, 328, 328, 328, - 328, 286, 286, 286, 286, 286, 478, 478, 478, 478, - 478, 478, 478, 478, 251, 478, 478, 478, 478, 478, - - 363, 478, 478, 478, 478, 478, 478, 363, 363, 363, - 363, 363, 363, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 252, 478, 478, 363, 363, 363, 363, - 363, 363, 365, 478, 478, 478, 478, 478, 478, 365, - 365, 365, 365, 365, 365, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 365, 365, - 365, 365, 365, 365, 113, 478, 478, 478, 478, 478, - 478, 113, 113, 113, 113, 113, 113, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 113, 113, 113, 113, 113, 113, 367, 478, 478, 478, - 478, 478, 478, 367, 367, 367, 367, 367, 367, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 367, 367, 367, 367, 367, 367, 146, 146, - 146, 146, 146, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 128, 478, 478, - 478, 478, 478, 478, 128, 128, 128, 128, 128, 128, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 128, 128, 128, 128, 128, 128, 199, - 199, 199, 199, 199, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 369, 478, - 478, 478, 478, 478, 478, 369, 369, 369, 369, 369, - 369, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 369, 369, 369, 369, 369, 369, - 373, 478, 478, 478, 478, 478, 478, 373, 373, 373, - - 373, 373, 373, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 373, 373, 373, 373, - 373, 373, 374, 478, 478, 478, 478, 478, 478, 374, - 374, 374, 374, 374, 374, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 374, 374, - 374, 374, 374, 374, 286, 286, 286, 286, 286, 478, - 478, 478, 478, 478, 478, 478, 478, 251, 478, 478, - 478, 478, 478, 375, 478, 478, 478, 478, 478, 478, - - 375, 375, 375, 375, 375, 375, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 252, 478, 478, 375, - 375, 375, 375, 375, 375, 378, 478, 478, 478, 478, - 478, 478, 379, 478, 380, 478, 478, 478, 478, 381, - 382, 478, 478, 383, 478, 478, 478, 478, 152, 478, - 478, 478, 478, 478, 378, 478, 478, 478, 478, 478, - 379, 478, 380, 478, 478, 478, 478, 381, 382, 478, - 478, 383, 387, 478, 478, 478, 478, 478, 478, 387, - 387, 387, 387, 387, 387, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 387, 387, - 387, 387, 387, 387, 388, 478, 478, 478, 478, 478, - 478, 388, 388, 388, 388, 388, 388, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 388, 388, 388, 388, 388, 388, 389, 478, 478, 478, - 478, 478, 478, 389, 389, 389, 389, 389, 389, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 389, 389, 389, 389, 389, 389, 397, 478, - 478, 478, 478, 478, 478, 397, 397, 397, 397, 397, - 397, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 397, 397, 397, 397, 397, 397, - 398, 478, 478, 478, 478, 478, 478, 398, 398, 398, - 398, 398, 398, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 398, 398, 398, 398, - 398, 398, 399, 478, 478, 478, 478, 478, 478, 399, - - 399, 399, 399, 399, 399, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 399, 399, - 399, 399, 399, 399, 409, 478, 478, 478, 478, 478, - 478, 409, 409, 409, 409, 409, 409, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 409, 409, 409, 409, 409, 409, 410, 478, 478, 478, - 478, 478, 478, 410, 410, 410, 410, 410, 410, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 410, 410, 410, 410, 410, 410, 428, 478, - 478, 478, 478, 478, 478, 428, 428, 428, 428, 428, - 428, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 428, 428, 428, 428, 428, 428, - 437, 478, 478, 478, 478, 478, 478, 437, 437, 437, - 437, 437, 437, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 437, 437, 437, 437, - - 437, 437, 438, 438, 438, 438, 438, 478, 478, 478, - 478, 478, 478, 478, 478, 424, 478, 478, 478, 478, - 478, 439, 478, 478, 478, 478, 478, 478, 439, 439, - 439, 439, 439, 439, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 426, 478, 478, 439, 439, 439, - 439, 439, 439, 445, 445, 445, 445, 445, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 446, 478, 478, 478, 478, 478, 478, 446, - 446, 446, 446, 446, 446, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 446, 446, - 446, 446, 446, 446, 447, 478, 478, 478, 478, 478, - 478, 447, 447, 447, 447, 447, 447, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 447, 447, 447, 447, 447, 447, 452, 478, 478, 478, - 478, 478, 478, 452, 452, 452, 452, 452, 452, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 452, 452, 452, 452, 452, 452, 453, 478, - 478, 478, 478, 478, 478, 453, 453, 453, 453, 453, - 453, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 453, 453, 453, 453, 453, 453, - 458, 478, 478, 478, 478, 478, 478, 458, 458, 458, - 458, 458, 458, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 458, 458, 458, 458, - 458, 458, 459, 478, 478, 478, 478, 478, 478, 459, - - 459, 459, 459, 459, 459, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 459, 459, - 459, 459, 459, 459, 464, 478, 478, 478, 478, 478, - 478, 464, 464, 464, 464, 464, 464, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 464, 464, 464, 464, 464, 464, 465, 478, 478, 478, - 478, 478, 478, 465, 465, 465, 465, 465, 465, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 465, 465, 465, 465, 465, 465, 469, 478, - 478, 478, 478, 478, 478, 469, 469, 469, 469, 469, - 469, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 469, 469, 469, 469, 469, 469, - 39, 478, 478, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 45, 45, 478, 45, 45, 48, 478, - 478, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 53, 53, 478, 53, 53, 81, 478, 478, 81, - - 81, 90, 478, 90, 90, 478, 90, 90, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 108, 108, + 20, 8, 21, 8, 8, 8, 22, 23, 24, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 26, 25, 25, 25, 25, 25, 25, + 27, 25, 25, 25, 25, 25, 8, 28, 29, 25, + 30, 131, 30, 36, 36, 36, 36, 36, 40, 31, + 191, 31, 36, 36, 36, 36, 36, 37, 37, 37, + 37, 37, 32, 33, 32, 33, 42, 131, 41, 43, + 40, 40, 52, 92, 134, 34, 44, 34, 92, 46, + + 46, 46, 46, 46, 46, 49, 51, 94, 80, 52, + 92, 41, 94, 98, 38, 124, 53, 92, 81, 131, + 95, 96, 131, 83, 94, 40, 84, 478, 102, 85, + 478, 94, 55, 86, 87, 154, 88, 44, 139, 137, + 49, 56, 59, 90, 99, 131, 92, 132, 97, 60, + 61, 203, 62, 90, 90, 90, 90, 90, 90, 63, + 94, 64, 65, 65, 66, 67, 68, 65, 69, 70, + 71, 65, 72, 65, 73, 74, 65, 75, 65, 76, + 77, 78, 65, 65, 65, 65, 65, 65, 92, 92, + 92, 65, 95, 96, 36, 36, 36, 36, 36, 478, + + 112, 57, 94, 94, 94, 37, 37, 37, 37, 37, + 112, 112, 112, 112, 112, 112, 114, 154, 104, 92, + 103, 105, 95, 96, 65, 117, 114, 114, 114, 114, + 114, 114, 116, 94, 156, 117, 117, 117, 117, 117, + 117, 90, 38, 39, 39, 39, 107, 92, 131, 109, + 131, 90, 90, 90, 90, 90, 90, 131, 131, 154, + 140, 94, 110, 133, 195, 131, 158, 131, 125, 111, + 144, 131, 110, 110, 110, 110, 110, 110, 48, 48, + 48, 118, 135, 95, 143, 138, 141, 145, 129, 120, + 154, 146, 142, 136, 131, 131, 478, 121, 129, 129, + + 129, 129, 129, 129, 122, 154, 81, 121, 121, 121, + 121, 121, 121, 131, 152, 155, 147, 154, 148, 154, + 154, 92, 159, 160, 152, 152, 152, 152, 152, 152, + 92, 150, 157, 92, 40, 94, 89, 89, 89, 89, + 89, 95, 95, 194, 94, 131, 163, 94, 92, 92, + 131, 154, 40, 170, 41, 161, 163, 163, 163, 163, + 163, 163, 94, 94, 92, 161, 161, 161, 161, 161, + 161, 165, 41, 193, 48, 154, 167, 40, 94, 92, + 92, 168, 92, 92, 40, 166, 167, 167, 167, 167, + 167, 167, 49, 94, 94, 39, 94, 94, 40, 49, + + 40, 92, 127, 154, 154, 131, 186, 169, 192, 154, + 172, 198, 202, 49, 131, 94, 171, 173, 177, 184, + 41, 108, 175, 175, 175, 108, 131, 40, 177, 177, + 177, 177, 177, 177, 196, 154, 211, 131, 154, 154, + 176, 205, 154, 230, 213, 190, 154, 41, 207, 92, + 176, 176, 176, 176, 176, 176, 39, 39, 39, 107, + 204, 206, 109, 94, 131, 194, 180, 154, 154, 210, + 215, 229, 131, 370, 239, 110, 180, 180, 180, 180, + 180, 180, 111, 94, 94, 110, 110, 110, 110, 110, + 110, 113, 113, 113, 113, 113, 154, 154, 226, 154, + + 232, 181, 186, 92, 210, 92, 240, 154, 238, 154, + 178, 181, 181, 181, 181, 181, 181, 94, 94, 94, + 178, 178, 178, 178, 178, 178, 119, 182, 182, 182, + 119, 236, 211, 40, 269, 154, 189, 40, 271, 40, + 245, 154, 154, 154, 154, 183, 189, 189, 189, 189, + 189, 189, 49, 41, 49, 183, 183, 183, 183, 183, + 183, 48, 48, 48, 118, 92, 154, 211, 403, 154, + 154, 201, 120, 131, 92, 277, 306, 303, 307, 94, + 121, 201, 201, 201, 201, 201, 201, 122, 94, 231, + 121, 121, 121, 121, 121, 121, 128, 128, 128, 128, + + 128, 224, 211, 154, 368, 154, 208, 154, 344, 154, + 314, 154, 345, 154, 154, 187, 208, 208, 208, 208, + 208, 208, 131, 235, 237, 187, 187, 187, 187, 187, + 187, 151, 151, 151, 151, 151, 154, 92, 92, 131, + 211, 154, 154, 154, 165, 92, 371, 433, 349, 265, + 199, 94, 94, 154, 264, 154, 154, 154, 92, 94, + 199, 199, 199, 199, 199, 199, 162, 162, 162, 162, + 162, 154, 94, 283, 268, 270, 218, 272, 384, 216, + 154, 300, 376, 261, 444, 209, 218, 218, 218, 218, + 218, 218, 219, 284, 283, 209, 209, 209, 209, 209, + + 209, 220, 219, 219, 219, 219, 219, 219, 154, 286, + 154, 220, 220, 220, 220, 220, 220, 179, 179, 179, + 179, 179, 281, 281, 281, 281, 281, 222, 309, 283, + 308, 154, 211, 154, 396, 252, 221, 222, 222, 222, + 222, 222, 222, 223, 286, 364, 221, 221, 221, 221, + 221, 221, 227, 223, 223, 223, 223, 223, 223, 283, + 154, 154, 227, 227, 227, 227, 227, 227, 188, 188, + 188, 188, 188, 319, 319, 319, 319, 319, 233, 284, + 92, 283, 340, 343, 337, 354, 320, 228, 233, 233, + 233, 233, 233, 233, 94, 283, 286, 228, 228, 228, + + 228, 228, 228, 200, 200, 200, 200, 200, 319, 319, + 319, 319, 319, 241, 154, 284, 283, 432, 353, 352, + 285, 320, 234, 241, 241, 241, 241, 241, 241, 242, + 283, 286, 234, 234, 234, 234, 234, 234, 243, 242, + 242, 242, 242, 242, 242, 286, 283, 351, 243, 243, + 243, 243, 243, 243, 248, 248, 248, 248, 248, 255, + 250, 154, 92, 283, 283, 251, 284, 252, 385, 255, + 255, 255, 255, 255, 255, 256, 94, 282, 350, 286, + 253, 257, 283, 284, 92, 256, 256, 256, 256, 256, + 256, 257, 257, 257, 257, 257, 257, 258, 94, 154, + + 366, 377, 284, 259, 154, 154, 391, 258, 258, 258, + 258, 258, 258, 259, 259, 259, 259, 259, 259, 260, + 113, 113, 113, 113, 113, 262, 154, 394, 421, 260, + 260, 260, 260, 260, 260, 262, 262, 262, 262, 262, + 262, 263, 154, 154, 116, 154, 116, 266, 435, 392, + 393, 263, 263, 263, 263, 263, 263, 266, 266, 266, + 266, 266, 266, 267, 128, 128, 128, 128, 128, 273, + 154, 154, 154, 267, 267, 267, 267, 267, 267, 273, + 273, 273, 273, 273, 273, 274, 154, 448, 154, 442, + 131, 275, 429, 395, 404, 274, 274, 274, 274, 274, + + 274, 275, 275, 275, 275, 275, 275, 248, 248, 248, + 248, 248, 154, 250, 332, 400, 154, 154, 251, 419, + 252, 281, 281, 281, 281, 281, 294, 478, 92, 94, + 405, 406, 478, 253, 252, 154, 294, 294, 294, 294, + 294, 294, 94, 154, 154, 154, 416, 253, 281, 281, + 281, 281, 287, 417, 289, 418, 468, 407, 295, 289, + 289, 290, 390, 408, 318, 154, 154, 291, 295, 295, + 295, 295, 295, 295, 292, 296, 422, 291, 291, 291, + 291, 291, 291, 297, 154, 296, 296, 296, 296, 296, + 296, 298, 317, 297, 297, 297, 297, 297, 297, 299, + + 430, 298, 298, 298, 298, 298, 298, 301, 316, 299, + 299, 299, 299, 299, 299, 302, 315, 301, 301, 301, + 301, 301, 301, 304, 154, 302, 302, 302, 302, 302, + 302, 305, 131, 304, 304, 304, 304, 304, 304, 310, + 293, 305, 305, 305, 305, 305, 305, 311, 280, 310, + 310, 310, 310, 310, 310, 312, 154, 311, 311, 311, + 311, 311, 311, 420, 154, 312, 312, 312, 312, 312, + 312, 282, 282, 282, 321, 154, 154, 323, 415, 154, + 401, 154, 279, 402, 441, 281, 281, 281, 281, 281, + 324, 478, 278, 450, 154, 131, 478, 325, 252, 431, + + 324, 324, 324, 324, 324, 324, 285, 285, 285, 326, + 131, 253, 478, 478, 478, 478, 478, 328, 281, 281, + 281, 281, 281, 154, 478, 329, 154, 154, 478, 478, + 434, 252, 330, 440, 154, 329, 329, 329, 329, 329, + 329, 154, 226, 154, 253, 281, 281, 281, 281, 281, + 449, 478, 254, 154, 456, 451, 478, 472, 252, 281, + 281, 281, 281, 281, 333, 478, 154, 476, 154, 154, + 478, 253, 252, 454, 333, 333, 333, 333, 333, 333, + 425, 425, 425, 425, 425, 253, 287, 287, 287, 287, + 287, 443, 478, 426, 154, 467, 334, 478, 247, 252, + + 151, 151, 151, 151, 151, 331, 334, 334, 334, 334, + 334, 334, 253, 246, 462, 331, 331, 331, 331, 331, + 331, 281, 281, 281, 281, 287, 154, 289, 154, 154, + 154, 335, 289, 289, 290, 455, 457, 154, 131, 131, + 291, 335, 335, 335, 335, 335, 335, 292, 336, 131, + 291, 291, 291, 291, 291, 291, 338, 466, 336, 336, + 336, 336, 336, 336, 339, 154, 338, 338, 338, 338, + 338, 338, 341, 131, 339, 339, 339, 339, 339, 339, + 342, 154, 341, 341, 341, 341, 341, 341, 470, 226, + 342, 342, 342, 342, 342, 342, 89, 89, 89, 89, + + 89, 346, 463, 154, 154, 116, 217, 214, 92, 460, + 471, 346, 346, 346, 346, 346, 346, 347, 154, 154, + 164, 154, 94, 154, 477, 473, 475, 347, 347, 347, + 347, 347, 347, 355, 319, 319, 319, 355, 154, 283, + 461, 359, 319, 319, 319, 359, 356, 197, 154, 131, + 131, 131, 283, 131, 360, 474, 131, 131, 363, 284, + 322, 357, 357, 357, 322, 131, 283, 286, 363, 363, + 363, 363, 363, 363, 355, 319, 319, 319, 355, 358, + 283, 179, 179, 179, 179, 179, 284, 356, 131, 358, + 358, 358, 358, 358, 358, 282, 282, 282, 321, 131, + + 284, 323, 131, 131, 131, 39, 127, 116, 116, 188, + 188, 188, 188, 188, 324, 39, 39, 39, 39, 39, + 39, 325, 116, 174, 324, 324, 324, 324, 324, 324, + 327, 361, 361, 361, 327, 131, 164, 154, 149, 131, + 365, 283, 131, 200, 200, 200, 200, 200, 57, 362, + 365, 365, 365, 365, 365, 365, 286, 63, 59, 362, + 362, 362, 362, 362, 362, 285, 285, 285, 326, 154, + 127, 123, 116, 106, 101, 48, 328, 100, 91, 79, + 58, 57, 50, 47, 329, 48, 48, 48, 48, 48, + 48, 330, 367, 478, 329, 329, 329, 329, 329, 329, + + 369, 35, 367, 367, 367, 367, 367, 367, 35, 478, + 369, 369, 369, 369, 369, 369, 162, 162, 162, 162, + 162, 372, 478, 478, 478, 478, 478, 478, 92, 478, + 478, 372, 372, 372, 372, 372, 372, 373, 478, 478, + 478, 478, 94, 478, 478, 478, 478, 373, 373, 373, + 373, 373, 373, 359, 319, 319, 319, 359, 374, 478, + 478, 478, 478, 478, 283, 478, 360, 478, 374, 374, + 374, 374, 374, 374, 375, 478, 478, 154, 478, 286, + 478, 478, 478, 378, 375, 375, 375, 375, 375, 375, + 379, 478, 380, 386, 478, 478, 478, 381, 382, 387, + + 478, 383, 478, 386, 386, 386, 386, 386, 386, 387, + 387, 387, 387, 387, 387, 388, 478, 478, 478, 478, + 478, 389, 478, 478, 478, 388, 388, 388, 388, 388, + 388, 389, 389, 389, 389, 389, 389, 397, 478, 478, + 478, 478, 478, 398, 478, 478, 478, 397, 397, 397, + 397, 397, 397, 398, 398, 398, 398, 398, 398, 399, + 478, 478, 478, 478, 478, 409, 478, 478, 478, 399, + 399, 399, 399, 399, 399, 409, 409, 409, 409, 409, + 409, 410, 478, 478, 478, 478, 478, 249, 478, 478, + 478, 410, 410, 410, 410, 410, 410, 249, 249, 249, + + 249, 249, 249, 411, 411, 411, 411, 411, 478, 478, + 282, 478, 478, 478, 478, 478, 478, 478, 478, 412, + 282, 282, 282, 282, 282, 282, 285, 478, 478, 413, + 411, 411, 411, 411, 411, 478, 285, 285, 285, 285, + 285, 285, 478, 478, 478, 478, 412, 424, 478, 478, + 425, 425, 425, 425, 425, 478, 413, 424, 424, 424, + 424, 424, 424, 426, 425, 425, 425, 425, 425, 478, + 425, 425, 425, 425, 425, 478, 428, 426, 478, 478, + 478, 478, 478, 426, 478, 478, 478, 439, 478, 478, + 428, 436, 436, 436, 436, 436, 428, 439, 439, 439, + + 439, 439, 439, 478, 426, 425, 425, 425, 425, 425, + 437, 478, 478, 478, 478, 478, 478, 428, 426, 478, + 437, 437, 437, 437, 437, 437, 445, 478, 478, 478, + 478, 428, 478, 478, 478, 478, 445, 445, 445, 445, + 445, 445, 425, 425, 425, 425, 425, 452, 478, 478, + 425, 425, 425, 425, 425, 426, 478, 452, 452, 452, + 452, 452, 452, 426, 478, 478, 478, 453, 428, 446, + 446, 446, 446, 446, 478, 478, 428, 453, 453, 453, + 453, 453, 453, 478, 478, 478, 478, 478, 447, 478, + 478, 478, 478, 478, 458, 478, 478, 478, 447, 447, + + 447, 447, 447, 447, 458, 458, 458, 458, 458, 458, + 459, 478, 478, 478, 478, 478, 464, 478, 478, 478, + 459, 459, 459, 459, 459, 459, 464, 464, 464, 464, + 464, 464, 465, 478, 478, 478, 478, 478, 427, 478, + 478, 478, 465, 465, 465, 465, 465, 465, 427, 427, + 427, 427, 427, 427, 469, 478, 478, 478, 478, 478, + 427, 478, 478, 478, 469, 469, 469, 469, 469, 469, + 427, 427, 427, 427, 427, 427, 39, 478, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 45, 45, 478, + 45, 45, 48, 478, 48, 48, 48, 48, 48, 48, + + 48, 48, 48, 54, 54, 478, 54, 54, 82, 478, + 478, 82, 82, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 93, 478, 93, 93, 478, 93, 93, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 113, 113, 478, 113, 113, 116, 116, 116, 116, - 116, 116, 116, 116, 116, 116, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 128, 128, 478, 128, 128, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 151, 151, - 478, 151, 151, 159, 159, 159, 159, 159, 159, 159, - - 159, 159, 159, 161, 161, 161, 161, 161, 161, 161, - 161, 161, 161, 166, 166, 166, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 48, 48, 478, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - - 211, 211, 211, 211, 39, 478, 478, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 225, 225, 225, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 115, + 115, 478, 115, 115, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 65, 65, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 130, 130, + 478, 130, 130, 151, 151, 151, 151, 151, 151, 151, + + 151, 151, 153, 153, 478, 153, 153, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 212, 212, 212, 478, 212, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, - 225, 243, 243, 243, 243, 248, 248, 248, 248, 248, - 248, 478, 248, 248, 248, 248, 248, 248, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 275, 275, 275, 275, 248, - 248, 248, 248, 248, 248, 478, 248, 248, 248, 248, - 248, 248, 281, 478, 478, 281, 281, 281, 281, 281, - - 281, 281, 281, 281, 281, 284, 478, 478, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 287, 287, - 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - 287, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 113, 113, 478, 113, 113, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 312, 312, 312, 312, 321, 321, 321, 321, - 321, 321, 321, 321, 321, 321, 321, 321, 321, 284, - 478, 478, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 326, 326, 326, 326, 326, 326, 326, 326, - - 326, 326, 326, 326, 326, 248, 248, 248, 248, 248, - 478, 478, 248, 248, 248, 248, 248, 248, 287, 287, - 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - 287, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 113, 113, 478, 113, 113, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 348, 348, 348, 348, 281, 281, 478, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 321, - 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - 321, 321, 284, 284, 478, 284, 284, 284, 284, 284, - - 284, 284, 284, 284, 284, 326, 326, 326, 326, 326, - 326, 326, 326, 326, 326, 326, 326, 326, 248, 248, - 248, 248, 248, 478, 478, 248, 248, 248, 248, 248, - 248, 413, 413, 413, 413, 478, 478, 478, 478, 413, - 478, 478, 413, 413, 425, 425, 425, 425, 478, 478, - 478, 425, 425, 425, 478, 425, 425, 427, 427, 427, - 427, 427, 427, 427, 427, 427, 427, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 7, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, + 225, 225, 244, 244, 244, 478, 244, 249, 249, 249, + 249, 478, 249, 249, 249, 249, 249, 249, 276, 276, + 276, 478, 276, 282, 478, 282, 282, 282, 282, 282, + + 282, 282, 282, 282, 285, 478, 285, 285, 285, 285, + 285, 285, 285, 285, 285, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 313, 313, 313, 478, + 313, 322, 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 348, 348, 348, 478, 348, 414, 414, + 414, 478, 478, 478, 414, 478, 478, 414, 414, 423, + 423, 423, 423, 423, 423, 423, 423, 423, 427, 427, + 427, 478, 478, 427, 427, 427, 478, 427, 427, 438, + 438, 438, 438, 438, 438, 438, 438, 438, 7, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478 + 478, 478, 478, 478, 478, 478, 478, 478, 478 } ; -static yyconst flex_int16_t yy_chk[6664] = +static yyconst flex_int16_t yy_chk[2460] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1048,733 +576,270 @@ static yyconst flex_int16_t yy_chk[6664] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 5, 4, 6, 15, - 12, 3, 477, 4, 9, 9, 9, 9, 9, 10, - - 10, 10, 10, 10, 3, 3, 4, 4, 11, 11, - 11, 11, 11, 23, 39, 5, 17, 6, 35, 17, - 3, 24, 4, 32, 24, 24, 32, 32, 38, 48, - 15, 69, 3, 3, 4, 4, 12, 42, 25, 17, - 42, 25, 11, 474, 69, 3, 35, 4, 17, 24, - 53, 32, 17, 23, 31, 78, 38, 78, 35, 69, - 39, 24, 467, 32, 33, 461, 65, 17, 83, 25, - 48, 11, 13, 42, 35, 13, 17, 24, 25, 32, - 83, 31, 13, 13, 13, 13, 13, 13, 65, 54, - 53, 33, 54, 54, 31, 65, 83, 25, 36, 36, - - 36, 36, 36, 70, 33, 68, 68, 456, 13, 31, - 166, 13, 13, 13, 13, 13, 13, 20, 166, 33, - 211, 90, 70, 440, 20, 20, 434, 20, 211, 54, - 124, 124, 70, 68, 20, 20, 20, 20, 20, 20, + 3, 134, 4, 9, 9, 9, 9, 9, 12, 3, + 134, 4, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 3, 3, 4, 4, 13, 67, 12, 13, + 15, 39, 52, 25, 67, 3, 13, 4, 31, 13, + + 13, 13, 13, 13, 13, 15, 17, 25, 22, 17, + 27, 39, 31, 27, 11, 52, 17, 26, 22, 69, + 26, 26, 71, 22, 27, 48, 22, 42, 31, 22, + 42, 26, 17, 22, 22, 156, 22, 42, 71, 69, + 48, 17, 20, 23, 27, 64, 54, 64, 26, 20, + 20, 156, 20, 23, 23, 23, 23, 23, 23, 20, + 54, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 90, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 64, 52, - 106, 20, 22, 74, 55, 429, 37, 37, 37, 37, - - 37, 57, 64, 57, 22, 243, 487, 22, 487, 52, - 22, 419, 55, 243, 22, 22, 64, 22, 106, 74, - 67, 66, 74, 57, 72, 72, 385, 127, 22, 67, - 37, 127, 66, 22, 55, 66, 22, 52, 71, 22, - 97, 55, 22, 22, 71, 22, 26, 73, 67, 66, - 82, 57, 71, 26, 26, 26, 26, 26, 26, 37, - 66, 72, 108, 109, 73, 80, 71, 76, 73, 82, - 107, 73, 71, 76, 86, 107, 73, 85, 140, 82, - 97, 384, 26, 26, 26, 26, 26, 26, 41, 41, - 41, 41, 73, 118, 41, 76, 73, 80, 84, 85, - - 86, 80, 87, 86, 348, 175, 85, 41, 108, 109, - 96, 140, 84, 93, 41, 41, 41, 41, 41, 41, - 93, 107, 94, 119, 102, 80, 84, 104, 87, 342, - 250, 87, 103, 119, 118, 96, 317, 105, 161, 316, - 41, 102, 315, 41, 41, 41, 41, 41, 41, 44, - 96, 175, 104, 93, 314, 94, 44, 44, 44, 44, - 44, 44, 94, 96, 102, 103, 120, 104, 105, 125, - 102, 250, 103, 275, 119, 131, 120, 105, 161, 134, - 104, 275, 44, 94, 125, 44, 44, 44, 44, 44, - 44, 46, 144, 103, 150, 131, 105, 145, 46, 46, - - 46, 46, 46, 46, 131, 134, 145, 165, 134, 125, - 137, 137, 148, 125, 156, 144, 150, 120, 192, 153, - 226, 144, 148, 150, 226, 145, 154, 46, 46, 46, - 46, 46, 46, 49, 49, 49, 49, 156, 137, 154, - 148, 157, 155, 156, 49, 153, 158, 165, 153, 174, - 190, 192, 49, 155, 154, 157, 168, 170, 164, 49, - 49, 49, 49, 49, 49, 164, 158, 171, 173, 157, - 155, 172, 182, 190, 235, 158, 184, 174, 216, 190, - 249, 499, 182, 499, 284, 49, 194, 217, 49, 49, - 49, 49, 49, 49, 56, 196, 168, 170, 164, 194, - - 184, 56, 56, 56, 56, 56, 56, 171, 173, 172, - 235, 172, 201, 198, 194, 217, 184, 196, 216, 325, - 293, 201, 202, 182, 196, 284, 249, 203, 184, 202, - 56, 56, 56, 56, 56, 56, 77, 172, 198, 203, - 201, 204, 198, 77, 77, 77, 77, 77, 77, 293, - 202, 231, 232, 234, 390, 203, 281, 320, 390, 204, - 325, 234, 205, 492, 492, 231, 254, 509, 232, 509, - 204, 206, 77, 77, 77, 77, 77, 77, 88, 231, - 232, 234, 224, 236, 205, 88, 88, 88, 88, 88, - 88, 205, 236, 206, 254, 214, 214, 214, 214, 214, - - 206, 214, 281, 320, 224, 265, 214, 313, 214, 237, - 306, 236, 332, 238, 88, 88, 88, 88, 88, 88, - 91, 238, 224, 265, 364, 307, 271, 91, 91, 91, - 91, 91, 91, 224, 265, 237, 306, 271, 237, 306, - 332, 238, 247, 247, 247, 247, 247, 214, 247, 267, - 296, 268, 364, 247, 271, 247, 91, 91, 91, 91, - 91, 91, 98, 98, 98, 98, 98, 279, 511, 337, - 511, 267, 268, 340, 98, 269, 303, 305, 267, 312, - 268, 98, 269, 303, 305, 278, 308, 312, 98, 98, - 98, 98, 98, 98, 247, 248, 248, 248, 248, 248, - - 337, 248, 277, 269, 303, 305, 248, 276, 248, 340, - 463, 515, 308, 515, 98, 308, 270, 98, 98, 98, - 98, 98, 98, 110, 110, 110, 110, 110, 337, 110, - 280, 280, 280, 280, 280, 282, 282, 282, 282, 282, - 321, 343, 110, 280, 246, 321, 463, 248, 282, 110, - 110, 110, 110, 110, 110, 286, 286, 286, 286, 286, - 318, 318, 318, 318, 318, 343, 245, 366, 286, 517, - 343, 517, 370, 318, 394, 110, 344, 366, 110, 110, - 110, 110, 110, 110, 111, 111, 111, 111, 244, 394, - 111, 321, 239, 229, 370, 287, 287, 287, 287, 287, - - 344, 370, 394, 111, 383, 344, 366, 286, 287, 228, - 111, 111, 111, 111, 111, 111, 288, 288, 288, 288, - 288, 289, 289, 289, 289, 289, 356, 225, 326, 288, - 383, 356, 213, 383, 289, 392, 111, 392, 326, 111, - 111, 111, 111, 111, 111, 114, 393, 287, 462, 212, - 462, 403, 114, 114, 114, 114, 114, 114, 322, 322, - 322, 322, 322, 392, 322, 357, 199, 193, 288, 393, - 357, 322, 403, 289, 191, 393, 462, 356, 114, 326, - 403, 114, 114, 114, 114, 114, 114, 115, 189, 327, - 327, 327, 327, 327, 115, 115, 115, 115, 115, 115, - - 327, 187, 327, 331, 331, 331, 331, 331, 185, 179, - 322, 333, 333, 333, 333, 333, 357, 333, 167, 331, - 371, 163, 159, 115, 115, 115, 115, 115, 115, 117, - 117, 117, 117, 117, 346, 346, 346, 346, 346, 151, - 149, 327, 371, 336, 336, 336, 336, 336, 117, 371, - 346, 360, 361, 146, 336, 117, 117, 117, 117, 117, - 117, 360, 361, 333, 365, 365, 365, 365, 365, 416, - 345, 345, 345, 345, 345, 367, 367, 367, 367, 367, - 143, 142, 416, 377, 117, 117, 117, 117, 117, 117, - 121, 121, 121, 121, 121, 336, 524, 416, 524, 141, - - 441, 121, 360, 361, 369, 369, 369, 369, 369, 121, - 377, 378, 379, 139, 441, 380, 121, 121, 121, 121, - 121, 121, 345, 355, 355, 355, 355, 355, 441, 355, - 527, 415, 527, 378, 379, 138, 355, 380, 377, 415, - 378, 379, 121, 395, 380, 121, 121, 121, 121, 121, - 121, 122, 122, 122, 122, 381, 369, 136, 395, 415, - 418, 381, 122, 359, 359, 359, 359, 359, 382, 391, - 122, 395, 391, 402, 359, 355, 359, 122, 122, 122, - 122, 122, 122, 381, 135, 401, 418, 133, 407, 418, - 382, 402, 132, 391, 407, 130, 405, 382, 391, 396, - - 401, 391, 402, 122, 128, 396, 122, 122, 122, 122, - 122, 122, 129, 401, 396, 359, 407, 406, 405, 129, - 129, 129, 129, 129, 129, 405, 537, 396, 537, 544, - 545, 544, 545, 396, 399, 399, 399, 399, 399, 406, - 126, 404, 408, 116, 113, 95, 406, 399, 129, 129, - 129, 129, 129, 129, 147, 147, 147, 147, 147, 404, - 408, 92, 81, 79, 410, 410, 410, 410, 410, 417, - 404, 408, 75, 147, 63, 410, 420, 61, 417, 421, - 147, 147, 147, 147, 147, 147, 399, 400, 400, 400, - 400, 400, 409, 409, 409, 409, 409, 417, 409, 60, - - 420, 421, 59, 400, 58, 420, 147, 51, 421, 147, - 147, 147, 147, 147, 147, 152, 410, 411, 411, 411, - 411, 411, 152, 152, 152, 152, 152, 152, 413, 413, - 413, 413, 413, 411, 45, 29, 28, 422, 27, 400, - 21, 413, 430, 19, 409, 435, 412, 412, 412, 412, - 412, 152, 152, 152, 152, 152, 152, 160, 160, 160, - 160, 160, 412, 422, 430, 18, 422, 432, 431, 411, - 435, 430, 433, 16, 435, 442, 160, 432, 468, 433, - 413, 442, 448, 160, 160, 160, 160, 160, 160, 423, - 423, 423, 423, 423, 431, 432, 443, 431, 412, 14, - - 433, 468, 423, 442, 448, 449, 7, 468, 443, 160, - 444, 448, 160, 160, 160, 160, 160, 160, 162, 162, - 162, 162, 162, 0, 443, 444, 0, 449, 425, 425, - 425, 425, 425, 450, 449, 0, 454, 162, 444, 0, - 451, 425, 450, 0, 162, 162, 162, 162, 162, 162, - 427, 427, 427, 427, 427, 436, 436, 436, 436, 436, - 0, 450, 451, 427, 454, 466, 0, 0, 436, 451, - 0, 466, 454, 162, 162, 162, 162, 162, 162, 169, - 425, 438, 438, 438, 438, 438, 169, 169, 169, 169, - 169, 169, 454, 466, 438, 0, 0, 0, 457, 0, - - 455, 460, 427, 476, 0, 0, 457, 436, 471, 455, - 460, 476, 472, 0, 473, 169, 169, 169, 169, 169, - 169, 176, 176, 176, 176, 176, 457, 176, 455, 460, - 471, 476, 0, 438, 472, 0, 0, 471, 473, 0, - 176, 472, 0, 473, 0, 0, 0, 176, 176, 176, - 176, 176, 176, 445, 445, 445, 445, 445, 465, 465, - 465, 465, 465, 0, 0, 0, 445, 0, 0, 0, - 0, 465, 0, 176, 0, 0, 176, 176, 176, 176, - 176, 176, 178, 469, 469, 469, 469, 469, 470, 178, - 178, 178, 178, 178, 178, 0, 469, 0, 0, 0, - - 0, 0, 475, 470, 0, 445, 0, 0, 0, 0, - 465, 0, 0, 0, 0, 0, 470, 475, 178, 178, - 178, 178, 178, 178, 180, 180, 180, 180, 180, 0, - 475, 0, 0, 0, 0, 469, 0, 0, 0, 0, - 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, - 180, 180, 180, 180, 180, 180, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, - 180, 180, 180, 180, 180, 181, 181, 181, 181, 181, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, - 0, 181, 181, 181, 181, 181, 181, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 181, 181, 181, 181, 181, 181, 183, 183, 183, 183, - 183, 0, 0, 0, 0, 0, 0, 183, 0, 0, - 0, 0, 0, 0, 0, 183, 0, 0, 0, 0, - 0, 0, 183, 183, 183, 183, 183, 183, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 183, 0, - - 0, 183, 183, 183, 183, 183, 183, 188, 188, 188, - 188, 188, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 188, 0, 0, 0, - 0, 0, 0, 188, 188, 188, 188, 188, 188, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 188, 188, 188, 188, 188, 188, 195, 0, - 0, 0, 0, 0, 0, 195, 195, 195, 195, 195, - 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 195, 195, 195, 195, 195, 195, - 200, 200, 200, 200, 200, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, - 0, 0, 0, 0, 0, 0, 200, 200, 200, 200, - 200, 200, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 200, 200, 200, 200, 200, - 200, 207, 0, 0, 0, 0, 0, 0, 207, 207, - 207, 207, 207, 207, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 207, 207, 207, - 207, 207, 207, 208, 208, 208, 208, 208, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 208, 0, 0, 0, 0, 0, 0, 208, - 208, 208, 208, 208, 208, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 208, 208, - 208, 208, 208, 208, 215, 0, 0, 0, 0, 0, - 0, 215, 215, 215, 215, 215, 215, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 215, 215, 215, 215, 215, 215, 218, 218, 218, 218, - 218, 0, 218, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 218, 0, 0, 0, 0, - 0, 0, 218, 218, 218, 218, 218, 218, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 218, 0, - 0, 218, 218, 218, 218, 218, 218, 220, 0, 0, - 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 220, 220, 220, 220, 220, 220, 221, - 221, 221, 221, 221, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, - 0, 0, 0, 0, 0, 221, 221, 221, 221, 221, - 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 221, 221, 221, 221, 221, 221, - 222, 222, 222, 222, 222, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, - - 0, 0, 0, 0, 0, 0, 222, 222, 222, 222, - 222, 222, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 222, 222, 222, 222, 222, - 222, 223, 223, 223, 223, 223, 0, 0, 0, 0, - 0, 0, 223, 0, 0, 0, 0, 0, 0, 0, - 223, 0, 0, 0, 0, 0, 0, 223, 223, 223, - 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 223, 0, 0, 223, 223, 223, 223, - - 223, 223, 227, 227, 227, 227, 227, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 227, 0, 0, 0, 0, 0, 0, 227, 227, - 227, 227, 227, 227, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 227, 227, 227, - 227, 227, 227, 230, 0, 0, 0, 0, 0, 0, - 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, - - 230, 230, 230, 230, 230, 233, 233, 233, 233, 233, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, - 0, 233, 233, 233, 233, 233, 233, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 233, 233, 233, 233, 233, 233, 240, 0, 0, 0, - 0, 0, 0, 240, 240, 240, 240, 240, 240, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 240, 240, 240, 240, 240, 240, 241, 241, - 241, 241, 241, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, - 0, 0, 0, 0, 241, 241, 241, 241, 241, 241, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 241, 241, 241, 241, 241, 241, 252, - 252, 252, 252, 252, 0, 252, 0, 0, 0, 0, - 252, 252, 252, 0, 0, 0, 0, 0, 252, 0, - 0, 0, 0, 0, 0, 252, 252, 252, 252, 252, - - 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 252, 0, 0, 252, 252, 252, 252, 252, 252, - 253, 0, 0, 0, 0, 0, 0, 253, 253, 253, - 253, 253, 253, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 253, 253, 253, 253, - 253, 253, 255, 255, 255, 255, 255, 0, 255, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 255, 0, 0, 0, 0, 0, 0, 255, 255, - - 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 255, 0, 0, 255, 255, 255, - 255, 255, 255, 257, 0, 0, 0, 0, 0, 0, - 257, 257, 257, 257, 257, 257, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 257, 0, 0, 257, - 257, 257, 257, 257, 257, 258, 258, 258, 258, 258, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 258, 0, 0, 0, 0, 0, - - 0, 258, 258, 258, 258, 258, 258, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 258, 0, 0, - 258, 258, 258, 258, 258, 258, 259, 259, 259, 259, - 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 259, 0, 0, 0, 0, - 0, 0, 259, 259, 259, 259, 259, 259, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 259, 259, 259, 259, 259, 259, 260, 260, 260, - - 260, 260, 0, 0, 0, 0, 0, 0, 260, 0, - 0, 0, 0, 0, 0, 0, 260, 0, 0, 0, - 0, 0, 0, 260, 260, 260, 260, 260, 260, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, - 0, 0, 260, 260, 260, 260, 260, 260, 261, 261, - 261, 261, 261, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 261, 0, 0, - 0, 0, 0, 0, 261, 261, 261, 261, 261, 261, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 261, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 261, 261, 261, 261, 261, 261, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 261, 262, 262, 262, 262, 262, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 262, 0, 0, 0, 0, 0, 0, 262, 262, - 262, 262, 262, 262, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 262, 262, 262, - 262, 262, 262, 263, 0, 0, 0, 0, 0, 0, - - 263, 263, 263, 263, 263, 263, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, - 263, 263, 263, 263, 263, 264, 264, 264, 264, 264, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 264, 0, 0, 0, 0, 0, - 0, 264, 264, 264, 264, 264, 264, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 264, 264, 264, 264, 264, 264, 266, 266, 266, 266, - - 266, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, - 0, 0, 266, 266, 266, 266, 266, 266, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 266, 266, 266, 266, 266, 266, 272, 0, 0, - 0, 0, 0, 0, 272, 272, 272, 272, 272, 272, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 272, 272, 272, 272, 272, 272, 273, - - 273, 273, 273, 273, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 273, 0, - 0, 0, 0, 0, 0, 273, 273, 273, 273, 273, - 273, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 273, 273, 273, 273, 273, 273, - 283, 283, 283, 283, 0, 0, 283, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 283, - 0, 0, 0, 0, 0, 0, 283, 283, 283, 283, - 283, 283, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 283, 0, 0, 283, 283, 283, 283, 283, - 283, 285, 285, 285, 285, 0, 0, 0, 0, 0, - 0, 0, 285, 0, 0, 0, 0, 0, 0, 0, - 285, 0, 0, 0, 0, 0, 0, 285, 285, 285, - 285, 285, 285, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 285, 0, 0, 285, 285, 285, 285, - 285, 285, 290, 290, 290, 290, 290, 0, 0, 0, - 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, - - 0, 290, 0, 0, 0, 0, 0, 0, 290, 290, - 290, 290, 290, 290, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 290, 0, 0, 290, 290, 290, - 290, 290, 290, 291, 291, 291, 291, 291, 0, 291, - 0, 0, 0, 0, 291, 291, 291, 0, 0, 0, - 0, 0, 291, 0, 0, 0, 0, 0, 0, 291, - 291, 291, 291, 291, 291, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 291, 0, 0, 291, 291, - - 291, 291, 291, 291, 292, 0, 0, 0, 0, 0, - 0, 292, 292, 292, 292, 292, 292, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 292, 292, 292, 292, 292, 292, 294, 294, 294, 294, - 294, 0, 294, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 294, 0, 0, 0, 0, - 0, 0, 294, 294, 294, 294, 294, 294, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 294, 0, - - 0, 294, 294, 294, 294, 294, 294, 297, 297, 297, - 297, 297, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 297, 0, 0, 0, - 0, 0, 0, 297, 297, 297, 297, 297, 297, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, - 0, 0, 297, 297, 297, 297, 297, 297, 298, 298, - 298, 298, 298, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 298, 0, 0, - 0, 0, 0, 0, 298, 298, 298, 298, 298, 298, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 298, 298, 298, 298, 298, 298, 299, - 299, 299, 299, 299, 0, 0, 0, 0, 0, 0, - 299, 0, 0, 0, 0, 0, 0, 0, 299, 0, - 0, 0, 0, 0, 0, 299, 299, 299, 299, 299, - 299, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 299, 0, 0, 299, 299, 299, 299, 299, 299, - 300, 300, 300, 300, 300, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 300, 0, 0, 300, - 0, 0, 0, 0, 0, 0, 300, 300, 300, 300, - 300, 300, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 300, 300, 300, 300, 300, - 300, 301, 301, 301, 301, 301, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 301, 0, 0, 0, 0, 0, 0, 301, 301, 301, - 301, 301, 301, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 301, 301, 301, 301, - 301, 301, 302, 302, 302, 302, 302, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 302, 0, 0, 0, 0, 0, 0, 302, 302, - 302, 302, 302, 302, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 302, 302, 302, - 302, 302, 302, 304, 304, 304, 304, 304, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 304, 0, 0, 0, 0, 0, 0, 304, - - 304, 304, 304, 304, 304, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 304, 304, - 304, 304, 304, 304, 309, 0, 0, 0, 0, 0, - 0, 309, 309, 309, 309, 309, 309, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 309, 309, 309, 309, 309, 309, 310, 310, 310, 310, - 310, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, - - 0, 0, 310, 310, 310, 310, 310, 310, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 310, 310, 310, 310, 310, 310, 323, 323, 323, - 323, 323, 0, 323, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 323, 0, 0, 0, - 0, 0, 0, 323, 323, 323, 323, 323, 323, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, - 0, 0, 323, 323, 323, 323, 323, 323, 324, 324, - - 324, 324, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 324, 324, 324, 324, 324, 324, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 324, 0, 0, 324, 324, 324, 324, 324, 324, 328, - 328, 328, 328, 328, 0, 0, 0, 0, 0, 0, - 328, 0, 0, 0, 0, 0, 0, 0, 328, 0, - 0, 0, 0, 0, 0, 328, 328, 328, 328, 328, - 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 328, 0, 0, 328, 328, 328, 328, 328, 328, - 329, 329, 329, 329, 0, 0, 0, 0, 0, 0, - 0, 329, 0, 0, 0, 0, 0, 0, 0, 329, - 0, 0, 0, 0, 0, 0, 329, 329, 329, 329, - 329, 329, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 329, 0, 0, 329, 329, 329, 329, 329, - 329, 330, 330, 330, 330, 330, 0, 0, 0, 0, - 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, - - 330, 0, 0, 0, 0, 0, 0, 330, 330, 330, - 330, 330, 330, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 330, 0, 0, 330, 330, 330, 330, - 330, 330, 334, 0, 0, 0, 0, 0, 0, 334, - 334, 334, 334, 334, 334, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 334, 334, - 334, 334, 334, 334, 335, 0, 0, 0, 0, 0, - 0, 335, 335, 335, 335, 335, 335, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 335, 335, 335, 335, 335, 335, 338, 0, 0, 0, - 0, 0, 0, 338, 338, 338, 338, 338, 338, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 338, 338, 338, 338, 338, 338, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, - 0, 0, 0, 0, 339, 339, 339, 339, 339, 339, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 339, 339, 339, 339, 339, 339, 341, - 341, 341, 341, 341, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 341, 0, - 0, 0, 0, 0, 0, 341, 341, 341, 341, 341, - 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 341, 341, 341, 341, 341, 341, - 358, 0, 0, 0, 0, 0, 0, 358, 358, 358, - - 358, 358, 358, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 358, 358, 358, 358, - 358, 358, 362, 0, 0, 0, 0, 0, 0, 362, - 362, 362, 362, 362, 362, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 362, 362, - 362, 362, 362, 362, 363, 363, 363, 363, 363, 0, - 0, 0, 0, 0, 0, 0, 0, 363, 0, 0, - 0, 0, 0, 363, 0, 0, 0, 0, 0, 0, - - 363, 363, 363, 363, 363, 363, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 363, 0, 0, 363, - 363, 363, 363, 363, 363, 368, 0, 0, 0, 0, - 0, 0, 368, 0, 368, 0, 0, 0, 0, 368, - 368, 0, 0, 368, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, - 368, 0, 368, 0, 0, 0, 0, 368, 368, 0, - 0, 368, 373, 0, 0, 0, 0, 0, 0, 373, - 373, 373, 373, 373, 373, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 373, 373, - 373, 373, 373, 373, 374, 0, 0, 0, 0, 0, - 0, 374, 374, 374, 374, 374, 374, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 374, 374, 374, 374, 374, 374, 375, 0, 0, 0, - 0, 0, 0, 375, 375, 375, 375, 375, 375, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 375, 375, 375, 375, 375, 375, 387, 0, - 0, 0, 0, 0, 0, 387, 387, 387, 387, 387, - 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 387, 387, 387, 387, 387, 387, - 388, 0, 0, 0, 0, 0, 0, 388, 388, 388, - 388, 388, 388, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 388, 388, 388, 388, - 388, 388, 389, 0, 0, 0, 0, 0, 0, 389, - - 389, 389, 389, 389, 389, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 389, 389, - 389, 389, 389, 389, 397, 0, 0, 0, 0, 0, - 0, 397, 397, 397, 397, 397, 397, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 397, 397, 397, 397, 397, 397, 398, 0, 0, 0, - 0, 0, 0, 398, 398, 398, 398, 398, 398, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 398, 398, 398, 398, 398, 398, 414, 0, - 0, 0, 0, 0, 0, 414, 414, 414, 414, 414, - 414, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 414, 414, 414, 414, 414, 414, - 426, 0, 0, 0, 0, 0, 0, 426, 426, 426, - 426, 426, 426, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 426, 426, 426, 426, - - 426, 426, 428, 428, 428, 428, 428, 0, 0, 0, - 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, - 0, 428, 0, 0, 0, 0, 0, 0, 428, 428, - 428, 428, 428, 428, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 428, 0, 0, 428, 428, 428, - 428, 428, 428, 437, 437, 437, 437, 437, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 437, 0, 0, 0, 0, 0, 0, 437, - 437, 437, 437, 437, 437, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 437, 437, - 437, 437, 437, 437, 439, 0, 0, 0, 0, 0, - 0, 439, 439, 439, 439, 439, 439, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 439, 439, 439, 439, 439, 439, 446, 0, 0, 0, - 0, 0, 0, 446, 446, 446, 446, 446, 446, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 446, 446, 446, 446, 446, 446, 447, 0, - 0, 0, 0, 0, 0, 447, 447, 447, 447, 447, - 447, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 447, 447, 447, 447, 447, 447, - 452, 0, 0, 0, 0, 0, 0, 452, 452, 452, - 452, 452, 452, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 452, 452, 452, 452, - 452, 452, 453, 0, 0, 0, 0, 0, 0, 453, - - 453, 453, 453, 453, 453, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 453, 453, - 453, 453, 453, 453, 458, 0, 0, 0, 0, 0, - 0, 458, 458, 458, 458, 458, 458, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 458, 458, 458, 458, 458, 458, 459, 0, 0, 0, - 0, 0, 0, 459, 459, 459, 459, 459, 459, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 459, 459, 459, 459, 459, 459, 464, 0, - 0, 0, 0, 0, 0, 464, 464, 464, 464, 464, - 464, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 464, 464, 464, 464, 464, 464, - 479, 0, 0, 479, 479, 479, 479, 479, 479, 479, - 479, 479, 479, 480, 480, 0, 480, 480, 481, 0, - 0, 481, 481, 481, 481, 481, 481, 481, 481, 481, - 481, 482, 482, 0, 482, 482, 483, 0, 0, 483, - - 483, 484, 0, 484, 484, 0, 484, 484, 485, 485, - 485, 485, 485, 485, 485, 485, 485, 485, 486, 486, + 20, 20, 20, 20, 20, 20, 20, 20, 33, 32, + 35, 20, 32, 32, 36, 36, 36, 36, 36, 57, + + 43, 57, 33, 32, 35, 37, 37, 37, 37, 37, + 43, 43, 43, 43, 43, 43, 44, 84, 33, 55, + 32, 35, 55, 55, 57, 46, 44, 44, 44, 44, + 44, 44, 46, 55, 84, 46, 46, 46, 46, 46, + 46, 53, 37, 41, 41, 41, 41, 56, 66, 41, + 72, 53, 53, 53, 53, 53, 53, 70, 147, 86, + 72, 56, 41, 66, 147, 75, 86, 68, 56, 41, + 75, 73, 41, 41, 41, 41, 41, 41, 49, 49, + 49, 49, 68, 74, 74, 70, 73, 75, 63, 49, + 477, 75, 73, 68, 74, 78, 80, 49, 63, 63, + + 63, 63, 63, 63, 49, 83, 80, 49, 49, 49, + 49, 49, 49, 76, 81, 83, 76, 85, 78, 87, + 88, 89, 87, 88, 81, 81, 81, 81, 81, 81, + 93, 80, 85, 102, 108, 89, 90, 90, 90, 90, + 90, 124, 124, 143, 93, 140, 94, 102, 90, 97, + 143, 474, 109, 102, 108, 90, 94, 94, 94, 94, + 94, 94, 90, 97, 96, 90, 90, 90, 90, 90, + 90, 96, 109, 140, 118, 467, 98, 119, 96, 99, + 103, 98, 104, 105, 118, 97, 98, 98, 98, 98, + 98, 98, 119, 99, 103, 107, 104, 105, 120, 118, + + 107, 125, 127, 461, 150, 137, 127, 99, 137, 155, + 104, 150, 155, 120, 148, 125, 103, 105, 112, 125, + 107, 110, 110, 110, 110, 110, 132, 110, 112, 112, + 112, 112, 112, 112, 148, 158, 167, 192, 456, 160, + 110, 158, 157, 192, 167, 132, 159, 110, 160, 162, + 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, + 157, 159, 111, 162, 190, 194, 116, 206, 344, 166, + 169, 190, 194, 344, 206, 111, 116, 116, 116, 116, + 116, 116, 111, 166, 169, 111, 111, 111, 111, 111, + 111, 114, 114, 114, 114, 114, 198, 205, 226, 207, + + 198, 117, 226, 170, 171, 173, 207, 440, 205, 203, + 114, 117, 117, 117, 117, 117, 117, 170, 171, 173, + 114, 114, 114, 114, 114, 114, 121, 121, 121, 121, + 121, 203, 212, 175, 236, 238, 131, 121, 238, 182, + 212, 392, 434, 429, 236, 121, 131, 131, 131, 131, + 131, 131, 121, 175, 182, 121, 121, 121, 121, 121, + 121, 122, 122, 122, 122, 216, 265, 244, 392, 268, + 269, 154, 122, 196, 184, 244, 268, 265, 269, 216, + 122, 154, 154, 154, 154, 154, 154, 122, 184, 196, + 122, 122, 122, 122, 122, 122, 129, 129, 129, 129, + + 129, 184, 276, 202, 340, 307, 161, 204, 307, 309, + 276, 419, 309, 385, 340, 129, 161, 161, 161, 161, + 161, 161, 129, 202, 204, 129, 129, 129, 129, 129, + 129, 152, 152, 152, 152, 152, 232, 165, 172, 229, + 313, 345, 420, 384, 165, 261, 345, 420, 313, 232, + 152, 165, 172, 235, 229, 237, 239, 152, 224, 261, + 152, 152, 152, 152, 152, 152, 163, 163, 163, 163, + 163, 370, 224, 250, 235, 237, 176, 239, 370, 172, + 435, 261, 364, 224, 435, 163, 176, 176, 176, 176, + 176, 176, 177, 250, 251, 163, 163, 163, 163, 163, + + 163, 178, 177, 177, 177, 177, 177, 177, 270, 251, + 272, 178, 178, 178, 178, 178, 178, 180, 180, 180, + 180, 180, 281, 281, 281, 281, 281, 181, 272, 285, + 270, 383, 348, 343, 383, 281, 180, 181, 181, 181, + 181, 181, 181, 183, 285, 332, 180, 180, 180, 180, + 180, 180, 187, 183, 183, 183, 183, 183, 183, 282, + 303, 306, 187, 187, 187, 187, 187, 187, 189, 189, + 189, 189, 189, 283, 283, 283, 283, 283, 199, 282, + 300, 327, 303, 306, 300, 318, 283, 189, 199, 199, + 199, 199, 199, 199, 300, 322, 327, 189, 189, 189, + + 189, 189, 189, 201, 201, 201, 201, 201, 319, 319, + 319, 319, 319, 208, 418, 322, 360, 418, 317, 316, + 326, 319, 201, 208, 208, 208, 208, 208, 208, 209, + 326, 360, 201, 201, 201, 201, 201, 201, 211, 209, + 209, 209, 209, 209, 209, 326, 356, 315, 211, 211, + 211, 211, 211, 211, 215, 215, 215, 215, 215, 218, + 215, 371, 337, 357, 361, 215, 356, 215, 371, 218, + 218, 218, 218, 218, 218, 219, 337, 321, 314, 361, + 215, 220, 321, 357, 366, 219, 219, 219, 219, 219, + 219, 220, 220, 220, 220, 220, 220, 221, 366, 378, + + 337, 366, 321, 222, 381, 407, 378, 221, 221, 221, + 221, 221, 221, 222, 222, 222, 222, 222, 222, 223, + 334, 334, 334, 334, 334, 227, 308, 381, 407, 223, + 223, 223, 223, 223, 223, 227, 227, 227, 227, 227, + 227, 228, 379, 380, 298, 422, 334, 233, 422, 379, + 380, 228, 228, 228, 228, 228, 228, 233, 233, 233, + 233, 233, 233, 234, 338, 338, 338, 338, 338, 241, + 432, 415, 441, 234, 234, 234, 234, 234, 234, 241, + 241, 241, 241, 241, 241, 242, 382, 441, 393, 432, + 338, 243, 415, 382, 393, 242, 242, 242, 242, 242, + + 242, 243, 243, 243, 243, 243, 243, 248, 248, 248, + 248, 248, 405, 248, 293, 390, 394, 395, 248, 405, + 248, 249, 249, 249, 249, 249, 255, 249, 377, 390, + 394, 395, 249, 248, 249, 402, 255, 255, 255, 255, + 255, 255, 377, 396, 404, 403, 402, 249, 253, 253, + 253, 253, 253, 403, 253, 404, 463, 396, 256, 253, + 253, 253, 377, 396, 280, 408, 463, 253, 256, 256, + 256, 256, 256, 256, 253, 257, 408, 253, 253, 253, + 253, 253, 253, 258, 416, 257, 257, 257, 257, 257, + 257, 259, 279, 258, 258, 258, 258, 258, 258, 260, + + 416, 259, 259, 259, 259, 259, 259, 262, 278, 260, + 260, 260, 260, 260, 260, 263, 277, 262, 262, 262, + 262, 262, 262, 266, 271, 263, 263, 263, 263, 263, + 263, 267, 264, 266, 266, 266, 266, 266, 266, 273, + 254, 267, 267, 267, 267, 267, 267, 274, 247, 273, + 273, 273, 273, 273, 273, 275, 406, 274, 274, 274, + 274, 274, 274, 406, 401, 275, 275, 275, 275, 275, + 275, 284, 284, 284, 284, 391, 443, 284, 401, 417, + 391, 431, 246, 391, 431, 287, 287, 287, 287, 287, + 284, 287, 245, 443, 240, 231, 287, 284, 287, 417, + + 284, 284, 284, 284, 284, 284, 286, 286, 286, 286, + 230, 287, 412, 412, 412, 412, 412, 286, 288, 288, + 288, 288, 288, 421, 288, 286, 430, 442, 412, 288, + 421, 288, 286, 430, 450, 286, 286, 286, 286, 286, + 286, 444, 225, 470, 288, 289, 289, 289, 289, 289, + 442, 289, 217, 475, 450, 444, 289, 470, 289, 290, + 290, 290, 290, 290, 294, 290, 448, 475, 462, 433, + 290, 289, 290, 448, 294, 294, 294, 294, 294, 294, + 425, 425, 425, 425, 425, 290, 291, 291, 291, 291, + 291, 433, 291, 425, 455, 462, 296, 291, 214, 291, + + 341, 341, 341, 341, 341, 291, 296, 296, 296, 296, + 296, 296, 291, 213, 455, 291, 291, 291, 291, 291, + 291, 292, 292, 292, 292, 292, 341, 292, 449, 451, + 200, 297, 292, 292, 292, 449, 451, 460, 195, 193, + 292, 297, 297, 297, 297, 297, 297, 292, 299, 191, + 292, 292, 292, 292, 292, 292, 301, 460, 299, 299, + 299, 299, 299, 299, 302, 466, 301, 301, 301, 301, + 301, 301, 304, 188, 302, 302, 302, 302, 302, 302, + 305, 457, 304, 304, 304, 304, 304, 304, 466, 185, + 305, 305, 305, 305, 305, 305, 310, 310, 310, 310, + + 310, 311, 457, 476, 468, 179, 174, 168, 310, 454, + 468, 311, 311, 311, 311, 311, 311, 312, 471, 454, + 164, 473, 310, 153, 476, 471, 473, 312, 312, 312, + 312, 312, 312, 323, 323, 323, 323, 323, 151, 323, + 454, 328, 328, 328, 328, 328, 323, 149, 472, 146, + 145, 144, 328, 142, 328, 472, 141, 139, 331, 323, + 324, 324, 324, 324, 324, 138, 324, 328, 331, 331, + 331, 331, 331, 331, 355, 355, 355, 355, 355, 324, + 355, 365, 365, 365, 365, 365, 324, 355, 136, 324, + 324, 324, 324, 324, 324, 325, 325, 325, 325, 135, + + 355, 325, 133, 130, 128, 333, 126, 365, 115, 367, + 367, 367, 367, 367, 325, 333, 333, 333, 333, 333, + 333, 325, 113, 106, 325, 325, 325, 325, 325, 325, + 329, 329, 329, 329, 329, 367, 95, 82, 79, 77, + 335, 329, 65, 369, 369, 369, 369, 369, 61, 329, + 335, 335, 335, 335, 335, 335, 329, 60, 59, 329, + 329, 329, 329, 329, 329, 330, 330, 330, 330, 369, + 58, 51, 45, 38, 29, 336, 330, 28, 24, 21, + 19, 18, 16, 14, 330, 336, 336, 336, 336, 336, + 336, 330, 339, 7, 330, 330, 330, 330, 330, 330, + + 342, 6, 339, 339, 339, 339, 339, 339, 5, 0, + 342, 342, 342, 342, 342, 342, 346, 346, 346, 346, + 346, 347, 0, 0, 0, 0, 0, 0, 346, 0, + 0, 347, 347, 347, 347, 347, 347, 358, 0, 0, + 0, 0, 346, 0, 0, 0, 0, 358, 358, 358, + 358, 358, 358, 359, 359, 359, 359, 359, 362, 0, + 0, 0, 0, 0, 359, 0, 359, 0, 362, 362, + 362, 362, 362, 362, 363, 0, 0, 368, 0, 359, + 0, 0, 0, 368, 363, 363, 363, 363, 363, 363, + 368, 0, 368, 372, 0, 0, 0, 368, 368, 373, + + 0, 368, 0, 372, 372, 372, 372, 372, 372, 373, + 373, 373, 373, 373, 373, 374, 0, 0, 0, 0, + 0, 375, 0, 0, 0, 374, 374, 374, 374, 374, + 374, 375, 375, 375, 375, 375, 375, 387, 0, 0, + 0, 0, 0, 388, 0, 0, 0, 387, 387, 387, + 387, 387, 387, 388, 388, 388, 388, 388, 388, 389, + 0, 0, 0, 0, 0, 397, 0, 0, 0, 389, + 389, 389, 389, 389, 389, 397, 397, 397, 397, 397, + 397, 398, 0, 0, 0, 0, 0, 399, 0, 0, + 0, 398, 398, 398, 398, 398, 398, 399, 399, 399, + + 399, 399, 399, 400, 400, 400, 400, 400, 0, 0, + 409, 0, 0, 0, 0, 0, 0, 0, 0, 400, + 409, 409, 409, 409, 409, 409, 410, 0, 0, 400, + 411, 411, 411, 411, 411, 0, 410, 410, 410, 410, + 410, 410, 0, 0, 0, 0, 411, 413, 0, 0, + 414, 414, 414, 414, 414, 0, 411, 413, 413, 413, + 413, 413, 413, 414, 423, 423, 423, 423, 423, 0, + 427, 427, 427, 427, 427, 0, 414, 423, 0, 0, + 0, 0, 0, 427, 0, 0, 0, 428, 0, 0, + 423, 424, 424, 424, 424, 424, 427, 428, 428, 428, + + 428, 428, 428, 0, 424, 436, 436, 436, 436, 436, + 424, 0, 0, 0, 0, 0, 0, 424, 436, 0, + 424, 424, 424, 424, 424, 424, 437, 0, 0, 0, + 0, 436, 0, 0, 0, 0, 437, 437, 437, 437, + 437, 437, 438, 438, 438, 438, 438, 445, 0, 0, + 446, 446, 446, 446, 446, 438, 0, 445, 445, 445, + 445, 445, 445, 446, 0, 0, 0, 447, 438, 439, + 439, 439, 439, 439, 0, 0, 446, 447, 447, 447, + 447, 447, 447, 0, 0, 0, 0, 0, 439, 0, + 0, 0, 0, 0, 452, 0, 0, 0, 439, 439, + + 439, 439, 439, 439, 452, 452, 452, 452, 452, 452, + 453, 0, 0, 0, 0, 0, 458, 0, 0, 0, + 453, 453, 453, 453, 453, 453, 458, 458, 458, 458, + 458, 458, 459, 0, 0, 0, 0, 0, 464, 0, + 0, 0, 459, 459, 459, 459, 459, 459, 464, 464, + 464, 464, 464, 464, 465, 0, 0, 0, 0, 0, + 469, 0, 0, 0, 465, 465, 465, 465, 465, 465, + 469, 469, 469, 469, 469, 469, 479, 0, 479, 479, + 479, 479, 479, 479, 479, 479, 479, 480, 480, 0, + 480, 480, 481, 0, 481, 481, 481, 481, 481, 481, + + 481, 481, 481, 482, 482, 0, 482, 482, 483, 0, + 0, 483, 483, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 485, 0, 485, 485, 0, 485, 485, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, - 486, 488, 488, 0, 488, 488, 489, 489, 489, 489, - 489, 489, 489, 489, 489, 489, 490, 490, 490, 490, - 490, 490, 490, 490, 490, 490, 490, 490, 490, 491, - 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, - 491, 491, 491, 493, 493, 0, 493, 493, 494, 494, - 494, 494, 494, 494, 494, 494, 494, 494, 495, 495, - 0, 495, 495, 496, 496, 496, 496, 496, 496, 496, - - 496, 496, 496, 497, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 498, 498, 498, 500, 500, 500, 500, - 500, 500, 500, 500, 500, 500, 501, 501, 0, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 502, + 487, 487, 487, 487, 487, 487, 487, 487, 487, 488, + 488, 0, 488, 488, 489, 489, 489, 489, 489, 489, + 489, 489, 489, 489, 489, 490, 490, 490, 490, 490, + 490, 490, 490, 490, 490, 490, 490, 491, 491, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 493, 493, + 0, 493, 493, 494, 494, 494, 494, 494, 494, 494, + + 494, 494, 495, 495, 0, 495, 495, 496, 496, 496, + 496, 496, 496, 496, 496, 496, 497, 497, 497, 497, + 497, 497, 497, 497, 497, 498, 498, 498, 498, 498, + 498, 498, 498, 498, 498, 498, 498, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 500, 500, 500, 500, + 500, 500, 500, 500, 500, 501, 501, 501, 0, 501, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, - 502, 502, 503, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 503, 504, 504, 504, 504, - 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, - 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, - 506, 506, 506, 506, 506, 506, 506, 506, 506, 506, - - 507, 507, 507, 507, 508, 0, 0, 508, 508, 508, - 508, 508, 508, 508, 508, 508, 508, 510, 510, 510, - 510, 510, 510, 510, 510, 510, 510, 510, 510, 510, - 510, 512, 512, 512, 512, 513, 513, 513, 513, 513, - 513, 0, 513, 513, 513, 513, 513, 513, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, - 514, 516, 516, 516, 516, 516, 516, 516, 516, 516, - 516, 516, 516, 516, 516, 518, 518, 518, 518, 519, - 519, 519, 519, 519, 519, 0, 519, 519, 519, 519, - 519, 519, 520, 0, 0, 520, 520, 520, 520, 520, - - 520, 520, 520, 520, 520, 521, 0, 0, 521, 521, - 521, 521, 521, 521, 521, 521, 521, 521, 522, 522, - 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, - 522, 523, 523, 523, 523, 523, 523, 523, 523, 523, - 523, 523, 523, 523, 525, 525, 0, 525, 525, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 528, 528, 528, 528, 529, 529, 529, 529, - 529, 529, 529, 529, 529, 529, 529, 529, 529, 530, - 0, 0, 530, 530, 530, 530, 530, 530, 530, 530, - 530, 530, 531, 531, 531, 531, 531, 531, 531, 531, - - 531, 531, 531, 531, 531, 532, 532, 532, 532, 532, - 0, 0, 532, 532, 532, 532, 532, 532, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 534, 534, 534, 534, 534, 534, 534, 534, 534, - 534, 534, 534, 534, 535, 535, 0, 535, 535, 536, - 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, - 536, 536, 538, 538, 538, 538, 539, 539, 0, 539, - 539, 539, 539, 539, 539, 539, 539, 539, 539, 540, - 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, - 540, 540, 541, 541, 0, 541, 541, 541, 541, 541, - - 541, 541, 541, 541, 541, 542, 542, 542, 542, 542, - 542, 542, 542, 542, 542, 542, 542, 542, 543, 543, - 543, 543, 543, 0, 0, 543, 543, 543, 543, 543, - 543, 546, 546, 546, 546, 0, 0, 0, 0, 546, - 0, 0, 546, 546, 547, 547, 547, 547, 0, 0, - 0, 547, 547, 547, 0, 547, 547, 548, 548, 548, - 548, 548, 548, 548, 548, 548, 548, 549, 549, 549, - 549, 549, 549, 549, 549, 549, 549, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, + 502, 502, 503, 503, 503, 0, 503, 504, 504, 504, + 504, 0, 504, 504, 504, 504, 504, 504, 505, 505, + 505, 0, 505, 506, 0, 506, 506, 506, 506, 506, + + 506, 506, 506, 506, 507, 0, 507, 507, 507, 507, + 507, 507, 507, 507, 507, 508, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 508, 509, 509, 509, 0, + 509, 510, 510, 510, 510, 510, 510, 510, 510, 510, + 510, 510, 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 512, 512, 512, 0, 512, 513, 513, + 513, 0, 0, 0, 513, 0, 0, 513, 513, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 515, 515, + 515, 0, 0, 515, 515, 515, 0, 515, 515, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, - 478, 478, 478 + 478, 478, 478, 478, 478, 478, 478, 478, 478 } ; #line 1 "" @@ -1813,7 +878,7 @@ YY_DECL yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 6578 ); + while ( yy_base[yy_current_state] != 2399 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -2185,7 +1250,7 @@ YY_RULE_SETUP #line 110 "" ECHO; YY_BREAK -#line 2738 "" +#line 1761 "" case YY_STATE_EOF(INITIAL): case YY_END_OF_BUFFER: case YY_STATE_EOF(mediaquery): diff --git a/src/3rdparty/webkit/WebCore/html/HTMLCanvasElement.cpp b/src/3rdparty/webkit/WebCore/html/HTMLCanvasElement.cpp index fb6d9fe..76c3202 100644 --- a/src/3rdparty/webkit/WebCore/html/HTMLCanvasElement.cpp +++ b/src/3rdparty/webkit/WebCore/html/HTMLCanvasElement.cpp @@ -257,6 +257,10 @@ void HTMLCanvasElement::createImageBuffer() const return; m_imageBuffer.set(ImageBuffer::create(size, false).release()); + // The convertLogicalToDevice MaxCanvasArea check should prevent common cases + // where ImageBuffer::create() returns NULL, however we could still be low on memory. + if (!m_imageBuffer) + return; m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height())); m_imageBuffer->context()->setShadowsIgnoreTransforms(true); } diff --git a/src/3rdparty/webkit/WebCore/platform/qt/DragDataQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/DragDataQt.cpp index 9d95373..218f7be 100644 --- a/src/3rdparty/webkit/WebCore/platform/qt/DragDataQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/qt/DragDataQt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -126,6 +126,10 @@ String DragData::asURL(String* title) const if (!m_platformDragData) return String(); QList urls = m_platformDragData->urls(); + + if (urls.isEmpty()) + return String(); + return urls.first().toString(); } diff --git a/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp b/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp index e0e178b..1d7d570 100644 --- a/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp @@ -299,9 +299,6 @@ void PluginView::show() setSelfVisible(true); - if (isParentVisible() && platformPluginWidget()) - platformPluginWidget()->setVisible(true); - Widget::show(); } @@ -311,9 +308,6 @@ void PluginView::hide() setSelfVisible(false); - if (isParentVisible() && platformPluginWidget()) - platformPluginWidget()->setVisible(false); - Widget::hide(); } @@ -345,9 +339,6 @@ void PluginView::setParentVisible(bool visible) return; Widget::setParentVisible(visible); - - if (isSelfVisible() && platformPluginWidget()) - platformPluginWidget()->setVisible(visible); } void PluginView::setNPWindowRect(const IntRect&) diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp index 14288e2..de37383 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp @@ -1095,7 +1095,7 @@ QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const This enum describes the types of action which can be performed on the web page. Actions only have an effect when they are applicable. The availability of - actions can be be determined by checking \l{QAction::}{isEnabled()} on the + actions can be be determined by checking \l{QAction::}{enabled()} on the action returned by \l{QWebPage::}{action()}. One method of enabling the text editing, cursor movement, and text selection actions -- cgit v0.12 From a93551a2e3e590400b09bc076d3a6883c162b75d Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 6 Apr 2009 16:18:40 +0200 Subject: compile for non x11 systems Reviewed-by: joerg --- tests/auto/qwidget/tst_qwidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index dfd0792..4b41bdb 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -8734,7 +8734,9 @@ void tst_QWidget::toplevelLineEditFocus() QLineEdit w; w.show(); +#ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&w); +#endif QTest::qWait(200); QCOMPARE(QApplication::activeWindow(), &w); -- cgit v0.12 From fc0a71e4b4e4ce1e0f57c6d7be6bd9d935062fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Mon, 6 Apr 2009 16:22:04 +0200 Subject: Update the autotest to pass again due to a previous behaviuour change. Font propagation changed slightly in some cases due to change 22d472c17167c4ca8df5678842768ab63b7baadd. However, the change is sane - its just the autotest that is not optimal. Task-number: 246215 Reviewed-by: andreas --- .../tst_qgraphicsproxywidget.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index d1d1857..b99f111 100644 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -1475,7 +1475,7 @@ void tst_QGraphicsProxyWidget::scrollUpdate() view.paintEventRegion = QRegion(); view.npaints = 0; QTimer::singleShot(0, widget, SLOT(updateScroll())); - QTest::qWait(500); + QTest::qWait(500); QCOMPARE(view.npaints, 2); // QRect(0, 0, 200, 12) is the first update, expanded (-2, -2, 2, 2) // QRect(0, 12, 102, 10) is the scroll update, expanded (-2, -2, 2, 2), @@ -2582,7 +2582,7 @@ void tst_QGraphicsProxyWidget::childPos() { #ifdef Q_OS_IRIX QSKIP("This test is not reliable on IRIX.", SkipAll); -#endif +#endif QFETCH(bool, moveCombo); QFETCH(QPoint, comboPos); QFETCH(QPointF, proxyPos); @@ -2797,6 +2797,7 @@ void tst_QGraphicsProxyWidget::palettePropagation() void tst_QGraphicsProxyWidget::fontPropagation() { // Construct a font with an unlikely setup + QGraphicsScene scene; QFont lineEditFont = QApplication::font("QLineEdit"); QFont font = lineEditFont; font.setPointSize(43); @@ -2805,6 +2806,7 @@ void tst_QGraphicsProxyWidget::fontPropagation() QGraphicsProxyWidget proxy; proxy.setWidget(edit); + scene.addItem(&proxy); EventSpy editSpy(edit); EventSpy proxySpy(&proxy); @@ -2825,6 +2827,7 @@ void tst_QGraphicsProxyWidget::fontPropagation() // Proxy to widget proxy.setFont(font); + QApplication::processEvents(); // wait for QEvent::Polish QVERIFY(proxy.testAttribute(Qt::WA_SetFont)); QCOMPARE(editSpy.counts[QEvent::FontChange], 3); QCOMPARE(proxySpy.counts[QEvent::FontChange], 1); @@ -2893,7 +2896,7 @@ void tst_QGraphicsProxyWidget::createProxyForChildWidget() edit2->setText("QLineEdit 2"); QCheckBox *checkbox = new QCheckBox("QCheckBox"); QVBoxLayout *vlayout = new QVBoxLayout; - + vlayout->addWidget(edit1); vlayout->addWidget(edit2); vlayout->addWidget(checkbox); @@ -2916,7 +2919,7 @@ void tst_QGraphicsProxyWidget::createProxyForChildWidget() QVERIFY(window.graphicsProxyWidget() == 0); QVERIFY(checkbox->graphicsProxyWidget() == 0); - + QGraphicsProxyWidget *windowProxy = scene.addWidget(&window); QGraphicsView view(&scene); view.show(); @@ -2946,10 +2949,10 @@ void tst_QGraphicsProxyWidget::createProxyForChildWidget() QVERIFY(boxProxy->size() == box->size()); QTest::qWait(10); - + QSignalSpy spy(checkbox, SIGNAL(clicked())); - + QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8)))); QTRY_COMPARE(spy.count(), 0); @@ -2958,7 +2961,7 @@ void tst_QGraphicsProxyWidget::createProxyForChildWidget() QTRY_COMPARE(spy.count(), 1); - + boxProxy->setWidget(0); QVERIFY(checkbox->graphicsProxyWidget() == 0); @@ -3006,10 +3009,10 @@ void tst_QGraphicsProxyWidget::actionsContextMenu() widget->addAction(new QAction("item 2", widget)); widget->addAction(new QAction("item 3", widget)); widget->setContextMenuPolicy(Qt::ActionsContextMenu); - + QGraphicsScene scene; scene.addWidget(widget); - + QGraphicsView view(&scene); view.show(); #ifdef Q_WS_X11 -- cgit v0.12 From 003223dcfc1fa884b82085db19d4c4056bf6eaa0 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 6 Apr 2009 16:56:36 +0200 Subject: Removed usage of NaN in SVG gradients. The previous change 6c2dd295b2ca2f9125fe072d035a3784ce748718 to remove usage of NaN in SVG gradients was incomplete. This commit should fix that. Task-number: 250146 Reviewed-by: Samuel --- src/svg/qsvghandler.cpp | 6 ++++-- src/svg/qsvgstyle.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 18ba71c..433a3ad 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -2587,10 +2587,12 @@ static void parseBaseGradient(QSvgNode *node, if (prop && prop->type() == QSvgStyleProperty::GRADIENT) { QSvgGradientStyle *inherited = static_cast(prop); - if (!inherited->stopLink().isEmpty()) + if (!inherited->stopLink().isEmpty()) { gradProp->setStopLink(inherited->stopLink(), handler->document()); - else + } else { grad->setStops(inherited->qgradient()->stops()); + gradProp->setGradientStopsSet(inherited->gradientStopsSet()); + } matrix = inherited->qmatrix(); } else { diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 4a40bed..b065395 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -257,7 +257,7 @@ void QSvgGradientStyle::apply(QPainter *p, const QRectF &/*rect*/, QSvgNode *, Q // If the gradient is marked as empty, insert transparent black if (!m_gradientStopsSet) { - m_gradient->setColorAt(0.0, QColor(0, 0, 0, 0)); + m_gradient->setStops(QGradientStops() << QGradientStop(0.0, QColor(0, 0, 0, 0))); m_gradientStopsSet = true; } -- cgit v0.12 From 707012f57bf3abf7ddd829e5752b4e1791250bea Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 27 Mar 2009 16:53:30 +0100 Subject: Splitted qhttpnetworkconnection* files into individual files (cherry picked from commit fd9b788bd6a99630b06cffee4c9fa9f4c06b0ef1) --- src/network/access/access.pri | 6 + src/network/access/qhttpnetworkconnection.cpp | 1119 +------------------------ src/network/access/qhttpnetworkconnection_p.h | 243 +++--- src/network/access/qhttpnetworkheader.cpp | 123 +++ src/network/access/qhttpnetworkheader_p.h | 111 +++ src/network/access/qhttpnetworkreply.cpp | 663 +++++++++++++++ src/network/access/qhttpnetworkreply_p.h | 226 +++++ src/network/access/qhttpnetworkrequest.cpp | 261 ++++++ src/network/access/qhttpnetworkrequest_p.h | 144 ++++ 9 files changed, 1659 insertions(+), 1237 deletions(-) create mode 100644 src/network/access/qhttpnetworkheader.cpp create mode 100644 src/network/access/qhttpnetworkheader_p.h create mode 100644 src/network/access/qhttpnetworkreply.cpp create mode 100644 src/network/access/qhttpnetworkreply_p.h create mode 100644 src/network/access/qhttpnetworkrequest.cpp create mode 100644 src/network/access/qhttpnetworkrequest_p.h diff --git a/src/network/access/access.pri b/src/network/access/access.pri index 6bcca0c..3269b2e 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -2,6 +2,9 @@ HEADERS += access/qftp.h \ access/qhttp.h \ + access/qhttpnetworkheader_p.h \ + access/qhttpnetworkrequest_p.h \ + access/qhttpnetworkreply_p.h \ access/qhttpnetworkconnection_p.h \ access/qnetworkaccessmanager.h \ access/qnetworkaccessmanager_p.h \ @@ -27,6 +30,9 @@ HEADERS += access/qftp.h \ SOURCES += access/qftp.cpp \ access/qhttp.cpp \ + access/qhttpnetworkheader.cpp \ + access/qhttpnetworkrequest.cpp \ + access/qhttpnetworkreply.cpp \ access/qhttpnetworkconnection.cpp \ access/qnetworkaccessmanager.cpp \ access/qnetworkaccesscache.cpp \ diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index edb2988..980c0e0 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -45,7 +45,7 @@ #include #include #include -#include + #include #include #include @@ -59,875 +59,9 @@ # include #endif -#ifndef QT_NO_COMPRESS -# include -static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header -// gzip flag byte -#define HEAD_CRC 0x02 // bit 1 set: header CRC present -#define EXTRA_FIELD 0x04 // bit 2 set: extra field present -#define ORIG_NAME 0x08 // bit 3 set: original file name present -#define COMMENT 0x10 // bit 4 set: file comment present -#define RESERVED 0xE0 // bits 5..7: reserved -#define CHUNK 16384 -#endif - -QT_BEGIN_NAMESPACE - -class QHttpNetworkHeaderPrivate : public QSharedData -{ -public: - QUrl url; - QList > fields; - - QHttpNetworkHeaderPrivate(const QUrl &newUrl = QUrl()); - QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other); - inline qint64 contentLength() const; - inline void setContentLength(qint64 length); - - inline QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; - inline QList headerFieldValues(const QByteArray &name) const; - inline void setHeaderField(const QByteArray &name, const QByteArray &data); - bool operator==(const QHttpNetworkHeaderPrivate &other) const; - -}; - -QHttpNetworkHeaderPrivate::QHttpNetworkHeaderPrivate(const QUrl &newUrl) - :url(newUrl) -{ -} - -QHttpNetworkHeaderPrivate::QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other) - :QSharedData(other) -{ - url = other.url; - fields = other.fields; -} - -qint64 QHttpNetworkHeaderPrivate::contentLength() const -{ - bool ok = false; - QByteArray value = headerField("content-length"); - qint64 length = value.toULongLong(&ok); - if (ok) - return length; - return -1; // the header field is not set -} - -void QHttpNetworkHeaderPrivate::setContentLength(qint64 length) -{ - setHeaderField("Content-Length", QByteArray::number(length)); -} - -QByteArray QHttpNetworkHeaderPrivate::headerField(const QByteArray &name, const QByteArray &defaultValue) const -{ - QList allValues = headerFieldValues(name); - if (allValues.isEmpty()) - return defaultValue; - - QByteArray result; - bool first = true; - foreach (QByteArray value, allValues) { - if (!first) - result += ", "; - first = false; - result += value; - } - return result; -} - -QList QHttpNetworkHeaderPrivate::headerFieldValues(const QByteArray &name) const -{ - QList result; - QByteArray lowerName = name.toLower(); - QList >::ConstIterator it = fields.constBegin(), - end = fields.constEnd(); - for ( ; it != end; ++it) - if (lowerName == it->first.toLower()) - result += it->second; - - return result; -} - -void QHttpNetworkHeaderPrivate::setHeaderField(const QByteArray &name, const QByteArray &data) -{ - QByteArray lowerName = name.toLower(); - QList >::Iterator it = fields.begin(); - while (it != fields.end()) { - if (lowerName == it->first.toLower()) - it = fields.erase(it); - else - ++it; - } - fields.append(qMakePair(name, data)); -} - -bool QHttpNetworkHeaderPrivate::operator==(const QHttpNetworkHeaderPrivate &other) const -{ - return (url == other.url); -} - -// QHttpNetworkRequestPrivate -class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate -{ -public: - QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, - QHttpNetworkRequest::Priority pri, const QUrl &newUrl = QUrl()); - QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other); - ~QHttpNetworkRequestPrivate(); - bool operator==(const QHttpNetworkRequestPrivate &other) const; - QByteArray methodName() const; - QByteArray uri(bool throughProxy) const; - - static QByteArray header(const QHttpNetworkRequest &request, bool throughProxy); - - QHttpNetworkRequest::Operation operation; - QHttpNetworkRequest::Priority priority; - mutable QIODevice *data; - bool autoDecompress; -}; - -QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, - QHttpNetworkRequest::Priority pri, const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0), - autoDecompress(false) -{ -} - -QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other) - : QHttpNetworkHeaderPrivate(other) -{ - operation = other.operation; - priority = other.priority; - data = other.data; - autoDecompress = other.autoDecompress; -} - -QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() -{ -} - -bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &other) const -{ - return QHttpNetworkHeaderPrivate::operator==(other) - && (operation == other.operation) - && (data == other.data); -} - -QByteArray QHttpNetworkRequestPrivate::methodName() const -{ - QByteArray ba; - switch (operation) { - case QHttpNetworkRequest::Options: - ba += "OPTIONS"; - break; - case QHttpNetworkRequest::Get: - ba += "GET"; - break; - case QHttpNetworkRequest::Head: - ba += "HEAD"; - break; - case QHttpNetworkRequest::Post: - ba += "POST"; - break; - case QHttpNetworkRequest::Put: - ba += "PUT"; - break; - case QHttpNetworkRequest::Delete: - ba += "DELETE"; - break; - case QHttpNetworkRequest::Trace: - ba += "TRACE"; - break; - case QHttpNetworkRequest::Connect: - ba += "CONNECT"; - break; - default: - break; - } - return ba; -} - -QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const -{ - QUrl::FormattingOptions format(QUrl::RemoveFragment); - - // for POST, query data is send as content - if (operation == QHttpNetworkRequest::Post && !data) - format |= QUrl::RemoveQuery; - // for requests through proxy, the Request-URI contains full url - if (throughProxy) - format |= QUrl::RemoveUserInfo; - else - format |= QUrl::RemoveScheme | QUrl::RemoveAuthority; - QByteArray uri = url.toEncoded(format); - if (uri.isEmpty() || (throughProxy && url.path().isEmpty())) - uri += '/'; - return uri; -} - -QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy) -{ - QByteArray ba = request.d->methodName(); - QByteArray uri = request.d->uri(throughProxy); - ba += " " + uri; - - QString majorVersion = QString::number(request.majorVersion()); - QString minorVersion = QString::number(request.minorVersion()); - ba += " HTTP/" + majorVersion.toLatin1() + "." + minorVersion.toLatin1() + "\r\n"; - - QList > fields = request.header(); - QList >::const_iterator it = fields.constBegin(); - for (; it != fields.constEnd(); ++it) - ba += it->first + ": " + it->second + "\r\n"; - if (request.d->operation == QHttpNetworkRequest::Post) { - // add content type, if not set in the request - if (request.headerField("content-type").isEmpty()) - ba += "Content-Type: application/x-www-form-urlencoded\r\n"; - if (!request.d->data && request.d->url.hasQuery()) { - QByteArray query = request.d->url.encodedQuery(); - ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n"; - ba += "\r\n"; - ba += query; - } else { - ba += "\r\n"; - } - } else { - ba += "\r\n"; - } - return ba; -} - -class QHttpNetworkReplyPrivate : public QObjectPrivate, public QHttpNetworkHeaderPrivate -{ -public: - QHttpNetworkReplyPrivate(const QUrl &newUrl = QUrl()); - ~QHttpNetworkReplyPrivate(); - qint64 readStatus(QAbstractSocket *socket); - void parseStatus(const QByteArray &status); - qint64 readHeader(QAbstractSocket *socket); - void parseHeader(const QByteArray &header); - qint64 readBody(QAbstractSocket *socket, QIODevice *out); - bool findChallenge(bool forProxy, QByteArray &challenge) const; - QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; - void clear(); - - qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size); - qint64 transferChunked(QIODevice *in, QIODevice *out); - qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); - - qint64 bytesAvailable() const; - bool isChunked(); - bool connectionCloseEnabled(); - bool isGzipped(); -#ifndef QT_NO_COMPRESS - bool gzipCheckHeader(QByteArray &content, int &pos); - int gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated); -#endif - void removeAutoDecompressHeader(); - - enum ReplyState { - NothingDoneState, - ReadingStatusState, - ReadingHeaderState, - ReadingDataState, - AllDoneState - } state; - - QHttpNetworkRequest request; - int statusCode; - int majorVersion; - int minorVersion; - QString errorString; - QString reasonPhrase; - qint64 bodyLength; - qint64 contentRead; - qint64 totalProgress; - QByteArray fragment; - qint64 currentChunkSize; - qint64 currentChunkRead; - QPointer connection; - bool initInflate; - bool streamEnd; -#ifndef QT_NO_COMPRESS - z_stream inflateStrm; -#endif - bool autoDecompress; - - QByteArray responseData; // uncompressed body - QByteArray compressedData; // compressed body (temporary) - QBuffer requestDataBuffer; - bool requestIsBuffering; - bool requestIsPrepared; -}; - -QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), - majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), - currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), - autoDecompress(false), requestIsBuffering(false), requestIsPrepared(false) -{ -} - -QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate() -{ -} - -void QHttpNetworkReplyPrivate::clear() -{ - state = NothingDoneState; - statusCode = 100; - bodyLength = 0; - contentRead = 0; - totalProgress = 0; - currentChunkSize = 0; - currentChunkRead = 0; - connection = 0; -#ifndef QT_NO_COMPRESS - if (initInflate) - inflateEnd(&inflateStrm); -#endif - initInflate = false; - streamEnd = false; - autoDecompress = false; - fields.clear(); -} - -// QHttpNetworkReplyPrivate -qint64 QHttpNetworkReplyPrivate::bytesAvailable() const -{ - return (state != ReadingDataState ? 0 : fragment.size()); -} - -bool QHttpNetworkReplyPrivate::isGzipped() -{ - QByteArray encoding = headerField("content-encoding"); - return encoding.toLower() == "gzip"; -} - -void QHttpNetworkReplyPrivate::removeAutoDecompressHeader() -{ - // The header "Content-Encoding = gzip" is retained. - // Content-Length is removed since the actual one send by the server is for compressed data - QByteArray name("content-length"); - QByteArray lowerName = name.toLower(); - QList >::Iterator it = fields.begin(), - end = fields.end(); - while (it != end) { - if (name == it->first.toLower()) { - fields.erase(it); - break; - } - ++it; - } - -} - -bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const -{ - challenge.clear(); - // find out the type of authentication protocol requested. - QByteArray header = forProxy ? "proxy-authenticate" : "www-authenticate"; - // pick the best protocol (has to match parsing in QAuthenticatorPrivate) - QList challenges = headerFieldValues(header); - for (int i = 0; i challenges = headerFieldValues(header); - for (int i = 0; i maxPos) - return ret; - if ((flags & EXTRA_FIELD) && ((pos+2) <= maxPos)) { // skip the extra field - unsigned len = (unsigned)body[++pos]; - len += ((unsigned)body[++pos])<<8; - pos += len; - if (pos > maxPos) - return ret; - } - if ((flags & ORIG_NAME) != 0) { // skip the original file name - while(++pos <= maxPos && body[pos]) {} - } - if ((flags & COMMENT) != 0) { // skip the .gz file comment - while(++pos <= maxPos && body[pos]) {} - } - if ((flags & HEAD_CRC) != 0) { // skip the header crc - pos += 2; - if (pos > maxPos) - return ret; - } - ret = (pos < maxPos); // return failed, if no more bytes left - return ret; -} - -int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated) -{ - int ret = Z_DATA_ERROR; - unsigned have; - unsigned char out[CHUNK]; - int pos = -1; - - if (!initInflate) { - // check the header - if (!gzipCheckHeader(compressed, pos)) - return ret; - // allocate inflate state - inflateStrm.zalloc = Z_NULL; - inflateStrm.zfree = Z_NULL; - inflateStrm.opaque = Z_NULL; - inflateStrm.avail_in = 0; - inflateStrm.next_in = Z_NULL; - ret = inflateInit2(&inflateStrm, -MAX_WBITS); - if (ret != Z_OK) - return ret; - initInflate = true; - streamEnd = false; - } - - //remove the header. - compressed.remove(0, pos+1); - // expand until deflate stream ends - inflateStrm.next_in = (unsigned char *)compressed.data(); - inflateStrm.avail_in = compressed.size(); - do { - inflateStrm.avail_out = sizeof(out); - inflateStrm.next_out = out; - ret = inflate(&inflateStrm, Z_NO_FLUSH); - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; - // and fall through - case Z_DATA_ERROR: - case Z_MEM_ERROR: - inflateEnd(&inflateStrm); - initInflate = false; - return ret; - } - have = sizeof(out) - inflateStrm.avail_out; - inflated.append(QByteArray((const char *)out, have)); - } while (inflateStrm.avail_out == 0); - // clean up and return - if (ret <= Z_ERRNO || ret == Z_STREAM_END) { - inflateEnd(&inflateStrm); - initInflate = false; - } - streamEnd = (ret == Z_STREAM_END); - return ret; -} -#endif - -qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) -{ - qint64 bytes = 0; - char c; - - while (socket->bytesAvailable()) { - // allow both CRLF & LF (only) line endings - if (socket->peek(&c, 1) == 1 && c == '\n') { - bytes += socket->read(&c, 1); // read the "n" - // remove the CR at the end - if (fragment.endsWith('\r')) { - fragment.truncate(fragment.length()-1); - } - parseStatus(fragment); - state = ReadingHeaderState; - fragment.clear(); // next fragment - break; - } else { - c = 0; - bytes += socket->read(&c, 1); - fragment.append(c); - } - } - return bytes; -} - -void QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status) -{ - const QByteArrayMatcher sp(" "); - int i = sp.indexIn(status); - const QByteArray version = status.mid(0, i); - int j = sp.indexIn(status, i + 1); - const QByteArray code = status.mid(i + 1, j - i - 1); - const QByteArray reason = status.mid(j + 1, status.count() - j); - - const QByteArrayMatcher slash("/"); - int k = slash.indexIn(version); - const QByteArrayMatcher dot("."); - int l = dot.indexIn(version, k); - const QByteArray major = version.mid(k + 1, l - k - 1); - const QByteArray minor = version.mid(l + 1, version.count() - l); - - majorVersion = QString::fromAscii(major.constData()).toInt(); - minorVersion = QString::fromAscii(minor.constData()).toInt(); - statusCode = QString::fromAscii(code.constData()).toInt(); - reasonPhrase = QString::fromAscii(reason.constData()); -} - -qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) -{ - qint64 bytes = 0; - char crlfcrlf[5]; - crlfcrlf[4] = '\0'; - char c = 0; - bool allHeaders = false; - while (!allHeaders && socket->bytesAvailable()) { - if (socket->peek(&c, 1) == 1 && c == '\n') { - // check for possible header endings. As per HTTP rfc, - // the header endings will be marked by CRLFCRLF. But - // we will allow CRLFLF, LFLF & CRLFCRLF - if (fragment.endsWith("\n\r") || fragment.endsWith('\n')) - allHeaders = true; - } - bytes += socket->read(&c, 1); - fragment.append(c); - } - // we received all headers now parse them - if (allHeaders) { - parseHeader(fragment); - state = ReadingDataState; - fragment.clear(); // next fragment - bodyLength = contentLength(); // cache the length - } - return bytes; -} - -void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header) -{ - // see rfc2616, sec 4 for information about HTTP/1.1 headers. - // allows relaxed parsing here, accepts both CRLF & LF line endings - const QByteArrayMatcher lf("\n"); - const QByteArrayMatcher colon(":"); - int i = 0; - while (i < header.count()) { - int j = colon.indexIn(header, i); // field-name - if (j == -1) - break; - const QByteArray field = header.mid(i, j - i).trimmed(); - j++; - // any number of LWS is allowed before and after the value - QByteArray value; - do { - i = lf.indexIn(header, j); - if (i == -1) - break; - if (!value.isEmpty()) - value += ' '; - // check if we have CRLF or only LF - bool hasCR = (i && header[i-1] == '\r'); - int length = i -(hasCR ? 1: 0) - j; - value += header.mid(j, length).trimmed(); - j = ++i; - } while (i < header.count() && (header.at(i) == ' ' || header.at(i) == '\t')); - if (i == -1) - break; // something is wrong - - fields.append(qMakePair(field, value)); - } -} - -bool QHttpNetworkReplyPrivate::isChunked() -{ - return headerField("transfer-encoding").toLower().contains("chunked"); -} - -bool QHttpNetworkReplyPrivate::connectionCloseEnabled() -{ - return (headerField("connection").toLower().contains("close") || - headerField("proxy-connection").toLower().contains("close")); -} - -qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out) -{ - qint64 bytes = 0; - if (isChunked()) { - bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) - } else if (bodyLength > 0) { // we have a Content-Length - bytes += transferRaw(socket, out, bodyLength - contentRead); - if (contentRead + bytes == bodyLength) - state = AllDoneState; - } else { - bytes += transferRaw(socket, out, socket->bytesAvailable()); - } - if (state == AllDoneState) - socket->readAll(); // Read the rest to clean (CRLF) - contentRead += bytes; - return bytes; -} - -qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size) -{ - qint64 bytes = 0; - Q_ASSERT(in); - Q_ASSERT(out); - - int toBeRead = qMin(128*1024, qMin(size, in->bytesAvailable())); - QByteArray raw(toBeRead, 0); - while (size > 0) { - qint64 read = in->read(raw.data(), raw.size()); - if (read == 0) - return bytes; - // ### error checking here - qint64 written = out->write(raw.data(), read); - if (written == 0) - return bytes; - if (read != written) - qDebug() << "### read" << read << "written" << written; - bytes += read; - size -= read; - out->waitForBytesWritten(-1); // throttle - } - return bytes; - -} - -qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out) -{ - qint64 bytes = 0; - while (in->bytesAvailable()) { // while we can read from input - // if we are done with the current chunk, get the size of the new chunk - if (currentChunkRead >= currentChunkSize) { - currentChunkSize = 0; - currentChunkRead = 0; - if (bytes) { - char crlf[2]; - bytes += in->read(crlf, 2); // read the "\r\n" after the chunk - } - bytes += getChunkSize(in, ¤tChunkSize); - if (currentChunkSize == -1) - break; - } - // if the chunk size is 0, end of the stream - if (currentChunkSize == 0) { - state = AllDoneState; - break; - } - // otherwise, read data - qint64 readSize = qMin(in->bytesAvailable(), currentChunkSize - currentChunkRead); - QByteArray buffer(readSize, 0); - qint64 read = in->read(buffer.data(), readSize); - bytes += read; - currentChunkRead += read; - qint64 written = out->write(buffer); - Q_UNUSED(written); // Avoid compile warning when building release - Q_ASSERT(read == written); - // ### error checking here - out->waitForBytesWritten(-1); - } - return bytes; -} - -qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) -{ - qint64 bytes = 0; - char crlf[2]; - *chunkSize = -1; - int bytesAvailable = in->bytesAvailable(); - while (bytesAvailable > bytes) { - qint64 sniffedBytes = in->peek(crlf, 2); - int fragmentSize = fragment.size(); - // check the next two bytes for a "\r\n", skip blank lines - if ((fragmentSize && sniffedBytes == 2 && crlf[0] == '\r' && crlf[1] == '\n') - ||(fragmentSize > 1 && fragment.endsWith('\r') && crlf[0] == '\n')) - { - bytes += in->read(crlf, 1); // read the \r or \n - if (crlf[0] == '\r') - bytes += in->read(crlf, 1); // read the \n - bool ok = false; - // ignore the chunk-extension - fragment = fragment.mid(0, fragment.indexOf(';')).trimmed(); - *chunkSize = fragment.toLong(&ok, 16); - fragment.clear(); - break; // size done - } else { - // read the fragment to the buffer - char c = 0; - bytes += in->read(&c, 1); - fragment.append(c); - } - } - return bytes; -} - -// QHttpNetworkConnectionPrivate - -typedef QPair HttpMessagePair; - -class QHttpNetworkConnectionPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QHttpNetworkConnection) -public: - QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt); - ~QHttpNetworkConnectionPrivate(); - void init(); - void connectSignals(QAbstractSocket *socket); - - enum SocketState { - IdleState = 0, // ready to send request - ConnectingState = 1, // connecting to host - WritingState = 2, // writing the data - WaitingState = 4, // waiting for reply - ReadingState = 8, // reading the reply - Wait4AuthState = 0x10, // blocked for send till the current authentication slot is done - BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState) - }; - - enum { ChunkSize = 4096 }; - - int indexOf(QAbstractSocket *socket) const; - bool isSocketBusy(QAbstractSocket *socket) const; - bool isSocketWriting(QAbstractSocket *socket) const; - bool isSocketWaiting(QAbstractSocket *socket) const; - bool isSocketReading(QAbstractSocket *socket) const; - - QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request); - void unqueueRequest(QAbstractSocket *socket); - void prepareRequest(HttpMessagePair &request); - bool sendRequest(QAbstractSocket *socket); - void receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply); - void resendCurrentRequest(QAbstractSocket *socket); - void closeChannel(int channel); - void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy); - - // private slots - void _q_bytesWritten(qint64 bytes); // proceed sending - void _q_readyRead(); // pending data to read - void _q_disconnected(); // disconnected from host - void _q_startNextRequest(); // send the next request from the queue - void _q_restartPendingRequest(); // send the currently blocked request - void _q_connected(); // start sending request - void _q_error(QAbstractSocket::SocketError); // error from socket -#ifndef QT_NO_NETWORKPROXY - void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy -#endif - void _q_dataReadyReadNoBuffer(); - void _q_dataReadyReadBuffer(); - - void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); - bool ensureConnection(QAbstractSocket *socket); - QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket); - void eraseData(QHttpNetworkReply *reply); -#ifndef QT_NO_COMPRESS - bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete); -#endif - void bufferData(HttpMessagePair &request); - void removeReply(QHttpNetworkReply *reply); - - QString hostName; - quint16 port; - bool encrypt; - - struct Channel { - QAbstractSocket *socket; - SocketState state; - QHttpNetworkRequest request; // current request - QHttpNetworkReply *reply; // current reply for this request - qint64 written; - qint64 bytesTotal; - bool resendCurrent; - int lastStatus; // last status received on this channel - bool pendingEncrypt; // for https (send after encrypted) - int reconnectAttempts; // maximum 2 reconnection attempts - QAuthenticatorPrivate::Method authMehtod; - QAuthenticatorPrivate::Method proxyAuthMehtod; - QAuthenticator authenticator; - QAuthenticator proxyAuthenticator; -#ifndef QT_NO_OPENSSL - bool ignoreSSLErrors; -#endif - Channel() :state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), reconnectAttempts(2), - authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None) -#ifndef QT_NO_OPENSSL - , ignoreSSLErrors(false) -#endif - {} - }; - static const int channelCount; - Channel channels[2]; // maximum of 2 socket connections to the server - bool pendingAuthSignal; // there is an incomplete authentication signal - bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal - - void appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed); - qint64 bytesAvailable(const QHttpNetworkReply &reply, bool compressed = false) const; - qint64 read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed); - void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode); - bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend); - void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply); - void handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply); - inline bool emitSignals(QHttpNetworkReply *reply); - inline bool expectContent(QHttpNetworkReply *reply); - -#ifndef QT_NO_OPENSSL - void _q_encrypted(); // start sending request (https) - void _q_sslErrors(const QList &errors); // ssl errors from the socket - QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const; -#endif -#ifndef QT_NO_NETWORKPROXY - QNetworkProxy networkProxy; -#endif - //The request queues - QList highPriorityQueue; - QList lowPriorityQueue; -}; +QT_BEGIN_NAMESPACE const int QHttpNetworkConnectionPrivate::channelCount = 2; @@ -2150,235 +1284,6 @@ QNetworkProxy QHttpNetworkConnection::transparentProxy() const } #endif -// QHttpNetworkRequest - -QHttpNetworkRequest::QHttpNetworkRequest(const QUrl &url, Operation operation, Priority priority) - : d(new QHttpNetworkRequestPrivate(operation, priority, url)) -{ -} - -QHttpNetworkRequest::QHttpNetworkRequest(const QHttpNetworkRequest &other) - : QHttpNetworkHeader(other), d(other.d) -{ -} - -QHttpNetworkRequest::~QHttpNetworkRequest() -{ -} - -QUrl QHttpNetworkRequest::url() const -{ - return d->url; -} -void QHttpNetworkRequest::setUrl(const QUrl &url) -{ - d->url = url; -} - -qint64 QHttpNetworkRequest::contentLength() const -{ - return d->contentLength(); -} - -void QHttpNetworkRequest::setContentLength(qint64 length) -{ - d->setContentLength(length); -} - -QList > QHttpNetworkRequest::header() const -{ - return d->fields; -} - -QByteArray QHttpNetworkRequest::headerField(const QByteArray &name, const QByteArray &defaultValue) const -{ - return d->headerField(name, defaultValue); -} - -void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArray &data) -{ - d->setHeaderField(name, data); -} - -QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other) -{ - d = other.d; - return *this; -} - -bool QHttpNetworkRequest::operator==(const QHttpNetworkRequest &other) const -{ - return d->operator==(*other.d); -} - -QHttpNetworkRequest::Operation QHttpNetworkRequest::operation() const -{ - return d->operation; -} - -void QHttpNetworkRequest::setOperation(Operation operation) -{ - d->operation = operation; -} - -QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const -{ - return d->priority; -} - -void QHttpNetworkRequest::setPriority(Priority priority) -{ - d->priority = priority; -} - -QIODevice *QHttpNetworkRequest::data() const -{ - return d->data; -} - -void QHttpNetworkRequest::setData(QIODevice *data) -{ - d->data = data; -} - -int QHttpNetworkRequest::majorVersion() const -{ - return 1; -} - -int QHttpNetworkRequest::minorVersion() const -{ - return 1; -} - -// QHttpNetworkReply - -QHttpNetworkReply::QHttpNetworkReply(const QUrl &url, QObject *parent) - : QObject(*new QHttpNetworkReplyPrivate(url), parent) -{ -} - -QHttpNetworkReply::~QHttpNetworkReply() -{ - Q_D(QHttpNetworkReply); - if (d->connection) { - d->connection->d_func()->removeReply(this); - } -} - -QUrl QHttpNetworkReply::url() const -{ - return d_func()->url; -} -void QHttpNetworkReply::setUrl(const QUrl &url) -{ - Q_D(QHttpNetworkReply); - d->url = url; -} - -qint64 QHttpNetworkReply::contentLength() const -{ - return d_func()->contentLength(); -} - -void QHttpNetworkReply::setContentLength(qint64 length) -{ - Q_D(QHttpNetworkReply); - d->setContentLength(length); -} - -QList > QHttpNetworkReply::header() const -{ - return d_func()->fields; -} - -QByteArray QHttpNetworkReply::headerField(const QByteArray &name, const QByteArray &defaultValue) const -{ - return d_func()->headerField(name, defaultValue); -} - -void QHttpNetworkReply::setHeaderField(const QByteArray &name, const QByteArray &data) -{ - Q_D(QHttpNetworkReply); - d->setHeaderField(name, data); -} - -void QHttpNetworkReply::parseHeader(const QByteArray &header) -{ - Q_D(QHttpNetworkReply); - d->parseHeader(header); -} - -QHttpNetworkRequest QHttpNetworkReply::request() const -{ - return d_func()->request; -} - -void QHttpNetworkReply::setRequest(const QHttpNetworkRequest &request) -{ - Q_D(QHttpNetworkReply); - d->request = request; -} - -int QHttpNetworkReply::statusCode() const -{ - return d_func()->statusCode; -} - -void QHttpNetworkReply::setStatusCode(int code) -{ - Q_D(QHttpNetworkReply); - d->statusCode = code; -} - -QString QHttpNetworkReply::errorString() const -{ - return d_func()->errorString; -} - -QString QHttpNetworkReply::reasonPhrase() const -{ - return d_func()->reasonPhrase; -} - -void QHttpNetworkReply::setErrorString(const QString &error) -{ - Q_D(QHttpNetworkReply); - d->errorString = error; -} - -int QHttpNetworkReply::majorVersion() const -{ - return d_func()->majorVersion; -} - -int QHttpNetworkReply::minorVersion() const -{ - return d_func()->minorVersion; -} - -qint64 QHttpNetworkReply::bytesAvailable() const -{ - Q_D(const QHttpNetworkReply); - if (d->connection) - return d->connection->d_func()->bytesAvailable(*this); - else - return -1; -} - -QByteArray QHttpNetworkReply::read(qint64 maxSize) -{ - Q_D(QHttpNetworkReply); - QByteArray data; - if (d->connection) - d->connection->d_func()->read(*this, data, maxSize, false); - return data; -} - -bool QHttpNetworkReply::isFinished() const -{ - return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; -} // SSL support below #ifndef QT_NO_OPENSSL @@ -2433,27 +1338,7 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel) } } -QSslConfiguration QHttpNetworkReply::sslConfiguration() const -{ - Q_D(const QHttpNetworkReply); - if (d->connection) - return d->connection->d_func()->sslConfiguration(*this); - return QSslConfiguration(); -} -void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config) -{ - Q_D(QHttpNetworkReply); - if (d->connection) - d->connection->setSslConfiguration(config); -} - -void QHttpNetworkReply::ignoreSslErrors() -{ - Q_D(QHttpNetworkReply); - if (d->connection) - d->connection->ignoreSslErrors(); -} #endif //QT_NO_OPENSSL diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 8dbcb3d..09bd459 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -56,6 +56,16 @@ #include #include +#include +#include +#include +#include + +#include +#include +#include + + #ifndef QT_NO_HTTP #ifndef QT_NO_OPENSSL @@ -145,144 +155,137 @@ private: #endif }; -class Q_AUTOTEST_EXPORT QHttpNetworkHeader -{ -public: - virtual ~QHttpNetworkHeader() {}; - virtual QUrl url() const = 0; - virtual void setUrl(const QUrl &url) = 0; - virtual int majorVersion() const = 0; - virtual int minorVersion() const = 0; - virtual qint64 contentLength() const = 0; - virtual void setContentLength(qint64 length) = 0; - virtual QList > header() const = 0; - virtual QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const = 0; - virtual void setHeaderField(const QByteArray &name, const QByteArray &data) = 0; -}; +// private classes +typedef QPair HttpMessagePair; + -class QHttpNetworkRequestPrivate; -class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader +class QHttpNetworkConnectionPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QHttpNetworkConnection) public: - enum Operation { - Options, - Get, - Head, - Post, - Put, - Delete, - Trace, - Connect + QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt); + ~QHttpNetworkConnectionPrivate(); + void init(); + void connectSignals(QAbstractSocket *socket); + + enum SocketState { + IdleState = 0, // ready to send request + ConnectingState = 1, // connecting to host + WritingState = 2, // writing the data + WaitingState = 4, // waiting for reply + ReadingState = 8, // reading the reply + Wait4AuthState = 0x10, // blocked for send till the current authentication slot is done + BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState) }; - enum Priority { - HighPriority, - NormalPriority, - LowPriority + enum { ChunkSize = 4096 }; + + int indexOf(QAbstractSocket *socket) const; + bool isSocketBusy(QAbstractSocket *socket) const; + bool isSocketWriting(QAbstractSocket *socket) const; + bool isSocketWaiting(QAbstractSocket *socket) const; + bool isSocketReading(QAbstractSocket *socket) const; + + QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request); + void unqueueRequest(QAbstractSocket *socket); + void prepareRequest(HttpMessagePair &request); + bool sendRequest(QAbstractSocket *socket); + void receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply); + void resendCurrentRequest(QAbstractSocket *socket); + void closeChannel(int channel); + void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy); + + // private slots + void _q_bytesWritten(qint64 bytes); // proceed sending + void _q_readyRead(); // pending data to read + void _q_disconnected(); // disconnected from host + void _q_startNextRequest(); // send the next request from the queue + void _q_restartPendingRequest(); // send the currently blocked request + void _q_connected(); // start sending request + void _q_error(QAbstractSocket::SocketError); // error from socket +#ifndef QT_NO_NETWORKPROXY + void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy +#endif + void _q_dataReadyReadNoBuffer(); + void _q_dataReadyReadBuffer(); + + void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); + bool ensureConnection(QAbstractSocket *socket); + QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket); + void eraseData(QHttpNetworkReply *reply); +#ifndef QT_NO_COMPRESS + bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete); +#endif + void bufferData(HttpMessagePair &request); + void removeReply(QHttpNetworkReply *reply); + + QString hostName; + quint16 port; + bool encrypt; + + struct Channel { + QAbstractSocket *socket; + SocketState state; + QHttpNetworkRequest request; // current request + QHttpNetworkReply *reply; // current reply for this request + qint64 written; + qint64 bytesTotal; + bool resendCurrent; + int lastStatus; // last status received on this channel + bool pendingEncrypt; // for https (send after encrypted) + int reconnectAttempts; // maximum 2 reconnection attempts + QAuthenticatorPrivate::Method authMehtod; + QAuthenticatorPrivate::Method proxyAuthMehtod; + QAuthenticator authenticator; + QAuthenticator proxyAuthenticator; +#ifndef QT_NO_OPENSSL + bool ignoreSSLErrors; +#endif + Channel() :state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), reconnectAttempts(2), + authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None) +#ifndef QT_NO_OPENSSL + , ignoreSSLErrors(false) +#endif + {} }; - - QHttpNetworkRequest(const QUrl &url = QUrl(), Operation operation = Get, Priority priority = NormalPriority); - QHttpNetworkRequest(const QHttpNetworkRequest &other); - virtual ~QHttpNetworkRequest(); - QHttpNetworkRequest &operator=(const QHttpNetworkRequest &other); - bool operator==(const QHttpNetworkRequest &other) const; - - QUrl url() const; - void setUrl(const QUrl &url); - - int majorVersion() const; - int minorVersion() const; - - qint64 contentLength() const; - void setContentLength(qint64 length); - - QList > header() const; - QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; - void setHeaderField(const QByteArray &name, const QByteArray &data); - - Operation operation() const; - void setOperation(Operation operation); - - Priority priority() const; - void setPriority(Priority priority); - - QIODevice *data() const; - void setData(QIODevice *data); - -private: - QSharedDataPointer d; - friend class QHttpNetworkRequestPrivate; - friend class QHttpNetworkConnectionPrivate; -}; - -class QHttpNetworkReplyPrivate; -class Q_AUTOTEST_EXPORT QHttpNetworkReply : public QObject, public QHttpNetworkHeader -{ - Q_OBJECT -public: - - explicit QHttpNetworkReply(const QUrl &url = QUrl(), QObject *parent = 0); - virtual ~QHttpNetworkReply(); - - QUrl url() const; - void setUrl(const QUrl &url); - - int majorVersion() const; - int minorVersion() const; - - qint64 contentLength() const; - void setContentLength(qint64 length); - - QList > header() const; - QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; - void setHeaderField(const QByteArray &name, const QByteArray &data); - void parseHeader(const QByteArray &header); // mainly for testing - - QHttpNetworkRequest request() const; - void setRequest(const QHttpNetworkRequest &request); - - int statusCode() const; - void setStatusCode(int code); - - QString errorString() const; - void setErrorString(const QString &error); - - QString reasonPhrase() const; - - qint64 bytesAvailable() const; - QByteArray read(qint64 maxSize = -1); - - bool isFinished() const; + static const int channelCount; + Channel channels[2]; // maximum of 2 socket connections to the server + bool pendingAuthSignal; // there is an incomplete authentication signal + bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal + + void appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed); + qint64 bytesAvailable(const QHttpNetworkReply &reply, bool compressed = false) const; + qint64 read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed); + void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode); + bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend); + void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply); + void handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply); + inline bool emitSignals(QHttpNetworkReply *reply); + inline bool expectContent(QHttpNetworkReply *reply); #ifndef QT_NO_OPENSSL - QSslConfiguration sslConfiguration() const; - void setSslConfiguration(const QSslConfiguration &config); - void ignoreSslErrors(); - -Q_SIGNALS: - void sslErrors(const QList &errors); + void _q_encrypted(); // start sending request (https) + void _q_sslErrors(const QList &errors); // ssl errors from the socket + QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const; #endif -Q_SIGNALS: - void readyRead(); - void finished(); - void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); - void headerChanged(); - void dataReadProgress(int done, int total); - void dataSendProgress(int done, int total); +#ifndef QT_NO_NETWORKPROXY + QNetworkProxy networkProxy; +#endif -private: - Q_DECLARE_PRIVATE(QHttpNetworkReply) - friend class QHttpNetworkConnection; - friend class QHttpNetworkConnectionPrivate; + //The request queues + QList highPriorityQueue; + QList lowPriorityQueue; }; + + QT_END_NAMESPACE -Q_DECLARE_METATYPE(QHttpNetworkRequest) +//Q_DECLARE_METATYPE(QHttpNetworkRequest) //Q_DECLARE_METATYPE(QHttpNetworkReply) #endif // QT_NO_HTTP diff --git a/src/network/access/qhttpnetworkheader.cpp b/src/network/access/qhttpnetworkheader.cpp new file mode 100644 index 0000000..6f7f6f7 --- /dev/null +++ b/src/network/access/qhttpnetworkheader.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhttpnetworkheader_p.h" + + +QT_BEGIN_NAMESPACE + +QHttpNetworkHeaderPrivate::QHttpNetworkHeaderPrivate(const QUrl &newUrl) + :url(newUrl) +{ +} + +QHttpNetworkHeaderPrivate::QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other) + :QSharedData(other) +{ + url = other.url; + fields = other.fields; +} + +qint64 QHttpNetworkHeaderPrivate::contentLength() const +{ + bool ok = false; + QByteArray value = headerField("content-length"); + qint64 length = value.toULongLong(&ok); + if (ok) + return length; + return -1; // the header field is not set +} + +void QHttpNetworkHeaderPrivate::setContentLength(qint64 length) +{ + setHeaderField("Content-Length", QByteArray::number(length)); +} + +QByteArray QHttpNetworkHeaderPrivate::headerField(const QByteArray &name, const QByteArray &defaultValue) const +{ + QList allValues = headerFieldValues(name); + if (allValues.isEmpty()) + return defaultValue; + + QByteArray result; + bool first = true; + foreach (QByteArray value, allValues) { + if (!first) + result += ", "; + first = false; + result += value; + } + return result; +} + +QList QHttpNetworkHeaderPrivate::headerFieldValues(const QByteArray &name) const +{ + QList result; + QByteArray lowerName = name.toLower(); + QList >::ConstIterator it = fields.constBegin(), + end = fields.constEnd(); + for ( ; it != end; ++it) + if (lowerName == it->first.toLower()) + result += it->second; + + return result; +} + +void QHttpNetworkHeaderPrivate::setHeaderField(const QByteArray &name, const QByteArray &data) +{ + QByteArray lowerName = name.toLower(); + QList >::Iterator it = fields.begin(); + while (it != fields.end()) { + if (lowerName == it->first.toLower()) + it = fields.erase(it); + else + ++it; + } + fields.append(qMakePair(name, data)); +} + +bool QHttpNetworkHeaderPrivate::operator==(const QHttpNetworkHeaderPrivate &other) const +{ + return (url == other.url); +} + + +QT_END_NAMESPACE diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h new file mode 100644 index 0000000..ce538c8 --- /dev/null +++ b/src/network/access/qhttpnetworkheader_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHTTPNETWORKHEADER_H +#define QHTTPNETWORKHEADER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the Network Access API. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +#ifndef QT_NO_HTTP + +QT_BEGIN_NAMESPACE + +#include +#include + +class Q_AUTOTEST_EXPORT QHttpNetworkHeader +{ +public: + virtual ~QHttpNetworkHeader() {}; + virtual QUrl url() const = 0; + virtual void setUrl(const QUrl &url) = 0; + + virtual int majorVersion() const = 0; + virtual int minorVersion() const = 0; + + virtual qint64 contentLength() const = 0; + virtual void setContentLength(qint64 length) = 0; + + virtual QList > header() const = 0; + virtual QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const = 0; + virtual void setHeaderField(const QByteArray &name, const QByteArray &data) = 0; +}; + +class QHttpNetworkHeaderPrivate : public QSharedData +{ +public: + QUrl url; + QList > fields; + + QHttpNetworkHeaderPrivate(const QUrl &newUrl = QUrl()); + QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other); + inline qint64 contentLength() const; + inline void setContentLength(qint64 length); + + inline QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; + inline QList headerFieldValues(const QByteArray &name) const; + inline void setHeaderField(const QByteArray &name, const QByteArray &data); + bool operator==(const QHttpNetworkHeaderPrivate &other) const; + +}; + + +QT_END_NAMESPACE + + +#endif // QT_NO_HTTP + + +#endif // QHTTPNETWORKHEADER_H + + + + + + diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp new file mode 100644 index 0000000..fe3f6af --- /dev/null +++ b/src/network/access/qhttpnetworkreply.cpp @@ -0,0 +1,663 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhttpnetworkreply_p.h" +#include "qhttpnetworkconnection_p.h" + +#include + +#ifndef QT_NO_HTTP + +#ifndef QT_NO_OPENSSL +# include +# include +# include +#endif + +QT_BEGIN_NAMESPACE + +QHttpNetworkReply::QHttpNetworkReply(const QUrl &url, QObject *parent) + : QObject(*new QHttpNetworkReplyPrivate(url), parent) +{ +} + +QHttpNetworkReply::~QHttpNetworkReply() +{ + Q_D(QHttpNetworkReply); + if (d->connection) { + d->connection->d_func()->removeReply(this); + } +} + +QUrl QHttpNetworkReply::url() const +{ + return d_func()->url; +} +void QHttpNetworkReply::setUrl(const QUrl &url) +{ + Q_D(QHttpNetworkReply); + d->url = url; +} + +qint64 QHttpNetworkReply::contentLength() const +{ + return d_func()->contentLength(); +} + +void QHttpNetworkReply::setContentLength(qint64 length) +{ + Q_D(QHttpNetworkReply); + d->setContentLength(length); +} + +QList > QHttpNetworkReply::header() const +{ + return d_func()->fields; +} + +QByteArray QHttpNetworkReply::headerField(const QByteArray &name, const QByteArray &defaultValue) const +{ + return d_func()->headerField(name, defaultValue); +} + +void QHttpNetworkReply::setHeaderField(const QByteArray &name, const QByteArray &data) +{ + Q_D(QHttpNetworkReply); + d->setHeaderField(name, data); +} + +void QHttpNetworkReply::parseHeader(const QByteArray &header) +{ + Q_D(QHttpNetworkReply); + d->parseHeader(header); +} + +QHttpNetworkRequest QHttpNetworkReply::request() const +{ + return d_func()->request; +} + +void QHttpNetworkReply::setRequest(const QHttpNetworkRequest &request) +{ + Q_D(QHttpNetworkReply); + d->request = request; +} + +int QHttpNetworkReply::statusCode() const +{ + return d_func()->statusCode; +} + +void QHttpNetworkReply::setStatusCode(int code) +{ + Q_D(QHttpNetworkReply); + d->statusCode = code; +} + +QString QHttpNetworkReply::errorString() const +{ + return d_func()->errorString; +} + +QString QHttpNetworkReply::reasonPhrase() const +{ + return d_func()->reasonPhrase; +} + +void QHttpNetworkReply::setErrorString(const QString &error) +{ + Q_D(QHttpNetworkReply); + d->errorString = error; +} + +int QHttpNetworkReply::majorVersion() const +{ + return d_func()->majorVersion; +} + +int QHttpNetworkReply::minorVersion() const +{ + return d_func()->minorVersion; +} + +qint64 QHttpNetworkReply::bytesAvailable() const +{ + Q_D(const QHttpNetworkReply); + if (d->connection) + return d->connection->d_func()->bytesAvailable(*this); + else + return -1; +} + +QByteArray QHttpNetworkReply::read(qint64 maxSize) +{ + Q_D(QHttpNetworkReply); + QByteArray data; + if (d->connection) + d->connection->d_func()->read(*this, data, maxSize, false); + return data; +} + +bool QHttpNetworkReply::isFinished() const +{ + return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; +} + + + +QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) + : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), + majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), + currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), + autoDecompress(false), requestIsBuffering(false), requestIsPrepared(false) +{ +} + +QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate() +{ +} + +void QHttpNetworkReplyPrivate::clear() +{ + state = NothingDoneState; + statusCode = 100; + bodyLength = 0; + contentRead = 0; + totalProgress = 0; + currentChunkSize = 0; + currentChunkRead = 0; + connection = 0; +#ifndef QT_NO_COMPRESS + if (initInflate) + inflateEnd(&inflateStrm); +#endif + initInflate = false; + streamEnd = false; + autoDecompress = false; + fields.clear(); +} + +// QHttpNetworkReplyPrivate +qint64 QHttpNetworkReplyPrivate::bytesAvailable() const +{ + return (state != ReadingDataState ? 0 : fragment.size()); +} + +bool QHttpNetworkReplyPrivate::isGzipped() +{ + QByteArray encoding = headerField("content-encoding"); + return encoding.toLower() == "gzip"; +} + +void QHttpNetworkReplyPrivate::removeAutoDecompressHeader() +{ + // The header "Content-Encoding = gzip" is retained. + // Content-Length is removed since the actual one send by the server is for compressed data + QByteArray name("content-length"); + QByteArray lowerName = name.toLower(); + QList >::Iterator it = fields.begin(), + end = fields.end(); + while (it != end) { + if (name == it->first.toLower()) { + fields.erase(it); + break; + } + ++it; + } + +} + +bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const +{ + challenge.clear(); + // find out the type of authentication protocol requested. + QByteArray header = forProxy ? "proxy-authenticate" : "www-authenticate"; + // pick the best protocol (has to match parsing in QAuthenticatorPrivate) + QList challenges = headerFieldValues(header); + for (int i = 0; i challenges = headerFieldValues(header); + for (int i = 0; i maxPos) + return ret; + if ((flags & EXTRA_FIELD) && ((pos+2) <= maxPos)) { // skip the extra field + unsigned len = (unsigned)body[++pos]; + len += ((unsigned)body[++pos])<<8; + pos += len; + if (pos > maxPos) + return ret; + } + if ((flags & ORIG_NAME) != 0) { // skip the original file name + while(++pos <= maxPos && body[pos]) {} + } + if ((flags & COMMENT) != 0) { // skip the .gz file comment + while(++pos <= maxPos && body[pos]) {} + } + if ((flags & HEAD_CRC) != 0) { // skip the header crc + pos += 2; + if (pos > maxPos) + return ret; + } + ret = (pos < maxPos); // return failed, if no more bytes left + return ret; +} + +int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated) +{ + int ret = Z_DATA_ERROR; + unsigned have; + unsigned char out[CHUNK]; + int pos = -1; + + if (!initInflate) { + // check the header + if (!gzipCheckHeader(compressed, pos)) + return ret; + // allocate inflate state + inflateStrm.zalloc = Z_NULL; + inflateStrm.zfree = Z_NULL; + inflateStrm.opaque = Z_NULL; + inflateStrm.avail_in = 0; + inflateStrm.next_in = Z_NULL; + ret = inflateInit2(&inflateStrm, -MAX_WBITS); + if (ret != Z_OK) + return ret; + initInflate = true; + streamEnd = false; + } + + //remove the header. + compressed.remove(0, pos+1); + // expand until deflate stream ends + inflateStrm.next_in = (unsigned char *)compressed.data(); + inflateStrm.avail_in = compressed.size(); + do { + inflateStrm.avail_out = sizeof(out); + inflateStrm.next_out = out; + ret = inflate(&inflateStrm, Z_NO_FLUSH); + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + // and fall through + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&inflateStrm); + initInflate = false; + return ret; + } + have = sizeof(out) - inflateStrm.avail_out; + inflated.append(QByteArray((const char *)out, have)); + } while (inflateStrm.avail_out == 0); + // clean up and return + if (ret <= Z_ERRNO || ret == Z_STREAM_END) { + inflateEnd(&inflateStrm); + initInflate = false; + } + streamEnd = (ret == Z_STREAM_END); + return ret; +} +#endif + +qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) +{ + qint64 bytes = 0; + char c; + + while (socket->bytesAvailable()) { + // allow both CRLF & LF (only) line endings + if (socket->peek(&c, 1) == 1 && c == '\n') { + bytes += socket->read(&c, 1); // read the "n" + // remove the CR at the end + if (fragment.endsWith('\r')) { + fragment.truncate(fragment.length()-1); + } + parseStatus(fragment); + state = ReadingHeaderState; + fragment.clear(); // next fragment + break; + } else { + c = 0; + bytes += socket->read(&c, 1); + fragment.append(c); + } + } + return bytes; +} + +void QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status) +{ + const QByteArrayMatcher sp(" "); + int i = sp.indexIn(status); + const QByteArray version = status.mid(0, i); + int j = sp.indexIn(status, i + 1); + const QByteArray code = status.mid(i + 1, j - i - 1); + const QByteArray reason = status.mid(j + 1, status.count() - j); + + const QByteArrayMatcher slash("/"); + int k = slash.indexIn(version); + const QByteArrayMatcher dot("."); + int l = dot.indexIn(version, k); + const QByteArray major = version.mid(k + 1, l - k - 1); + const QByteArray minor = version.mid(l + 1, version.count() - l); + + majorVersion = QString::fromAscii(major.constData()).toInt(); + minorVersion = QString::fromAscii(minor.constData()).toInt(); + statusCode = QString::fromAscii(code.constData()).toInt(); + reasonPhrase = QString::fromAscii(reason.constData()); +} + +qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) +{ + qint64 bytes = 0; + char crlfcrlf[5]; + crlfcrlf[4] = '\0'; + char c = 0; + bool allHeaders = false; + while (!allHeaders && socket->bytesAvailable()) { + if (socket->peek(&c, 1) == 1 && c == '\n') { + // check for possible header endings. As per HTTP rfc, + // the header endings will be marked by CRLFCRLF. But + // we will allow CRLFLF, LFLF & CRLFCRLF + if (fragment.endsWith("\n\r") || fragment.endsWith('\n')) + allHeaders = true; + } + bytes += socket->read(&c, 1); + fragment.append(c); + } + // we received all headers now parse them + if (allHeaders) { + parseHeader(fragment); + state = ReadingDataState; + fragment.clear(); // next fragment + bodyLength = contentLength(); // cache the length + } + return bytes; +} + +void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header) +{ + // see rfc2616, sec 4 for information about HTTP/1.1 headers. + // allows relaxed parsing here, accepts both CRLF & LF line endings + const QByteArrayMatcher lf("\n"); + const QByteArrayMatcher colon(":"); + int i = 0; + while (i < header.count()) { + int j = colon.indexIn(header, i); // field-name + if (j == -1) + break; + const QByteArray field = header.mid(i, j - i).trimmed(); + j++; + // any number of LWS is allowed before and after the value + QByteArray value; + do { + i = lf.indexIn(header, j); + if (i == -1) + break; + if (!value.isEmpty()) + value += ' '; + // check if we have CRLF or only LF + bool hasCR = (i && header[i-1] == '\r'); + int length = i -(hasCR ? 1: 0) - j; + value += header.mid(j, length).trimmed(); + j = ++i; + } while (i < header.count() && (header.at(i) == ' ' || header.at(i) == '\t')); + if (i == -1) + break; // something is wrong + + fields.append(qMakePair(field, value)); + } +} + +bool QHttpNetworkReplyPrivate::isChunked() +{ + return headerField("transfer-encoding").toLower().contains("chunked"); +} + +bool QHttpNetworkReplyPrivate::connectionCloseEnabled() +{ + return (headerField("connection").toLower().contains("close") || + headerField("proxy-connection").toLower().contains("close")); +} + +qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out) +{ + qint64 bytes = 0; + if (isChunked()) { + bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) + } else if (bodyLength > 0) { // we have a Content-Length + bytes += transferRaw(socket, out, bodyLength - contentRead); + if (contentRead + bytes == bodyLength) + state = AllDoneState; + } else { + bytes += transferRaw(socket, out, socket->bytesAvailable()); + } + if (state == AllDoneState) + socket->readAll(); // Read the rest to clean (CRLF) + contentRead += bytes; + return bytes; +} + +qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size) +{ + qint64 bytes = 0; + Q_ASSERT(in); + Q_ASSERT(out); + + int toBeRead = qMin(128*1024, qMin(size, in->bytesAvailable())); + QByteArray raw(toBeRead, 0); + while (size > 0) { + qint64 read = in->read(raw.data(), raw.size()); + if (read == 0) + return bytes; + // ### error checking here + qint64 written = out->write(raw.data(), read); + if (written == 0) + return bytes; + if (read != written) + qDebug() << "### read" << read << "written" << written; + bytes += read; + size -= read; + out->waitForBytesWritten(-1); // throttle + } + return bytes; + +} + +qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out) +{ + qint64 bytes = 0; + while (in->bytesAvailable()) { // while we can read from input + // if we are done with the current chunk, get the size of the new chunk + if (currentChunkRead >= currentChunkSize) { + currentChunkSize = 0; + currentChunkRead = 0; + if (bytes) { + char crlf[2]; + bytes += in->read(crlf, 2); // read the "\r\n" after the chunk + } + bytes += getChunkSize(in, ¤tChunkSize); + if (currentChunkSize == -1) + break; + } + // if the chunk size is 0, end of the stream + if (currentChunkSize == 0) { + state = AllDoneState; + break; + } + // otherwise, read data + qint64 readSize = qMin(in->bytesAvailable(), currentChunkSize - currentChunkRead); + QByteArray buffer(readSize, 0); + qint64 read = in->read(buffer.data(), readSize); + bytes += read; + currentChunkRead += read; + qint64 written = out->write(buffer); + Q_UNUSED(written); // Avoid compile warning when building release + Q_ASSERT(read == written); + // ### error checking here + out->waitForBytesWritten(-1); + } + return bytes; +} + +qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) +{ + qint64 bytes = 0; + char crlf[2]; + *chunkSize = -1; + int bytesAvailable = in->bytesAvailable(); + while (bytesAvailable > bytes) { + qint64 sniffedBytes = in->peek(crlf, 2); + int fragmentSize = fragment.size(); + // check the next two bytes for a "\r\n", skip blank lines + if ((fragmentSize && sniffedBytes == 2 && crlf[0] == '\r' && crlf[1] == '\n') + ||(fragmentSize > 1 && fragment.endsWith('\r') && crlf[0] == '\n')) + { + bytes += in->read(crlf, 1); // read the \r or \n + if (crlf[0] == '\r') + bytes += in->read(crlf, 1); // read the \n + bool ok = false; + // ignore the chunk-extension + fragment = fragment.mid(0, fragment.indexOf(';')).trimmed(); + *chunkSize = fragment.toLong(&ok, 16); + fragment.clear(); + break; // size done + } else { + // read the fragment to the buffer + char c = 0; + bytes += in->read(&c, 1); + fragment.append(c); + } + } + return bytes; +} + +// SSL support below +#ifndef QT_NO_OPENSSL + +QSslConfiguration QHttpNetworkReply::sslConfiguration() const +{ + Q_D(const QHttpNetworkReply); + if (d->connection) + return d->connection->d_func()->sslConfiguration(*this); + return QSslConfiguration(); +} + +void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config) +{ + Q_D(QHttpNetworkReply); + if (d->connection) + d->connection->setSslConfiguration(config); +} + +void QHttpNetworkReply::ignoreSslErrors() +{ + Q_D(QHttpNetworkReply); + if (d->connection) + d->connection->ignoreSslErrors(); +} + + +#endif //QT_NO_OPENSSL + + +QT_END_NAMESPACE + +#endif // QT_NO_HTTP \ No newline at end of file diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h new file mode 100644 index 0000000..9881bb3 --- /dev/null +++ b/src/network/access/qhttpnetworkreply_p.h @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHTTPNETWORKREPLY_H +#define QHTTPNETWORKREPLY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the Network Access API. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +#ifndef QT_NO_HTTP + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_COMPRESS +# include +static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header +// gzip flag byte +#define HEAD_CRC 0x02 // bit 1 set: header CRC present +#define EXTRA_FIELD 0x04 // bit 2 set: extra field present +#define ORIG_NAME 0x08 // bit 3 set: original file name present +#define COMMENT 0x10 // bit 4 set: file comment present +#define RESERVED 0xE0 // bits 5..7: reserved +#define CHUNK 16384 +#endif + +#ifndef QT_NO_OPENSSL +# include +# include +#else +# include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +class QHttpNetworkConnection; +class QHttpNetworkRequest; +class QHttpNetworkConnectionPrivate; +class QHttpNetworkReplyPrivate; +class Q_AUTOTEST_EXPORT QHttpNetworkReply : public QObject, public QHttpNetworkHeader +{ + Q_OBJECT +public: + + explicit QHttpNetworkReply(const QUrl &url = QUrl(), QObject *parent = 0); + virtual ~QHttpNetworkReply(); + + QUrl url() const; + void setUrl(const QUrl &url); + + int majorVersion() const; + int minorVersion() const; + + qint64 contentLength() const; + void setContentLength(qint64 length); + + QList > header() const; + QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; + void setHeaderField(const QByteArray &name, const QByteArray &data); + void parseHeader(const QByteArray &header); // mainly for testing + + QHttpNetworkRequest request() const; + void setRequest(const QHttpNetworkRequest &request); + + int statusCode() const; + void setStatusCode(int code); + + QString errorString() const; + void setErrorString(const QString &error); + + QString reasonPhrase() const; + + qint64 bytesAvailable() const; + QByteArray read(qint64 maxSize = -1); + + bool isFinished() const; + +#ifndef QT_NO_OPENSSL + QSslConfiguration sslConfiguration() const; + void setSslConfiguration(const QSslConfiguration &config); + void ignoreSslErrors(); + +Q_SIGNALS: + void sslErrors(const QList &errors); +#endif + +Q_SIGNALS: + void readyRead(); + void finished(); + void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); + void headerChanged(); + void dataReadProgress(int done, int total); + void dataSendProgress(int done, int total); + +private: + Q_DECLARE_PRIVATE(QHttpNetworkReply) + friend class QHttpNetworkConnection; + friend class QHttpNetworkConnectionPrivate; +}; + + +class QHttpNetworkReplyPrivate : public QObjectPrivate, public QHttpNetworkHeaderPrivate +{ +public: + QHttpNetworkReplyPrivate(const QUrl &newUrl = QUrl()); + ~QHttpNetworkReplyPrivate(); + qint64 readStatus(QAbstractSocket *socket); + void parseStatus(const QByteArray &status); + qint64 readHeader(QAbstractSocket *socket); + void parseHeader(const QByteArray &header); + qint64 readBody(QAbstractSocket *socket, QIODevice *out); + bool findChallenge(bool forProxy, QByteArray &challenge) const; + QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; + void clear(); + + qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size); + qint64 transferChunked(QIODevice *in, QIODevice *out); + qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); + + qint64 bytesAvailable() const; + bool isChunked(); + bool connectionCloseEnabled(); + bool isGzipped(); +#ifndef QT_NO_COMPRESS + bool gzipCheckHeader(QByteArray &content, int &pos); + int gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated); +#endif + void removeAutoDecompressHeader(); + + enum ReplyState { + NothingDoneState, + ReadingStatusState, + ReadingHeaderState, + ReadingDataState, + AllDoneState + } state; + + QHttpNetworkRequest request; + int statusCode; + int majorVersion; + int minorVersion; + QString errorString; + QString reasonPhrase; + qint64 bodyLength; + qint64 contentRead; + qint64 totalProgress; + QByteArray fragment; + qint64 currentChunkSize; + qint64 currentChunkRead; + QPointer connection; + bool initInflate; + bool streamEnd; +#ifndef QT_NO_COMPRESS + z_stream inflateStrm; +#endif + bool autoDecompress; + + QByteArray responseData; // uncompressed body + QByteArray compressedData; // compressed body (temporary) + QBuffer requestDataBuffer; + bool requestIsBuffering; + bool requestIsPrepared; +}; + + + + +QT_END_NAMESPACE + +//Q_DECLARE_METATYPE(QHttpNetworkReply) + +#endif // QT_NO_HTTP + + +#endif // QHTTPNETWORKREPLY_H \ No newline at end of file diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp new file mode 100644 index 0000000..420cb69 --- /dev/null +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhttpnetworkrequest_p.h" + +QT_BEGIN_NAMESPACE + +QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, + QHttpNetworkRequest::Priority pri, const QUrl &newUrl) + : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0), + autoDecompress(false) +{ +} + +QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other) + : QHttpNetworkHeaderPrivate(other) +{ + operation = other.operation; + priority = other.priority; + data = other.data; + autoDecompress = other.autoDecompress; +} + +QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() +{ +} + +bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &other) const +{ + return QHttpNetworkHeaderPrivate::operator==(other) + && (operation == other.operation) + && (data == other.data); +} + +QByteArray QHttpNetworkRequestPrivate::methodName() const +{ + QByteArray ba; + switch (operation) { + case QHttpNetworkRequest::Options: + ba += "OPTIONS"; + break; + case QHttpNetworkRequest::Get: + ba += "GET"; + break; + case QHttpNetworkRequest::Head: + ba += "HEAD"; + break; + case QHttpNetworkRequest::Post: + ba += "POST"; + break; + case QHttpNetworkRequest::Put: + ba += "PUT"; + break; + case QHttpNetworkRequest::Delete: + ba += "DELETE"; + break; + case QHttpNetworkRequest::Trace: + ba += "TRACE"; + break; + case QHttpNetworkRequest::Connect: + ba += "CONNECT"; + break; + default: + break; + } + return ba; +} + +QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const +{ + QUrl::FormattingOptions format(QUrl::RemoveFragment); + + // for POST, query data is send as content + if (operation == QHttpNetworkRequest::Post && !data) + format |= QUrl::RemoveQuery; + // for requests through proxy, the Request-URI contains full url + if (throughProxy) + format |= QUrl::RemoveUserInfo; + else + format |= QUrl::RemoveScheme | QUrl::RemoveAuthority; + QByteArray uri = url.toEncoded(format); + if (uri.isEmpty() || (throughProxy && url.path().isEmpty())) + uri += '/'; + return uri; +} + +QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy) +{ + QByteArray ba = request.d->methodName(); + QByteArray uri = request.d->uri(throughProxy); + ba += " " + uri; + + QString majorVersion = QString::number(request.majorVersion()); + QString minorVersion = QString::number(request.minorVersion()); + ba += " HTTP/" + majorVersion.toLatin1() + "." + minorVersion.toLatin1() + "\r\n"; + + QList > fields = request.header(); + QList >::const_iterator it = fields.constBegin(); + for (; it != fields.constEnd(); ++it) + ba += it->first + ": " + it->second + "\r\n"; + if (request.d->operation == QHttpNetworkRequest::Post) { + // add content type, if not set in the request + if (request.headerField("content-type").isEmpty()) + ba += "Content-Type: application/x-www-form-urlencoded\r\n"; + if (!request.d->data && request.d->url.hasQuery()) { + QByteArray query = request.d->url.encodedQuery(); + ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n"; + ba += "\r\n"; + ba += query; + } else { + ba += "\r\n"; + } + } else { + ba += "\r\n"; + } + return ba; +} + + +// QHttpNetworkRequest + +QHttpNetworkRequest::QHttpNetworkRequest(const QUrl &url, Operation operation, Priority priority) + : d(new QHttpNetworkRequestPrivate(operation, priority, url)) +{ +} + +QHttpNetworkRequest::QHttpNetworkRequest(const QHttpNetworkRequest &other) + : QHttpNetworkHeader(other), d(other.d) +{ +} + +QHttpNetworkRequest::~QHttpNetworkRequest() +{ +} + +QUrl QHttpNetworkRequest::url() const +{ + return d->url; +} +void QHttpNetworkRequest::setUrl(const QUrl &url) +{ + d->url = url; +} + +qint64 QHttpNetworkRequest::contentLength() const +{ + return d->contentLength(); +} + +void QHttpNetworkRequest::setContentLength(qint64 length) +{ + d->setContentLength(length); +} + +QList > QHttpNetworkRequest::header() const +{ + return d->fields; +} + +QByteArray QHttpNetworkRequest::headerField(const QByteArray &name, const QByteArray &defaultValue) const +{ + return d->headerField(name, defaultValue); +} + +void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArray &data) +{ + d->setHeaderField(name, data); +} + +QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other) +{ + d = other.d; + return *this; +} + +bool QHttpNetworkRequest::operator==(const QHttpNetworkRequest &other) const +{ + return d->operator==(*other.d); +} + +QHttpNetworkRequest::Operation QHttpNetworkRequest::operation() const +{ + return d->operation; +} + +void QHttpNetworkRequest::setOperation(Operation operation) +{ + d->operation = operation; +} + +QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const +{ + return d->priority; +} + +void QHttpNetworkRequest::setPriority(Priority priority) +{ + d->priority = priority; +} + +QIODevice *QHttpNetworkRequest::data() const +{ + return d->data; +} + +void QHttpNetworkRequest::setData(QIODevice *data) +{ + d->data = data; +} + +int QHttpNetworkRequest::majorVersion() const +{ + return 1; +} + +int QHttpNetworkRequest::minorVersion() const +{ + return 1; +} + + +QT_END_NAMESPACE + diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h new file mode 100644 index 0000000..4e64ca6 --- /dev/null +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHTTPNETWORKREQUEST_H +#define QHTTPNETWORKREQUEST_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the Network Access API. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +#ifndef QT_NO_HTTP + +QT_BEGIN_NAMESPACE + +#include + +class QHttpNetworkRequestPrivate; +class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader +{ +public: + enum Operation { + Options, + Get, + Head, + Post, + Put, + Delete, + Trace, + Connect + }; + + enum Priority { + HighPriority, + NormalPriority, + LowPriority + }; + + QHttpNetworkRequest(const QUrl &url = QUrl(), Operation operation = Get, Priority priority = NormalPriority); + QHttpNetworkRequest(const QHttpNetworkRequest &other); + virtual ~QHttpNetworkRequest(); + QHttpNetworkRequest &operator=(const QHttpNetworkRequest &other); + bool operator==(const QHttpNetworkRequest &other) const; + + QUrl url() const; + void setUrl(const QUrl &url); + + int majorVersion() const; + int minorVersion() const; + + qint64 contentLength() const; + void setContentLength(qint64 length); + + QList > header() const; + QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; + void setHeaderField(const QByteArray &name, const QByteArray &data); + + Operation operation() const; + void setOperation(Operation operation); + + Priority priority() const; + void setPriority(Priority priority); + + QIODevice *data() const; + void setData(QIODevice *data); + +private: + QSharedDataPointer d; + friend class QHttpNetworkRequestPrivate; + friend class QHttpNetworkConnectionPrivate; +}; + + +class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate +{ +public: + QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, + QHttpNetworkRequest::Priority pri, const QUrl &newUrl = QUrl()); + QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other); + ~QHttpNetworkRequestPrivate(); + bool operator==(const QHttpNetworkRequestPrivate &other) const; + QByteArray methodName() const; + QByteArray uri(bool throughProxy) const; + + static QByteArray header(const QHttpNetworkRequest &request, bool throughProxy); + + QHttpNetworkRequest::Operation operation; + QHttpNetworkRequest::Priority priority; + mutable QIODevice *data; + bool autoDecompress; +}; + + +QT_END_NAMESPACE + +//Q_DECLARE_METATYPE(QHttpNetworkRequest) + +#endif // QT_NO_HTTP + + +#endif // QHTTPNETWORKREQUEST_H \ No newline at end of file -- cgit v0.12 From 9b3de2a229bfd393a13bcf08750c2284f775d8c5 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 6 Apr 2009 17:03:12 +0200 Subject: De-inlined 2 functions in QHttpNetworkHeader RevBy: Thiago --- src/network/access/qhttpnetworkheader_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h index ce538c8..306ae85 100644 --- a/src/network/access/qhttpnetworkheader_p.h +++ b/src/network/access/qhttpnetworkheader_p.h @@ -85,8 +85,8 @@ public: QHttpNetworkHeaderPrivate(const QUrl &newUrl = QUrl()); QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other); - inline qint64 contentLength() const; - inline void setContentLength(qint64 length); + qint64 contentLength() const; + void setContentLength(qint64 length); inline QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; inline QList headerFieldValues(const QByteArray &name) const; -- cgit v0.12 From 1bb9d8fcd59a91751c8d91e2885e2b05eff4d1bb Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Mon, 6 Apr 2009 17:10:26 +0200 Subject: BT: Adjust the colliding mice example to work with coalesced updates. It seems that Cocoa is much more strict about coalesced updates than Carbon ever was. The upshot of this is that some examples that "worked" after a fashion in Carbon, do not exhibit good frame rates with Cocoa. The reason why is that apparently Cocoa will decide to flush to the screen every time a timer fires. If you have a lot of timers that are all dependent on doing on update to the screen, you will get undesirable effects. Thankfully, it is possible to adjust the examples to follow best practices and get a good result. So, we now only do the animation once using QGraphicsScene::advance(). We are also able to make the mice less heavy (no QObject subclass). I've updated the docs and someone on the doc team has kindly volunteered to go through them. Reviewed-by: Andreas --- doc/src/examples/collidingmice-example.qdoc | 39 ++++++++++++++------------- examples/graphicsview/collidingmice/main.cpp | 4 +++ examples/graphicsview/collidingmice/mouse.cpp | 5 ++-- examples/graphicsview/collidingmice/mouse.h | 7 ++--- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/doc/src/examples/collidingmice-example.qdoc b/doc/src/examples/collidingmice-example.qdoc index 7ea2ca2..657a204 100644 --- a/doc/src/examples/collidingmice-example.qdoc +++ b/doc/src/examples/collidingmice-example.qdoc @@ -66,7 +66,7 @@ \section1 Mouse Class Definition - The \c mouse class inherits both QObject and QGraphicsItem. The + The \c mouse class inherits from QGraphicsItem. The QGraphicsItem class is the base class for all graphical items in the Graphics View framework, and provides a light-weight foundation for writing your own custom items. @@ -78,14 +78,11 @@ {QGraphicsItem::}{boundingRect()}, which returns an estimate of the area painted by the item, and \l {QGraphicsItem::}{paint()}, which implements the actual painting. In addition, we reimplement - the \l {QGraphicsItem::}{shape()} function to return an accurate + the \l {QGraphicsItem::}{shape()} and \l {QGraphicsItem::}{advance()}. + We reimplement \l {QGraphicsItem::}{shape()} to return an accurate shape of our mouse item; the default implementation simply returns - the item's bounding rectangle. - - The rationale for deriving from QObject in addition to - QGraphicsItem is to be able to animate our items by reimplementing - QObject's \l {QObject::}{timerEvent()} function and use - QObject::startTimer() to generate timer events. + the item's bounding rectangle. We reimplement \l {QGraphicsItem::}{advance()} + to handle the animation so it all happens on one update. \section1 Mouse Class Definition @@ -105,19 +102,18 @@ calling the item's \l {QGraphicsItem::rotate()}{rotate()} function we alter the direction in which the mouse will start moving. - In the end we call QObject's \l {QObject::}{startTimer()} - function, emitting a timer event every 1000/33 millisecond. This - enables us to animate our mouse item using our reimplementation of - the \l {QObject::}{timerEvent()} function; whenever a mouse - receives a timer event it will trigger \l - {QObject::}{timerEvent()}: - + When the QGraphicsScene decides to advance the scene a frame it will call + QGraphicsItem::advance() on each of the items. This enables us to animate + our mouse using our reimplementation of the advance() function. + \snippet examples/graphicsview/collidingmice/mouse.cpp 4 \snippet examples/graphicsview/collidingmice/mouse.cpp 5 \snippet examples/graphicsview/collidingmice/mouse.cpp 6 - First we ensure that the mice stays within a circle with a radius - of 150 pixels. + First, we don't bother doing any advance if the step is 0 since we want to our advance in + the actual advance (advance() is called twice, once with step == 0 indicating that items + are about to advance and with step == 1 for the actual advance). We also ensure that the + mice stays within a circle with a radius of 150 pixels. Note the \l {QGraphicsItem::mapFromScene()}{mapFromScene()} function provided by QGraphicsItem. This function maps a position @@ -275,5 +271,12 @@ In the end, we set the application window's title and size before we enter the main event loop using the QApplication::exec() function. -*/ + Finally, we create a QTimer and connect its timeout() signal to the advance() + slot of the scene. Every time the timer fires, the scene will advance one frame. + We then tell the timer to fire every 1000/33 millisecond. This will + give us a frame rate of 30 frames a second, which is fast enough for most animations. + Doing the animation with a single timer connect to advance the scene ensures that all the + mice are moved at one point and, more importantly, only one update is sent to the screen + after all the mice have moved. +*/ \ No newline at end of file diff --git a/examples/graphicsview/collidingmice/main.cpp b/examples/graphicsview/collidingmice/main.cpp index 4a44481..23c91b0 100644 --- a/examples/graphicsview/collidingmice/main.cpp +++ b/examples/graphicsview/collidingmice/main.cpp @@ -83,6 +83,10 @@ int main(int argc, char **argv) view.resize(400, 300); view.show(); + QTimer timer; + QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance())); + timer.start(1000 / 33); + return app.exec(); } //! [6] diff --git a/examples/graphicsview/collidingmice/mouse.cpp b/examples/graphicsview/collidingmice/mouse.cpp index 1d10574..bbdb4e3 100644 --- a/examples/graphicsview/collidingmice/mouse.cpp +++ b/examples/graphicsview/collidingmice/mouse.cpp @@ -65,7 +65,6 @@ Mouse::Mouse() color(qrand() % 256, qrand() % 256, qrand() % 256) { rotate(qrand() % (360 * 16)); - startTimer(1000 / 33); } //! [0] @@ -123,8 +122,10 @@ void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * //! [3] //! [4] -void Mouse::timerEvent(QTimerEvent *) +void Mouse::advance(int step) { + if (!step) + return; //! [4] // Don't move too far away //! [5] diff --git a/examples/graphicsview/collidingmice/mouse.h b/examples/graphicsview/collidingmice/mouse.h index 832ea53..c08ce4a 100644 --- a/examples/graphicsview/collidingmice/mouse.h +++ b/examples/graphicsview/collidingmice/mouse.h @@ -43,13 +43,10 @@ #define MOUSE_H #include -#include //! [0] -class Mouse : public QObject, public QGraphicsItem +class Mouse : public QGraphicsItem { - Q_OBJECT - public: Mouse(); @@ -59,7 +56,7 @@ public: QWidget *widget); protected: - void timerEvent(QTimerEvent *event); + void advance(int step); private: qreal angle; -- cgit v0.12 From 041a8ecdb5f11dfc499f8f8f77d85cb63508c093 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Mon, 6 Apr 2009 17:52:58 +0200 Subject: BT: Fixed treeview painting regression on Vista The old code did not split up the frame from the central parts of the itemview selection box correctly. We now draw the edges as border images instead. Previously this would lead to somewhat ugly scaling artifacts for small header sections. Task: 248839 Reviewed-by: ogoffart --- src/gui/styles/qwindowsvistastyle.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 4c3060d..b14b8b3 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -801,12 +801,20 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt if (vopt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne || vopt->viewItemPosition == QStyleOptionViewItemV4::Invalid) painter->drawPixmap(pixmapRect.topLeft(), pixmap); - else if (reverse ? rightSection : leftSection) - painter->drawPixmap(pixmapRect, pixmap, srcRect.adjusted(0, 0, -frame, 0)); - else if (reverse ? leftSection : rightSection) - painter->drawPixmap(pixmapRect, pixmap, - srcRect.adjusted(frame, 0, 0, 0)); - else if (vopt->viewItemPosition == QStyleOptionViewItemV4::Middle) + else if (reverse ? rightSection : leftSection){ + painter->drawPixmap(QRect(pixmapRect.topLeft(), + QSize(frame, pixmapRect.height())), pixmap, + QRect(QPoint(0, 0), QSize(frame, pixmapRect.height()))); + painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0), + pixmap, srcRect.adjusted(frame, 0, -frame, 0)); + } else if (reverse ? leftSection : rightSection) { + painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0), + QSize(frame, pixmapRect.height())), pixmap, + QRect(QPoint(pixmapRect.width() - frame, 0), + QSize(frame, pixmapRect.height()))); + painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0), + pixmap, srcRect.adjusted(frame, 0, -frame, 0)); + } else if (vopt->viewItemPosition == QStyleOptionViewItemV4::Middle) painter->drawPixmap(pixmapRect, pixmap, srcRect.adjusted(frame, 0, -frame, 0)); } else { -- cgit v0.12 From 948de0dc991e324cdfb01f2e84a6aadfbf8d737f Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 6 Apr 2009 15:49:40 +1000 Subject: Fixes: QSqlTableModel does not handle updates when one of the fields has a NULL value Task-number: 189093 --- src/sql/kernel/qsqldriver.cpp | 11 ++++++++--- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index ddebe45..a995005 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -406,9 +406,14 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, break; case WhereStatement: if (preparedStatement) { - for (int i = 0; i < rec.count(); ++i) - s.append(escapeIdentifier(rec.fieldName(i), FieldName)).append( - QLatin1String(" = ? AND ")); + for (int i = 0; i < rec.count(); ++i) { + s.append(escapeIdentifier(rec.fieldName(i), FieldName)); + if (rec.isNull(i)) + s.append(QLatin1String(" IS NULL")); + else + s.append(QLatin1String(" = ?")); + s.append(QLatin1String(" AND ")); + } } else { for (i = 0; i < rec.count(); ++i) { s.append(escapeIdentifier(rec.fieldName(i), FieldName)); diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index e10a0ca..51d5267 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -191,6 +191,10 @@ private slots: void sqlite_bindAndFetchUInt_data() { generic_data("QSQLITE3"); } void sqlite_bindAndFetchUInt(); + void sqlStatementUseIsNull_189093_data() { generic_data(); } + void sqlStatementUseIsNull_189093(); + + private: void createTestTables(QSqlDatabase db); void dropTestTables(QSqlDatabase db); @@ -363,6 +367,7 @@ void tst_QSqlDatabase::populateTestTables(QSqlDatabase db) QVERIFY_SQL(q, exec("insert into " + qTableName("qtest") + " (id, t_varchar, t_char, t_numeric) values (1, 'VarChar1', 'Char1', 2.2)")); QVERIFY_SQL(q, exec("insert into " + qTableName("qtest") + " (id, t_varchar, t_char, t_numeric) values (2, 'VarChar2', 'Char2', 3.3)")); QVERIFY_SQL(q, exec("insert into " + qTableName("qtest") + " (id, t_varchar, t_char, t_numeric) values (3, 'VarChar3', 'Char3', 4.4)")); + QVERIFY_SQL(q, exec("insert into " + qTableName("qtest") + " (id, t_varchar, t_char, t_numeric) values (4, 'VarChar4', NULL, NULL)")); } void tst_QSqlDatabase::initTestCase() @@ -2267,5 +2272,28 @@ void tst_QSqlDatabase::db2_valueCacheUpdate() QCOMPARE(c1.toString(), q.value(0).toString()); } +void tst_QSqlDatabase::sqlStatementUseIsNull_189093() +{ + // NULL = NULL is unknow, the sqlStatment must use IS NULL + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + // select a record with NULL value + QSqlQuery q(QString::null, db); + QVERIFY_SQL(q, exec("select * from " + qTableName("qtest") + " where id = 4")); + QVERIFY_SQL(q, next()); + + QSqlDriver *driver = db.driver(); + QVERIFY(driver); + + QString preparedStatment = driver->sqlStatement(QSqlDriver::WhereStatement, QString("qtest"), q.record(), true); + QCOMPARE(preparedStatment.count("IS NULL", Qt::CaseInsensitive), 2); + + QString statment = driver->sqlStatement(QSqlDriver::WhereStatement, QString("qtest"), q.record(), false); + QCOMPARE(statment.count("IS NULL", Qt::CaseInsensitive), 2); +} + + QTEST_MAIN(tst_QSqlDatabase) #include "tst_qsqldatabase.moc" -- cgit v0.12 From 6393b9fa8474b7b9e86319f54477cba9bec65d11 Mon Sep 17 00:00:00 2001 From: Bill King Date: Tue, 7 Apr 2009 07:45:10 +1000 Subject: Make compile when Qt3Support is turned off --- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 51d5267..8dede12 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -1050,6 +1050,7 @@ void tst_QSqlDatabase::recordMySQL() int minor = tst_Databases::getMySqlVersion( db ).section( QChar('.'), 1, 1 ).toInt(); int revision = tst_Databases::getMySqlVersion( db ).section( QChar('.'), 2, 2 ).toInt(); +#ifdef QT3_SUPPORT /* The below is broken in mysql below 5.0.15 see http://dev.mysql.com/doc/refman/5.0/en/binary-varbinary.html specifically: Before MySQL 5.0.15, the pad value is space. Values are right-padded @@ -1059,6 +1060,7 @@ void tst_QSqlDatabase::recordMySQL() bin10 = FieldDef("binary(10)", QVariant::ByteArray, QByteArray(Q3CString("123abc "))); varbin10 = FieldDef("varbinary(10)", QVariant::ByteArray, QByteArray(Q3CString("123abcv "))); } +#endif static QDateTime dt(QDate::currentDate(), QTime(1, 2, 3, 0)); static const FieldDef fieldDefs[] = { -- cgit v0.12 From 3b68e5157e103dec536d5aaff508c1751f20c62e Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 16:24:41 -0700 Subject: Don't use uninitialized caps If flags does not contain DSDESC_CAPS caps might very well be uninitialized. Make sure to properly deal with this situation. Reviewed-by: Donald --- src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index fd6f48a..39a2d48 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -218,8 +218,12 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription if (d_ptr->videoonly && !(desc->flags & DSDESC_PREALLOCATED)) { // Add the video only capability. This means the surface will be created in video ram DFBSurfaceDescription voDesc = *desc; - voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY); - voDesc.flags = DFBSurfaceDescriptionFlags(voDesc.flags | DSDESC_CAPS); + if (!(voDesc.flags & DSDESC_CAPS)) { + voDesc.caps = DSCAPS_VIDEOONLY; + voDesc.flags = DFBSurfaceDescriptionFlags(voDesc.flags | DSDESC_CAPS); + } else { + voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY); + } result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &voDesc, &newSurface); } -- cgit v0.12 From 723eea029f98b802563c0bc06ba82ff741e1ac73 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 7 Apr 2009 10:55:31 +1000 Subject: Move QT_BEGIN_NAMESPACE to after the usual Qt header includes QT_BEGIN_NAMESPACE is not defined until qglobal.h is included, but some of the QtNetwork headers were listing it before. Reviewed-by: Ian Walters --- src/network/access/qhttpnetworkheader_p.h | 4 ++-- src/network/access/qhttpnetworkreply_p.h | 6 +++--- src/network/access/qhttpnetworkrequest_p.h | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h index 306ae85..3052309 100644 --- a/src/network/access/qhttpnetworkheader_p.h +++ b/src/network/access/qhttpnetworkheader_p.h @@ -54,11 +54,11 @@ // #ifndef QT_NO_HTTP -QT_BEGIN_NAMESPACE - #include #include +QT_BEGIN_NAMESPACE + class Q_AUTOTEST_EXPORT QHttpNetworkHeader { public: diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 9881bb3..21f4116 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -54,8 +54,6 @@ // #ifndef QT_NO_HTTP -QT_BEGIN_NAMESPACE - #ifndef QT_NO_COMPRESS # include static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header @@ -84,6 +82,8 @@ static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header #include #include +QT_BEGIN_NAMESPACE + class QHttpNetworkConnection; class QHttpNetworkRequest; class QHttpNetworkConnectionPrivate; @@ -223,4 +223,4 @@ QT_END_NAMESPACE #endif // QT_NO_HTTP -#endif // QHTTPNETWORKREPLY_H \ No newline at end of file +#endif // QHTTPNETWORKREPLY_H diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index 4e64ca6..d18e116 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -54,10 +54,10 @@ // #ifndef QT_NO_HTTP -QT_BEGIN_NAMESPACE - #include +QT_BEGIN_NAMESPACE + class QHttpNetworkRequestPrivate; class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader { @@ -141,4 +141,4 @@ QT_END_NAMESPACE #endif // QT_NO_HTTP -#endif // QHTTPNETWORKREQUEST_H \ No newline at end of file +#endif // QHTTPNETWORKREQUEST_H -- cgit v0.12 From 0002b0285269f69648a7eede33a1d9df5fab8c53 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 18:20:28 -0700 Subject: Fix up some QT_...NO_PALETTE codepaths Make sure we create the surface from the converted image and not the original one. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 39a2d48..dd147cf 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -171,7 +171,7 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCr } #endif #ifndef QT_NO_DIRECTFB_PALETTE - if (img.numColors() != 0) + if (img.numColors() != 0 && surface) QDirectFBScreen::setSurfaceColorTable(surface, img); #endif return surface; @@ -261,19 +261,21 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, #ifdef QT_NO_DIRECTFB_PREALLOCATED || image.format() != pixmapFormat #endif +#ifdef QT_NO_DIRECTFB_PALETTE + || image.numColors() != 0 +#endif ) { image = image.convertToFormat(pixmapFormat); } - - IDirectFBSurface *dfbSurface = createDFBSurface(img.size(), pixmapFormat, options); + IDirectFBSurface *dfbSurface = createDFBSurface(image.size(), pixmapFormat, options); if (!dfbSurface) { qWarning("QDirectFBPixmapData::fromImage() Couldn't create surface"); return 0; } #ifndef QT_NO_DIRECTFB_PREALLOCATED - IDirectFBSurface *imgSurface = createDFBSurface(img, DontTrackSurface); + IDirectFBSurface *imgSurface = createDFBSurface(image, DontTrackSurface); if (!imgSurface) { qWarning("QDirectFBPixmapData::fromImage()"); QDirectFBScreen::releaseDFBSurface(dfbSurface); -- cgit v0.12 From fb7275161fa646c76cf47dfc8eb41e9356639e70 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 18:41:58 -0700 Subject: Pens can have brushes DirectFB can only handle cases where the pen's brush is Qt::SolidPattern Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 3b6ea80..d0a9dc6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -367,7 +367,9 @@ void QDirectFBPaintEnginePrivate::setPen(const QPen &p) { pen = p; simplePen = (pen.style() == Qt::NoPen) || - (pen.style() == Qt::SolidLine && !antialiased + (pen.style() == Qt::SolidLine + && !antialiased + && (pen.brush().style() == Qt::SolidPattern) && (pen.widthF() <= 1 && !matrixScale)); } -- cgit v0.12 From 5fb7752ff93b31635e64fa321917749744cc9db6 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 18:51:52 -0700 Subject: Make sure RGB32 workaround works for windows Need to set forceRaster to true if the window surface is RGB32. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index ef208af..ec108c4 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -111,6 +111,7 @@ void QDirectFBSurface::createWindow() dfbSurface->Release(dfbSurface); dfbWindow->GetSurface(dfbWindow, &dfbSurface); + forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } #endif // QT_NO_DIRECTFB_WM @@ -143,6 +144,7 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) IDirectFBSurface *primarySurface = screen->dfbSurface(); Q_ASSERT(primarySurface); result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface); + forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } else { #ifdef QT_NO_DIRECTFB_WM if (isResize) { @@ -164,6 +166,7 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, QDirectFBScreen::instance()->pixelFormat()); dfbSurface = QDirectFBScreen::instance()->createDFBSurface(&description, false); + forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } else { Q_ASSERT(dfbSurface); } -- cgit v0.12 From 80d83e72fca6a60ca9cfec8bfa37a82087c931a9 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Tue, 31 Mar 2009 18:10:26 -0700 Subject: Make windows the right formats and videoonly CreateWindow gives you more control over how windows are created. Make sure to specify that they're in the same format as the primary surface and that they're in video memory if this is supported. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index ec108c4..15c2f7c 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -98,10 +98,19 @@ void QDirectFBSurface::createWindow() if (!layer) qFatal("QDirectFBWindowSurface: Unable to get primary display layer!"); - DFBWindowDescription description; - description.caps = DFBWindowCapabilities(DWCAPS_NODECORATION | - DWCAPS_ALPHACHANNEL); - description.flags = DWDESC_CAPS; + DFBWindowDescription description; + description.caps = DFBWindowCapabilities(DWCAPS_NODECORATION); + description.flags = DFBWindowDescriptionFlags(DWDESC_CAPS + |DWDESC_SURFACE_CAPS + |DWDESC_PIXELFORMAT); + + description.surface_caps = DSCAPS_NONE; + if (QDirectFBScreen::instance()->preferVideoOnly()) + description.surface_caps = DFBSurfaceCapabilities(description.surface_caps|DSCAPS_VIDEOONLY); + const QImage::Format format = QDirectFBScreen::instance()->pixelFormat(); + description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); + if (QDirectFBScreen::isPremultiplied(format)) + description.surface_caps = DFBSurfaceCapabilities(DSCAPS_PREMULTIPLIED|description.caps); DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow); if (result != DFB_OK) @@ -111,7 +120,7 @@ void QDirectFBSurface::createWindow() dfbSurface->Release(dfbSurface); dfbWindow->GetSurface(dfbWindow, &dfbSurface); - forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); + forceRaster = (format == QImage::Format_RGB32); } #endif // QT_NO_DIRECTFB_WM -- cgit v0.12 From 5a0b19a4559fa83e77cc6c6cd05fc492e692b667 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 19:18:58 -0700 Subject: Make sure to dirty clip in setState For an example of something that breaks without this fix show a spinbox in plastique style. The clip is never removed. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index d0a9dc6..4732c65 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -909,8 +909,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s) { Q_D(QDirectFBPaintEngine); QRasterPaintEngine::setState(s); - if (d->surface) - d->updateClip(); + d->setClipDirty(); d->setPen(state()->pen); d->setBrush(state()->brush); d->setOpacity(state()->opacity); -- cgit v0.12 From cab39df3deb99aba7aa71a397055a2ec742921f4 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 7 Apr 2009 12:32:04 +1000 Subject: Make OpenGL/ES 1.1 CommonLite and OpenGL/ES 1.0 builds work Reviewed-by: trustme --- src/opengl/qgl_cl_p.h | 2 +- src/opengl/qglframebufferobject.cpp | 4 ++++ src/opengl/qglpixelbuffer_egl.cpp | 8 +++++-- src/opengl/qpaintengine_opengl.cpp | 44 ++++++++++++++++++------------------- src/opengl/qwindowsurface_gl.cpp | 4 ++++ 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/opengl/qgl_cl_p.h b/src/opengl/qgl_cl_p.h index e514ff5..c05a7d7 100644 --- a/src/opengl/qgl_cl_p.h +++ b/src/opengl/qgl_cl_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE inline void glTexParameterf (GLenum target, GLenum pname, GLfloat param) { - glTexParameterx(target, pname, param); + glTexParameterx(target, pname, FLOAT2X(param)); } inline void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index fb22272..c362b7e 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -48,6 +48,10 @@ #include #include +#ifdef QT_OPENGL_ES_1_CL +#include "qgl_cl_p.h" +#endif + QT_BEGIN_NAMESPACE extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool); diff --git a/src/opengl/qglpixelbuffer_egl.cpp b/src/opengl/qglpixelbuffer_egl.cpp index 964efa2..5390fd1 100644 --- a/src/opengl/qglpixelbuffer_egl.cpp +++ b/src/opengl/qglpixelbuffer_egl.cpp @@ -47,6 +47,10 @@ #include #include +#ifdef QT_OPENGL_ES_1_CL +#include "qgl_cl_p.h" +#endif + QT_BEGIN_NAMESPACE #ifdef EGL_BIND_TO_TEXTURE_RGBA @@ -188,8 +192,8 @@ GLuint QGLPixelBuffer::generateDynamicTexture() const glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, d->req_size.width(), d->req_size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); return texture; #else return 0; diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 976a021..88fd379 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -1983,7 +1983,7 @@ public: void QOpenGLTrapezoidToArrayTessellator::addTrap(const Trapezoid &trap) { // On OpenGL ES we convert the trap to 2 triangles -#ifndef QT_OPENGL_ES_1 +#ifndef QT_OPENGL_ES if (size > allocated - 8) { #else if (size > allocated - 12) { @@ -1994,31 +1994,31 @@ void QOpenGLTrapezoidToArrayTessellator::addTrap(const Trapezoid &trap) QGLTrapezoid t = toGLTrapezoid(trap); -#ifndef QT_OPENGL_ES_1 - vertices[size++] = t.topLeftX; - vertices[size++] = t.top; - vertices[size++] = t.topRightX; - vertices[size++] = t.top; - vertices[size++] = t.bottomRightX; - vertices[size++] = t.bottom; - vertices[size++] = t.bottomLeftX; - vertices[size++] = t.bottom; +#ifndef QT_OPENGL_ES + vertices[size++] = f2vt(t.topLeftX); + vertices[size++] = f2vt(t.top); + vertices[size++] = f2vt(t.topRightX); + vertices[size++] = f2vt(t.top); + vertices[size++] = f2vt(t.bottomRightX); + vertices[size++] = f2vt(t.bottom); + vertices[size++] = f2vt(t.bottomLeftX); + vertices[size++] = f2vt(t.bottom); #else // First triangle - vertices[size++] = t.topLeftX; - vertices[size++] = t.top; - vertices[size++] = t.topRightX; - vertices[size++] = t.top; - vertices[size++] = t.bottomRightX; - vertices[size++] = t.bottom; + vertices[size++] = f2vt(t.topLeftX); + vertices[size++] = f2vt(t.top); + vertices[size++] = f2vt(t.topRightX); + vertices[size++] = f2vt(t.top); + vertices[size++] = f2vt(t.bottomRightX); + vertices[size++] = f2vt(t.bottom); // Second triangle - vertices[size++] = t.bottomLeftX; - vertices[size++] = t.bottom; - vertices[size++] = t.topLeftX; - vertices[size++] = t.top; - vertices[size++] = t.bottomRightX; - vertices[size++] = t.bottom; + vertices[size++] = f2vt(t.bottomLeftX); + vertices[size++] = f2vt(t.bottom); + vertices[size++] = f2vt(t.topLeftX); + vertices[size++] = f2vt(t.top); + vertices[size++] = f2vt(t.bottomRightX); + vertices[size++] = f2vt(t.bottom); #endif } diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 3dd3064..837ccf2 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -76,6 +76,10 @@ #define GLX_SAMPLES_ARB 100001 #endif +#ifdef QT_OPENGL_ES_1_CL +#include "qgl_cl_p.h" +#endif + QT_BEGIN_NAMESPACE // -- cgit v0.12 From 7d2593c767d6006ec123cb4564071dbc7948a3fc Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Tue, 7 Apr 2009 12:59:44 +1000 Subject: Remove inline keywords, fix compile bug The compile under OS-X was failing due to unfound symbols. Given that the implementation of these functions is not in the header file, they should not have inline keywords. Removing the inline keywords allowed compilation to succeed. Reviewed-by: Rhys Weatherley --- src/network/access/qhttpnetworkheader_p.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h index 3052309..4e62352 100644 --- a/src/network/access/qhttpnetworkheader_p.h +++ b/src/network/access/qhttpnetworkheader_p.h @@ -88,9 +88,9 @@ public: qint64 contentLength() const; void setContentLength(qint64 length); - inline QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; - inline QList headerFieldValues(const QByteArray &name) const; - inline void setHeaderField(const QByteArray &name, const QByteArray &data); + QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; + QList headerFieldValues(const QByteArray &name) const; + void setHeaderField(const QByteArray &name, const QByteArray &data); bool operator==(const QHttpNetworkHeaderPrivate &other) const; }; -- cgit v0.12 From 018edd573eac026f861e97ffab611b4eeb059830 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 20:10:01 -0700 Subject: Clean up surface creation code Use the intended functions for surface creation. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 9f5c055..6857d96 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -144,15 +144,11 @@ void QDirectFBPixmapData::fill(const QColor &color) Q_ASSERT(dfbSurface); if (color.alpha() < 255 && !hasAlphaChannel()) { - DFBSurfaceDescription description; - description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | - DSDESC_HEIGHT | - DSDESC_PIXELFORMAT); - dfbSurface->GetSize(dfbSurface, &description.width, &description.height); - QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, screen->alphaPixmapFormat()); - screen->releaseDFBSurface(dfbSurface); // release old surface - - dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); + + QSize size; + dfbSurface->GetSize(dfbSurface, &size.rwidth(), &size.rheight()); + screen->releaseDFBSurface(dfbSurface); + dfbSurface = screen->createDFBSurface(size, screen->alphaPixmapFormat(), QDirectFBScreen::TrackSurface); forceRaster = false; setSerialNumber(++global_ser_no); if (!dfbSurface) { -- cgit v0.12 From f70dcb0ed48bb393d3e7ed8941e98f1e52fff80e Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 20:25:12 -0700 Subject: Improve QDirectFBPixmapData::transformed Make sure we keep retain alpha if there is one in the source. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 6857d96..ee60302 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -231,13 +231,22 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, return QPixmap(); QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType); - data->resize(size.width(), size.height()); - - IDirectFBSurface *dest = data->dfbSurface; - dest->SetBlittingFlags(dest, DSBLIT_NOFX); + QImage::Format format = screen->pixelFormat(); + DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; + if (hasAlphaChannel()) { + flags = DSBLIT_BLEND_ALPHACHANNEL; + format = screen->alphaPixmapFormat(); + } + data->dfbSurface = screen->createDFBSurface(size, + format, + QDirectFBScreen::TrackSurface); + if (flags & DSBLIT_BLEND_ALPHACHANNEL) { + data->dfbSurface->Clear(data->dfbSurface, 0, 0, 0, 0); + } + data->dfbSurface->SetBlittingFlags(data->dfbSurface, flags); const DFBRectangle destRect = { 0, 0, size.width(), size.height() }; - dest->StretchBlit(dest, dfbSurface, 0, &destRect); + data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect); return QPixmap(data); } -- cgit v0.12 From 3eb0951fa7664e39c74df8edfca51c2a1199209b Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 20:28:38 -0700 Subject: Improve QDirectFBPixmapData::copy Make sure we retain the alpha channel of the original surface. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index ee60302..9df3051 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -109,7 +109,8 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) } IDirectFBSurface *src = static_cast(data)->directFBSurface(); - const QImage::Format format = (data->hasAlphaChannel() + const bool hasAlpha = data->hasAlphaChannel(); + const QImage::Format format = (hasAlpha ? QDirectFBScreen::instance()->alphaPixmapFormat() : QDirectFBScreen::instance()->pixelFormat()); @@ -122,7 +123,12 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) } forceRaster = (format == QImage::Format_RGB32); - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); + if (hasAlpha) { + dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); + dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_BLEND_ALPHACHANNEL); + } else { + dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); + } const DFBRectangle blitRect = { rect.x(), rect.y(), rect.width(), rect.height() }; DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0); -- cgit v0.12 From 6ee9fd3cdb932dd8d7a2ad6a5ac61300aefc1058 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:16:13 -0700 Subject: Make sure to set blitting flags Need to set blitting flags before blitting from a surface with alpha channel. Otherwise alpha areas become white. For some reason setting the porterduff to DSPD_SRC does not fix this. Reviewed-by: TrustMe --- .../gfxdrivers/directfb/qdirectfbpixmap.cpp | 23 +++------------------ .../gfxdrivers/directfb/qdirectfbscreen.cpp | 24 +++++++++++++++++----- src/plugins/gfxdrivers/directfb/qdirectfbscreen.h | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 9df3051..923025a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -187,30 +187,13 @@ bool QDirectFBPixmapData::hasAlphaChannel() const { if (!serialNumber()) return false; + DFBSurfacePixelFormat format; + dfbSurface->GetPixelFormat(dfbSurface, &format); + return QDirectFBScreen::hasAlpha(format); // We don't need to ask DFB for this really. Can just keep track // of what image format this has. It should always have either // QDirectFBScreen::alphaPixmapFormat() or QScreen::pixelFormat() - - DFBSurfacePixelFormat format; - dfbSurface->GetPixelFormat(dfbSurface, &format); - switch (format) { - case DSPF_ARGB1555: - case DSPF_ARGB: - case DSPF_LUT8: - case DSPF_AiRGB: - case DSPF_A1: - case DSPF_ARGB2554: - case DSPF_ARGB4444: - case DSPF_AYUV: - case DSPF_A4: - case DSPF_ARGB1666: - case DSPF_ARGB6666: - case DSPF_LUT2: - return true; - default: - return false; - } } QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index dd147cf..bbb0678 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -185,7 +185,15 @@ IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src, QSize size; src->GetSize(src, &size.rwidth(), &size.rheight()); IDirectFBSurface *surface = createDFBSurface(size, format, options); - surface->SetBlittingFlags(surface, DSBLIT_NOFX); + DFBSurfacePixelFormat dspf; + src->GetPixelFormat(src, &dspf); + DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlpha(dspf) + ? DSBLIT_BLEND_ALPHACHANNEL + : DSBLIT_NOFX; + if (flags & DSBLIT_BLEND_ALPHACHANNEL) + surface->Clear(surface, 0, 0, 0, 0); + + surface->SetBlittingFlags(surface, flags); surface->Blit(surface, src, 0, 0, 0); surface->ReleaseSource(surface); // ??? Is this always right? return surface; @@ -281,10 +289,16 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, QDirectFBScreen::releaseDFBSurface(dfbSurface); return 0; } + Q_ASSERT(imgSurface); - DFBResult result; - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); - result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); + DFBSurfaceBlittingFlags flags = img.hasAlphaChannel() + ? DSBLIT_BLEND_ALPHACHANNEL + : DSBLIT_NOFX; + if (flags & DSBLIT_BLEND_ALPHACHANNEL) + dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); + + dfbSurface->SetBlittingFlags(dfbSurface, flags); + DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); if (result != DFB_OK) DirectFBError("QDirectFBPixmapData::fromImage()", result); dfbSurface->ReleaseSource(dfbSurface); @@ -370,7 +384,7 @@ DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format form }; } -static inline bool isPremultiplied(IDirectFBSurface *surface) +static inline bool isPremultiplied(IDirectFBSurface *surface) { Q_ASSERT(surface); DFBSurfaceCapabilities caps; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index a1e93c6..f394ac1 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -119,6 +119,7 @@ public: static QImage::Format getImageFormat(IDirectFBSurface *surface); static bool initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, QImage::Format format); static inline bool isPremultiplied(QImage::Format format); + static inline bool hasAlpha(DFBSurfacePixelFormat format); QImage::Format alphaPixmapFormat() const; #ifndef QT_NO_DIRECTFB_PALETTE @@ -151,6 +152,26 @@ inline bool QDirectFBScreen::isPremultiplied(QImage::Format format) return false; } +inline bool QDirectFBScreen::hasAlpha(DFBSurfacePixelFormat format) +{ + switch (format) { + case DSPF_ARGB1555: + case DSPF_ARGB: + case DSPF_LUT8: + case DSPF_AiRGB: + case DSPF_A1: + case DSPF_ARGB2554: + case DSPF_ARGB4444: + case DSPF_AYUV: + case DSPF_A4: + case DSPF_ARGB1666: + case DSPF_ARGB6666: + case DSPF_LUT2: + return true; + default: + return false; + } +} QT_END_HEADER -- cgit v0.12 From 7b72b28464b4ffba6b39cbb863731202dd922064 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:18:18 -0700 Subject: Cleanup. This function is no longer used. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index bbb0678..cb40935 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -384,16 +384,6 @@ DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format form }; } -static inline bool isPremultiplied(IDirectFBSurface *surface) -{ - Q_ASSERT(surface); - DFBSurfaceCapabilities caps; - const DFBResult result = surface->GetCapabilities(surface, &caps); - Q_ASSERT(result == DFB_OK); - Q_UNUSED(result); - return caps & DSCAPS_PREMULTIPLIED; -} - QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface) { DFBSurfacePixelFormat format; -- cgit v0.12 From 13e3bd76869c0e9be2408b0928b87565aa48ae3d Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:23:01 -0700 Subject: Optimize fillRects/fillRegion This is not X11. There's no need to create another structure to hold the DFB rectangles. Verified by DirectFB expert. Reviewed-by: TrustMe --- .../gfxdrivers/directfb/qdirectfbpaintengine.cpp | 28 ++++------------------ 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 4732c65..a93bbf7 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -558,43 +558,25 @@ void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®ion) const { const QVector rects = region.rects(); const int n = rects.size(); - QVarLengthArray dfbRects(n); - - for (int i = 0; i < n; ++i) { - const QRect r = rects.at(i); - dfbRects[i].x = r.x(); - dfbRects[i].y = r.y(); - dfbRects[i].w = r.width(); - dfbRects[i].h = r.height(); - - } - surface->FillRectangles(surface, dfbRects.data(), n); + fillRects(rects.constData(), n); } void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) const { - QVarLengthArray dfbRects(n); for (int i = 0; i < n; ++i) { const QRect r = transform.mapRect(rects[i]); - dfbRects[i].x = r.x(); - dfbRects[i].y = r.y(); - dfbRects[i].w = r.width(); - dfbRects[i].h = r.height(); + surface->FillRectangle(surface, r.x(), r.y(), + r.width(), r.height()); } - surface->FillRectangles(surface, dfbRects.data(), n); } void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) const { - QVarLengthArray dfbRects(n); for (int i = 0; i < n; ++i) { const QRect r = transform.mapRect(rects[i]).toRect(); - dfbRects[i].x = r.x(); - dfbRects[i].y = r.y(); - dfbRects[i].w = r.width(); - dfbRects[i].h = r.height(); + surface->FillRectangle(surface, r.x(), r.y(), + r.width(), r.height()); } - surface->FillRectangles(surface, dfbRects.data(), n); } void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) const -- cgit v0.12 From bf3fdc3f6697cfaec689e8422b6c43cfe49bf9b4 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:34:05 -0700 Subject: Optimize bytesPerLine further If we're asking for the stride it's very likely the next thing we'll do is ask for the bits() so there's no good reason to unlock it again. In the raster buffer case memory() will be called just before bytesPerLine() so the code won't be hit but it's still the right thing to do. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index edbfa7d..2a2ef5c 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -110,7 +110,6 @@ int QDirectFBPaintDevice::bytesPerLine() const QDirectFBPaintDevice* that = const_cast(this); that->lockDirectFB(); Q_ASSERT(bpl != -1); - that->unlockDirectFB(); } return bpl; } -- cgit v0.12 From 3923604b4390e613000f4c2b00db9e0a954f92ed Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:45:07 -0700 Subject: Better QDirectFBPixmapData::toImage() This is essentially a return to the earlier version of toImage(). Use a preallocated surface that operates on the returned image to do the conversion. If this causes drawing bugs it is likely a bug in the directfb driver and can be worked around by compiling with QT_NO_DIRECTFB_PREALLOCATED. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 923025a..45f0710 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -245,6 +245,17 @@ QImage QDirectFBPixmapData::toImage() const if (!dfbSurface) return QImage(); +#ifndef QT_NO_DIRECTFB_PREALLOCATED + QImage ret(size(), QDirectFBScreen::getImageFormat(dfbSurface)); + if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) { + imgSurface->SetBlittingFlags(imgSurface, hasAlphaChannel() ? DSBLIT_BLEND_ALPHACHANNEL : DSBLIT_NOFX); + imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0); + imgSurface->ReleaseSource(imgSurface); + imgSurface->Release(imgSurface); + return ret; + } +#endif + QDirectFBPixmapData *that = const_cast(this); const QImage *img = that->buffer(); return img->copy(); -- cgit v0.12 From fd4a62bfc18006b3c29918a65b60d9bacf22c9c0 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:52:12 -0700 Subject: Call ReleaseSource where appropriate DirectFB caches the last source surface in the target surface after a Blit. This can cause a surface to be kept around longer than desired since the caching increases the ref-count. Unless it's likely that the blit will happen again soon we Release the source. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 2 ++ src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 3 ++- src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 45f0710..c4144bd 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -132,6 +132,7 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) const DFBRectangle blitRect = { rect.x(), rect.y(), rect.width(), rect.height() }; DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0); + dfbSurface->ReleaseSource(dfbSurface); if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::copy()", result); setSerialNumber(0); @@ -236,6 +237,7 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, const DFBRectangle destRect = { 0, 0, size.width(), size.height() }; data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect); + data->dfbSurface->ReleaseSource(data->dfbSurface); return QPixmap(data); } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index cb40935..4ae64f7 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -195,7 +195,7 @@ IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src, surface->SetBlittingFlags(surface, flags); surface->Blit(surface, src, 0, 0, 0); - surface->ReleaseSource(surface); // ??? Is this always right? + surface->ReleaseSource(surface); return surface; } @@ -1093,6 +1093,7 @@ void QDirectFBScreen::compose(const QRegion ®ion) blit(surface->image(), offset, r); } } + d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); } // Normally, when using DirectFB to compose the windows (I.e. when diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index 15c2f7c..592ad47 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -262,7 +262,7 @@ bool QDirectFBSurface::scroll(const QRegion ®ion, int dx, int dy) dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); dfbSurface->BatchBlit(dfbSurface, dfbSurface, dfbRects.data(), dfbPoints.data(), n); - + dfbSurface->ReleaseSource(dfbSurface); return true; } -- cgit v0.12 From 79adaaf479bfe2e5c252c7aad20db7d04d315444 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 22:55:22 -0700 Subject: Code cleanup. QDirectFBPaintDevice's know their screen. No need to use instance() in these cases. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 10 +++++----- src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index c4144bd..35ab859 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -71,9 +71,9 @@ void QDirectFBPixmapData::resize(int width, int height) return; } - dfbSurface = QDirectFBScreen::instance()->createDFBSurface(QSize(width, height), - screen->pixelFormat(), - QDirectFBScreen::TrackSurface); + dfbSurface = screen->createDFBSurface(QSize(width, height), + screen->pixelFormat(), + QDirectFBScreen::TrackSurface); forceRaster = (screen->pixelFormat() == QImage::Format_RGB32); if (!dfbSurface) { setSerialNumber(0); @@ -111,8 +111,8 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) IDirectFBSurface *src = static_cast(data)->directFBSurface(); const bool hasAlpha = data->hasAlphaChannel(); const QImage::Format format = (hasAlpha - ? QDirectFBScreen::instance()->alphaPixmapFormat() - : QDirectFBScreen::instance()->pixelFormat()); + ? screen->alphaPixmapFormat() + : screen->pixelFormat()); dfbSurface = screen->createDFBSurface(rect.size(), format, QDirectFBScreen::TrackSurface); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index 592ad47..28b1e52 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -105,9 +105,9 @@ void QDirectFBSurface::createWindow() |DWDESC_PIXELFORMAT); description.surface_caps = DSCAPS_NONE; - if (QDirectFBScreen::instance()->preferVideoOnly()) + if (screen->preferVideoOnly()) description.surface_caps = DFBSurfaceCapabilities(description.surface_caps|DSCAPS_VIDEOONLY); - const QImage::Format format = QDirectFBScreen::instance()->pixelFormat(); + const QImage::Format format = screen->pixelFormat(); description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); if (QDirectFBScreen::isPremultiplied(format)) description.surface_caps = DFBSurfaceCapabilities(DSCAPS_PREMULTIPLIED|description.caps); @@ -173,8 +173,8 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) description.width = rect.width(); description.height = rect.height(); QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, - QDirectFBScreen::instance()->pixelFormat()); - dfbSurface = QDirectFBScreen::instance()->createDFBSurface(&description, false); + screen->pixelFormat()); + dfbSurface = screen->createDFBSurface(&description, false); forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } else { Q_ASSERT(dfbSurface); -- cgit v0.12 From d3a4c7314ad7694361f510beeadcc012daf7992b Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 23:02:20 -0700 Subject: Approriate warning with incompatible options QT_NO_DIRECTFB_LAYER doesn't work unless QT_NO_DIRECTFB_WM also is defined. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index 28b1e52..8140860 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -94,6 +94,9 @@ bool QDirectFBSurface::isValid() const #ifndef QT_NO_DIRECTFB_WM void QDirectFBSurface::createWindow() { +#ifdef QT_NO_DIRECTFB_LAYER +#warning QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM +#else IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer(); if (!layer) qFatal("QDirectFBWindowSurface: Unable to get primary display layer!"); @@ -121,6 +124,7 @@ void QDirectFBSurface::createWindow() dfbWindow->GetSurface(dfbWindow, &dfbSurface); forceRaster = (format == QImage::Format_RGB32); +#endif } #endif // QT_NO_DIRECTFB_WM -- cgit v0.12 From d821e3288c3f3dee0c4591e6fc64114511559680 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Mon, 6 Apr 2009 23:05:02 -0700 Subject: Kill some warnings Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index 8140860..4b8fe0a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -334,6 +334,12 @@ inline bool isWidgetOpaque(const QWidget *w) void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { + Q_UNUSED(widget); +#ifdef QT_NO_DIRECTFB_WM + Q_UNUSED(region); + Q_UNUSED(offset); +#endif + QWidget *win = window(); // hw: make sure opacity information is updated before compositing -- cgit v0.12 From 470d87ac503debe3bead80628044d176479975eb Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 30 Mar 2009 15:21:59 +0200 Subject: Fixes: Make drawPixmap slightly more optimal for QPaintEngineEx RevBy: Samuel --- src/gui/painting/qpainter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index fe6cc69..b2f0ac4 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5155,9 +5155,6 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) Q_D(QPainter); - if (!d->engine || pm.isNull()) - return; - #ifndef QT_NO_DEBUG qt_painter_thread_test(d->device->devType(), "drawPixmap()"); #endif @@ -5167,12 +5164,18 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) return; } + if (!d->engine) + return; + qreal x = p.x(); qreal y = p.y(); int w = pm.width(); int h = pm.height(); + if (w <= 0) + return; + // Emulate opaque background for bitmaps if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) { fillRect(QRectF(x, y, w, h), d->state->bgBrush.color()); -- cgit v0.12 From 7666940bc4a20c3db98ef8cefd4cd0196cf9a437 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 30 Mar 2009 16:25:54 +0200 Subject: Fixes: Make drawPixmap as fast as drawImage on rasterR RevBy: Samuel Details: The IMAGE_FROM_PIXMAP has to be doing a local copy or something, because it is sure not fast... --- src/gui/painting/qpaintengine_raster.cpp | 100 +++++++++++++++++++++---------- src/gui/painting/qpaintengine_raster_p.h | 2 +- 2 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 6dd5682..addd63d 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2355,11 +2355,6 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPoint *points, int pointCo } } -#define IMAGE_FROM_PIXMAP(pixmap) \ - pixmap.data->classId() == QPixmapData::RasterClass \ - ? ((QRasterPixmapData *) pixmap.data)->image \ - : pixmap.toImage() - /*! \internal */ @@ -2368,16 +2363,33 @@ void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap) #ifdef QT_DEBUG_DRAW qDebug() << " - QRasterPaintEngine::drawPixmap(), pos=" << pos << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth(); #endif - if (pixmap.depth() == 1) { - Q_D(QRasterPaintEngine); - QRasterPaintEngineState *s = state(); - if (s->matrix.type() <= QTransform::TxTranslate) { - drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), pixmap, &s->penData); + + if (pixmap.data->classId() == QPixmapData::RasterClass) { + const QImage &image = ((QRasterPixmapData *) pixmap.data)->image; + if (image.depth() == 1) { + Q_D(QRasterPaintEngine); + QRasterPaintEngineState *s = state(); + if (s->matrix.type() <= QTransform::TxTranslate) { + drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); + } else { + drawImage(pos, d->rasterBuffer->colorizeBitmap(image, s->pen.color())); + } } else { - drawImage(pos, d->rasterBuffer->colorizeBitmap(IMAGE_FROM_PIXMAP(pixmap), s->pen.color())); + QRasterPaintEngine::drawImage(pos, image); } } else { - QRasterPaintEngine::drawImage(pos, IMAGE_FROM_PIXMAP(pixmap)); + const QImage image = pixmap.toImage(); + if (pixmap.depth() == 1) { + Q_D(QRasterPaintEngine); + QRasterPaintEngineState *s = state(); + if (s->matrix.type() <= QTransform::TxTranslate) { + drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); + } else { + drawImage(pos, d->rasterBuffer->colorizeBitmap(image, s->pen.color())); + } + } else { + QRasterPaintEngine::drawImage(pos, image); + } } } @@ -2390,22 +2402,40 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons qDebug() << " - QRasterPaintEngine::drawPixmap(), r=" << r << " sr=" << sr << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth(); #endif - Q_D(QRasterPaintEngine); - QRasterPaintEngineState *s = state(); - - if (pixmap.depth() == 1) { - if (s->matrix.type() <= QTransform::TxTranslate - && r.size() == sr.size() - && r.size() == pixmap.size()) { - ensurePen(); - drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), pixmap, &s->penData); - return; + if (pixmap.data->classId() == QPixmapData::RasterClass) { + const QImage &image = ((QRasterPixmapData *) pixmap.data)->image; + if (image.depth() == 1) { + Q_D(QRasterPaintEngine); + QRasterPaintEngineState *s = state(); + if (s->matrix.type() <= QTransform::TxTranslate + && r.size() == sr.size() + && r.size() == pixmap.size()) { + ensurePen(); + drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); + return; + } else { + drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), sr); + } } else { - drawImage(r, d->rasterBuffer->colorizeBitmap(IMAGE_FROM_PIXMAP(pixmap), - s->pen.color()), sr); + drawImage(r, image, sr); } } else { - drawImage(r, IMAGE_FROM_PIXMAP(pixmap), sr); + const QImage image = pixmap.toImage(); + if (image.depth() == 1) { + Q_D(QRasterPaintEngine); + QRasterPaintEngineState *s = state(); + if (s->matrix.type() <= QTransform::TxTranslate + && r.size() == sr.size() + && r.size() == pixmap.size()) { + ensurePen(); + drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); + return; + } else { + drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), sr); + } + } else { + drawImage(r, image, sr); + } } } @@ -2614,10 +2644,15 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, QRasterPaintEngineState *s = state(); QImage image; - if (pixmap.depth() == 1) - image = d->rasterBuffer->colorizeBitmap(IMAGE_FROM_PIXMAP(pixmap), s->pen.color()); - else - image = IMAGE_FROM_PIXMAP(pixmap); + + if (pixmap.data->classId() == QPixmapData::RasterClass) { + image = ((QRasterPixmapData *) pixmap.data)->image; + } else { + image = pixmap.toImage(); + } + + if (image.depth() == 1) + image = d->rasterBuffer->colorizeBitmap(image, s->pen.color()); if (s->matrix.type() > QTransform::TxTranslate) { QTransform copy = s->matrix; @@ -3650,14 +3685,13 @@ void QRasterPaintEngine::drawBufferSpan(const uint *buffer, int bufsize, } #endif // Q_WS_QWS -void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QPixmap &pm, QSpanData *fg) +void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fg) { Q_ASSERT(fg); if (!fg->blend) return; Q_D(QRasterPaintEngine); - const QImage image = IMAGE_FROM_PIXMAP(pm); Q_ASSERT(image.depth() == 1); const int spanCount = 256; @@ -3665,8 +3699,8 @@ void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QPixmap &pm, QSpan int n = 0; // Boundaries - int w = pm.width(); - int h = pm.height(); + int w = image.width(); + int h = image.height(); int ymax = qMin(qRound(pos.y() + h), d->rasterBuffer->height()); int ymin = qMax(qRound(pos.y()), 0); int xmax = qMin(qRound(pos.x() + w), d->rasterBuffer->width()); diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 0f8060a..26a2b3f 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -256,7 +256,7 @@ private: void init(); void fillRect(const QRectF &rect, QSpanData *data); - void drawBitmap(const QPointF &pos, const QPixmap &image, QSpanData *fill); + void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill); void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti); -- cgit v0.12 From b78d46626aa3fd34009063fc0d870cf528119af5 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 1 Apr 2009 10:11:40 +0200 Subject: Fixes: Calling repaint() during a top-level resize RevBy: bnilsen Task: 249394 Details: When going through the backingstore a repaint in a toplevel resize should just discard the repaint() as it will repaint shortly after anyway. This is in line with the implementation of update(). --- src/gui/kernel/qwidget.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index f92d660..669c7a1 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -9417,11 +9417,13 @@ void QWidget::repaint(const QRect &rect) if (!isVisible() || !updatesEnabled() || rect.isEmpty()) return; - QTLWExtra *tlwExtra = !d->paintOnScreen() ? window()->d_func()->maybeTopData() : 0; - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; - tlwExtra->backingStore->markDirty(rect, this, true); - tlwExtra->inRepaint = false; + if (hasBackingStoreSupport()) { + QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { + tlwExtra->inRepaint = true; + tlwExtra->backingStore->markDirty(rect, this, true); + tlwExtra->inRepaint = false; + } } else { d->repaint_sys(rect); } @@ -9444,11 +9446,13 @@ void QWidget::repaint(const QRegion &rgn) if (!isVisible() || !updatesEnabled() || rgn.isEmpty()) return; - QTLWExtra *tlwExtra = !d->paintOnScreen() ? window()->d_func()->maybeTopData() : 0; - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; - tlwExtra->backingStore->markDirty(rgn, this, true); - tlwExtra->inRepaint = false; + if (hasBackingStoreSupport()) { + QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { + tlwExtra->inRepaint = true; + tlwExtra->backingStore->markDirty(rgn, this, true); + tlwExtra->inRepaint = false; + } } else { d->repaint_sys(rgn); } -- cgit v0.12 From e0560bcaa3703fafccc21dd709731341a123a0e4 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 2 Apr 2009 11:27:57 +0200 Subject: Works around a crash in q3richtext. Full fix will potentially break other code and is thus avoided Task-number: 248992 Reviewed-by: Trond --- src/qt3support/text/q3richtext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt3support/text/q3richtext.cpp b/src/qt3support/text/q3richtext.cpp index c058e37..e508001 100644 --- a/src/qt3support/text/q3richtext.cpp +++ b/src/qt3support/text/q3richtext.cpp @@ -4895,7 +4895,8 @@ void Q3TextParagraph::drawString(QPainter &painter, const QString &str, int star bool extendRight = false; bool extendLeft = false; bool selWrap = (real_selEnd == length()-1 && n && n->hasSelection(it.key())); - if (selWrap || this->str->at(real_selEnd).lineStart) { + if (selWrap + || ((real_selEnd < this->str->length()) && this->str->at(real_selEnd).lineStart)) { extendRight = (fullSelectionWidth != 0); if (!extendRight && !rightToLeft) tmpw += painter.fontMetrics().width(QLatin1Char(' ')); -- cgit v0.12 From 974680679b03c668ffce87bd50b5dacf44b0fa22 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 3 Apr 2009 11:16:40 +0200 Subject: Adds a few \warnings to the docs on do-not-use-for-performance-reasons Reviewed-by: Trond --- src/gui/graphicsview/qgraphicsproxywidget.cpp | 8 ++++++-- src/gui/image/qimage.cpp | 12 +++++++++++- src/gui/image/qpixmap.cpp | 18 ++++++++++++++++-- src/gui/painting/qpainter.cpp | 10 ++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 1d2721b..e660879 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -177,6 +177,10 @@ QT_BEGIN_NAMESPACE while the widget is embedded. In this state, the widget may differ slightly in behavior from when it is not embedded. + \warning This class is provided for convenience when bridging + QWidgets and QGraphicsItems, it should not be used for + high-performance scenarios. + \sa QGraphicsScene::addWidget(), QGraphicsWidget */ @@ -1033,7 +1037,7 @@ void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event) if (receiver != d->dragDropWidget) { // Try to enter before we leave QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers()); - dragEnter.setDropAction(event->proposedAction()); + dragEnter.setDropAction(event->proposedAction()); QApplication::sendEvent(receiver, &dragEnter); event->setAccepted(dragEnter.isAccepted()); event->setDropAction(dragEnter.dropAction()); @@ -1431,7 +1435,7 @@ int QGraphicsProxyWidget::type() const Creates a proxy widget for the given \a child of the widget contained in this proxy. - + This function makes it possible to aquire proxies for non top-level widgets. For instance, you can embed a dialog, and then transform only one of its widgets. diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index dc236e4..6945ef8 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -114,7 +114,7 @@ Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0; typedef void (*_qt_image_cleanup_hook_64)(qint64); Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0; -static QImage rotated90(const QImage &src); +static QImage rotated90(const QImage &src);= static QImage rotated180(const QImage &src); static QImage rotated270(const QImage &src); @@ -3607,6 +3607,9 @@ int QImage::pixelIndex(int x, int y) const If the \a position is not valid, the results are undefined. + \warning This function is expensive when used for massive pixel + manipulations. + \sa setPixel(), valid(), {QImage#Pixel Manipulation}{Pixel Manipulation} */ @@ -5581,6 +5584,8 @@ bool QImage::isDetached() const Use one of the composition mods in QPainter::CompositionMode instead. + \warning This function is expensive. + \sa alphaChannel(), {QImage#Image Transformations}{Image Transformations}, {QImage#Image Formats}{Image Formats} */ @@ -5663,6 +5668,11 @@ void QImage::setAlphaChannel(const QImage &alphaChannel) \l{QPixmap::}{alphaChannel()}, which works in the same way as this function on QPixmaps. + Most usecases for this function can be replaced with QPainter and + using composition modes. + + \warning This is an expensive function. + \sa setAlphaChannel(), hasAlphaChannel(), {QPixmap#Pixmap Information}{Pixmap}, {QImage#Image Transformations}{Image Transformations} diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 8684a1b..efb8260 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -674,7 +674,7 @@ void QPixmap::resize_helper(const QSize &s) pixels black. The effect of this function is undefined when the pixmap is being painted on. - This is potentially an expensive operation. + \warning This is potentially an expensive operation. \sa mask(), {QPixmap#Pixmap Transformations}{Pixmap Transformations}, QBitmap @@ -1380,6 +1380,12 @@ void QPixmap::deref() If the given \a size is empty, this function returns a null pixmap. + + In some cases it can be more beneficial to draw the pixmap to a + painter with a scale set rather than scaling the pixmap. This is + the case when the painter is for instance based on OpenGL or when + the scale factor changes rapidly. + \sa isNull(), {QPixmap#Pixmap Transformations}{Pixmap Transformations} @@ -1751,6 +1757,10 @@ int QPixmap::metric(PaintDeviceMetric metric) const The effect of this function is undefined when the pixmap is being painted on. + \warning This is potentially an expensive operation. Most usecases + for this function are covered by QPainter and compositionModes + which will normally execute faster. + \sa alphaChannel(), {QPixmap#Pixmap Transformations}{Pixmap Transformations} */ @@ -1793,6 +1803,9 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel) \image alphachannelimage.png The pixmap and channelImage QPixmaps + \warning This is an expensive operation. The alpha channel of the + pixmap is extracted dynamically from the pixeldata. + \sa setAlphaChannel(), {QPixmap#Pixmap Information}{Pixmap Information} */ @@ -1814,7 +1827,8 @@ QPaintEngine *QPixmap::paintEngine() const Extracts a bitmap mask from the pixmap's alphachannel. - This is potentially an expensive operation. + \warning This is potentially an expensive operation. The mask of + the pixmap is extracted dynamically from the pixeldata. \sa setMask(), {QPixmap#Pixmap Information}{Pixmap Information} */ diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index b2f0ac4..2beb8c2 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2371,6 +2371,11 @@ void QPainter::setClipping(bool enable) Returns the currently set clip region. Note that the clip region is given in logical coordinates. + \warning QPainter does not store the combined clip explicitly as + this is handled by the underlying QPaintEngine, so the path is + recreated on demand and transformed to the current logical + coordinate system. This is potentially an expensive operation. + \sa setClipRegion(), clipPath(), setClipping() */ @@ -2486,6 +2491,11 @@ extern QPainterPath qt_regionToPath(const QRegion ®ion); Returns the currently clip as a path. Note that the clip path is given in logical coordinates. + \warning QPainter does not store the combined clip explicitly as + this is handled by the underlying QPaintEngine, so the path is + recreated on demand and transformed to the current logical + coordinate system. This is potentially an expensive operation. + \sa setClipPath(), clipRegion(), setClipping() */ QPainterPath QPainter::clipPath() const -- cgit v0.12 From 640f2c732c6fd76866cd7e601a9140dbe7849e6f Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Mon, 6 Apr 2009 17:18:22 +0200 Subject: BT: Fix regression when tooltips dissappear suddenly in Unified toolbar QWidget::childAt() makes some assumptions about its children (they are all contained in its geometry). This does not hold up when using the unified toolbar because the toolbar ends up in the "non-client" area. So, when dispatching an enter/leave event in tooltip show, we end up dispatching to the wrong widgets and that results in the tooltip cleverly thinking that it needs to hide itself because we've left the widget that needs the tooltip. I've special cased this by just having a "native" mapFromParent() that is only called for on the mac, though there is nothing that is limiting this from being called on other platfroms. Also QWidget::mapFromParent() probably needs to be looked at at some point. Task-number: 248048 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qt_mac_p.h | 1 + src/gui/kernel/qwidget.cpp | 24 ++++++++++++++++++++++-- src/gui/kernel/qwidget_mac.mm | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h index 3aec23f..e65492d 100644 --- a/src/gui/kernel/qt_mac_p.h +++ b/src/gui/kernel/qt_mac_p.h @@ -233,6 +233,7 @@ extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.mm extern OSViewRef qt_mac_nativeview_for(const QWidget *); //qwidget_mac.mm +extern QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt); //qwidget_mac.mm #ifdef check # undef check diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 669c7a1..31fed5e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -66,6 +66,7 @@ #ifdef Q_WS_MAC # include "qt_mac_p.h" # include "qt_cocoa_helpers_mac_p.h" +# include "qmainwindow.h" #endif #if defined(Q_WS_QWS) # include "qwsdisplay_qws.h" @@ -8966,17 +8967,36 @@ QWidget *QWidget::childAt(const QPoint &p) const QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const { Q_Q(const QWidget); - if (!q->rect().contains(p)) +#ifdef Q_WS_MAC + bool includeFrame = q->isWindow() && qobject_cast(q) + && static_cast(q)->unifiedTitleAndToolBarOnMac(); +#endif + + if ( +#ifdef Q_WS_MAC + !includeFrame && +#endif + !q->rect().contains(p)) return 0; + for (int i = children.size(); i > 0 ;) { --i; QWidget *w = qobject_cast(children.at(i)); - if (w && !w->isWindow() && !w->isHidden() && w->geometry().contains(p)) { + if (w && !w->isWindow() && !w->isHidden() + && (w->geometry().contains(p) +#ifdef Q_WS_MAC + || (includeFrame && w->geometry().contains(qt_mac_nativeMapFromParent(w, p))) +#endif + )) { if (ignoreChildrenInDestructor && w->data->in_destructor) continue; if (w->testAttribute(Qt::WA_TransparentForMouseEvents)) continue; QPoint childPoint = w->mapFromParent(p); +#ifdef Q_WS_MAC + if (includeFrame && !w->geometry().contains(p)) + childPoint = qt_mac_nativeMapFromParent(w, p); +#endif if (QWidget *t = w->d_func()->childAt_helper(childPoint, ignoreChildrenInDestructor)) return t; // if WMouseNoMask is set the widget mask is ignored, if diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index f2a532f..5432c55 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3274,6 +3274,20 @@ void QWidgetPrivate::show_sys() qt_event_request_window_change(q); } + +QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt) +{ +#ifndef QT_MAC_USE_COCOA + CGPoint nativePoint = CGPointMake(pt.x(), pt.y()); + HIViewConvertPoint(&nativePoint, qt_mac_nativeview_for(child->parentWidget()), + qt_mac_nativeview_for(child)); +#else + NSPoint nativePoint = [qt_mac_nativeview_for(child) convertPoint:NSMakePoint(pt.x(), pt.y()) fromView:qt_mac_nativeview_for(child->parentWidget())]; +#endif + return QPoint(nativePoint.x, nativePoint.y); +} + + void QWidgetPrivate::hide_sys() { Q_Q(QWidget); -- cgit v0.12 From d2b10ebfa77a78687389d08627ab0b14cf48fb21 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Tue, 7 Apr 2009 09:28:20 +0200 Subject: Compile. Looks like a typo. Reviewed-by: Bradley T. Hughes --- src/gui/image/qimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 6945ef8..c7a20db 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -114,7 +114,7 @@ Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0; typedef void (*_qt_image_cleanup_hook_64)(qint64); Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0; -static QImage rotated90(const QImage &src);= +static QImage rotated90(const QImage &src); static QImage rotated180(const QImage &src); static QImage rotated270(const QImage &src); -- cgit v0.12 From e60d3622607cbf1b3583a205fc9e3e019a555b45 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 7 Apr 2009 07:42:30 +0200 Subject: QLocalSocket will disconnect 30 seconds after a successful delayed connect When the connection is established, the socket notifier is deleted, but not the connection timer, so the opened connection will be closed after 30 seconds. Task-number: none Reviewed-by: Andreas Reviewed-by: Thiago --- src/network/socket/qlocalsocket_p.h | 1 + src/network/socket/qlocalsocket_unix.cpp | 28 +++++++++++++++------------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index dd48d0a..781d3da 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -192,6 +192,7 @@ public: void _q_error(QAbstractSocket::SocketError newError); void _q_connectToSocket(); void _q_abortConnectionAttempt(); + void cancelDelayedConnect(); QSocketNotifier *delayConnect; QTimer *connectTimer; int connectingSocket; diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index a375e9b..38643f1 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -322,11 +322,8 @@ void QLocalSocketPrivate::_q_connectToSocket() } // connected! - if (delayConnect) { - delayConnect->setEnabled(false); - delete delayConnect; - delayConnect = 0; - } + cancelDelayedConnect(); + serverName = connectingName; fullServerName = connectingPathName; if (unixSocket.setSocketDescriptor(connectingSocket, @@ -373,6 +370,18 @@ void QLocalSocketPrivate::_q_abortConnectionAttempt() q->close(); } +void QLocalSocketPrivate::cancelDelayedConnect() +{ + if (delayConnect) { + delayConnect->setEnabled(false); + delete delayConnect; + delayConnect = 0; + connectTimer->stop(); + delete connectTimer; + connectTimer = 0; + } +} + quintptr QLocalSocket::socketDescriptor() const { Q_D(const QLocalSocket); @@ -419,14 +428,7 @@ void QLocalSocket::close() { Q_D(QLocalSocket); d->unixSocket.close(); - if (d->delayConnect) { - d->delayConnect->setEnabled(false); - delete d->delayConnect; - d->delayConnect = 0; - d->connectTimer->stop(); - delete d->connectTimer; - d->connectTimer = 0; - } + d->cancelDelayedConnect(); if (d->connectingSocket != -1) ::close(d->connectingSocket); d->connectingSocket = -1; -- cgit v0.12 From b9d6ecc1dbe5791fec6fb06de3be06186b485420 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Tue, 7 Apr 2009 09:51:31 +0200 Subject: BT: Compile without QT3SUPPORT Reviewed-by: ogoffart --- src/gui/styles/qgtkstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index 6354ce7..b569b5c 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -2634,7 +2634,7 @@ void QGtkStyle::drawControl(ControlElement element, QColor disabledTextColor = QColor(gdkDText.red>>8, gdkDText.green>>8, gdkDText.blue>>8); if (resolve_mask & (1 << QPalette::ButtonText)) { textColor = option->palette.buttonText().color(); - disabledTextColor = option->palette.brush(QPalette::Disabled, QPalette::ButtonText);; + disabledTextColor = option->palette.brush(QPalette::Disabled, QPalette::ButtonText).color(); } QColor highlightedTextColor = QColor(gdkHText.red>>8, gdkHText.green>>8, gdkHText.blue>>8); -- cgit v0.12 From 730b936b53633891e2b8c505a3ff4c93209e7ae8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 6 Apr 2009 17:06:28 +0200 Subject: fix QMAKE_VAR_FIRST_ expansion in compiler flags doesn't seem to be a terribly popular feature, given that nobody noticed this yet ... --- qmake/generators/makefile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 3e5452e..67e5bfb 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1492,7 +1492,7 @@ MakefileGenerator::replaceExtraCompilerVariables(const QString &orig_var, const val += project->values(varname); } if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_VAR_FIRST_"))) { - const QString varname = var.mid(12); + const QString varname = var.mid(16); val += project->first(varname); } -- cgit v0.12 From 3279b07302fde0eb14f9b197c9ad2e14d512817e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 6 Apr 2009 19:39:03 +0200 Subject: make shadow builds with default moc/ui dirs work again append the source dir to the include path, but only after the dirs with the generated files. this seems to have worked before only accidentally: the unqualified default dirs were expanded to the source dir instead of the build dir, but the build dir is added implicitly by default, so things magically worked. now that we qualify the moc/ui dirs, projects relying on the strange side effect suddenly break. we should probably add the source dir to the include path by default, but this coupling to uic/moc is closer to the historical behavior and thus should be safer. Reviewed-by: mariusSO --- mkspecs/features/include_source_dir.prf | 1 + mkspecs/features/moc.prf | 7 +++++++ mkspecs/features/uic.prf | 7 +++++++ 3 files changed, 15 insertions(+) create mode 100644 mkspecs/features/include_source_dir.prf diff --git a/mkspecs/features/include_source_dir.prf b/mkspecs/features/include_source_dir.prf new file mode 100644 index 0000000..8794998 --- /dev/null +++ b/mkspecs/features/include_source_dir.prf @@ -0,0 +1 @@ +!equals(_PRO_FILE_PWD_, $$OUT_PWD):INCLUDEPATH *= . diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index f1dcf37..f18d462 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -66,6 +66,13 @@ win32:moc_dir_short ~= s,^.:,/, contains(moc_dir_short, ^[/\\\\].*):INCLUDEPATH += $$MOC_DIR else:INCLUDEPATH += $$OUT_PWD/$$MOC_DIR +# Backwards compatibility: Make shadow builds with default MOC_DIR work +# if the user did not add the source dir explicitly. +equals(MOC_DIR, .) { + CONFIG -= include_source_dir + CONFIG = include_source_dir $$CONFIG +} + #auto depend on moc unix:!no_mocdepend { moc_source.depends += $$first(QMAKE_MOC) diff --git a/mkspecs/features/uic.prf b/mkspecs/features/uic.prf index c7b1686..0c7fb1b 100644 --- a/mkspecs/features/uic.prf +++ b/mkspecs/features/uic.prf @@ -39,6 +39,13 @@ win32:ui_dir_short ~= s,^.:,/, contains(ui_dir_short, ^[/\\\\].*):INCLUDEPATH += $$UI_HEADERS_DIR else:INCLUDEPATH += $$OUT_PWD/$$UI_HEADERS_DIR +# Backwards compatibility: Make shadow builds with default UI_DIR work +# if the user did not add the source dir explicitly. +equals(UI_DIR, .) { + CONFIG -= include_source_dir + CONFIG = include_source_dir $$CONFIG +} + uic3 { isEmpty(FORMS3) { UIC3_FORMS = FORMS -- cgit v0.12 From d8f76432c3937690c37972136c02a5a264bc941f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 7 Apr 2009 11:26:12 +0200 Subject: qmake: additional compiler options were written twice into vcproj files In the function initCompilerTool we handled QMAKE_CXXFLAGS twice for every configuration (debug / release). The call of parseOptions before the if clause is enough. Reviewed-by: mariusSO --- qmake/generators/win32/msvc_vcproj.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 08159b0..8901289 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1030,7 +1030,6 @@ void VcprojGenerator::initCompilerTool() conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); if(project->isActiveConfig("debug")){ // Debug version - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_DEBUG")); if((projectTarget == Application) || (projectTarget == StaticLib)) conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DBG")); @@ -1038,7 +1037,6 @@ void VcprojGenerator::initCompilerTool() conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLLDBG")); } else { // Release version - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_RELEASE")); conf.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; conf.compiler.PreprocessorDefinitions += "NDEBUG"; -- cgit v0.12