diff options
author | Warwick Allison <warwick.allison@nokia.com> | 2009-12-02 05:35:43 (GMT) |
---|---|---|
committer | Warwick Allison <warwick.allison@nokia.com> | 2009-12-02 05:35:43 (GMT) |
commit | 289645d2bf46c1d6eace7a0d60389a9c10dd0c34 (patch) | |
tree | 18f4566813e2e18adcdf5f0a605b95a2276bef04 | |
parent | 1893849a7e90781b85f15ac32bef972b0087a720 (diff) | |
download | Qt-289645d2bf46c1d6eace7a0d60389a9c10dd0c34.zip Qt-289645d2bf46c1d6eace7a0d60389a9c10dd0c34.tar.gz Qt-289645d2bf46c1d6eace7a0d60389a9c10dd0c34.tar.bz2 |
Change from scaling/zooming by zoomFactor to instead use painter scaling.
Uses a fixed zoomFactor of 4 to allow sufficient sub-"pixel" precision.
6 files changed, 107 insertions, 42 deletions
diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml index 105bb07..11776aa 100644 --- a/demos/declarative/webbrowser/webbrowser.qml +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -195,13 +195,14 @@ Item { smoothCache: true // We do want smooth rendering fillColor: "white" focus: true + zoomFactor: 4 onAlert: console.log(message) function doZoom(zoom,centerX,centerY) { if (centerX) { - var sc = zoom/zoomFactor; + var sc = zoom/contentsScale; scaleAnim.to = sc; flickVX.from = flickable.viewportX flickVX.to = Math.max(0,Math.min(centerX-flickable.width/2,webView.width*sc-flickable.width)) @@ -214,17 +215,28 @@ Item { } } + Keys.onLeftPressed: webView.contentsScale -= 0.1 + Keys.onRightPressed: webView.contentsScale += 0.1 + preferredWidth: flickable.width preferredHeight: flickable.height - zoomFactor: flickable.width > 980 ? 1 : flickable.width/980 - - onUrlChanged: { if (url != null) { editUrl.text = url.toString(); } } + contentsScale: 1/zoomFactor + onContentsSizeChanged: { + // zoom out + contentsScale = flickable.width / contentsSize.width + } + onUrlChanged: { + // got to topleft + flickable.viewportX = 0 + flickable.viewportY = 0 + if (url != null) { editUrl.text = url.toString(); } + } onDoubleClick: { if (!heuristicZoom(clickX,clickY,2.5)) { - var zf = flickable.width > 980 ? 1 : flickable.width/980; - if (zf > zoomFactor) - zf = 2.0 // zoom in (else zooming out) - doZoom(zf,clickX/zoomFactor*zf,clickY/zoomFactor*zf) + var zf = flickable.width / contentsSize.width + if (zf >= contentsScale) + zf = 2.0/zoomFactor // zoom in (else zooming out) + doZoom(zf,clickX*zf,clickY*zf) } } @@ -268,7 +280,7 @@ Item { PropertyAction { id: finalZoom target: webView - property: "zoomFactor" + property: "contentsScale" } PropertyAction { target: webView @@ -277,7 +289,7 @@ Item { } // Have to set the viewportXY, since the above 2 // size changes may have started a correction if - // zoomFactor < 1.0. + // contentsScale < 1.0. PropertyAction { id: finalX target: flickable diff --git a/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp b/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp index 948f69a..b4bb361 100644 --- a/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp +++ b/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp @@ -50,6 +50,7 @@ #include <QGraphicsSceneMouseEvent> #include <QPainter> #include <QPaintEngine> +#include <qmath.h> QT_BEGIN_NAMESPACE @@ -98,9 +99,13 @@ static int inpaint_clearcache=0; void QmlGraphicsPaintedItem::dirtyCache(const QRect& rect) { Q_D(QmlGraphicsPaintedItem); + QRect srect(qCeil(rect.x()*d->contentsScale), + qCeil(rect.y()*d->contentsScale), + qCeil(rect.width()*d->contentsScale), + qCeil(rect.height()*d->contentsScale)); for (int i=0; i < d->imagecache.count(); ) { QmlGraphicsPaintedItemPrivate::ImageCacheItem *c = d->imagecache[i]; - QRect isect = (c->area & rect) | c->dirty; + QRect isect = (c->area & srect) | c->dirty; if (isect == c->area && !inpaint) { delete d->imagecache.takeAt(i); } else { @@ -147,10 +152,32 @@ void QmlGraphicsPaintedItem::setContentsSize(const QSize &size) Q_D(QmlGraphicsPaintedItem); if (d->contentsSize == size) return; d->contentsSize = size; + setImplicitWidth(size.width()*d->contentsScale); + setImplicitHeight(size.height()*d->contentsScale); clearCache(); update(); + emit contentsSizeChanged(); } +qreal QmlGraphicsPaintedItem::contentsScale() const +{ + Q_D(const QmlGraphicsPaintedItem); + return d->contentsScale; +} + +void QmlGraphicsPaintedItem::setContentsScale(qreal scale) +{ + Q_D(QmlGraphicsPaintedItem); + if (d->contentsScale == scale) return; + d->contentsScale = scale; + setImplicitWidth(d->contentsSize.width()*scale); + setImplicitHeight(d->contentsSize.height()*scale); + clearCache(); + update(); + emit contentsScaleChanged(); +} + + /*! Constructs a new QmlGraphicsPaintedItem with the given \a parent. */ @@ -204,7 +231,8 @@ void QmlGraphicsPaintedItem::setCacheFrozen(bool frozen) void QmlGraphicsPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QmlGraphicsPaintedItem); - const QRect content(QPoint(0,0),d->contentsSize); + const QRect content(0,0,qCeil(d->contentsSize.width()*d->contentsScale), + qCeil(d->contentsSize.height()*d->contentsScale)); if (content.width() <= 0 || content.height() <= 0) return; @@ -244,21 +272,27 @@ void QmlGraphicsPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem * if (!d->cachefrozen) { if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) { QPainter qp(&d->imagecache[i]->image); - qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache); + qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache); qp.translate(-area.x(), -area.y()); + qp.scale(d->contentsScale,d->contentsScale); + QRect clip = d->imagecache[i]->dirty; + QRect sclip(qFloor(clip.x()/d->contentsScale), + qFloor(clip.y()/d->contentsScale), + qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)), + qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale))); + qp.setClipRect(sclip); if (d->fillColor.isValid()){ if(d->fillColor.alpha() < 255){ // ### Might not work outside of raster paintengine QPainter::CompositionMode prev = qp.compositionMode(); qp.setCompositionMode(QPainter::CompositionMode_Source); - qp.fillRect(d->imagecache[i]->dirty,d->fillColor); + qp.fillRect(sclip,d->fillColor); qp.setCompositionMode(prev); }else{ - qp.fillRect(d->imagecache[i]->dirty,d->fillColor); + qp.fillRect(sclip,d->fillColor); } } - qp.setClipRect(d->imagecache[i]->dirty); - drawContents(&qp, d->imagecache[i]->dirty); + drawContents(&qp, sclip); d->imagecache[i]->dirty = QRect(); } } @@ -300,10 +334,15 @@ void QmlGraphicsPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem * img.fill(d->fillColor); { QPainter qp(&img); - qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache); + qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache); qp.translate(-r.x(),-r.y()); - drawContents(&qp, r); + qp.scale(d->contentsScale,d->contentsScale); + QRect sclip(qFloor(r.x()/d->contentsScale), + qFloor(r.y()/d->contentsScale), + 1+qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)), + 1+qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale))); + drawContents(&qp, sclip); } QmlGraphicsPaintedItemPrivate::ImageCacheItem *newitem = new QmlGraphicsPaintedItemPrivate::ImageCacheItem; newitem->area = r; diff --git a/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h b/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h index f6bb078..d59f6d1 100644 --- a/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h +++ b/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h @@ -56,10 +56,11 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsPaintedItem : public QmlGraphicsItem { Q_OBJECT - Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize) + Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged) Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged) Q_PROPERTY(int pixelCacheSize READ pixelCacheSize WRITE setPixelCacheSize) Q_PROPERTY(bool smoothCache READ smoothCache WRITE setSmoothCache) + Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged) public: @@ -69,6 +70,9 @@ public: QSize contentsSize() const; void setContentsSize(const QSize &); + qreal contentsScale() const; + void setContentsScale(qreal); + int pixelCacheSize() const; void setPixelCacheSize(int pixels); @@ -89,6 +93,8 @@ protected: Q_SIGNALS: void fillColorChanged(); + void contentsSizeChanged(); + void contentsScaleChanged(); protected Q_SLOTS: void dirtyCache(const QRect &); diff --git a/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h b/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h index a49bbdf..6bcc51a 100644 --- a/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h @@ -63,7 +63,7 @@ class QmlGraphicsPaintedItemPrivate : public QmlGraphicsItemPrivate public: QmlGraphicsPaintedItemPrivate() - : max_imagecache_size(100000), fillColor(Qt::transparent), cachefrozen(false), smoothCache(true) + : max_imagecache_size(100000), contentsScale(1.0), fillColor(Qt::transparent), cachefrozen(false), smoothCache(true) { } @@ -80,6 +80,7 @@ public: int max_imagecache_size; QSize contentsSize; + qreal contentsScale; QColor fillColor; bool cachefrozen; bool smoothCache; diff --git a/src/declarative/graphicsitems/qmlgraphicswebview.cpp b/src/declarative/graphicsitems/qmlgraphicswebview.cpp index 0a1587e..c9ba37b 100644 --- a/src/declarative/graphicsitems/qmlgraphicswebview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicswebview.cpp @@ -349,7 +349,9 @@ void QmlGraphicsWebView::setPreferredWidth(int iw) Q_D(QmlGraphicsWebView); if (d->preferredwidth == iw) return; d->preferredwidth = iw; - expandToWebPage(); + if (d->preferredwidth > 0 && d->preferredheight > 0) + page()->setPreferredContentsSize(QSize(d->preferredwidth,d->preferredheight)); + //expandToWebPage(); emit preferredWidthChanged(); } @@ -368,6 +370,8 @@ void QmlGraphicsWebView::setPreferredHeight(int ih) Q_D(QmlGraphicsWebView); if (d->preferredheight == ih) return; d->preferredheight = ih; + if (d->preferredwidth > 0 && d->preferredheight > 0) + page()->setPreferredContentsSize(QSize(d->preferredwidth,d->preferredheight)); emit preferredHeightChanged(); } @@ -397,7 +401,7 @@ void QmlGraphicsWebView::initialLayout() // nothing useful to do at this point } -void QmlGraphicsWebView::contentsSizeChanged(const QSize&) +void QmlGraphicsWebView::noteContentsSizeChanged(const QSize&) { expandToWebPage(); } @@ -416,10 +420,9 @@ void QmlGraphicsWebView::expandToWebPage() cs.setHeight(height()); if (cs != page()->viewportSize()) { page()->setViewportSize(cs); - clearCache(); - setImplicitWidth(cs.width()); - setImplicitHeight(cs.height()); } + if (cs != contentsSize()) + setContentsSize(cs); } void QmlGraphicsWebView::geometryChanged(const QRectF &newGeometry, @@ -432,9 +435,6 @@ void QmlGraphicsWebView::geometryChanged(const QRectF &newGeometry, void QmlGraphicsWebView::paintPage(const QRect& r) { - Q_D(QmlGraphicsWebView); - if (d->page->mainFrame()->contentsSize() != contentsSize()) - setContentsSize(d->page->mainFrame()->contentsSize()); dirtyCache(r); update(); } @@ -536,7 +536,7 @@ void QmlGraphicsWebView::drawContents(QPainter *p, const QRect &r) page()->mainFrame()->render(p,r); } -static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e) +QMouseEvent *QmlGraphicsWebView::sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e) { QEvent::Type t; switch(e->type()) { @@ -555,15 +555,15 @@ static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e) break; } - QMouseEvent *me = new QMouseEvent(t, e->pos().toPoint(), e->button(), e->buttons(), 0); + QMouseEvent *me = new QMouseEvent(t, (e->pos()/contentsScale()).toPoint(), e->button(), e->buttons(), 0); return me; } -static QMouseEvent *sceneHoverMoveEventToMouseEvent(QGraphicsSceneHoverEvent *e) +QMouseEvent *QmlGraphicsWebView::sceneHoverMoveEventToMouseEvent(QGraphicsSceneHoverEvent *e) { QEvent::Type t = QEvent::MouseMove; - QMouseEvent *me = new QMouseEvent(t, e->pos().toPoint(), Qt::NoButton, Qt::NoButton, 0); + QMouseEvent *me = new QMouseEvent(t, (e->pos()/contentsScale()).toPoint(), Qt::NoButton, Qt::NoButton, 0); return me; } @@ -601,15 +601,15 @@ void QmlGraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) bool QmlGraphicsWebView::heuristicZoom(int clickX, int clickY, qreal maxzoom) { Q_D(QmlGraphicsWebView); - qreal ozf = zoomFactor(); - if (ozf >= maxzoom) + if (contentsScale() >= maxzoom/zoomFactor()) return false; + qreal ozf = contentsScale(); QRect showarea = elementAreaAt(clickX, clickY, d->preferredwidth/maxzoom, d->preferredheight/maxzoom); - qreal z = qMin(qreal(d->preferredwidth)*ozf/showarea.width(),qreal(d->preferredheight)*ozf/showarea.height()); - if (z > maxzoom) - z = maxzoom; - if (z/ozf > 1.1) { - QRectF r(showarea.left()/ozf*z, showarea.top()/ozf*z, showarea.width()/ozf*z, showarea.height()/ozf*z); + qreal z = qMin(qreal(d->preferredwidth)/showarea.width(),qreal(d->preferredheight)/showarea.height()); + if (z > maxzoom/zoomFactor()) + z = maxzoom/zoomFactor(); + if (z/ozf > 1.2) { + QRectF r(showarea.left()*z, showarea.top()*z, showarea.width()*z, showarea.height()*z); emit zoomTo(z,r.x()+r.width()/2, r.y()+r.height()/2); return true; } else { @@ -963,7 +963,7 @@ void QmlGraphicsWebView::setPage(QWebPage *page) connect(d->page->mainFrame(),SIGNAL(urlChanged(QUrl)),this,SLOT(pageUrlChanged())); connect(d->page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString))); connect(d->page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged())); - connect(d->page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SLOT(contentsSizeChanged(QSize))); + connect(d->page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SLOT(noteContentsSizeChanged(QSize))); connect(d->page->mainFrame(), SIGNAL(initialLayoutCompleted()), this, SLOT(initialLayout())); connect(d->page,SIGNAL(loadStarted()),this,SLOT(doLoadStarted())); @@ -1204,6 +1204,7 @@ QString QmlGraphicsWebPage::chooseFile(QWebFrame *originatingFrame, const QStrin void QmlGraphicsWebPage::javaScriptAlert(QWebFrame *originatingFrame, const QString& msg) { + Q_UNUSED(originatingFrame) emit viewItem()->alert(msg); } @@ -1218,6 +1219,10 @@ bool QmlGraphicsWebPage::javaScriptConfirm(QWebFrame *originatingFrame, const QS bool QmlGraphicsWebPage::javaScriptPrompt(QWebFrame *originatingFrame, const QString& msg, const QString& defaultValue, QString* result) { // Not supported (it's modal) + Q_UNUSED(originatingFrame) + Q_UNUSED(msg) + Q_UNUSED(defaultValue) + Q_UNUSED(result) return false; } diff --git a/src/declarative/graphicsitems/qmlgraphicswebview_p.h b/src/declarative/graphicsitems/qmlgraphicswebview_p.h index 1e44263..2280697 100644 --- a/src/declarative/graphicsitems/qmlgraphicswebview_p.h +++ b/src/declarative/graphicsitems/qmlgraphicswebview_p.h @@ -210,7 +210,7 @@ private Q_SLOTS: void setStatusText(const QString&); void windowObjectCleared(); void pageUrlChanged(); - void contentsSizeChanged(const QSize&); + void noteContentsSizeChanged(const QSize&); void initialLayout(); protected: @@ -235,6 +235,8 @@ private: virtual void componentComplete(); Q_DISABLE_COPY(QmlGraphicsWebView) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsWebView) + QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *); + QMouseEvent *sceneHoverMoveEventToMouseEvent(QGraphicsSceneHoverEvent *); friend class QmlGraphicsWebPage; }; |