diff options
Diffstat (limited to 'WebCore/platform/graphics/qt/GraphicsLayerQt.cpp')
-rw-r--r-- | WebCore/platform/graphics/qt/GraphicsLayerQt.cpp | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 11f7384..0fd0f1a 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -136,7 +136,9 @@ public: virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt - void setBaseTransform(const QTransform&); + void setBaseTransform(const TransformationMatrix&); + QTransform computeTransform(const TransformationMatrix& baseTransform) const; + void updateTransform(); // let the compositor-API tell us which properties were changed void notifyChange(ChangeMask); @@ -145,7 +147,7 @@ public: // this is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization // (meaning the sync would happen together with the next draw) // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) - void flushChanges(bool recursive = true); + void flushChanges(bool recursive = true, bool forceTransformUpdate = false); // optimization: when we have an animation running on an element with no contents, that has child-elements with contents, // ALL of them have to have ItemCoordinateCache and not DeviceCoordinateCache @@ -166,7 +168,7 @@ signals: public: GraphicsLayerQt* m_layer; - QTransform m_baseTransform; + TransformationMatrix m_baseTransform; bool m_transformAnimationRunning; bool m_opacityAnimationRunning; QWeakPointer<MaskEffectQt> m_maskEffect; @@ -237,7 +239,10 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) { // we use graphics-view for compositing, not for interactivity setAcceptedMouseButtons(Qt::NoButton); - setEnabled(false); + // we need to have the item enabled, or else wheel events are not + // passed to the parent class implementation of wheelEvent, where + // they are ignored and passed to the item below. + setEnabled(true); // we'll set the cache when we know what's going on setCacheMode(NoCache); @@ -280,18 +285,54 @@ void GraphicsLayerQtImpl::adjustCachingRecursively(bool animationIsRunning) } } -void GraphicsLayerQtImpl::setBaseTransform(const QTransform& transform) +void GraphicsLayerQtImpl::updateTransform() +{ + setBaseTransform(isTransformAnimationRunning() ? m_baseTransform : m_layer->transform()); +} + +void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) +{ + m_baseTransform = baseTransform; + setTransform(computeTransform(baseTransform)); +} + +QTransform GraphicsLayerQtImpl::computeTransform(const TransformationMatrix& baseTransform) const { if (!m_layer) - return; + return baseTransform; + + TransformationMatrix computedTransform; + + // The origin for childrenTransform is always the center of the ancestor which contains the childrenTransform. + // this has to do with how WebCore implements -webkit-perspective and -webkit-perspective-origin, which are the CSS + // attribute that call setChildrenTransform + QPointF offset = -pos() - boundingRect().bottomRight() / 2; + const GraphicsLayerQtImpl* ancestor = this; + while ((ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject()))) { + if (!ancestor->m_state.childrenTransform.isIdentity()) { + offset += ancestor->boundingRect().bottomRight() / 2; + computedTransform + .translate(offset.x(), offset.y()) + .multLeft(ancestor->m_state.childrenTransform) + .translate(-offset.x(), -offset.y()); + break; + } + offset -= ancestor->pos(); + } + + computedTransform.multLeft(baseTransform); + // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible - const qreal x = m_layer->anchorPoint().x() * m_layer->size().width(); - const qreal y = m_layer->anchorPoint().y() * m_layer->size().height(); - setTransform(QTransform::fromTranslate(x, y)); - setTransform(transform, true); - translate(-x, -y); - m_baseTransform = transform; + const qreal originX = m_state.anchorPoint.x() * m_size.width(); + const qreal originY = m_state.anchorPoint.y() * m_size.height(); + computedTransform = TransformationMatrix() + .translate(originX, originY) + .multiply(computedTransform) + .translate(-originX, -originY); + + // now we project to 2D + return QTransform(computedTransform); } bool GraphicsLayerQtImpl::isTransformAnimationRunning() const @@ -357,7 +398,7 @@ void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) m_layer->client()->notifySyncRequired(m_layer); } -void GraphicsLayerQtImpl::flushChanges(bool recursive) +void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform) { // this is the bulk of the work. understanding what the compositor is trying to achieve, // what graphics-view can do, and trying to find a sane common-grounds @@ -425,12 +466,15 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) } } - if (m_changeMask & (TransformChange | AnchorPointChange | SizeChange)) { - // since we convert a percentage-based origin-point to a pixel-based one, - // the anchor-point, transform and size from WebCore all affect the one - // that we give Qt - if (m_state.transform != m_layer->transform() || m_state.anchorPoint != m_layer->anchorPoint() || m_state.size != m_layer->size()) - setBaseTransform(m_layer->transform()); + // FIXME: this is a hack, due to a probable QGraphicsScene bug when rapidly modifying the perspective + // but without this line we get graphic artifacts + if ((m_changeMask & ChildrenTransformChange) && m_state.childrenTransform != m_layer->childrenTransform()) + scene()->update(); + + if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange)) { + // due to the differences between the way WebCore handles transforms and the way Qt handles transforms, + // all these elements affect the transforms of all the descendants. + forceUpdateTransform = true; } if (m_changeMask & (ContentChange | DrawsContentChange | MaskLayerChange)) { @@ -439,8 +483,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) update(); setFlag(ItemHasNoContents, false); - // we only use ItemUsesExtendedStyleOption for HTML content - pixmap can be handled better with regular clipping - setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); break; case ColorContentType: @@ -524,6 +566,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) m_state.drawsContent = m_layer->drawsContent(); m_state.contentsOpaque = m_layer->contentsOpaque(); m_state.backfaceVisibility = m_layer->backfaceVisibility(); + m_state.childrenTransform = m_layer->childrenTransform(); m_currentContent.pixmap = m_pendingContent.pixmap; m_currentContent.contentType = m_pendingContent.contentType; m_currentContent.backgroundColor = m_pendingContent.backgroundColor; @@ -534,6 +577,9 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) afterLayerChanges: + if (forceUpdateTransform) + updateTransform(); + if (!recursive) return; @@ -544,7 +590,7 @@ afterLayerChanges: for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) { if (QGraphicsItem* item = *it) if (GraphicsLayerQtImpl* layer = qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject())) - layer->flushChanges(true); + layer->flushChanges(true, forceUpdateTransform); } } @@ -1013,7 +1059,7 @@ public: // this came up during the compositing/animation LayoutTests // when the animation dies, the transform has to go back to default if (m_layer) - m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); + m_layer.data()->updateTransform(); } // the idea is that we let WebCore manage the transform-operations |