diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-03-09 23:12:48 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-03-09 23:12:48 (GMT) |
commit | 858e01e954ac9f3203ada6b61b47c418cc4b0a82 (patch) | |
tree | 80116a18d608b5be90e728cf9698b34651fda1d5 | |
parent | 7f2836aba3334dc4c9da5cc5f57889c11a2bd85c (diff) | |
parent | 40c018c7a0c8e95fcf928a6c1ce5301f16ffa5e3 (diff) | |
download | Qt-858e01e954ac9f3203ada6b61b47c418cc4b0a82.zip Qt-858e01e954ac9f3203ada6b61b47c418cc4b0a82.tar.gz Qt-858e01e954ac9f3203ada6b61b47c418cc4b0a82.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
44 files changed, 1444 insertions, 347 deletions
diff --git a/doc/src/declarative/qdeclarativemodels.qdoc b/doc/src/declarative/qdeclarativemodels.qdoc index c0e028e..f7d1a73 100644 --- a/doc/src/declarative/qdeclarativemodels.qdoc +++ b/doc/src/declarative/qdeclarativemodels.qdoc @@ -208,7 +208,7 @@ QStringList provides the contents of the list via the \e modelData role: QStringList dataList; dataList.append("Fred"); dataList.append("Ginger"); -dataList.appenf("Skipper"); +dataList.append("Skipper"); QDeclarativeContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(&dataList)); diff --git a/doc/src/examples/svgalib.qdoc b/doc/src/examples/svgalib.qdoc index cf6512c..9142112 100644 --- a/doc/src/examples/svgalib.qdoc +++ b/doc/src/examples/svgalib.qdoc @@ -43,9 +43,6 @@ \example qws/svgalib \title Accelerated Graphics Driver Example - \warning This example was designed to work with Qt 4.4 and will not work - with current versions of Qt. It will be removed from Qt 4.7. - The Accelerated Graphics Driver example shows how you can write your own accelerated graphics driver and \l {add your graphics driver to Qt for Embedded Linux}. In \l{Qt for Embedded Linux}, diff --git a/examples/qws/svgalib/README b/examples/qws/svgalib/README index 0b2831f..227c066 100644 --- a/examples/qws/svgalib/README +++ b/examples/qws/svgalib/README @@ -1,5 +1,9 @@ -This is the SVGA screen driver plugin example from Qt 4.4. The code does -not compile with Qt 4.5, because the internal graphics engine has changed. +This is the SVGA screen driver plugin example for QWS. -This is unsupported code, provided for convenience in case there is -interest in porting it to Qt 4.5. +You may need to set the SVGALIB_DEFAULT_MODE environment +variable. These values have been confirmed to work on one specific +machine using svgalib 1.4.3: 18, 24, 34, 35, 36 + +There is a bug in the example causing missing updates in 8-bit mode +(e.g. modes 10 and 12). Fixing this bug is left as an exercise for the +reader. diff --git a/examples/qws/svgalib/svgalibpaintdevice.cpp b/examples/qws/svgalib/svgalibpaintdevice.cpp index 090311f..86613d2 100644 --- a/examples/qws/svgalib/svgalibpaintdevice.cpp +++ b/examples/qws/svgalib/svgalibpaintdevice.cpp @@ -48,7 +48,7 @@ SvgalibPaintDevice::SvgalibPaintDevice(QWidget *w) : QCustomRasterPaintDevice(w) { - pengine = new SvgalibPaintEngine; + pengine = new SvgalibPaintEngine(this); } SvgalibPaintDevice::~SvgalibPaintDevice() diff --git a/examples/qws/svgalib/svgalibpaintengine.cpp b/examples/qws/svgalib/svgalibpaintengine.cpp index 8713863..59740da 100644 --- a/examples/qws/svgalib/svgalibpaintengine.cpp +++ b/examples/qws/svgalib/svgalibpaintengine.cpp @@ -45,7 +45,8 @@ #include <vga.h> #include <vgagl.h> -SvgalibPaintEngine::SvgalibPaintEngine() +SvgalibPaintEngine::SvgalibPaintEngine(QPaintDevice *device) + : QRasterPaintEngine(device) { } @@ -61,7 +62,7 @@ bool SvgalibPaintEngine::begin(QPaintDevice *dev) simplePen = true; brush = Qt::NoBrush; simpleBrush = true; - matrix = QMatrix(); + matrix = QTransform(); simpleMatrix = true; setClip(QRect(0, 0, device->width(), device->height())); opaque = true; @@ -81,54 +82,52 @@ bool SvgalibPaintEngine::end() //! [1] //! [2] -void SvgalibPaintEngine::updateState(const QPaintEngineState &state) +void SvgalibPaintEngine::updateState() { - QPaintEngine::DirtyFlags flags = state.state(); + QRasterPaintEngineState *s = state(); - if (flags & DirtyTransform) { - matrix = state.matrix(); + if (s->dirty & DirtyTransform) { + matrix = s->matrix; simpleMatrix = (matrix.m12() == 0 && matrix.m21() == 0); } - if (flags & DirtyPen) { - pen = state.pen(); + if (s->dirty & DirtyPen) { + pen = s->pen; simplePen = (pen.width() == 0 || pen.widthF() <= 1) && (pen.style() == Qt::NoPen || pen.style() == Qt::SolidLine) && (pen.color().alpha() == 255); } - if (flags & DirtyBrush) { - brush = state.brush(); + if (s->dirty & DirtyBrush) { + brush = s->brush; simpleBrush = (brush.style() == Qt::SolidPattern || brush.style() == Qt::NoBrush) && (brush.color().alpha() == 255); } - if (flags & DirtyClipRegion) - setClip(state.clipRegion()); + if (s->dirty & DirtyClipRegion) + setClip(s->clipRegion); - if (flags & DirtyClipEnabled) { - clipEnabled = state.isClipEnabled(); + if (s->dirty & DirtyClipEnabled) { + clipEnabled = s->isClipEnabled(); updateClip(); } - if (flags & DirtyClipPath) { + if (s->dirty & DirtyClipPath) { setClip(QRegion()); simpleClip = false; } - if (flags & DirtyCompositionMode) { - const QPainter::CompositionMode m = state.compositionMode(); + if (s->dirty & DirtyCompositionMode) { + const QPainter::CompositionMode m = s->composition_mode; sourceOver = (m == QPainter::CompositionMode_SourceOver); } - if (flags & DirtyOpacity) - opaque = (state.opacity() == 256); + if (s->dirty & DirtyOpacity) + opaque = (s->opacity == 256); - if (flags & DirtyHints) - aliased = !(state.renderHints() & QPainter::Antialiasing); - - QRasterPaintEngine::updateState(state); + if (s->dirty & DirtyHints) + aliased = !(s->flags.antialiased); } //! [2] diff --git a/examples/qws/svgalib/svgalibpaintengine.h b/examples/qws/svgalib/svgalibpaintengine.h index f43d201..27b77ee 100644 --- a/examples/qws/svgalib/svgalibpaintengine.h +++ b/examples/qws/svgalib/svgalibpaintengine.h @@ -48,12 +48,12 @@ class SvgalibPaintEngine : public QRasterPaintEngine { public: - SvgalibPaintEngine(); + SvgalibPaintEngine(QPaintDevice *device); ~SvgalibPaintEngine(); bool begin(QPaintDevice *device); bool end(); - void updateState(const QPaintEngineState &state); + void updateState(); void drawRects(const QRect *rects, int rectCount); private: @@ -64,7 +64,7 @@ private: bool simplePen; QBrush brush; bool simpleBrush; - QMatrix matrix; + QTransform matrix; bool simpleMatrix; QRegion clip; bool clipEnabled; diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 76ebcb4..55df063 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -101,7 +101,7 @@ private: qreal m_height; }; -class QDeclarativeItemPrivate : public QGraphicsItemPrivate +class Q_DECLARATIVE_EXPORT QDeclarativeItemPrivate : public QGraphicsItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeItem) @@ -259,7 +259,7 @@ public: static int consistentTime; static QTime currentTime(); - static void Q_DECLARATIVE_EXPORT setConsistentTime(int t); + static void setConsistentTime(int t); static void start(QTime &); static int elapsed(QTime &); static int restart(QTime &); diff --git a/src/declarative/graphicsitems/qdeclarativeparticles.cpp b/src/declarative/graphicsitems/qdeclarativeparticles.cpp index ec0bf6c..593c80a 100644 --- a/src/declarative/graphicsitems/qdeclarativeparticles.cpp +++ b/src/declarative/graphicsitems/qdeclarativeparticles.cpp @@ -1263,7 +1263,7 @@ void QDeclarativeParticlesPainter::paint(QPainter *p, const QStyleOptionGraphics const int myY = y() + parentItem()->y(); #if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) - QVarLengthArray<QPainter::Fragment, 256> pixmapData; + QVarLengthArray<QPainter::PixmapFragment, 256> pixmapData; #else QVarLengthArray<QDrawPixmaps::Data, 256> pixmapData; #endif diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 1145235..78184a9 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -679,16 +679,20 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto d->defaultItemHeight = indexRowSizeHint(topLeft); bool sizeChanged = false; if (topViewIndex != -1) { - if (topLeft == bottomRight) { + if (topLeft.row() == bottomRight.row()) { int oldHeight = d->itemHeight(topViewIndex); d->invalidateHeightCache(topViewIndex); sizeChanged = (oldHeight != d->itemHeight(topViewIndex)); + if (topLeft.column() == 0) + d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft); } else { int bottomViewIndex = d->viewIndex(bottomRight); for (int i = topViewIndex; i <= bottomViewIndex; ++i) { int oldHeight = d->itemHeight(i); d->invalidateHeightCache(i); sizeChanged |= (oldHeight != d->itemHeight(i)); + if (topLeft.column() == 0) + d->viewItems[i].hasChildren = d->hasVisibleChildren(d->viewItems.at(i).index); } } } diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp index d76c709..a62f06b 100644 --- a/src/gui/painting/qdrawutil.cpp +++ b/src/gui/painting/qdrawutil.cpp @@ -1081,7 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs, according to the \a margins structure. */ -typedef QVarLengthArray<QPainter::Fragment, 16> QPixmapFragmentsArray; +typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray; /*! \since 4.6 @@ -1102,7 +1102,7 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) { - QPainter::Fragment d; + QPainter::PixmapFragment d; d.opacity = 1.0; d.rotation = 0.0; diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 98762f0..1fd622d 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -970,8 +970,8 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con fill(path, brush); } -void QPaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, QPainter::FragmentHints /*hints*/) +void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/) { qreal oldOpacity = state()->opacity; QTransform oldTransform = state()->matrix; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 2401b94..6c654bd 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -197,7 +197,8 @@ public: virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints); + virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QFlags<QPainter::PixmapFragmentHint> hints); virtual void updateState(const QPaintEngineState &state); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 9d83718..c5ce76c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7994,10 +7994,11 @@ start_lengthVariant: for (int i = 0; i < textLayout.lineCount(); i++) { QTextLine line = textLayout.lineAt(i); + qreal advance = textLayout.engine()->lines[i].textAdvance.toReal(); if (tf & Qt::AlignRight) - xoff = r.width() - line.naturalTextWidth(); + xoff = r.width() - advance; else if (tf & Qt::AlignHCenter) - xoff = (r.width() - line.naturalTextWidth())/2; + xoff = (r.width() - advance)/2; line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff)); } @@ -8914,11 +8915,11 @@ QTransform QPainter::combinedTransform() const This function is potentially faster than multiple calls to drawPixmap(), since the backend can optimize state changes. - \sa QPainter::Fragment, QPainter::FragmentHint + \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint */ -void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, FragmentHints hints) +void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, PixmapFragmentHints hints) { Q_D(QPainter); @@ -8959,7 +8960,7 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, /*! \since 4.7 - \class QPainter::Fragment + \class QPainter::PixmapFragment \brief This class is used in conjunction with the QPainter::drawPixmapFragments() function to specify how a pixmap, or @@ -8980,73 +8981,73 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, /*! \since 4.7 - This is a convenience function that returns a QPainter::Fragment that is + This is a convenience function that returns a QPainter::PixmapFragment that is initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a rotation, \a opacity parameters. */ -QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF &sourceRect, +QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX, qreal scaleY, qreal rotation, qreal opacity) { - Fragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), - sourceRect.height(), scaleX, scaleY, rotation, opacity}; + PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), + sourceRect.height(), scaleX, scaleY, rotation, opacity}; return fragment; } /*! - \variable QPainter::Fragment::x + \variable QPainter::PixmapFragment::x \brief the x coordinate of center point in the target rectangle. */ /*! - \variable QPainter::Fragment::y + \variable QPainter::PixmapFragment::y \brief the y coordinate of the center point in the target rectangle. */ /*! - \variable QPainter::Fragment::sourceLeft + \variable QPainter::PixmapFragment::sourceLeft \brief the left coordinate of the source rectangle. */ /*! - \variable QPainter::Fragment::sourceTop + \variable QPainter::PixmapFragment::sourceTop \brief the top coordinate of the source rectangle. */ /*! - \variable QPainter::Fragment::width + \variable QPainter::PixmapFragment::width \brief the width of the source rectangle and is used to calculate the width of the target rectangle. */ /*! - \variable QPainter::Fragment::height + \variable QPainter::PixmapFragment::height \brief the height of the source rectangle and is used to calculate the height of the target rectangle. */ /*! - \variable QPainter::Fragment::scaleX + \variable QPainter::PixmapFragment::scaleX \brief the horizontal scale of the target rectangle. */ /*! - \variable QPainter::Fragment::scaleY + \variable QPainter::PixmapFragment::scaleY \brief the vertical scale of the target rectangle. */ /*! - \variable QPainter::Fragment::rotation + \variable QPainter::PixmapFragment::rotation \brief the rotation of the target rectangle in degrees. The target rectangle is rotated after it has been scaled. */ /*! - \variable QPainter::Fragment::opacity + \variable QPainter::PixmapFragment::opacity \brief the opacity of the target rectangle, where 0.0 is fully transparent and 1.0 is fully opaque. @@ -9055,12 +9056,12 @@ QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF & /*! \since 4.7 - \enum QPainter::FragmentHint + \enum QPainter::PixmapFragmentHint \value OpaqueHint Indicates that the pixmap fragments to be drawn are opaque. Opaque fragments are potentially faster to draw. - \sa QPainter::drawPixmapFragments(), QPainter::Fragment + \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment */ void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation) diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index bcb0b50..443925b 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -99,7 +99,7 @@ public: Q_DECLARE_FLAGS(RenderHints, RenderHint) - class Fragment { + class PixmapFragment { public: qreal x; qreal y; @@ -111,16 +111,16 @@ public: qreal scaleY; qreal rotation; qreal opacity; - static Fragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, + static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX = 1, qreal scaleY = 1, qreal rotation = 0, qreal opacity = 1); }; - enum FragmentHint { + enum PixmapFragmentHint { OpaqueHint = 0x01 }; - Q_DECLARE_FLAGS(FragmentHints, FragmentHint) + Q_DECLARE_FLAGS(PixmapFragmentHints, PixmapFragmentHint) QPainter(); explicit QPainter(QPaintDevice *); @@ -375,8 +375,8 @@ public: inline void drawPixmap(const QRect &r, const QPixmap &pm); inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm); - void drawPixmapFragments(const Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, FragmentHints hints = 0); + void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, PixmapFragmentHints hints = 0); void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags = Qt::AutoColor); diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index f36cbd2..5054b66 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -382,6 +382,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine QFixed y; QFixed width; QFixed textWidth; + QFixed textAdvance; int from; signed int length : 29; mutable uint justified : 1; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index af91603..cc6793d 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1875,6 +1875,7 @@ void QTextLine::layout_helper(int maxGlyphs) line.textWidth += lbh.softHyphenWidth; } + line.textAdvance = line.textWidth; line.textWidth += lbh.rightBearing; goto found; @@ -1885,6 +1886,7 @@ void QTextLine::layout_helper(int maxGlyphs) } LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); + line.textAdvance = line.textWidth; line.textWidth += lbh.rightBearing; found: diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 8eb72b0..2b5f2f4 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1641,7 +1641,8 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp s->matrix = old; } -void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints) +void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints) { Q_D(QGL2PaintEngineEx); // Use fallback for extended composition modes. @@ -1655,9 +1656,9 @@ void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, } -void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::Fragment *fragments, +void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, - QPainter::FragmentHints hints) + QPainter::PixmapFragmentHints hints) { GLfloat dx = 1.0f / pixmap.size().width(); GLfloat dy = 1.0f / pixmap.size().height(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 5d3608b..ed8fbbc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -125,7 +125,8 @@ public: virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints); + virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); @@ -196,7 +197,8 @@ public: void fill(const QVectorPath &path); void stroke(const QVectorPath &path, const QPen &pen); void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); - void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints); + void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints); void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem, bool includeMatrixInCache); diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 4df894a..2c850c9 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3041,8 +3041,8 @@ void QVGPaintEngine::drawTiledPixmap // (i.e. no opacity), no rotation or scaling, and drawing the full // pixmap rather than parts of the pixmap. Even having just one of // these conditions will improve performance. -void QVGPaintEngine::drawPixmapFragments(const QPainter::Fragment *drawingData, int dataCount, - const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints) +void QVGPaintEngine::drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount, + const QPixmap &pixmap, QFlags<QPainter::PixmapFragmentHint> hints) { #if !defined(QT_SHIVAVG) Q_D(QVGPaintEngine); diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 1203af5..1e7e26c 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -137,7 +137,8 @@ public: void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - void drawPixmapFragments(const QPainter::Fragment *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints); + void drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount, const QPixmap &pixmap, + QFlags<QPainter::PixmapFragmentHint> hints); void drawTextItem(const QPointF &p, const QTextItem &textItem); void drawStaticTextItem(QStaticTextItem *staticTextItem); diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index 4a8fc0b..cb9086c 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -310,7 +310,6 @@ public: { *d_func()->stream << QLatin1String("fill=\"none\" "); *d_func()->stream << QLatin1String("stroke=\"black\" "); - *d_func()->stream << QLatin1String("vector-effect=\"non-scaling-stroke\" "); *d_func()->stream << QLatin1String("stroke-width=\"1\" "); *d_func()->stream << QLatin1String("fill-rule=\"evenodd\" "); *d_func()->stream << QLatin1String("stroke-linecap=\"square\" "); @@ -380,13 +379,10 @@ public: break; } - if (spen.widthF() == 0) { - width = QLatin1String("1"); - stream() << "vector-effect=\"non-scaling-stroke\" "; - } + if (spen.widthF() == 0) + stream() <<"stroke-width=\"1\" "; else - width = QString::number(spen.widthF()); - stream() <<"stroke-width=\""<<width<<"\" "; + stream() <<"stroke-width=\"" << spen.widthF() << "\" "; switch (spen.capStyle()) { case Qt::FlatCap: @@ -983,14 +979,11 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p) { Q_D(QSvgPaintEngine); - *d->stream << "<path " - "fill-rule="; - if (p.fillRule() == Qt::OddEvenFill) - *d->stream << "\"evenodd\" "; - else - *d->stream << "\"nonzero\" "; - - *d->stream << "d=\""; + *d->stream << "<path vector-effect=\"" + << (state->pen().isCosmetic() ? "non-scaling-stroke" : "none") + << "\" fill-rule=\"" + << (p.fillRule() == Qt::OddEvenFill ? "evenodd" : "nonzero") + << "\" d=\""; for (int i=0; i<p.elementCount(); ++i) { const QPainterPath::Element &e = p.elementAt(i); @@ -1038,7 +1031,9 @@ void QSvgPaintEngine::drawPolygon(const QPointF *points, int pointCount, path.lineTo(points[i]); if (mode == PolylineMode) { - stream() << "<polyline fill=\"none\" points=\""; + stream() << "<polyline fill=\"none\" vector-effect=\"" + << (state->pen().isCosmetic() ? "non-scaling-stroke" : "none") + << "\" points=\""; for (int i = 0; i < pointCount; ++i) { const QPointF &pt = points[i]; stream() << pt.x() << ',' << pt.y() << ' '; diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp index cd0e1ac..a29764a 100644 --- a/src/svg/qsvggraphics.cpp +++ b/src/svg/qsvggraphics.cpp @@ -78,33 +78,29 @@ void QSvgAnimation::draw(QPainter *, QSvgExtraStates &) qWarning("<animation> no implemented"); } -static inline QRectF boundsOnStroke(const QPainterPath &path, qreal width) +static inline QRectF boundsOnStroke(QPainter *p, const QPainterPath &path, qreal width) { QPainterPathStroker stroker; stroker.setWidth(width); QPainterPath stroke = stroker.createStroke(path); - return stroke.boundingRect(); + return p->transform().map(stroke).boundingRect(); } -QSvgCircle::QSvgCircle(QSvgNode *parent, const QRectF &rect) +QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect) : QSvgNode(parent), m_bounds(rect) { } -QRectF QSvgCircle::bounds() const +QRectF QSvgEllipse::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_bounds; - else { - QPainterPath path; - path.addRect(m_bounds); - return boundsOnStroke(path, sw); - } + QPainterPath path; + path.addEllipse(m_bounds); + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(path).boundingRect() : boundsOnStroke(p, path, sw); } -void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) +void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); @@ -112,9 +108,8 @@ void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) } QSvgArc::QSvgArc(QSvgNode *parent, const QPainterPath &path) - : QSvgNode(parent), cubic(path) + : QSvgNode(parent), m_path(path) { - m_cachedBounds = path.boundingRect(); } void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) @@ -123,36 +118,12 @@ void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); - p->drawPath(cubic); + p->drawPath(m_path); p->setOpacity(oldOpacity); } revertStyle(p, states); } -QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect) - : QSvgNode(parent), m_bounds(rect) -{ -} - -QRectF QSvgEllipse::bounds() const -{ - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_bounds; - else { - QPainterPath path; - path.addEllipse(m_bounds); - return boundsOnStroke(path, sw); - } -} - -void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) -{ - applyStyle(p, states); - QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); - revertStyle(p, states); -} - QSvgImage::QSvgImage(QSvgNode *parent, const QImage &image, const QRect &bounds) : QSvgNode(parent), m_image(image), @@ -173,7 +144,7 @@ void QSvgImage::draw(QPainter *p, QSvgExtraStates &states) QSvgLine::QSvgLine(QSvgNode *parent, const QLineF &line) - : QSvgNode(parent), m_bounds(line) + : QSvgNode(parent), m_line(line) { } @@ -184,7 +155,7 @@ void QSvgLine::draw(QPainter *p, QSvgExtraStates &states) if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); - p->drawLine(m_bounds); + p->drawLine(m_line); p->setOpacity(oldOpacity); } revertStyle(p, states); @@ -203,19 +174,11 @@ void QSvgPath::draw(QPainter *p, QSvgExtraStates &states) revertStyle(p, states); } -QRectF QSvgPath::bounds() const +QRectF QSvgPath::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) { - if (m_cachedBounds.isNull()) - //m_cachedBounds = m_path.controlPointRect(); - m_cachedBounds = m_path.boundingRect(); - - return m_cachedBounds; - } - else { - return boundsOnStroke(m_path, sw); - } + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(m_path).boundingRect() + : boundsOnStroke(p, m_path, sw); } QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly) @@ -223,15 +186,15 @@ QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly) { } -QRectF QSvgPolygon::bounds() const +QRectF QSvgPolygon::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_poly.boundingRect(); - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().map(m_poly).boundingRect(); + } else { QPainterPath path; path.addPolygon(m_poly); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } @@ -274,15 +237,15 @@ QSvgRect::QSvgRect(QSvgNode *node, const QRectF &rect, int rx, int ry) { } -QRectF QSvgRect::bounds() const +QRectF QSvgRect::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_rect; - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().mapRect(m_rect); + } else { QPainterPath path; path.addRect(m_rect); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } @@ -322,7 +285,7 @@ void QSvgText::setTextArea(const QSizeF &size) m_type = TEXTAREA; } -//QRectF QSvgText::bounds() const {} +//QRectF QSvgText::bounds(QPainter *p, QSvgExtraStates &) const {} void QSvgText::draw(QPainter *p, QSvgExtraStates &states) { @@ -593,80 +556,57 @@ QSvgNode::Type QSvgVideo::type() const return VIDEO; } -QRectF QSvgUse::bounds() const -{ - if (m_link && m_bounds.isEmpty()) { - m_bounds = m_link->bounds(); - m_bounds = QRectF(m_bounds.x()+m_start.x(), - m_bounds.y()+m_start.y(), - m_bounds.width(), - m_bounds.height()); - - return m_bounds; - } - return m_bounds; -} - -QRectF QSvgUse::transformedBounds(const QTransform &transform) const +QRectF QSvgUse::bounds(QPainter *p, QSvgExtraStates &states) const { QRectF bounds; - QTransform t = transform; - - if (m_link) { - QSvgTransformStyle *transStyle = m_style.transform; - if (transStyle) { - t = transStyle->qtransform() * t; - } - t.translate(m_start.x(), m_start.y()); - - bounds = m_link->transformedBounds(t); - - return bounds; + if (m_link) { + p->translate(m_start); + bounds = m_link->transformedBounds(p, states); + p->translate(-m_start); } return bounds; } -QRectF QSvgPolyline::bounds() const +QRectF QSvgPolyline::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_poly.boundingRect(); - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().map(m_poly).boundingRect(); + } else { QPainterPath path; path.addPolygon(m_poly); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } -QRectF QSvgArc::bounds() const +QRectF QSvgArc::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_cachedBounds; - else { - return boundsOnStroke(cubic, sw); - } + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(m_path).boundingRect() + : boundsOnStroke(p, m_path, sw); } -QRectF QSvgImage::bounds() const +QRectF QSvgImage::bounds(QPainter *p, QSvgExtraStates &) const { - return m_bounds; + return p->transform().mapRect(m_bounds); } -QRectF QSvgLine::bounds() const +QRectF QSvgLine::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); + qreal sw = strokeWidth(p); if (qFuzzyIsNull(sw)) { - qreal minX = qMin(m_bounds.x1(), m_bounds.x2()); - qreal minY = qMin(m_bounds.y1(), m_bounds.y2()); - qreal maxX = qMax(m_bounds.x1(), m_bounds.x2()); - qreal maxY = qMax(m_bounds.y1(), m_bounds.y2()); - return QRectF(minX, minY, maxX-minX, maxY-minY); + QPointF p1 = p->transform().map(m_line.p1()); + QPointF p2 = p->transform().map(m_line.p2()); + qreal minX = qMin(p1.x(), p2.x()); + qreal minY = qMin(p1.y(), p2.y()); + qreal maxX = qMax(p1.x(), p2.x()); + qreal maxY = qMax(p1.y(), p2.y()); + return QRectF(minX, minY, maxX - minX, maxY - minY); } else { QPainterPath path; - path.moveTo(m_bounds.x1(), m_bounds.y1()); - path.lineTo(m_bounds.x2(), m_bounds.y2()); - return boundsOnStroke(path, sw); + path.moveTo(m_line.p1()); + path.lineTo(m_line.p2()); + return boundsOnStroke(p, path, sw); } } diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h index ca06777..fdc770a 100644 --- a/src/svg/qsvggraphics_p.h +++ b/src/svg/qsvggraphics_p.h @@ -80,32 +80,27 @@ public: QSvgArc(QSvgNode *parent, const QPainterPath &path); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: - QPainterPath cubic; - QRectF m_cachedBounds; + QPainterPath m_path; }; -class QSvgCircle : public QSvgNode +class QSvgEllipse : public QSvgNode { public: - QSvgCircle(QSvgNode *parent, const QRectF &rect); + QSvgEllipse(QSvgNode *parent, const QRectF &rect); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QRectF m_bounds; }; -class QSvgEllipse : public QSvgNode +class QSvgCircle : public QSvgEllipse { public: - QSvgEllipse(QSvgNode *parent, const QRectF &rect); - virtual void draw(QPainter *p, QSvgExtraStates &states); + QSvgCircle(QSvgNode *parent, const QRectF &rect) : QSvgEllipse(parent, rect) { } virtual Type type() const; - virtual QRectF bounds() const; -private: - QRectF m_bounds; }; class QSvgImage : public QSvgNode @@ -115,7 +110,7 @@ public: const QRect &bounds); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QImage m_image; QRect m_bounds; @@ -127,9 +122,9 @@ public: QSvgLine(QSvgNode *parent, const QLineF &line); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: - QLineF m_bounds; + QLineF m_line; }; class QSvgPath : public QSvgNode @@ -138,14 +133,13 @@ public: QSvgPath(QSvgNode *parent, const QPainterPath &qpath); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; QPainterPath *qpath() { return &m_path; } private: QPainterPath m_path; - mutable QRectF m_cachedBounds; }; class QSvgPolygon : public QSvgNode @@ -154,7 +148,7 @@ public: QSvgPolygon(QSvgNode *parent, const QPolygonF &poly); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QPolygonF m_poly; }; @@ -165,7 +159,7 @@ public: QSvgPolyline(QSvgNode *parent, const QPolygonF &poly); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QPolygonF m_poly; }; @@ -176,7 +170,7 @@ public: QSvgRect(QSvgNode *paren, const QRectF &rect, int rx=0, int ry=0); virtual Type type() const; virtual void draw(QPainter *p, QSvgExtraStates &states); - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QRectF m_rect; int m_rx, m_ry; @@ -205,7 +199,7 @@ public: void addLineBreak() {m_tspans.append(LINEBREAK);} void setWhitespaceMode(WhitespaceMode mode) {m_mode = mode;} - //virtual QRectF bounds() const; + //virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: static QSvgTspan * const LINEBREAK; @@ -248,13 +242,11 @@ public: QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *link); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; - virtual QRectF transformedBounds(const QTransform &transform) const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QSvgNode *m_link; QPointF m_start; - mutable QRectF m_bounds; }; class QSvgVideo : public QSvgNode diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp index 86f2af5..f6bc1c0 100644 --- a/src/svg/qsvgnode.cpp +++ b/src/svg/qsvgnode.cpp @@ -45,6 +45,7 @@ #ifndef QT_NO_SVG #include "qdebug.h" +#include "qstack.h" QT_BEGIN_NAMESPACE @@ -114,12 +115,12 @@ void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id) } } -void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) +void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const { - m_style.apply(p, bounds(), this, states); + m_style.apply(p, this, states); } -void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) +void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const { m_style.revert(p, states); } @@ -195,11 +196,40 @@ QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const return doc ? doc->namedStyle(rid) : 0; } -QRectF QSvgNode::bounds() const +QRectF QSvgNode::bounds(QPainter *, QSvgExtraStates &) const { return QRectF(0, 0, 0, 0); } +QRectF QSvgNode::transformedBounds() const +{ + if (!m_cachedBounds.isEmpty()) + return m_cachedBounds; + + QImage dummy(1, 1, QImage::Format_RGB32); + QPainter p(&dummy); + QSvgExtraStates states; + + QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); + pen.setMiterLimit(4); + p.setPen(pen); + + QStack<QSvgNode*> parentApplyStack; + QSvgNode *parent = m_parent; + while (parent) { + parentApplyStack.push(parent); + parent = parent->parent(); + } + + for (int i = parentApplyStack.size() - 1; i >= 0; --i) + parentApplyStack[i]->applyStyle(&p, states); + + p.setWorldTransform(QTransform()); + + m_cachedBounds = transformedBounds(&p, states); + return m_cachedBounds; +} + QSvgTinyDocument * QSvgNode::document() const { QSvgTinyDocument *doc = 0; @@ -274,19 +304,11 @@ void QSvgNode::setVisible(bool visible) m_visible = visible; } -QRectF QSvgNode::transformedBounds(const QTransform &transform) const +QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const { - QTransform t = transform; - - QSvgTransformStyle *transStyle = m_style.transform; - if (transStyle) { - t = transStyle->qtransform() * t; - } - - QRectF rect = bounds(); - - rect = t.mapRect(rect); - + applyStyle(p, states); + QRectF rect = bounds(p, states); + revertStyle(p, states); return rect; } @@ -310,15 +332,12 @@ QSvgNode::DisplayMode QSvgNode::displayMode() const return m_displayMode; } -qreal QSvgNode::strokeWidth() const +qreal QSvgNode::strokeWidth(QPainter *p) { - QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle*>( - styleProperty(QSvgStyleProperty::STROKE)); - if (!stroke) - return 0; - if (stroke->stroke().brush().style() == Qt::NoBrush) + QPen pen = p->pen(); + if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic()) return 0; - return stroke->width(); + return pen.widthF(); } QT_END_NAMESPACE diff --git a/src/svg/qsvgnode_p.h b/src/svg/qsvgnode_p.h index 15466f2..a34c7c0 100644 --- a/src/svg/qsvgnode_p.h +++ b/src/svg/qsvgnode_p.h @@ -118,16 +118,17 @@ public: QSvgNode *parent() const; void appendStyleProperty(QSvgStyleProperty *prop, const QString &id); - void applyStyle(QPainter *p, QSvgExtraStates &states); - void revertStyle(QPainter *p, QSvgExtraStates &states); + void applyStyle(QPainter *p, QSvgExtraStates &states) const; + void revertStyle(QPainter *p, QSvgExtraStates &states) const; QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const; QSvgFillStyleProperty *styleProperty(const QString &id) const; QSvgTinyDocument *document() const; virtual Type type() const =0; - virtual QRectF bounds() const; - virtual QRectF transformedBounds(const QTransform &transform) const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; + virtual QRectF transformedBounds(QPainter *p, QSvgExtraStates &states) const; + QRectF transformedBounds() const; void setRequiredFeatures(const QStringList &lst); const QStringList & requiredFeatures() const; @@ -156,9 +157,9 @@ public: QString xmlClass() const; void setXmlClass(const QString &str); protected: - QSvgStyle m_style; + mutable QSvgStyle m_style; - qreal strokeWidth() const; + static qreal strokeWidth(QPainter *p); private: QSvgNode *m_parent; @@ -174,6 +175,7 @@ private: QString m_class; DisplayMode m_displayMode; + mutable QRectF m_cachedBounds; friend class QSvgTinyDocument; }; diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp index 34426b7..db5cb9e 100644 --- a/src/svg/qsvgstructure.cpp +++ b/src/svg/qsvgstructure.cpp @@ -357,15 +357,12 @@ void QSvgSwitch::init() m_systemLanguagePrefix = m_systemLanguage.mid(0, idx); } -QRectF QSvgStructureNode::bounds() const +QRectF QSvgStructureNode::bounds(QPainter *p, QSvgExtraStates &states) const { - if (m_bounds.isEmpty()) { - foreach(QSvgNode *node, m_renderers) { - m_bounds |= node->transformedBounds(QTransform()); - } - } - - return m_bounds; + QRectF bounds; + foreach(QSvgNode *node, m_renderers) + bounds |= node->transformedBounds(p, states); + return bounds; } QSvgNode * QSvgStructureNode::previousSiblingNode(QSvgNode *n) const diff --git a/src/svg/qsvgstructure_p.h b/src/svg/qsvgstructure_p.h index fd6eb0a..dd82fc0 100644 --- a/src/svg/qsvgstructure_p.h +++ b/src/svg/qsvgstructure_p.h @@ -74,14 +74,13 @@ public: ~QSvgStructureNode(); QSvgNode *scopeNode(const QString &id) const; void addChild(QSvgNode *child, const QString &id); - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; QSvgNode *previousSiblingNode(QSvgNode *n) const; QList<QSvgNode*> renderers() const { return m_renderers; } protected: QList<QSvgNode*> m_renderers; QHash<QString, QSvgNode*> m_scope; QList<QSvgStructureNode*> m_linkedScopes; - mutable QRectF m_bounds; }; class QSvgG : public QSvgStructureNode diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 2b12c49..0d1bad9 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -73,7 +73,7 @@ QSvgStyleProperty::~QSvgStyleProperty() { } -void QSvgFillStyleProperty::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgFillStyleProperty::apply(QPainter *, const QSvgNode *, QSvgExtraStates &) { Q_ASSERT(!"This should not be called!"); } @@ -89,7 +89,7 @@ QSvgQualityStyle::QSvgQualityStyle(int color) { } -void QSvgQualityStyle::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgQualityStyle::apply(QPainter *, const QSvgNode *, QSvgExtraStates &) { } @@ -136,7 +136,7 @@ void QSvgFillStyle::setBrush(QBrush brush) m_fillSet = 1; } -void QSvgFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldFill = p->brush(); m_oldFillRule = states.fillRule; @@ -169,7 +169,7 @@ QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush) { } -void QSvgViewportFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgViewportFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldFill = p->brush(); p->setBrush(m_viewportFill); @@ -224,7 +224,7 @@ int QSvgFontStyle::SVGToQtWeight(int weight) { return QFont::Normal; } -void QSvgFontStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgFontStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldQFont = p->font(); m_oldSvgFont = states.svgFont; @@ -292,7 +292,7 @@ QSvgStrokeStyle::QSvgStrokeStyle() { } -void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgStrokeStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldStroke = p->pen(); m_oldStrokeOpacity = states.strokeOpacity; @@ -443,7 +443,7 @@ QSvgTransformStyle::QSvgTransformStyle(const QTransform &trans) { } -void QSvgTransformStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgTransformStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldWorldTransform = p->worldTransform(); p->setWorldTransform(m_transform, true); @@ -501,7 +501,7 @@ QSvgCompOpStyle::QSvgCompOpStyle(QPainter::CompositionMode mode) } -void QSvgCompOpStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgCompOpStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldMode = p->compositionMode(); p->setCompositionMode(m_mode); @@ -521,34 +521,34 @@ QSvgStyle::~QSvgStyle() { } -void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states) +void QSvgStyle::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) { if (quality) { - quality->apply(p, rect, node, states); + quality->apply(p, node, states); } if (fill) { - fill->apply(p, rect, node, states); + fill->apply(p, node, states); } if (viewportFill) { - viewportFill->apply(p, rect, node, states); + viewportFill->apply(p, node, states); } if (font) { - font->apply(p, rect, node, states); + font->apply(p, node, states); } if (stroke) { - stroke->apply(p, rect, node, states); + stroke->apply(p, node, states); } if (transform) { - transform->apply(p, rect, node, states); + transform->apply(p, node, states); } if (animateColor) { - animateColor->apply(p, rect, node, states); + animateColor->apply(p, node, states); } //animated transforms have to be applied @@ -572,16 +572,16 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra // Apply the animateTransforms after and including the last one with additive="replace". for (; itr != animateTransforms.constEnd(); ++itr) { if ((*itr)->animActive(totalTimeElapsed)) - (*itr)->apply(p, rect, node, states); + (*itr)->apply(p, node, states); } } if (opacity) { - opacity->apply(p, rect, node, states); + opacity->apply(p, node, states); } if (compop) { - compop->apply(p, rect, node, states); + compop->apply(p, node, states); } } @@ -655,7 +655,7 @@ void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const m_count = args.count() / 3; } -void QSvgAnimateTransform::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &) +void QSvgAnimateTransform::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &) { m_oldWorldTransform = p->worldTransform(); resolveMatrix(node); @@ -669,7 +669,7 @@ void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &) m_transformApplied = false; } -void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) +void QSvgAnimateTransform::resolveMatrix(const QSvgNode *node) { static const qreal deg2rad = qreal(0.017453292519943295769); qreal totalTimeElapsed = node->document()->currentElapsed(); @@ -834,7 +834,7 @@ void QSvgAnimateColor::setRepeatCount(qreal repeatCount) m_repeatCount = repeatCount; } -void QSvgAnimateColor::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &) +void QSvgAnimateColor::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &) { qreal totalTimeElapsed = node->document()->currentElapsed(); if (totalTimeElapsed < m_from || m_finished) @@ -912,7 +912,7 @@ QSvgOpacityStyle::QSvgOpacityStyle(qreal opacity) } -void QSvgOpacityStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgOpacityStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldOpacity = p->opacity(); p->setOpacity(m_opacity * m_oldOpacity); diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index 202de93..af3b4e5 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -172,7 +172,7 @@ public: }; public: virtual ~QSvgStyleProperty(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states) =0; + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0; virtual void revert(QPainter *p, QSvgExtraStates &states) =0; virtual Type type() const=0; }; @@ -181,7 +181,7 @@ class QSvgFillStyleProperty : public QSvgStyleProperty { public: virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0; - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); }; @@ -189,7 +189,7 @@ class QSvgQualityStyle : public QSvgStyleProperty { public: QSvgQualityStyle(int color); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -221,7 +221,7 @@ class QSvgOpacityStyle : public QSvgStyleProperty { public: QSvgOpacityStyle(qreal opacity); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -233,7 +233,7 @@ class QSvgFillStyle : public QSvgStyleProperty { public: QSvgFillStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -306,7 +306,7 @@ class QSvgViewportFillStyle : public QSvgStyleProperty { public: QSvgViewportFillStyle(const QBrush &brush); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -330,7 +330,7 @@ public: QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc); QSvgFontStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -410,7 +410,7 @@ class QSvgStrokeStyle : public QSvgStyleProperty { public: QSvgStrokeStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -617,7 +617,7 @@ class QSvgTransformStyle : public QSvgStyleProperty { public: QSvgTransformStyle(const QTransform &transform); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -654,7 +654,7 @@ public: void setArgs(TransformType type, Additive additive, const QVector<qreal> &args); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; QSvgAnimateTransform::Additive additiveType() const @@ -688,7 +688,7 @@ public: } protected: - void resolveMatrix(QSvgNode *node); + void resolveMatrix(const QSvgNode *node); private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; @@ -712,7 +712,7 @@ public: void setArgs(bool fill, const QList<QColor> &colors); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -732,7 +732,7 @@ class QSvgCompOpStyle : public QSvgStyleProperty { public: QSvgCompOpStyle(QPainter::CompositionMode mode); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -766,7 +766,7 @@ public: {} ~QSvgStyle(); - void apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states); + void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); void revert(QPainter *p, QSvgExtraStates &states); QSvgRefCounter<QSvgQualityStyle> quality; QSvgRefCounter<QSvgFillStyle> fill; diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index 17618f7..b21b99f 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -277,7 +277,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id, p->save(); - const QRectF elementBounds = node->transformedBounds(QTransform()); + const QRectF elementBounds = node->transformedBounds(); mapSourceToTarget(p, bounds, elementBounds); QTransform originalTransform = p->worldTransform(); @@ -299,7 +299,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id, for (int i = parentApplyStack.size() - 1; i >= 0; --i) parentApplyStack[i]->applyStyle(p, m_states); - + // Reset the world transform so that our parents don't affect // the position QTransform currentTransform = p->worldTransform(); @@ -432,8 +432,7 @@ QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const const QSvgNode *node = scopeNode(id); if (!node) node = this; - - return node->transformedBounds(QTransform()); + return node->transformedBounds(); } bool QSvgTinyDocument::elementExists(const QString &id) const diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h index c03c798..3b40770 100644 --- a/src/svg/qsvgtinydocument_p.h +++ b/src/svg/qsvgtinydocument_p.h @@ -173,9 +173,8 @@ inline bool QSvgTinyDocument::heightPercent() const inline QRectF QSvgTinyDocument::viewBox() const { - if (m_viewBox.isNull()) { - m_viewBox = transformedBounds(QTransform()); - } + if (m_viewBox.isNull()) + m_viewBox = transformedBounds(); return m_viewBox; } diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml b/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml index 12b1b7b..5e1891a 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml @@ -10,7 +10,7 @@ Rectangle { width: 100; height: 100 color: Qt.rgba(1,0,0) Behavior on x { - NumberAnimation { objectName: "MyAnim"; running: true } + NumberAnimation {id: myAnim; objectName: "MyAnim"; running: true } } } diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml index 6419a6b..11b2d3a 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml @@ -8,8 +8,8 @@ Rectangle { width: 100; height: 100; color: "green" Behavior on x { objectName: "MyBehavior" - NumberAnimation { duration: 200 } - NumberAnimation { duration: 1000 } + NumberAnimation {id: na1; duration: 200 } + NumberAnimation {id: na2; duration: 1000 } } } MouseArea { diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml b/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml index c28fa9a..5e72bca 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml @@ -8,7 +8,7 @@ Rectangle { width: 100; height: 100; color: "green" Behavior on x { objectName: "MyBehavior"; - NumberAnimation { duration: 500; } + NumberAnimation {id: na; duration: 500; } } } MouseArea { diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp index 51f9a07..eba83ce 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp +++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp @@ -314,8 +314,17 @@ void tst_qdeclarativevaluetypes::font() font.setLetterSpacing(QFont::AbsoluteSpacing, 9.7); font.setWordSpacing(11.2); - QEXPECT_FAIL("", "QT-2920", Continue); - QCOMPARE(object->font(), font); + QFont f = object->font(); + QCOMPARE(f.family(), font.family()); + QCOMPARE(f.bold(), font.bold()); + QCOMPARE(f.weight(), font.weight()); + QCOMPARE(f.italic(), font.italic()); + QCOMPARE(f.underline(), font.underline()); + QCOMPARE(f.strikeOut(), font.strikeOut()); + QCOMPARE(f.pointSize(), font.pointSize()); + QCOMPARE(f.capitalization(), font.capitalization()); + QCOMPARE(f.letterSpacing(), font.letterSpacing()); + QCOMPARE(f.wordSpacing(), font.wordSpacing()); delete object; } diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index a03b2c7..701dc2e 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -999,10 +999,10 @@ void tst_QPainter::drawPixmapFragments() { QPixmap origPixmap(20, 20); QPixmap resPixmap(20, 20); - QPainter::Fragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, - { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, - {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, - { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; + QPainter::PixmapFragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, + { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, + {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, + { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; { QPainter p(&origPixmap); p.fillRect(0, 0, 10, 10, Qt::red); @@ -1025,7 +1025,7 @@ void tst_QPainter::drawPixmapFragments() QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5)); - QPainter::Fragment fragment = QPainter::Fragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); + QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); QVERIFY(fragment.x == 20); QVERIFY(fragment.y == 20); QVERIFY(fragment.sourceLeft == 30); diff --git a/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg b/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg index 99926b3..f1f9e35 100644 --- a/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg +++ b/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg @@ -4,12 +4,12 @@ <desc>Generated with Qt</desc> <defs> </defs> -<g fill="none" stroke="black" vector-effect="non-scaling-stroke" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > +<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > <g fill="#ff0000" fill-opacity="1" stroke="none" transform="matrix(1,0,0,1,0,0)" -font-family="Arial" font-size="11pt" font-weight="400" font-style="normal" +font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal" > -<path fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> +<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> </g> </g> </svg> diff --git a/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg b/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg index f61dd40..84afbf3 100644 --- a/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg +++ b/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg @@ -13,18 +13,18 @@ <stop offset="1" stop-color="#0000ff" stop-opacity="1" /> </radialGradient> </defs> -<g fill="none" stroke="black" vector-effect="non-scaling-stroke" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > +<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" > <g fill="url(#gradient1)" stroke="none" transform="matrix(1,0,0,1,0,0)" -font-family="Sans Serif" font-size="9pt" font-weight="400" font-style="normal" +font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal" > -<path fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> +<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,0 L100,0 L100,100 L0,100 L0,0"/> </g> <g fill="url(#gradient2)" stroke="none" transform="matrix(1,0,0,1,0,0)" -font-family="Sans Serif" font-size="9pt" font-weight="400" font-style="normal" +font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal" > -<path fill-rule="evenodd" d="M100,0 L200,0 L200,100 L100,100 L100,0"/> +<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M100,0 L200,0 L200,100 L100,100 L100,0"/> </g> </g> </svg> diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 16dd2b4..106fd8c 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -74,6 +74,7 @@ private slots: void nestedQXmlStreamReader() const; void stylePropagation() const; void matrixForElement() const; + void boundsOnElement() const; void gradientStops() const; void gradientRefs(); void fillRule(); @@ -470,6 +471,36 @@ void tst_QSvgRenderer::matrixForElement() const compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("firkant")))); } +void tst_QSvgRenderer::boundsOnElement() const +{ + QByteArray data("<svg>" + "<g id=\"prim\" transform=\"translate(-3,1)\">" + "<g id=\"sjokade\" stroke=\"none\" stroke-width=\"10\">" + "<rect id=\"kaviar\" transform=\"rotate(45)\" x=\"-10\" y=\"-10\" width=\"20\" height=\"20\"/>" + "</g>" + "<g id=\"nugatti\" stroke=\"black\" stroke-width=\"2\">" + "<use x=\"0\" y=\"0\" transform=\"rotate(45)\" xlink:href=\"#kaviar\"/>" + "</g>" + "<g id=\"nutella\" stroke=\"none\" stroke-width=\"10\">" + "<path id=\"baconost\" transform=\"rotate(45)\" d=\"M-10 -10 L10 -10 L10 10 L-10 10 Z\"/>" + "</g>" + "<g id=\"hapaa\" transform=\"translate(-2,2)\" stroke=\"black\" stroke-width=\"2\">" + "<use x=\"0\" y=\"0\" transform=\"rotate(45)\" xlink:href=\"#baconost\"/>" + "</g>" + "</g>" + "</svg>"); + + qreal sqrt2 = qSqrt(2); + QSvgRenderer renderer(data); + QCOMPARE(renderer.boundsOnElement(QLatin1String("sjokade")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("kaviar")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("nugatti")), QRectF(-11, -11, 22, 22)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("nutella")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("baconost")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("hapaa")), QRectF(-13, -9, 22, 22)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("prim")), QRectF(-10 * sqrt2 - 3, -10 * sqrt2 + 1, 20 * sqrt2, 20 * sqrt2)); +} + void tst_QSvgRenderer::gradientStops() const { { diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro index 2c042b5..76c26c1 100644 --- a/tests/benchmarks/gui/painting/painting.pro +++ b/tests/benchmarks/gui/painting/painting.pro @@ -3,4 +3,5 @@ SUBDIRS = \ qpainter \ qregion \ qtransform \ - qtracebench + qtracebench \ + qtbench diff --git a/tests/benchmarks/gui/painting/qtbench/benchmarktests.h b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h new file mode 100644 index 0000000..362d121 --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h @@ -0,0 +1,841 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BENCHMARKTESTS_H +#define BENCHMARKTESTS_H + +#include <QApplication> +#include <QTextDocument> +#include <QDesktopWidget> +#include <QTextLayout> +#include <QFontMetrics> +#include <QDebug> + +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) +# include <QStaticText> +#endif + +class Benchmark +{ +public: + virtual ~Benchmark() {} + + Benchmark(const QSize &size) + : m_size(size) + { + for (int i=0; i<16; ++i) { + m_colors[i] = QColor::fromRgbF((rand() % 4) / 3.0, + (rand() % 4) / 3.0, + (rand() % 4) / 3.0, + 1); + } + } + + virtual void draw(QPainter *p, const QRect &rect, int iteration) = 0; + virtual QString name() const = 0; + + inline const QSize &size() const + { + return m_size; + } + virtual void begin(QPainter *, int iterations = 1) { Q_UNUSED(iterations); } + virtual void end(QPainter *) { } + + inline const QColor &randomColor(int i) { return m_colors[i % 16]; } + +protected: + QColor m_colors[16]; + QSize m_size; +}; + +class PaintingRectAdjuster +{ +public: + PaintingRectAdjuster() + : m_benchmark(0), + m_bounds(), + m_screen_filled(false) + { + } + + const QRect &newPaintingRect() { + m_rect.translate(m_rect.width(), 0); + + if (m_rect.right() > m_bounds.width()) { + m_rect.moveLeft(m_bounds.left()); + m_rect.translate(0,m_rect.height()); + if (m_rect.bottom() > m_bounds.height()) { + m_screen_filled = true; + m_rect.moveTo(m_bounds.topLeft()); + } + } + return m_rect; + } + + inline bool isScreenFilled() const + { return m_screen_filled; } + + void reset(const QRect &bounds) + { + m_bounds = bounds; + m_rect.moveTo(m_bounds.topLeft()); + m_rect = QRect(m_bounds.topLeft(),m_benchmark->size()); + m_rect.translate(-m_rect.width(),0); + m_screen_filled = false; + } + + inline void setNewBenchmark( Benchmark *benchmark ) + { + m_benchmark = benchmark; + } + +protected: + Benchmark *m_benchmark; + QRect m_rect; + QRect m_bounds; + bool m_screen_filled; +}; + +class FillRectBenchmark : public Benchmark +{ +public: + FillRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + } + + virtual void draw(QPainter *p, const QRect &rect, int iterationCount) { + p->fillRect(rect, randomColor(iterationCount)); + } + + virtual QString name() const { + return QString::fromLatin1("fillRect(%1)").arg(m_size.width()); + } +}; + +class ImageFillRectBenchmark : public Benchmark +{ +public: + ImageFillRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + int s = rand() % 24 + 8; + m_content = QImage(s, s, QImage::Format_ARGB32_Premultiplied); + QPainter p(&m_content); + p.fillRect(0, 0, s, s, Qt::white); + p.fillRect(s/2, 0, s/2, s/2, Qt::gray); + p.fillRect(0, s/2, s/2, s/2, Qt::gray); + p.end(); + + m_brush = QBrush(m_content); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->fillRect(rect, m_brush); + } + + virtual QString name() const { + return QString::fromLatin1("fillRect with image(%1)").arg(m_size.width()); + } + +private: + QImage m_content; + QBrush m_brush; +}; + + +class DrawRectBenchmark : public Benchmark +{ +public: + DrawRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + } + + virtual void begin(QPainter *p, int) { + p->setPen(Qt::NoPen); + p->setBrush(randomColor(m_size.width())); + } + + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->drawRect(rect); + } + + virtual QString name() const { + return QString::fromLatin1("drawRect(%1)").arg(m_size.width()); + } +}; + + +class DrawRectWithBrushChangeBenchmark : public Benchmark +{ +public: + DrawRectWithBrushChangeBenchmark(int size) + : Benchmark(QSize(size, size)) + { + } + + virtual void begin(QPainter *p, int) { + p->setPen(Qt::NoPen); + } + + + virtual void draw(QPainter *p, const QRect &rect, int i) { + p->setBrush(randomColor(i)); + p->drawRect(rect); + } + + virtual QString name() const { + return QString::fromLatin1("drawRect with brushchange(%1)").arg(m_size.width()); + } +}; + +class RoundRectBenchmark : public Benchmark +{ +public: + RoundRectBenchmark(int size) + : Benchmark(QSize(size, size)) + { + m_roundness = size / 4.; + } + + virtual void begin(QPainter *p, int) { + p->setPen(Qt::NoPen); + p->setBrush(Qt::red); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->drawRoundedRect(rect, m_roundness, m_roundness); + } + + virtual QString name() const { + return QString::fromLatin1("drawRoundedRect(%1)").arg(m_size.width()); + } + + qreal m_roundness; +}; + + +class ArcsBenchmark : public Benchmark +{ +public: + enum Type { + Stroked = 0x0001, + Filled = 0x0002, + + ArcShape = 0x0010, + ChordShape = 0x0020, + PieShape = 0x0040, + CircleShape = 0x0080, + Shapes = 0x00f0 + + }; + + ArcsBenchmark(int size, uint type) + : Benchmark(QSize(size, size)), + m_type(type) + { + } + + virtual void begin(QPainter *p, int) { + if (m_type & Stroked) + p->setPen(Qt::black); + else + p->setPen(Qt::NoPen); + + if (m_type & Filled) + p->setBrush(Qt::red); + else + p->setBrush(Qt::NoBrush); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + switch (m_type & Shapes) { + case ArcShape: + p->drawArc(rect, 45*16, 120*16); + break; + case ChordShape: + p->drawChord(rect, 45*16, 120*16); + break; + case PieShape: + p->drawPie(rect, 45*16, 120*16); + break; + case CircleShape: + p->drawEllipse(rect); + break; + } + } + + virtual QString name() const { + QString fillStroke; + + if ((m_type & (Stroked|Filled)) == (Stroked|Filled)) { + fillStroke = QLatin1String("Fill & Outline"); + } else if (m_type & Stroked) { + fillStroke = QLatin1String("Outline"); + } else if (m_type & Filled) { + fillStroke = QLatin1String("Fill"); + } + + QString shape; + if (m_type & PieShape) shape = QLatin1String("drawPie"); + else if (m_type & ChordShape) shape = QLatin1String("drawChord"); + else if (m_type & ArcShape) shape = QLatin1String("drawArc"); + else if (m_type & CircleShape) shape = QLatin1String("drawEllipse"); + + return QString::fromLatin1("%1(%2) %3").arg(shape).arg(m_size.width()).arg(fillStroke); + } + + uint m_type; +}; + + +class DrawScaledImage : public Benchmark +{ +public: + DrawScaledImage(const QImage &image, qreal scale, bool asPixmap) + : Benchmark(QSize(image.width(), image.height())), + m_image(image), + m_type(m_as_pixmap ? "Pixmap" : "Image"), + m_scale(scale), + m_as_pixmap(asPixmap) + { + m_pixmap = QPixmap::fromImage(m_image); + } + DrawScaledImage(const QString& type, const QPixmap &pixmap, qreal scale) + : Benchmark(QSize(pixmap.width(), pixmap.height())), + m_type(type), + m_scale(scale), + m_as_pixmap(true), + m_pixmap(pixmap) + { + } + + virtual void begin(QPainter *p, int) { + p->scale(m_scale, m_scale); + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + if (m_as_pixmap) + p->drawPixmap(rect.topLeft(), m_pixmap); + else + p->drawImage(rect.topLeft(), m_image); + } + + virtual QString name() const { + return QString::fromLatin1("draw%4(%1) at scale=%2, depth=%3") + .arg(m_size.width()) + .arg(m_scale) + .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth()) + .arg(m_type); + } + +private: + QImage m_image; + QString m_type; + qreal m_scale; + bool m_as_pixmap; + QPixmap m_pixmap; +}; + +class DrawTransformedImage : public Benchmark +{ +public: + DrawTransformedImage(const QImage &image, bool asPixmap) + : Benchmark(QSize(image.width(), image.height())), + m_image(image), + m_type(m_as_pixmap ? "Pixmap" : "Image"), + m_as_pixmap(asPixmap) + { + m_pixmap = QPixmap::fromImage(m_image); + } + DrawTransformedImage(const QString& type, const QPixmap &pixmap) + : Benchmark(QSize(pixmap.width(), pixmap.height())), + m_type(type), + m_as_pixmap(true), + m_pixmap(pixmap) + { + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + QTransform oldTransform = p->transform(); + p->translate(0.5 * rect.width() + rect.left(), 0.5 * rect.height() + rect.top()); + p->shear(0.25, 0.0); + p->rotate(5.0); + if (m_as_pixmap) + p->drawPixmap(-0.5 * rect.width(), -0.5 * rect.height(), m_pixmap); + else + p->drawImage(-0.5 * rect.width(), -0.5 * rect.height(), m_image); + p->setTransform(oldTransform); + } + + virtual QString name() const { + return QString::fromLatin1("draw%3(%1) w/transform, depth=%2") + .arg(m_size.width()) + .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth()) + .arg(m_type); + } + +private: + QImage m_image; + QString m_type; + bool m_as_pixmap; + QPixmap m_pixmap; +}; + + +class DrawImage : public Benchmark +{ +public: + DrawImage(const QImage &image, bool asPixmap) + : Benchmark(QSize(image.width(), image.height())), + m_image(image), + m_type(m_as_pixmap ? "Pixmap" : "Image"), + m_as_pixmap(asPixmap) + { + m_pixmap = QPixmap::fromImage(image); + } + DrawImage(const QString& type, const QPixmap &pixmap) + : Benchmark(QSize(pixmap.width(), pixmap.height())), + m_type(type), + m_as_pixmap(true), + m_pixmap(pixmap) + { + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + if (m_as_pixmap) + p->drawPixmap(rect.topLeft(), m_pixmap); + else + p->drawImage(rect.topLeft(), m_image); + } + + virtual QString name() const { + return QString::fromLatin1("draw%2(%1), depth=%3") + .arg(m_size.width()) + .arg(m_type) + .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth()); + } + +private: + QImage m_image; + QString m_type; + bool m_as_pixmap; + QPixmap m_pixmap; +}; + + +class DrawText : public Benchmark +{ +public: + enum Mode { + PainterMode, + PainterQPointMode, + LayoutMode, + DocumentMode, + PixmapMode + +#if QT_VERSION >= 0x040700 + , StaticTextMode, + StaticTextWithMaximumSizeMode, + StaticTextBackendOptimizations +#endif + }; + + DrawText(const QString &text, Mode mode) + : Benchmark(QSize()), m_mode(mode), m_text(text), m_document(text), m_layout(text) + { + } + + virtual void begin(QPainter *p, int iterations) { +#if QT_VERSION >= 0x040700 + m_staticTexts.clear(); + m_currentStaticText = 0; +#else + Q_UNUSED(iterations); +#endif + m_pixmaps.clear(); + m_currentPixmap = 0; + QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height()); + switch (m_mode) { + case PainterMode: + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); +// m_rect = m_rect.translated(-m_rect.topLeft()); + break; + case DocumentMode: + m_size = QSize(m_document.size().toSize()); + break; + case PixmapMode: + for (int i=0; i<4; ++i) { + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); + QPixmap pixmap = QPixmap(m_size); + pixmap.fill(Qt::transparent); + { + QPainter p(&pixmap); + p.drawText(pixmap.rect(), m_text); + } + m_pixmaps.append(pixmap); + } + break; + + case LayoutMode: { + QRect r = p->boundingRect(m_bounds, 0, m_text); + QStringList lines = m_text.split('\n'); + int height = 0; + int leading = p->fontMetrics().leading(); + m_layout.beginLayout(); + for (int i=0; i<lines.size(); ++i) { + QTextLine textLine = m_layout.createLine(); + if (textLine.isValid()) { + textLine.setLineWidth(r.width()); + textLine.setPosition(QPointF(0, height)); + height += leading + textLine.height(); + } + } + m_layout.endLayout(); + m_layout.setCacheEnabled(true); + m_size = m_layout.boundingRect().toRect().size(); + break; } + +#if QT_VERSION >= 0x040700 + case StaticTextWithMaximumSizeMode: { + QStaticText staticText; + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); + staticText.setMaximumSize(m_size + QSize(10, 10)); + staticText.setText(m_text); + staticText.prepare(p->transform(), p->font()); + m_staticTexts.append(staticText); + break; + } + case StaticTextBackendOptimizations: { + m_size = (p->boundingRect(m_bounds, 0, m_text)).size(); + for (int i=0; i<iterations; ++i) { + QStaticText staticText; + staticText.setPerformanceHint(QStaticText::AggressiveCaching); + staticText.setMaximumSize(m_size + QSize(10, 10)); + staticText.setText(m_text); + staticText.prepare(p->transform(), p->font()); + m_staticTexts.append(staticText); + } + + break; + } + case StaticTextMode: { + QStaticText staticText; + staticText.setText(m_text); + staticText.prepare(p->transform(), p->font()); + m_staticTexts.append(staticText); + + QFontMetrics fm(p->font()); + m_size = QSize(fm.width(m_text, m_text.length()), fm.height()); + + break; + } +#endif + + case PainterQPointMode: { + QFontMetrics fm(p->font()); + m_size = QSize(fm.width(m_text, m_text.length()), fm.height()); + break; + } + + } + } + + virtual void draw(QPainter *p, const QRect &rect, int) + { + switch (m_mode) { + case PainterMode: + p->drawText(rect, 0, m_text); + break; + case PainterQPointMode: + p->drawText(rect.topLeft(), m_text); + break; + case PixmapMode: + p->drawPixmap(rect.topLeft(), m_pixmaps.at(m_currentPixmap)); + m_currentPixmap = (m_currentPixmap + 1) % m_pixmaps.size(); + break; + case DocumentMode: + p->translate(rect.topLeft()); + m_document.drawContents(p); + p->translate(-rect.topLeft()); + break; + case LayoutMode: + m_layout.draw(p, rect.topLeft()); + break; + +#if QT_VERSION >= 0x040700 + case StaticTextWithMaximumSizeMode: + case StaticTextMode: + p->drawStaticText(rect.topLeft(), m_staticTexts.at(0)); + break; + case StaticTextBackendOptimizations: + p->drawStaticText(rect.topLeft(), m_staticTexts.at(m_currentStaticText)); + m_currentStaticText = (m_currentStaticText + 1) % m_staticTexts.size(); + break; +#endif + } + } + + virtual QString name() const { + int letters = m_text.length(); + int lines = m_text.count('\n'); + if (lines == 0) + lines = 1; + QString type; + switch (m_mode) { + case PainterMode: type = "drawText(rect)"; break; + case PainterQPointMode: type = "drawText(point)"; break; + case LayoutMode: type = "layout.draw()"; break; + case DocumentMode: type = "doc.drawContents()"; break; + case PixmapMode: type = "pixmap cached text"; break; + +#if QT_VERSION >= 0x040700 + case StaticTextMode: type = "drawStaticText()"; break; + case StaticTextWithMaximumSizeMode: type = "drawStaticText() w/ maxsize"; break; + case StaticTextBackendOptimizations: type = "drawStaticText() w/ backend optimizations"; break; +#endif + } + + return QString::fromLatin1("%3, len=%1, lines=%2") + .arg(letters) + .arg(lines) + .arg(type); + } + +private: + Mode m_mode; + QString m_text; + QTextDocument m_document; + QTextLayout m_layout; + + QList<QPixmap> m_pixmaps; + int m_currentPixmap; + +#if QT_VERSION >= 0x040700 + int m_currentStaticText; + QList<QStaticText> m_staticTexts; +#endif +}; + + + + +class ClippedDrawRectBenchmark : public Benchmark +{ +public: + enum ClipType { + RectClip, + TwoRectRegionClip, + EllipseRegionClip, + TwoRectPathClip, + EllipsePathClip, + AAEllipsePathClip, + EllipseRegionThenRectClip, + EllipsePathThenRectClip + }; + + ClippedDrawRectBenchmark(int size, ClipType type) + : Benchmark(QSize(size, size)), m_type(type) + { + } + + virtual void begin(QPainter *p, int) { + QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height()); + p->setPen(Qt::NoPen); + p->setBrush(Qt::red); + + switch (m_type) { + case RectClip: + p->setClipRect(m_bounds.adjusted(1, 1, -1, -1)); + break; + case TwoRectRegionClip: + p->setClipRegion(QRegion(m_bounds.adjusted(0, 0, -1, -1)) + | QRegion(m_bounds.adjusted(1, 1, 0, 0))); + break; + case EllipseRegionClip: + p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse)); + break; + case TwoRectPathClip: + { + QPainterPath path; + path.addRect(m_bounds.adjusted(0, 0, -1, -1)); + path.addRect(m_bounds.adjusted(1, 1, 0, 0)); + path.setFillRule(Qt::WindingFill); + p->setClipPath(path); + } + break; + case EllipsePathClip: + { + QPainterPath path; + path.addEllipse(m_bounds); + p->setClipPath(path); + } + break; + case AAEllipsePathClip: + { + QPainterPath path; + path.addEllipse(m_bounds); + p->setRenderHint(QPainter::Antialiasing); + p->setClipPath(path); + p->setRenderHint(QPainter::Antialiasing, false); + } + break; + case EllipseRegionThenRectClip: + p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse)); + p->setClipRegion(QRegion(m_bounds.width() / 4, + m_bounds.height() / 4, + m_bounds.width() / 2, + m_bounds.height() / 2), Qt::IntersectClip); + break; + case EllipsePathThenRectClip: + { + QPainterPath path; + path.addEllipse(m_bounds); + p->setClipPath(path); + p->setClipRegion(QRegion(m_bounds.width() / 4, + m_bounds.height() / 4, + m_bounds.width() / 2, + m_bounds.height() / 2), Qt::IntersectClip); + } + break; + } + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + p->drawRect(rect); + } + + virtual QString name() const { + QString namedType; + switch (m_type) { + case RectClip: + namedType = "rect"; + break; + case TwoRectRegionClip: + namedType = "two-rect-region"; + break; + case EllipseRegionClip: + namedType = "ellipse-region"; + break; + case TwoRectPathClip: + namedType = "two-rect-path"; + break; + case EllipsePathClip: + namedType = "ellipse-path"; + break; + case AAEllipsePathClip: + namedType = "aa-ellipse-path"; + break; + case EllipseRegionThenRectClip: + namedType = "ellipseregion&rect"; + break; + case EllipsePathThenRectClip: + namedType = "ellipsepath&rect"; + break; + } + return QString::fromLatin1("%1-clipped-drawRect(%2)").arg(namedType).arg(m_size.width()); + } + + ClipType m_type; +}; + +class LinesBenchmark : public Benchmark +{ +public: + enum LineType { + Horizontal_Integer, + Diagonal_Integer, + Vertical_Integer, + Horizontal_Float, + Diagonal_Float, + Vertical_Float + }; + + LinesBenchmark(int length, LineType type) + : Benchmark(QSize(qAbs(length), qAbs(length))), + m_type(type), + m_length(length) + { + + } + + virtual void draw(QPainter *p, const QRect &rect, int) { + switch (m_type) { + case Horizontal_Integer: + p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y())); + break; + case Diagonal_Integer: + p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length)); + break; + case Vertical_Integer: + p->drawLine(QLine(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length)); + break; + case Horizontal_Float: + p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y())); + break; + case Diagonal_Float: + p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length)); + break; + case Vertical_Float: + p->drawLine(QLineF(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length)); + break; + } + } + + virtual QString name() const { + const char *names[] = { + "Hor_I", + "Diag_I", + "Ver_I", + "Hor_F", + "Diag_F", + "Ver_F" + }; + return QString::fromLatin1("drawLine(size=%1,type=%2)").arg(m_length).arg(names[m_type]); + } + + LineType m_type; + int m_length; +}; + +#endif // BENCHMARKTESTS_H diff --git a/tests/benchmarks/gui/painting/qtbench/qtbench.pro b/tests/benchmarks/gui/painting/qtbench/qtbench.pro new file mode 100644 index 0000000..91f416d --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/qtbench.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qtbench + +SOURCES += tst_qtbench.cpp + diff --git a/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp new file mode 100644 index 0000000..8eef472 --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> + +#include <QtGui> + +#include "benchmarktests.h" + +//TESTED_FILES= + +class BenchWidget : public QWidget +{ +public: + BenchWidget(Benchmark *benchmark); + + void paintEvent(QPaintEvent *event); + + bool done() const { return m_done; } + qreal result() const { return m_result; } + +public: + QTime timer; + + Benchmark *m_benchmark; + + bool m_done; + qreal m_result; + + uint m_total; + uint m_iteration; + + QVector<uint> iterationTimes; +}; + +void BenchWidget::paintEvent(QPaintEvent *) +{ + if (m_done) + return; + + QPainter p(this); + + m_benchmark->begin(&p, 100); + + PaintingRectAdjuster adjuster; + adjuster.setNewBenchmark(m_benchmark); + adjuster.reset(rect()); + + for (int i = 0; i < 100; ++i) + m_benchmark->draw(&p, adjuster.newPaintingRect(), i); + + m_benchmark->end(&p); + + ++m_iteration; + + uint currentElapsed = timer.isNull() ? 0 : timer.elapsed(); + timer.restart(); + + m_total += currentElapsed; + + // warm up for at most 5 iterations or half a second + if (m_iteration >= 5 || m_total >= 500) { + iterationTimes << currentElapsed; + + if (iterationTimes.size() >= 5) { + qreal mean = 0; + qreal stddev = 0; + uint min = INT_MAX; + + for (int i = 0; i < iterationTimes.size(); ++i) { + mean += iterationTimes.at(i); + min = qMin(min, iterationTimes.at(i)); + } + + mean /= qreal(iterationTimes.size()); + + for (int i = 0; i < iterationTimes.size(); ++i) { + qreal delta = iterationTimes.at(i) - mean; + stddev += delta * delta; + } + + stddev = qSqrt(stddev / iterationTimes.size()); + + stddev = 100 * stddev / mean; + // do 50 iterations, break earlier if we spend more than 5 seconds or have a low std deviation after 2 seconds + if (iterationTimes.size() >= 50 || m_total >= 5000 || (m_total >= 2000 && stddev < 4)) { + m_result = min; + m_done = true; + return; + } + } + } +} + +BenchWidget::BenchWidget(Benchmark *benchmark) + : m_benchmark(benchmark) + , m_done(false) + , m_result(0) + , m_total(0) + , m_iteration(0) +{ + setWindowTitle(benchmark->name()); + resize(640, 480); +} + +class tst_QtBench : public QObject +{ + Q_OBJECT + +private slots: + void qtBench(); + void qtBench_data(); +}; + +QString makeString(int length) +{ + const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234"; + int len = strlen(chars); + + QString ret; + for (int j = 0; j < length; j++) { + ret += QChar(chars[(j * 97) % len]); + } + + return ret; +} + +void tst_QtBench::qtBench_data() +{ + QTest::addColumn<void *>("benchmark"); + + QString shortString = makeString(5); + QString middleString = makeString(50); + QString longString = makeString(35) + "\n" + + makeString(45) + "\n" + + makeString(75); + QString superLongString = "Lorem ipsum dolor sit am\n" + "et, consectetur adipisci\n" + "ng elit. Integer mi leo,\n" + "interdum ut congue at, p\n" + "ulvinar et tellus. Quisq\n" + "ue pretium eleifend laci\n" + "nia. Ut semper gravida l\n" + "ectus in commodo. Vestib\n" + "ulum pharetra arcu in en\n" + "im ultrices hendrerit. P\n" + "ellentesque habitant mor\n" + "bi tristique senectus et\n" + "netus et malesuada fames\n" + "ac turpis egestas. Ut er\n" + "os sem, feugiat in eleme\n" + "ntum in, porta sit amet \n" + "neque. Fusce mi tellus, \n" + "congue non dapibus eget,\n" + "pharetra quis quam. Duis\n" + "dui massa, pulvinar ac s\n" + "odales pharetra, dictum \n" + "in enim. Phasellus a nis\n" + "i erat, sed pellentesque\n" + "mi. Curabitur sed."; + + QList<Benchmark *> benchmarks; + benchmarks << (new DrawText(shortString, DrawText::PainterMode)); + benchmarks << (new DrawText(middleString, DrawText::PainterMode)); + benchmarks << (new DrawText(longString, DrawText::PainterMode)); + benchmarks << (new DrawText(superLongString, DrawText::PainterMode)); + + benchmarks << (new DrawText(shortString, DrawText::PainterQPointMode)); + benchmarks << (new DrawText(middleString, DrawText::PainterQPointMode)); + benchmarks << (new DrawText(longString, DrawText::PainterQPointMode)); + benchmarks << (new DrawText(superLongString, DrawText::PainterQPointMode)); + + benchmarks << (new DrawText(shortString, DrawText::PixmapMode)); + benchmarks << (new DrawText(middleString, DrawText::PixmapMode)); + benchmarks << (new DrawText(longString, DrawText::PixmapMode)); + benchmarks << (new DrawText(superLongString, DrawText::PixmapMode)); + +#if QT_VERSION >= 0x040700 + benchmarks << (new DrawText(shortString, DrawText::StaticTextMode)); + benchmarks << (new DrawText(middleString, DrawText::StaticTextMode)); + benchmarks << (new DrawText(longString, DrawText::StaticTextMode)); + benchmarks << (new DrawText(superLongString, DrawText::StaticTextMode)); + + benchmarks << (new DrawText(shortString, DrawText::StaticTextWithMaximumSizeMode)); + benchmarks << (new DrawText(middleString, DrawText::StaticTextWithMaximumSizeMode)); + benchmarks << (new DrawText(longString, DrawText::StaticTextWithMaximumSizeMode)); + benchmarks << (new DrawText(superLongString, DrawText::StaticTextWithMaximumSizeMode)); + + benchmarks << (new DrawText(shortString, DrawText::StaticTextBackendOptimizations)); + benchmarks << (new DrawText(middleString, DrawText::StaticTextBackendOptimizations)); + benchmarks << (new DrawText(longString, DrawText::StaticTextBackendOptimizations)); + benchmarks << (new DrawText(superLongString, DrawText::StaticTextBackendOptimizations)); +#endif + + foreach (Benchmark *benchmark, benchmarks) + QTest::newRow(qPrintable(benchmark->name())) << reinterpret_cast<void *>(benchmark); +} + +void tst_QtBench::qtBench() +{ + QFETCH(void *, benchmark); + + BenchWidget widget(reinterpret_cast<Benchmark *>(benchmark)); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + while (!widget.done()) { + widget.update(); + QApplication::processEvents(); + } + + QTest::setBenchmarkResult(widget.result(), QTest::WalltimeMilliseconds); +} + +QTEST_MAIN(tst_QtBench) +#include "tst_qtbench.moc" diff --git a/tools/qml/content/Browser.qml b/tools/qml/content/Browser.qml index 35120bc..62996ef 100644 --- a/tools/qml/content/Browser.qml +++ b/tools/qml/content/Browser.qml @@ -137,12 +137,12 @@ Rectangle { Transition { to: "current" SequentialAnimation { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } }, Transition { - NumberAnimation { matchProperties: "x"; duration: 250 } - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } ] Keys.onPressed: { root.keyPressed = true; } @@ -177,11 +177,11 @@ Rectangle { Transition { to: "current" SequentialAnimation { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } }, Transition { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } ] Keys.onPressed: { root.keyPressed = true; } |