diff options
Diffstat (limited to 'WebCore/rendering')
70 files changed, 1588 insertions, 821 deletions
diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp index 96efbe2..951df9f 100644 --- a/WebCore/rendering/EllipsisBox.cpp +++ b/WebCore/rendering/EllipsisBox.cpp @@ -113,6 +113,7 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } } +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE IntRect boundsRect = IntRect(tx, ty, m_width, m_height); if (visibleToHitTesting() && result.intersects(x, y, boundsRect)) { @@ -129,6 +130,13 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } #endif return true; +======= + IntRect boundsRect = IntRect(tx, ty, m_width, m_height); + if (visibleToHitTesting() && boundsRect.intersects(result.rectFromPoint(x, y))) { + renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); + if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, boundsRect)) + return true; +>>>>>>> webkit.org at r64523 } return false; diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp index 8a4ef3c..e1dfecb 100644 --- a/WebCore/rendering/HitTestResult.cpp +++ b/WebCore/rendering/HitTestResult.cpp @@ -49,9 +49,11 @@ using namespace HTMLNames; HitTestResult::HitTestResult(const IntPoint& point) : m_point(point) , m_isOverWidget(false) + , m_isRectBased(false) { } +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE HitTestResult::HitTestResult(const IntPoint& point, const IntSize& padding) : m_point(point) @@ -60,6 +62,17 @@ HitTestResult::HitTestResult(const IntPoint& point, const IntSize& padding) { } #endif +======= +HitTestResult::HitTestResult(const IntPoint& centerPoint, const IntSize& padding) + : m_point(centerPoint) + , m_isOverWidget(false) +{ + // If a zero padding is passed in or either width or height is negative, then it + // is not a valid padding and hence not a rect based hit test. + m_isRectBased = !(padding.isZero() || (padding.width() < 0 || padding.height() < 0)); + m_padding = m_isRectBased ? padding : IntSize(); +} +>>>>>>> webkit.org at r64523 HitTestResult::HitTestResult(const HitTestResult& other) : m_innerNode(other.innerNode()) @@ -74,6 +87,12 @@ HitTestResult::HitTestResult(const HitTestResult& other) , m_rawNodeList(other.rawNodeList()) #endif { + // Only copy the padding and ListHashSet in case of rect hit test. + // Copying the later is rather expensive. + if ((m_isRectBased = other.isRectBasedTest())) { + m_padding = other.padding(); + m_rectBasedTestResult = other.rectBasedTestResult(); + } } HitTestResult::~HitTestResult() @@ -89,10 +108,19 @@ HitTestResult& HitTestResult::operator=(const HitTestResult& other) m_innerURLElement = other.URLElement(); m_scrollbar = other.scrollbar(); m_isOverWidget = other.isOverWidget(); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE m_pointPadding = other.pointPadding(); m_rawNodeList = other.rawNodeList(); #endif +======= + // Only copy the padding and ListHashSet in case of rect hit test. + // Copying the later is rather expensive. + if ((m_isRectBased = other.isRectBasedTest())) { + m_padding = other.padding(); + m_rectBasedTestResult = other.rectBasedTestResult(); + } +>>>>>>> webkit.org at r64523 return *this; } @@ -379,6 +407,7 @@ bool HitTestResult::isContentEditable() const return m_innerNonSharedNode->isContentEditable(); } +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE bool HitTestResult::intersects(int x, int y, const IntRect& other) const @@ -395,6 +424,29 @@ bool HitTestResult::containedBy(int x, int y, const IntRect& other) const void HitTestResult::merge(const HitTestResult& other) { +======= +bool HitTestResult::addNodeToRectBasedTestResult(Node* node, int x, int y, const IntRect& rect) +{ + // If it is not a rect-based hit test, this method has to be no-op. + // Return false, so the hit test stops. + if (!isRectBasedTest()) + return false; + + // If node is null, return true so the hit test can continue. + if (!node) + return true; + + node = node->shadowAncestorNode(); + m_rectBasedTestResult.add(node); + + return !rect.contains(rectFromPoint(x, y)); +} + +void HitTestResult::append(const HitTestResult& other) +{ + ASSERT(isRectBasedTest() && other.isRectBasedTest()); + +>>>>>>> webkit.org at r64523 if (!m_innerNode && other.innerNode()) { m_innerNode = other.innerNode(); m_innerNonSharedNode = other.innerNonSharedNode(); @@ -404,6 +456,7 @@ void HitTestResult::merge(const HitTestResult& other) m_isOverWidget = other.isOverWidget(); } +<<<<<<< HEAD const Vector<RefPtr<Node> >& list = other.rawNodeList(); Vector<RefPtr<Node> >::const_iterator last = list.end(); for (Vector<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) @@ -425,4 +478,12 @@ void HitTestResult::addRawNode(Node* node) #endif // ANDROID_HITTEST_WITHSIZE +======= + const ListHashSet<RefPtr<Node> >& list = other.rectBasedTestResult(); + ListHashSet<RefPtr<Node> >::const_iterator last = list.end(); + for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) + m_rectBasedTestResult.add(it->get()); +} + +>>>>>>> webkit.org at r64523 } // namespace WebCore diff --git a/WebCore/rendering/HitTestResult.h b/WebCore/rendering/HitTestResult.h index 0f45900..6d39e8d 100644 --- a/WebCore/rendering/HitTestResult.h +++ b/WebCore/rendering/HitTestResult.h @@ -21,11 +21,17 @@ #define HitTestResult_h #include "IntPoint.h" +#include "IntRect.h" +#include "IntSize.h" #include "TextDirection.h" +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE #include <IntSize.h> #include <wtf/Vector.h> #endif +======= +#include <wtf/ListHashSet.h> +>>>>>>> webkit.org at r64523 #include <wtf/RefPtr.h> namespace WebCore { @@ -42,6 +48,8 @@ class String; class HitTestResult { public: HitTestResult(const IntPoint&); + // Pass a non-negative IntSize value as padding to perform a rect-based hit test. + HitTestResult(const IntPoint& centerPoint, const IntSize& padding); HitTestResult(const HitTestResult&); ~HitTestResult(); HitTestResult& operator=(const HitTestResult&); @@ -80,6 +88,7 @@ public: bool isLiveLink() const; bool isContentEditable() const; +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE HitTestResult(const IntPoint&, const IntSize&); @@ -92,8 +101,23 @@ public: void addRawNode(Node*); const Vector<RefPtr<Node> >& rawNodeList() const { return m_rawNodeList; } #endif +======= + // Rect-based hit test related methods. + bool isRectBasedTest() const { return m_isRectBased; } + IntRect rectFromPoint(int x, int y) const; + IntRect rectFromPoint(const IntPoint&) const; + IntSize padding() const { return m_padding; } + int paddingWidth() const { return m_padding.width() >= 0 ? m_padding.width() : 0; } + int paddingHeight() const { return m_padding.height() >= 0 ? m_padding.height() : 0; } + // Returns true if it is rect-based hit test and needs to continue until the rect is fully + // enclosed by the boundaries of a node. + bool addNodeToRectBasedTestResult(Node*, int x, int y, const IntRect& rect = IntRect()); + const ListHashSet<RefPtr<Node> >& rectBasedTestResult() const { return m_rectBasedTestResult; } + void append(const HitTestResult&); +>>>>>>> webkit.org at r64523 private: + RefPtr<Node> m_innerNode; RefPtr<Node> m_innerNonSharedNode; IntPoint m_point; @@ -102,13 +126,45 @@ private: RefPtr<Element> m_innerURLElement; RefPtr<Scrollbar> m_scrollbar; bool m_isOverWidget; // Returns true if we are over a widget (and not in the border/padding area of a RenderWidget for example). +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE IntSize m_pointPadding; Vector<RefPtr<Node> > m_rawNodeList; #endif +======= + bool m_isRectBased; + IntSize m_padding; + ListHashSet<RefPtr<Node> > m_rectBasedTestResult; +>>>>>>> webkit.org at r64523 }; +inline IntRect HitTestResult::rectFromPoint(int x, int y) const +{ + return rectFromPoint(IntPoint(x, y)); +} + +// Formula: +// x = p.x() - padding.width() +// y = p.y() - padding.height() +// width = 2 * padding.width() + 1 +// height = 2 * m_padding.height() + 1 +inline IntRect HitTestResult::rectFromPoint(const IntPoint& point) const +{ + IntPoint realPoint(point); + IntSize realPadding(m_padding); + + // Real IntPoint for the rect. + realPadding.clampNegativeToZero(); + realPoint -= realPadding; + + // Real IntSize for the rect. + realPadding.scale(2); + realPadding += IntSize(1, 1); + + return IntRect(realPoint, realPadding); +} + String displayString(const String&, const Node*); } // namespace WebCore diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 8ac8c40..daa48f2 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -611,11 +611,15 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re { IntRect overflowRect(visibleOverflowRect()); overflowRect.move(tx, ty); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (!result.intersects(x, y, overflowRect)) #else if (!overflowRect.contains(x, y)) #endif +======= + if (!overflowRect.intersects(result.rectFromPoint(x, y))) +>>>>>>> webkit.org at r64523 return false; // Check children first. @@ -628,6 +632,7 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re // Now check ourselves. IntRect rect(tx + m_x, ty + m_y, m_width, height()); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (visibleToHitTesting() && result.intersects(x, y, rect)) { #else @@ -643,6 +648,12 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re } #endif return true; +======= + if (visibleToHitTesting() && rect.intersects(result.rectFromPoint(x, y))) { + renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space. + if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, rect)) + return true; +>>>>>>> webkit.org at r64523 } return false; diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index d6bd70c..b0e2887 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -287,6 +287,7 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in return false; IntRect rect(tx + m_x, ty + m_y, m_width, height()); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (m_truncation != cFullTruncation && visibleToHitTesting() && result.intersects(x, y, rect)) { #else @@ -302,6 +303,12 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in } #endif return true; +======= + if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.intersects(result.rectFromPoint(x, y))) { + renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); + if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, rect)) + return true; +>>>>>>> webkit.org at r64523 } return false; } diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 1b855d4..3f369c3 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -3767,16 +3767,21 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Check if we need to do anything at all. IntRect overflowBox = visibleOverflowRect(); overflowBox.move(tx, ty); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (!result.intersects(_x, _y, overflowBox)) #else if (!overflowBox.contains(_x, _y)) #endif +======= + if (!overflowBox.intersects(result.rectFromPoint(_x, _y))) +>>>>>>> webkit.org at r64523 return false; } if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) { updateHitTestResult(result, IntPoint(_x - tx, _y - ty)); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE // TODO: isPointInOverflowControl() doesn't handle region test yet. if (result.isRegionTest()) { @@ -3785,16 +3790,26 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } else #endif return true; +======= + // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet. + if (!result.addNodeToRectBasedTestResult(node(), _x, _y)) + return true; +>>>>>>> webkit.org at r64523 } // If we have clipping, then we can't have any spillout. bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer(); bool useClip = (hasControlClip() || useOverflowClip); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE bool checkChildren = !useClip || (hasControlClip() ? result.intersects(_x, _y, controlClipRect(tx, ty)) : result.intersects(_x, _y, overflowClipRect(tx, ty))); #else bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).contains(_x, _y) : overflowClipRect(tx, ty).contains(_x, _y)); #endif +======= + IntRect hitTestArea(result.rectFromPoint(_x, _y)); + bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).intersects(hitTestArea) : overflowClipRect(tx, ty).intersects(hitTestArea)); +>>>>>>> webkit.org at r64523 if (checkChildren) { // Hit test descendants first. int scrolledX = tx; @@ -3842,6 +3857,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Now hit test our background if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) { IntRect boundsRect(tx, ty, width(), height()); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (visibleToHitTesting() && result.intersects(_x, _y, boundsRect)) { #else @@ -3857,6 +3873,12 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } #endif return true; +======= + if (visibleToHitTesting() && boundsRect.intersects(result.rectFromPoint(_x, _y))) { + updateHitTestResult(result, IntPoint(_x - tx, _y - ty)); + if (!result.addNodeToRectBasedTestResult(node(), _x, _y, boundsRect)) + return true; +>>>>>>> webkit.org at r64523 } } @@ -3881,22 +3903,33 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r currYOffset += colRect.height(); colRect.move(tx, ty); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (result.intersects(x, y, colRect)) { #else if (colRect.contains(x, y)) { #endif +======= + if (colRect.intersects(result.rectFromPoint(x, y))) { +>>>>>>> webkit.org at r64523 // The point is inside this column. // Adjust tx and ty to change where we hit test. int finalX = tx + currXOffset; int finalY = ty + currYOffset; +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (result.isRegionTest() && !result.containedBy(x, y, colRect)) hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); else #endif return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); +======= + if (result.isRectBasedTest() && !colRect.contains(result.rectFromPoint(x, y))) + hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); + else + return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); +>>>>>>> webkit.org at r64523 } } diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 2deeffc..b546893 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -31,6 +31,7 @@ #include "Document.h" #include "FrameView.h" #include "GraphicsContext.h" +#include "HitTestResult.h" #include "htmlediting.h" #include "HTMLElement.h" #include "HTMLNames.h" @@ -568,6 +569,7 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result #else // Check our bounds next. For this purpose always assume that we can only be hit in the // foreground phase (which is true for replaced elements like images). +<<<<<<< HEAD if (visibleToHitTesting() && action == HitTestForeground && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) { #endif updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); @@ -580,6 +582,13 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result } #endif return true; +======= + IntRect boundsRect = IntRect(tx, ty, width(), height()); + if (visibleToHitTesting() && action == HitTestForeground && boundsRect.intersects(result.rectFromPoint(xPos, yPos))) { + updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); + if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect)) + return true; +>>>>>>> webkit.org at r64523 } return false; @@ -1595,7 +1604,7 @@ void RenderBox::calcHeight() && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->height().isPercent())); if (stretchesToViewHeight() || printingNeedsBaseHeight) { int margins = collapsedMarginTop() + collapsedMarginBottom(); - int visHeight = document()->printing() ? view()->frameView()->visibleHeight() : view()->viewHeight(); + int visHeight = document()->printing() ? view()->frameView()->pageHeight() : view()->viewHeight(); if (isRoot()) setHeight(max(height(), visHeight - margins)); else { diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp index 8b84f97..50c1a42 100644 --- a/WebCore/rendering/RenderForeignObject.cpp +++ b/WebCore/rendering/RenderForeignObject.cpp @@ -117,14 +117,16 @@ void RenderForeignObject::layout() // FIXME: Investigate in location rounding issues - only affects RenderForeignObject & RenderSVGText setLocation(roundedIntPoint(viewportLocation)); + + bool layoutChanged = m_everHadLayout && selfNeedsLayout(); RenderBlock::layout(); + ASSERT(!needsLayout()); - // Invalidate all resources of this client, if we changed something. - if (m_everHadLayout && selfNeedsLayout()) - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + // Invalidate all resources of this client if our layout changed. + if (layoutChanged) + SVGResourcesCache::clientLayoutChanged(this); repainter.repaintAfterLayout(); - setNeedsLayout(false); } bool RenderForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) diff --git a/WebCore/rendering/RenderHTMLCanvas.cpp b/WebCore/rendering/RenderHTMLCanvas.cpp index 8c17a0e..c89495b 100644 --- a/WebCore/rendering/RenderHTMLCanvas.cpp +++ b/WebCore/rendering/RenderHTMLCanvas.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "RenderHTMLCanvas.h" +#include "CanvasRenderingContext.h" #include "Document.h" #include "GraphicsContext.h" #include "HTMLCanvasElement.h" @@ -48,12 +49,8 @@ bool RenderHTMLCanvas::requiresLayer() const if (RenderReplaced::requiresLayer()) return true; -#if ENABLE(3D_CANVAS) HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(node()); - return canvas && canvas->is3D(); -#else - return false; -#endif + return canvas && canvas->renderingContext() && canvas->renderingContext()->isAccelerated(); } void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, int tx, int ty) diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 643fac9..3612ed5 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -387,6 +387,7 @@ HTMLMapElement* RenderImage::imageMap() const bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE HitTestResult tempResult(result.point(), result.pointPadding()); #else @@ -399,6 +400,12 @@ bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu #else if (inside && node()) { #endif +======= + HitTestResult tempResult(result.point(), result.padding()); + bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction); + + if (tempResult.innerNode() && node()) { +>>>>>>> webkit.org at r64523 if (HTMLMapElement* map = imageMap()) { IntRect contentBox = contentBoxRect(); float zoom = style()->effectiveZoom(); @@ -409,10 +416,15 @@ bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } } +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (!inside && result.isRegionTest()) result.merge(tempResult); #endif +======= + if (!inside && result.isRectBasedTest()) + result.append(tempResult); +>>>>>>> webkit.org at r64523 if (inside) result = tempResult; return inside; diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 756a9b3..998ffa7 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -1800,6 +1800,9 @@ void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation) { RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar; if (scrollbar) { + if (scrollbar->isCustomScrollbar()) + static_cast<RenderScrollbar*>(scrollbar.get())->clearOwningRenderer(); + scrollbar->removeFromParent(); scrollbar->setClient(0); scrollbar = 0; @@ -2749,18 +2752,24 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont #if USE(ACCELERATED_COMPOSITING) useTemporaryClipRects = compositor()->inCompositingMode(); #endif - + + IntRect hitTestArea = result.rectFromPoint(hitTestPoint); + // Apply a transform if we have one. if (transform() && !appliedTransform) { // Make sure the parent's clip rects have been calculated. if (parent()) { IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects); // Go ahead and test the enclosing clip now. +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (!result.intersects(hitTestPoint.x(), hitTestPoint.y(), clipRect)) #else if (!clipRect.contains(hitTestPoint)) #endif +======= + if (!clipRect.intersects(hitTestArea)) +>>>>>>> webkit.org at r64523 return 0; } @@ -2873,6 +2882,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont } // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (result.intersects(hitTestPoint.x(), hitTestPoint.y(), fgRect) && isSelfPaintingLayer()) { #else @@ -2892,15 +2902,31 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont else #endif result = tempResult; +======= + if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) { + // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost. + HitTestResult tempResult(result.point(), result.padding()); + if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) && + isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { + if (result.isRectBasedTest()) + result.append(tempResult); + else + result = tempResult; +>>>>>>> webkit.org at r64523 if (!depthSortDescendants) return this; // Foreground can depth-sort with descendant layers, so keep this as a candidate. candidateLayer = this; +<<<<<<< HEAD } #ifdef ANDROID_HITTEST_WITHSIZE else if (result.isRegionTest()) result.merge(tempResult); #endif +======= + } else if (result.isRectBasedTest()) + result.append(tempResult); +>>>>>>> webkit.org at r64523 } // Now check our negative z-index children. @@ -2916,6 +2942,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont if (candidateLayer) return candidateLayer; +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (result.intersects(hitTestPoint.x(), hitTestPoint.y(), bgRect) && isSelfPaintingLayer()) { HitTestResult tempResult(result.point(), result.pointPadding()); @@ -2937,6 +2964,19 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont else if (result.isRegionTest()) result.merge(tempResult); #endif +======= + if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) { + HitTestResult tempResult(result.point(), result.padding()); + if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) && + isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { + if (result.isRectBasedTest()) + result.append(tempResult); + else + result = tempResult; + return this; + } else if (result.isRectBasedTest()) + result.append(tempResult); +>>>>>>> webkit.org at r64523 } return 0; @@ -2948,8 +2988,9 @@ bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& layerBounds.x() - renderBoxX(), layerBounds.y() - renderBoxY(), hitTestFilter)) { - // It's wrong to set innerNode, but then claim that you didn't hit anything. - ASSERT(!result.innerNode()); + // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is + // a rect-based test. + ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size())); return false; } @@ -2983,25 +3024,39 @@ RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* r for (int i = list->size() - 1; i >= 0; --i) { RenderLayer* childLayer = list->at(i); RenderLayer* hitLayer = 0; +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE HitTestResult tempResult(result.point(), result.pointPadding()); #else HitTestResult tempResult(result.point()); #endif +======= + HitTestResult tempResult(result.point(), result.padding()); +>>>>>>> webkit.org at r64523 if (childLayer->isPaginated()) hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants); else hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (result.isRegionTest()) result.merge(tempResult); #endif +======= + + // If it a rect-based test, we can safely append the temporary result since it might had hit + // nodes but not necesserily had hitLayer set. + if (result.isRectBasedTest()) + result.append(tempResult); + +>>>>>>> webkit.org at r64523 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) { #ifdef ANDROID_HITTEST_WITHSIZE if (!result.isRegionTest()) #endif resultLayer = hitLayer; - result = tempResult; + if (!result.isRectBasedTest()) + result = tempResult; if (!depthSortDescendants) break; } @@ -3061,7 +3116,7 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend IntRect localClipRect(hitTestRect); localClipRect.intersect(colRect); - if (!localClipRect.isEmpty() && localClipRect.contains(hitTestPoint)) { + if (!localClipRect.isEmpty() && localClipRect.intersects(result.rectFromPoint(hitTestPoint))) { RenderLayer* hitLayer = 0; if (!columnIndex) { // Apply a translation transform to change where the layer paints. diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index d66dfc2..e1cf2a2 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -666,6 +666,9 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const if (hasBoxDecorationsOrBackground(renderObject)) return false; + if (m_owningLayer->hasOverflowControls()) + return false; + // If we have got this far and the renderer has no children, then we're ok. if (!renderObject->firstChild()) return true; @@ -694,26 +697,23 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const if (hasBoxDecorationsOrBackgroundImage(style)) return false; - // Ceck to see if all the body's children are compositing layers. - if (hasNonCompositingContent()) + // Check to see if all the body's children are compositing layers. + if (hasNonCompositingDescendants()) return false; return true; } // Check to see if all the renderer's children are compositing layers. - if (hasNonCompositingContent()) + if (hasNonCompositingDescendants()) return false; return true; } // Conservative test for having no rendered children. -bool RenderLayerBacking::hasNonCompositingContent() const +bool RenderLayerBacking::hasNonCompositingDescendants() const { - if (m_owningLayer->hasOverflowControls()) - return true; - // Some HTML can cause whitespace text nodes to have renderers, like: // <div> // <img src=...> @@ -911,7 +911,7 @@ FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const Graphics bool RenderLayerBacking::paintingGoesToWindow() const { if (m_owningLayer->isRootLayer()) - return compositor()->rootLayerAttachment() == RenderLayerCompositor::RootLayerAttachedViaChromeClient; + return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingIframe; return false; } diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index 852fc04..808000b 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -173,7 +173,7 @@ private: bool rendererHasBackground() const; const Color rendererBackgroundColor() const; - bool hasNonCompositingContent() const; + bool hasNonCompositingDescendants() const; void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior paintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index 3d16864..b60dec9 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -29,6 +29,7 @@ #include "RenderLayerCompositor.h" #include "AnimationController.h" +#include "CanvasRenderingContext.h" #include "CSSPropertyNames.h" #include "Chrome.h" #include "ChromeClient.h" @@ -1271,14 +1272,10 @@ bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const { -#if ENABLE(3D_CANVAS) if (renderer->isCanvas()) { HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); - return canvas->is3D(); + return canvas->renderingContext() && canvas->renderingContext()->isAccelerated(); } -#else - UNUSED_PARAM(renderer); -#endif return false; } diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 3e4c882..06aab89 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "RenderLineBoxList.h" +#include "HitTestResult.h" #include "InlineTextBox.h" #ifdef ANDROID_HITTEST_WITHSIZE #include "HitTestResult.h" @@ -248,22 +249,32 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq // contain the point. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in the following extremely obscure way: // if some line in the middle has a huge overflow, it might actually extend below the last line. +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if ((y - result.pointPadding().height() >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y + result.pointPadding().height() < ty + firstLineBox()->root()->topVisibleOverflow())) #else if ((y >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y < ty + firstLineBox()->root()->topVisibleOverflow())) #endif +======= + if (y - result.paddingHeight() >= ty + lastLineBox()->root()->bottomVisibleOverflow() + || y + result.paddingHeight() < ty + firstLineBox()->root()->topVisibleOverflow()) +>>>>>>> webkit.org at r64523 return false; // See if our root lines contain the point. If so, then we hit test // them further. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) { +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (y + result.pointPadding().height() >= ty + curr->root()->topVisibleOverflow() && y - result.pointPadding().height() < ty + curr->root()->bottomVisibleOverflow()) { #else if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) { #endif +======= + if (y + result.paddingHeight() >= ty + curr->root()->topVisibleOverflow() + && y - result.paddingHeight() < ty + curr->root()->bottomVisibleOverflow()) { +>>>>>>> webkit.org at r64523 bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); if (inside) { renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty)); diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp index ff16e7e..b6a97a9 100644 --- a/WebCore/rendering/RenderMenuList.cpp +++ b/WebCore/rendering/RenderMenuList.cpp @@ -26,6 +26,7 @@ #include "RenderMenuList.h" #include "AXObjectCache.h" +#include "Chrome.h" #include "CSSStyleSelector.h" #include "Frame.h" #include "FrameView.h" @@ -88,8 +89,8 @@ void RenderMenuList::adjustInnerStyle() m_innerBlock->style()->setPaddingRight(Length(theme()->popupInternalPaddingRight(style()), Fixed)); m_innerBlock->style()->setPaddingTop(Length(theme()->popupInternalPaddingTop(style()), Fixed)); m_innerBlock->style()->setPaddingBottom(Length(theme()->popupInternalPaddingBottom(style()), Fixed)); - - if (PopupMenu::itemWritingDirectionIsNatural()) { + + if (document()->page()->chrome()->selectItemWritingDirectionIsNatural()) { // Items in the popup will not respect the CSS text-align and direction properties, // so we must adjust our own style to match. m_innerBlock->style()->setTextAlign(LEFT); @@ -278,7 +279,7 @@ void RenderMenuList::showPopup() // inside the showPopup call and it would fail. createInnerBlock(); if (!m_popup) - m_popup = PopupMenu::create(this); + m_popup = document()->page()->chrome()->createPopupMenu(this); SelectElement* select = toSelectElement(static_cast<Element*>(node())); m_popupIsVisible = true; diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h index aef8d4f..512fa9b 100644 --- a/WebCore/rendering/RenderMenuList.h +++ b/WebCore/rendering/RenderMenuList.h @@ -24,6 +24,7 @@ #ifndef RenderMenuList_h #define RenderMenuList_h +#include "PopupMenu.h" #include "PopupMenuClient.h" #include "RenderFlexibleBox.h" @@ -35,7 +36,6 @@ namespace WebCore { -class PopupMenu; class RenderText; #if ENABLE(NO_LISTBOX_RENDERING) diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 3f78e45..46169d0 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -38,7 +38,7 @@ #include "TransformationMatrix.h" #include <wtf/UnusedParam.h> -#if PLATFORM(CG) +#if PLATFORM(CG) || PLATFORM(CAIRO) #define HAVE_PATH_BASED_BORDER_RADIUS_DRAWING 1 #endif diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index dd79397..915be5d 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -35,11 +35,12 @@ #include "PointerEventsHitRules.h" #include "RenderSVGContainer.h" #include "RenderSVGResourceMarker.h" -#include "StrokeStyleApplier.h" #include "SVGRenderSupport.h" +#include "SVGResources.h" #include "SVGStyledTransformableElement.h" #include "SVGTransformList.h" #include "SVGURIReference.h" +#include "StrokeStyleApplier.h" #include <wtf/MathExtras.h> namespace WebCore { @@ -72,7 +73,7 @@ RenderPath::RenderPath(SVGStyledTransformableElement* node) { } -bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill, WindRule fillRule) const +bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill, WindRule fillRule) { if (!m_fillBoundingBox.contains(point)) return false; @@ -83,7 +84,7 @@ bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill, WindRu return m_path.contains(point, fillRule); } -bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const +bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) { if (!m_strokeAndMarkerBoundingBox.contains(point)) return false; @@ -111,9 +112,9 @@ void RenderPath::layout() m_needsTransformUpdate = false; } - // Invalidate all resources of this client, if we changed something. + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientLayoutChanged(this); // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds @@ -234,8 +235,6 @@ bool RenderPath::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& FloatRect RenderPath::calculateMarkerBoundsIfNeeded() { - Document* doc = document(); - SVGElement* svgElement = static_cast<SVGElement*>(node()); ASSERT(svgElement && svgElement->document()); if (!svgElement->isStyled()) @@ -248,39 +247,24 @@ FloatRect RenderPath::calculateMarkerBoundsIfNeeded() const SVGRenderStyle* svgStyle = style()->svgStyle(); ASSERT(svgStyle->hasMarkers()); - AtomicString startMarkerId(svgStyle->markerStartResource()); - AtomicString midMarkerId(svgStyle->markerMidResource()); - AtomicString endMarkerId(svgStyle->markerEndResource()); - - RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, startMarkerId); - RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, midMarkerId); - RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, endMarkerId); - - if (!startMarker && !startMarkerId.isEmpty()) - svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement); - else if (startMarker) - startMarker->addClient(this); - - if (!midMarker && !midMarkerId.isEmpty()) - svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement); - else if (midMarker) - midMarker->addClient(this); - - if (!endMarker && !endMarkerId.isEmpty()) - svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement); - else if (endMarker) - endMarker->addClient(this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); + if (!resources) + return FloatRect(); - if (!startMarker && !midMarker && !endMarker) + RenderSVGResourceMarker* markerStart = resources->markerStart(); + RenderSVGResourceMarker* markerMid = resources->markerMid(); + RenderSVGResourceMarker* markerEnd = resources->markerEnd(); + if (!markerStart && !markerMid && !markerEnd) return FloatRect(); float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f); - return m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path); + return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, strokeWidth, m_path); } void RenderPath::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) { - setNeedsBoundariesUpdate(); + if (diff == StyleDifferenceLayout) + setNeedsBoundariesUpdate(); RenderSVGModelObject::styleWillChange(diff, newStyle); } diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h index 3748f39..57900ad 100644 --- a/WebCore/rendering/RenderPath.h +++ b/WebCore/rendering/RenderPath.h @@ -47,8 +47,8 @@ public: private: // Hit-detection seperated for the fill and the stroke - bool fillContains(const FloatPoint&, bool requiresFill = true, WindRule fillRule = RULE_NONZERO) const; - bool strokeContains(const FloatPoint&, bool requiresStroke = true) const; + bool fillContains(const FloatPoint&, bool requiresFill = true, WindRule fillRule = RULE_NONZERO); + bool strokeContains(const FloatPoint&, bool requiresStroke = true); virtual FloatRect objectBoundingBox() const { return m_fillBoundingBox; } virtual FloatRect strokeBoundingBox() const { return m_strokeAndMarkerBoundingBox; } diff --git a/WebCore/rendering/RenderSVGBlock.cpp b/WebCore/rendering/RenderSVGBlock.cpp index 2bae158..d6022b5 100644 --- a/WebCore/rendering/RenderSVGBlock.cpp +++ b/WebCore/rendering/RenderSVGBlock.cpp @@ -25,6 +25,7 @@ #if ENABLE(SVG) #include "RenderSVGBlock.h" +#include "RenderSVGResource.h" #include "SVGElement.h" namespace WebCore { @@ -73,6 +74,25 @@ void RenderSVGBlock::absoluteRects(Vector<IntRect>&, int, int) // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used. ASSERT_NOT_REACHED(); } + +void RenderSVGBlock::destroy() +{ + SVGResourcesCache::clientDestroyed(this); + RenderBlock::destroy(); +} + +void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderBlock::styleDidChange(diff, oldStyle); + SVGResourcesCache::clientStyleChanged(this, diff, style()); +} + +void RenderSVGBlock::updateFromElement() +{ + RenderBlock::updateFromElement(); + SVGResourcesCache::clientUpdatedFromElement(this, style()); +} + } #endif diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h index 8dd140b..c4337cc 100644 --- a/WebCore/rendering/RenderSVGBlock.h +++ b/WebCore/rendering/RenderSVGBlock.h @@ -38,6 +38,10 @@ private: virtual void updateBoxModelInfoFromStyle(); virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); + + virtual void destroy(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual void updateFromElement(); }; } diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp index ad63771..bab07a4 100644 --- a/WebCore/rendering/RenderSVGContainer.cpp +++ b/WebCore/rendering/RenderSVGContainer.cpp @@ -31,6 +31,7 @@ #include "RenderSVGResourceFilter.h" #include "RenderView.h" #include "SVGRenderSupport.h" +#include "SVGResources.h" #include "SVGStyledElement.h" namespace WebCore { @@ -58,23 +59,22 @@ void RenderSVGContainer::layout() SVGRenderSupport::layoutChildren(this, selfNeedsLayout()); - // Invalidate all resources of this client, if we changed something. + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientLayoutChanged(this); repainter.repaintAfterLayout(); setNeedsLayout(false); } -bool RenderSVGContainer::selfWillPaint() const +bool RenderSVGContainer::selfWillPaint() { #if ENABLE(FILTERS) - const SVGRenderStyle* svgStyle = style()->svgStyle(); - RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), svgStyle->filterResource()); - if (filter) - return true; -#endif + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); + return resources && resources->filter(); +#else return false; +#endif } void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h index 53f1a97..0a122cd 100644 --- a/WebCore/rendering/RenderSVGContainer.h +++ b/WebCore/rendering/RenderSVGContainer.h @@ -69,7 +69,7 @@ protected: virtual void applyViewportClip(PaintInfo&) { } virtual bool pointIsInsideViewportClip(const FloatPoint& /*pointInParent*/) { return true; } - bool selfWillPaint() const; + bool selfWillPaint(); private: RenderObjectChildList m_children; diff --git a/WebCore/rendering/RenderSVGGradientStop.cpp b/WebCore/rendering/RenderSVGGradientStop.cpp index 754f31f..3494aa7 100644 --- a/WebCore/rendering/RenderSVGGradientStop.cpp +++ b/WebCore/rendering/RenderSVGGradientStop.cpp @@ -25,8 +25,10 @@ #if ENABLE(SVG) #include "RenderSVGGradientStop.h" +#include "RenderSVGResourceContainer.h" #include "SVGGradientElement.h" #include "SVGNames.h" +#include "SVGResourcesCache.h" #include "SVGStopElement.h" namespace WebCore { @@ -48,8 +50,17 @@ void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderSty // <stop> elements should only be allowed to make renderers under gradient elements // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient. - if (SVGGradientElement* gradient = gradientElement()) - gradient->invalidateResourceClients(); + SVGGradientElement* gradient = gradientElement(); + if (!gradient) + return; + + RenderObject* renderer = gradient->renderer(); + if (!renderer) + return; + + ASSERT(renderer->isSVGResourceContainer()); + RenderSVGResourceContainer* container = renderer->toRenderSVGResourceContainer(); + container->invalidateClients(); } void RenderSVGGradientStop::layout() diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h index 297a738..e0daac1 100644 --- a/WebCore/rendering/RenderSVGHiddenContainer.h +++ b/WebCore/rendering/RenderSVGHiddenContainer.h @@ -24,7 +24,6 @@ #define RenderSVGHiddenContainer_h #if ENABLE(SVG) - #include "RenderSVGContainer.h" namespace WebCore { @@ -39,11 +38,13 @@ namespace WebCore { virtual const char* renderName() const { return "RenderSVGHiddenContainer"; } + protected: + virtual void layout(); + private: virtual bool isSVGHiddenContainer() const { return true; } virtual bool requiresLayer() const { return false; } - virtual void layout(); virtual void paint(PaintInfo&, int parentX, int parentY); virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 44b68b1..5a92e33 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -39,6 +39,7 @@ #include "SVGLength.h" #include "SVGPreserveAspectRatio.h" #include "SVGRenderSupport.h" +#include "SVGResources.h" namespace WebCore { @@ -70,9 +71,9 @@ void RenderSVGImage::layout() m_localBounds = FloatRect(image->x().value(image), image->y().value(image), image->width().value(image), image->height().value(image)); m_cachedLocalRepaintRect = FloatRect(); - // Invalidate all resources of this client, if we changed something. + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientLayoutChanged(this); repainter.repaintAfterLayout(); setNeedsLayout(false); @@ -110,10 +111,22 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) void RenderSVGImage::destroy() { - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientDestroyed(this); RenderImage::destroy(); } +void RenderSVGImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderImage::styleDidChange(diff, oldStyle); + SVGResourcesCache::clientStyleChanged(this, diff, style()); +} + +void RenderSVGImage::updateFromElement() +{ + RenderImage::updateFromElement(); + SVGResourcesCache::clientUpdatedFromElement(this, style()); +} + bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. @@ -160,12 +173,12 @@ FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect) { RenderImage::imageChanged(image, rect); -#if ENABLE(FILTERS) + // The image resource defaults to nullImage until the resource arrives. - // This empty image may be cached by SVG filter effects which must be invalidated. - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), style()->svgStyle()->filterResource())) - filter->invalidateClient(this); -#endif + // This empty image may be cached by SVG resources which must be invalidated. + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this)) + resources->invalidateClient(this); + repaint(); } diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index 3baac23..6ee0179 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -65,6 +65,8 @@ private: virtual void paint(PaintInfo&, int parentX, int parentY); virtual void destroy(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual void updateFromElement(); virtual bool requiresLayer() const { return false; } diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp index ffc6b62..93e6a06 100644 --- a/WebCore/rendering/RenderSVGInline.cpp +++ b/WebCore/rendering/RenderSVGInline.cpp @@ -26,6 +26,7 @@ #if ENABLE(SVG) #include "RenderSVGInline.h" +#include "RenderSVGResource.h" #include "SVGInlineFlowBox.h" namespace WebCore { @@ -92,6 +93,24 @@ void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads) quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->width(), box->height()))); } +void RenderSVGInline::destroy() +{ + SVGResourcesCache::clientDestroyed(this); + RenderInline::destroy(); +} + +void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderInline::styleDidChange(diff, oldStyle); + SVGResourcesCache::clientStyleChanged(this, diff, style()); +} + +void RenderSVGInline::updateFromElement() +{ + RenderInline::updateFromElement(); + SVGResourcesCache::clientUpdatedFromElement(this, style()); +} + } diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h index 6f44162..56d911f 100644 --- a/WebCore/rendering/RenderSVGInline.h +++ b/WebCore/rendering/RenderSVGInline.h @@ -54,6 +54,10 @@ public: private: virtual InlineFlowBox* createInlineFlowBox(); + + virtual void destroy(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual void updateFromElement(); }; } diff --git a/WebCore/rendering/RenderSVGModelObject.cpp b/WebCore/rendering/RenderSVGModelObject.cpp index 49404cb..5a19749 100644 --- a/WebCore/rendering/RenderSVGModelObject.cpp +++ b/WebCore/rendering/RenderSVGModelObject.cpp @@ -83,16 +83,20 @@ void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads) void RenderSVGModelObject::destroy() { - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientDestroyed(this); RenderObject::destroy(); } void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderObject::styleDidChange(diff, oldStyle); + SVGResourcesCache::clientStyleChanged(this, diff, style()); +} - if (style() && (diff == StyleDifferenceLayout || diff == StyleDifferenceRepaint)) - RenderSVGResource::markForLayoutAndParentResourceInvalidation(this, false); +void RenderSVGModelObject::updateFromElement() +{ + RenderObject::updateFromElement(); + SVGResourcesCache::clientUpdatedFromElement(this, style()); } bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h index 741cd61..35c4dc3 100644 --- a/WebCore/rendering/RenderSVGModelObject.h +++ b/WebCore/rendering/RenderSVGModelObject.h @@ -62,6 +62,7 @@ public: virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual void updateFromElement(); private: // This method should never be called, SVG uses a different nodeAtPoint method diff --git a/WebCore/rendering/RenderSVGResource.cpp b/WebCore/rendering/RenderSVGResource.cpp index b4f499e..9c89d3c 100644 --- a/WebCore/rendering/RenderSVGResource.cpp +++ b/WebCore/rendering/RenderSVGResource.cpp @@ -26,28 +26,13 @@ #if ENABLE(SVG) #include "RenderSVGResource.h" -#include "RenderSVGResourceClipper.h" #include "RenderSVGResourceContainer.h" -#include "RenderSVGResourceFilter.h" -#include "RenderSVGResourceMarker.h" -#include "RenderSVGResourceMasker.h" #include "RenderSVGResourceSolidColor.h" +#include "SVGResources.h" #include "SVGURIReference.h" namespace WebCore { -static inline void registerPendingResource(const AtomicString& id, const SVGPaint::SVGPaintType& paintType, const RenderObject* object) -{ - if (paintType != SVGPaint::SVG_PAINTTYPE_URI) - return; - - SVGElement* svgElement = static_cast<SVGElement*>(object->node()); - ASSERT(svgElement); - ASSERT(svgElement->isStyled()); - - object->document()->accessSVGExtensions()->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); -} - inline void RenderSVGResource::adjustColorForPseudoRules(const RenderStyle* style, bool useFillPaint, Color& color) { if (style->insideLink() != InsideVisitedLink) @@ -69,7 +54,7 @@ inline void RenderSVGResource::adjustColorForPseudoRules(const RenderStyle* styl } // FIXME: This method and strokePaintingResource() should be refactored, to share even more code -RenderSVGResource* RenderSVGResource::fillPaintingResource(const RenderObject* object, const RenderStyle* style) +RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style) { ASSERT(object); ASSERT(style); @@ -84,13 +69,9 @@ RenderSVGResource* RenderSVGResource::fillPaintingResource(const RenderObject* o RenderSVGResource* fillPaintingResource = 0; SVGPaint::SVGPaintType paintType = fillPaint->paintType(); - if (paintType == SVGPaint::SVG_PAINTTYPE_URI - || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) { - AtomicString id(SVGURIReference::getTarget(fillPaint->uri())); - fillPaintingResource = getRenderSVGResourceContainerById(object->document(), id); - - if (!fillPaintingResource) - registerPendingResource(id, paintType, object); + if (paintType == SVGPaint::SVG_PAINTTYPE_URI || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) { + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) + fillPaintingResource = resources->fill(); } if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !fillPaintingResource) { @@ -122,7 +103,7 @@ RenderSVGResource* RenderSVGResource::fillPaintingResource(const RenderObject* o return fillPaintingResource; } -RenderSVGResource* RenderSVGResource::strokePaintingResource(const RenderObject* object, const RenderStyle* style) +RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style) { ASSERT(object); ASSERT(style); @@ -138,13 +119,9 @@ RenderSVGResource* RenderSVGResource::strokePaintingResource(const RenderObject* FloatRect objectBoundingBox = object->objectBoundingBox(); SVGPaint::SVGPaintType paintType = strokePaint->paintType(); - if (!objectBoundingBox.isEmpty() - && (paintType == SVGPaint::SVG_PAINTTYPE_URI || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)) { - AtomicString id(SVGURIReference::getTarget(strokePaint->uri())); - strokePaintingResource = getRenderSVGResourceContainerById(object->document(), id); - - if (!strokePaintingResource) - registerPendingResource(id, paintType, object); + if (!objectBoundingBox.isEmpty() && (paintType == SVGPaint::SVG_PAINTTYPE_URI || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)) { + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) + strokePaintingResource = resources->stroke(); } if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !strokePaintingResource) { @@ -184,72 +161,6 @@ RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource() return s_sharedSolidPaintingResource; } -void RenderSVGResource::markForLayoutAndResourceInvalidation(RenderObject* object, bool needsBoundariesUpdate) -{ - ASSERT(object); - ASSERT(object->node()); - ASSERT(object->node()->isSVGElement()); - - // Eventually mark the renderer needing a boundaries update - if (needsBoundariesUpdate) - object->setNeedsBoundariesUpdate(); - - markForLayoutAndParentResourceInvalidation(object); -} - -static inline void invalidatePaintingResource(SVGPaint* paint, RenderObject* object) -{ - ASSERT(paint); - - SVGPaint::SVGPaintType paintType = paint->paintType(); - if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) - return; - - AtomicString id(SVGURIReference::getTarget(paint->uri())); - if (RenderSVGResourceContainer* paintingResource = getRenderSVGResourceContainerById(object->document(), id)) - paintingResource->invalidateClient(object); -} - -void RenderSVGResource::invalidateAllResourcesOfRenderer(RenderObject* object) -{ - ASSERT(object); - ASSERT(object->style()); - - Document* document = object->document(); - ASSERT(document); - - const SVGRenderStyle* svgStyle = object->style()->svgStyle(); - ASSERT(svgStyle); - - // Masker - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, svgStyle->maskerResource())) - masker->invalidateClient(object); - - // Clipper - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, svgStyle->clipperResource())) - clipper->invalidateClient(object); - - // Filter -#if ENABLE(FILTERS) - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, svgStyle->filterResource())) - filter->invalidateClient(object); -#endif - - // Markers - if (RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(document, svgStyle->markerStartResource())) - startMarker->invalidateClient(object); - if (RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(document, svgStyle->markerMidResource())) - midMarker->invalidateClient(object); - if (RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(document, svgStyle->markerEndResource())) - endMarker->invalidateClient(object); - - // Gradients/Patterns - if (svgStyle->hasFill()) - invalidatePaintingResource(svgStyle->fillPaint(), object); - if (svgStyle->hasStroke()) - invalidatePaintingResource(svgStyle->strokePaint(), object); -} - void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout) { ASSERT(object); @@ -259,8 +170,10 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* // Invalidate resources in ancestor chain, if needed. RenderObject* current = object->parent(); while (current) { - if (current->isSVGResourceContainer()) + if (current->isSVGResourceContainer()) { current->toRenderSVGResourceContainer()->invalidateClients(); + break; + } current = current->parent(); } diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index b3ea6fb..e2d8216 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -22,6 +22,7 @@ #define RenderSVGResource_h #if ENABLE(SVG) +#include "RenderStyleConstants.h" #include "SVGDocumentExtensions.h" namespace WebCore { @@ -75,18 +76,14 @@ public: } // Helper utilities used in the render tree to access resources used for painting shapes/text (gradients & patterns only) - static RenderSVGResource* fillPaintingResource(const RenderObject*, const RenderStyle*); - static RenderSVGResource* strokePaintingResource(const RenderObject*, const RenderStyle*); + static RenderSVGResource* fillPaintingResource(RenderObject*, const RenderStyle*); + static RenderSVGResource* strokePaintingResource(RenderObject*, const RenderStyle*); static RenderSVGResourceSolidColor* sharedSolidPaintingResource(); - static void invalidateAllResourcesOfRenderer(RenderObject*); static void markForLayoutAndParentResourceInvalidation(RenderObject*, bool needsLayout = true); private: static void adjustColorForPseudoRules(const RenderStyle*, bool useFillPaint, Color&); - -protected: - void markForLayoutAndResourceInvalidation(RenderObject*, bool needsBoundariesUpdate = true); }; } diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index e923f7e..a201d1f 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -21,6 +21,7 @@ */ #include "config.h" + #if ENABLE(SVG) #include "RenderSVGResourceClipper.h" @@ -32,11 +33,12 @@ #include "ImageBuffer.h" #include "IntRect.h" #include "RenderObject.h" -#include "RenderStyle.h" #include "RenderSVGResource.h" +#include "RenderStyle.h" #include "SVGClipPathElement.h" #include "SVGElement.h" #include "SVGRenderSupport.h" +#include "SVGResources.h" #include "SVGStyledElement.h" #include "SVGStyledTransformableElement.h" #include "SVGUnitTypes.h" @@ -55,6 +57,9 @@ RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node) RenderSVGResourceClipper::~RenderSVGResourceClipper() { + if (m_clipper.isEmpty()) + return; + deleteAllValues(m_clipper); m_clipper.clear(); } @@ -64,26 +69,26 @@ void RenderSVGResourceClipper::invalidateClients() if (m_invalidationBlocked) return; - HashMap<RenderObject*, ClipperData*>::const_iterator end = m_clipper.end(); - for (HashMap<RenderObject*, ClipperData*>::const_iterator it = m_clipper.begin(); it != end; ++it) - markForLayoutAndResourceInvalidation(it->first); - - deleteAllValues(m_clipper); - m_clipper.clear(); m_clipBoundaries = FloatRect(); + if (!m_clipper.isEmpty()) { + deleteAllValues(m_clipper); + m_clipper.clear(); + } + + markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); } -void RenderSVGResourceClipper::invalidateClient(RenderObject* object) +void RenderSVGResourceClipper::invalidateClient(RenderObject* client) { + ASSERT(client); if (m_invalidationBlocked) return; - ASSERT(object); - if (!m_clipper.contains(object)) - return; + ASSERT(client->selfNeedsLayout()); + if (m_clipper.contains(client)) + delete m_clipper.take(client); - delete m_clipper.take(object); - markForLayoutAndResourceInvalidation(object); + markClientForInvalidation(client, BoundariesInvalidation); } bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) @@ -96,10 +101,6 @@ bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, UNUSED_PARAM(resourceMode); #endif - // Early exit, if this resource contains a child which references ourselves. - if (containsCyclicReference(node())) - return false; - applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context); return true; } @@ -191,11 +192,13 @@ bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const Fl maskContext->translate(-repaintRect.x(), -repaintRect.y()); // clipPath can also be clipped by another clipPath. - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(this->document(), style()->svgStyle()->clipperResource())) { - if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext)) { - maskContext->restore(); - return false; - } + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this)) { + if (RenderSVGResourceClipper* clipper = resources->clipper()) { + if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext)) { + maskContext->restore(); + return false; + } + } } SVGClipPathElement* clipPath = static_cast<SVGClipPathElement*>(node()); @@ -280,12 +283,6 @@ void RenderSVGResourceClipper::calculateClipContentRepaintRect() bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint) { - // FIXME: We should be able to check whether m_clipper.contains(object) - this doesn't work at the moment - // as resourceBoundingBox() has already created ClipperData, even if applyResource() returned false. - // Early exit, if this resource contains a child which references ourselves. - if (containsCyclicReference(node())) - return false; - FloatPoint point = nodeAtPoint; if (!SVGRenderSupport::pointInClippingArea(this, point)) return false; @@ -312,14 +309,6 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin return false; } -bool RenderSVGResourceClipper::childElementReferencesResource(const SVGRenderStyle* style, const String& referenceId) const -{ - if (!style->hasClipper()) - return false; - - return style->clipperResource() == referenceId; -} - FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object) { // Resource was not layouted yet. Give back the boundingBox of the object. diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h index 7128aa1..3c76bc8 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.h +++ b/WebCore/rendering/RenderSVGResourceClipper.h @@ -68,8 +68,6 @@ private: bool createClipData(ClipperData*, const FloatRect&, const FloatRect&); void calculateClipContentRepaintRect(); - virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const; - bool m_invalidationBlocked; FloatRect m_clipBoundaries; HashMap<RenderObject*, ClipperData*> m_clipper; diff --git a/WebCore/rendering/RenderSVGResourceContainer.cpp b/WebCore/rendering/RenderSVGResourceContainer.cpp index 3707797..7e43300 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.cpp +++ b/WebCore/rendering/RenderSVGResourceContainer.cpp @@ -28,102 +28,147 @@ namespace WebCore { +static inline SVGDocumentExtensions* svgExtensionsFromNode(Node* node) +{ + ASSERT(node); + ASSERT(node->document()); + return node->document()->accessSVGExtensions(); +} + RenderSVGResourceContainer::RenderSVGResourceContainer(SVGStyledElement* node) : RenderSVGHiddenContainer(node) - , RenderSVGResource() , m_id(node->hasID() ? node->getIdAttribute() : nullAtom) + , m_registered(false) { - ASSERT(node->document()); - node->document()->accessSVGExtensions()->addResource(m_id, this); } RenderSVGResourceContainer::~RenderSVGResourceContainer() { - ASSERT(node()); - ASSERT(node()->document()); - node()->document()->accessSVGExtensions()->removeResource(m_id); + if (m_registered) + svgExtensionsFromNode(node())->removeResource(m_id); } -void RenderSVGResourceContainer::idChanged() +void RenderSVGResourceContainer::layout() { - ASSERT(node()); - ASSERT(node()->document()); - SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions(); + // Invalidate all resources if our layout changed. + if (m_everHadLayout && selfNeedsLayout()) + invalidateClients(); - // Remove old id, that is guaranteed to be present in cache - extensions->removeResource(m_id); - m_id = static_cast<Element*>(node())->getIdAttribute(); + RenderSVGHiddenContainer::layout(); +} - // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now - if (extensions->isPendingResource(m_id)) { - OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); - if (clients->isEmpty()) - return; +void RenderSVGResourceContainer::destroy() +{ + SVGResourcesCache::resourceDestroyed(this); + RenderSVGHiddenContainer::destroy(); +} - HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); - const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); +void RenderSVGResourceContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderSVGHiddenContainer::styleDidChange(diff, oldStyle); - for (; it != end; ++it) { - if (RenderObject* renderer = (*it)->renderer()) - renderer->setNeedsLayout(true); - } + if (!m_registered) { + m_registered = true; + registerResource(); } - - // Recache us with the new id - extensions->addResource(m_id, this); } -AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform) +void RenderSVGResourceContainer::idChanged() { - if (!object->isRenderPath()) - return resourceTransform; + // Invalidate all our current clients. + invalidateClients(); - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); - AffineTransform transform = resourceTransform; - transform.multiply(element->getScreenCTM()); - return transform; + // Remove old id, that is guaranteed to be present in cache. + SVGDocumentExtensions* extensions = svgExtensionsFromNode(node()); + extensions->removeResource(m_id); + m_id = static_cast<Element*>(node())->getIdAttribute(); + + registerResource(); } -bool RenderSVGResourceContainer::containsCyclicReference(const Node* startNode) const +void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode mode) { - ASSERT(startNode->document()); + if (m_clients.isEmpty()) + return; - for (Node* node = startNode->firstChild(); node; node = node->nextSibling()) { - if (!node->isSVGElement()) - continue; + bool needsLayout = mode == LayoutAndBoundariesInvalidation; - RenderObject* renderer = node->renderer(); - if (!renderer) + HashSet<RenderObject*>::iterator end = m_clients.end(); + for (HashSet<RenderObject*>::iterator it = m_clients.begin(); it != end; ++it) { + RenderObject* client = *it; + if (client->isSVGResourceContainer()) { + client->toRenderSVGResourceContainer()->invalidateClients(); continue; + } - RenderStyle* style = renderer->style(); - if (!style) - continue; + markClientForInvalidation(client, mode); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout); + } +} - const SVGRenderStyle* svgStyle = style->svgStyle(); - ASSERT(svgStyle); +void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client, InvalidationMode mode) +{ + ASSERT(client); + ASSERT(!m_clients.isEmpty()); + + switch (mode) { + case LayoutAndBoundariesInvalidation: + case BoundariesInvalidation: + client->setNeedsBoundariesUpdate(); + break; + case RepaintInvalidation: + if (client->view()) + client->repaint(); + break; + } +} - // Let the class inheriting from us decide whether the child element references ourselves. - if (childElementReferencesResource(svgStyle, m_id)) - return true; +void RenderSVGResourceContainer::addClient(RenderObject* client) +{ + ASSERT(client); + m_clients.add(client); +} - // Dive into shadow tree to check for cycles there. - if (node->hasTagName(SVGNames::useTag)) { - ASSERT(renderer->isSVGShadowTreeRootContainer()); - if (Node* shadowRoot = static_cast<RenderSVGShadowTreeRootContainer*>(renderer)->rootElement()) { - if (containsCyclicReference(shadowRoot)) - return true; - } +void RenderSVGResourceContainer::removeClient(RenderObject* client) +{ + ASSERT(client); + m_clients.remove(client); +} - } +void RenderSVGResourceContainer::registerResource() +{ + SVGDocumentExtensions* extensions = svgExtensionsFromNode(node()); + if (!extensions->isPendingResource(m_id)) { + extensions->addResource(m_id, this); + return; + } - if (node->hasChildNodes()) { - if (containsCyclicReference(node)) - return true; - } + OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); + + // Cache us with the new id. + extensions->addResource(m_id, this); + + // Update cached resources of pending clients. + const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); + for (HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); it != end; ++it) { + RenderObject* renderer = (*it)->renderer(); + if (!renderer) + continue; + SVGResourcesCache::clientUpdatedFromElement(renderer, renderer->style()); + renderer->setNeedsLayout(true); } +} + +// FIXME: This does not belong here. +AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform) +{ + if (!object->isRenderPath()) + return resourceTransform; - return false; + SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); + AffineTransform transform = resourceTransform; + transform.multiply(element->getScreenCTM()); + return transform; } } diff --git a/WebCore/rendering/RenderSVGResourceContainer.h b/WebCore/rendering/RenderSVGResourceContainer.h index d57b1db..4271a5f 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.h +++ b/WebCore/rendering/RenderSVGResourceContainer.h @@ -23,10 +23,7 @@ #if ENABLE(SVG) #include "RenderSVGHiddenContainer.h" - -#include "SVGStyledTransformableElement.h" #include "RenderSVGResource.h" -#include "RenderSVGShadowTreeRootContainer.h" namespace WebCore { @@ -36,27 +33,40 @@ public: RenderSVGResourceContainer(SVGStyledElement*); virtual ~RenderSVGResourceContainer(); - void idChanged(); + virtual void layout(); + virtual void destroy(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual bool isSVGResourceContainer() const { return true; } virtual bool drawsContents() { return false; } - virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; } - virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const { return false; } static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform); - bool containsCyclicReference(const Node* startNode) const; + void idChanged(); + +protected: + enum InvalidationMode { + LayoutAndBoundariesInvalidation, + BoundariesInvalidation, + RepaintInvalidation + }; + + // Used from the invalidateClient/invalidateClients methods from classes, inheriting from us. + void markAllClientsForInvalidation(InvalidationMode); + void markClientForInvalidation(RenderObject*, InvalidationMode); private: friend class SVGResourcesCache; - - // FIXME: No-ops for now, until follow-up patch on bug 43031 lands. - void addClient(RenderObject*) { } - void removeClient(RenderObject*) { } + void addClient(RenderObject*); + void removeClient(RenderObject*); private: + void registerResource(); + AtomicString m_id; + bool m_registered; + HashSet<RenderObject*> m_clients; }; inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document* document, const AtomicString& id) diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index a6358f0..bc5feaf 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -60,28 +60,32 @@ RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node) RenderSVGResourceFilter::~RenderSVGResourceFilter() { + if (m_filter.isEmpty()) + return; + deleteAllValues(m_filter); m_filter.clear(); } void RenderSVGResourceFilter::invalidateClients() { - HashMap<RenderObject*, FilterData*>::const_iterator end = m_filter.end(); - for (HashMap<RenderObject*, FilterData*>::const_iterator it = m_filter.begin(); it != end; ++it) - markForLayoutAndResourceInvalidation(it->first); + if (!m_filter.isEmpty()) { + deleteAllValues(m_filter); + m_filter.clear(); + } - deleteAllValues(m_filter); - m_filter.clear(); + markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); } -void RenderSVGResourceFilter::invalidateClient(RenderObject* object) +void RenderSVGResourceFilter::invalidateClient(RenderObject* client) { - ASSERT(object); - if (!m_filter.contains(object)) - return; + ASSERT(client); + ASSERT(client->selfNeedsLayout()); + + if (m_filter.contains(client)) + delete m_filter.take(client); - delete m_filter.take(object); - markForLayoutAndResourceInvalidation(object); + markClientForInvalidation(client, BoundariesInvalidation); } PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives() diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp index ce51369..73b2ab6 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.cpp +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -43,28 +43,32 @@ RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node) RenderSVGResourceGradient::~RenderSVGResourceGradient() { + if (m_gradient.isEmpty()) + return; + deleteAllValues(m_gradient); m_gradient.clear(); } void RenderSVGResourceGradient::invalidateClients() { - const HashMap<RenderObject*, GradientData*>::const_iterator end = m_gradient.end(); - for (HashMap<RenderObject*, GradientData*>::const_iterator it = m_gradient.begin(); it != end; ++it) - markForLayoutAndResourceInvalidation(it->first, false); + if (!m_gradient.isEmpty()) { + deleteAllValues(m_gradient); + m_gradient.clear(); + } - deleteAllValues(m_gradient); - m_gradient.clear(); + markAllClientsForInvalidation(RepaintInvalidation); } -void RenderSVGResourceGradient::invalidateClient(RenderObject* object) +void RenderSVGResourceGradient::invalidateClient(RenderObject* client) { - ASSERT(object); - if (!m_gradient.contains(object)) - return; + ASSERT(client); + ASSERT(client->selfNeedsLayout()); + + if (m_gradient.contains(client)) + delete m_gradient.take(client); - delete m_gradient.take(object); - markForLayoutAndResourceInvalidation(object, false); + markClientForInvalidation(client, RepaintInvalidation); } #if PLATFORM(CG) diff --git a/WebCore/rendering/RenderSVGResourceMarker.cpp b/WebCore/rendering/RenderSVGResourceMarker.cpp index 4f0cace..fa00fa3 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.cpp +++ b/WebCore/rendering/RenderSVGResourceMarker.cpp @@ -21,6 +21,7 @@ */ #include "config.h" + #if ENABLE(SVG) #include "RenderSVGResourceMarker.h" @@ -43,39 +44,30 @@ RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement* node) RenderSVGResourceMarker::~RenderSVGResourceMarker() { - m_marker.clear(); } void RenderSVGResourceMarker::layout() { + // Invalidate all resources if our layout changed. + if (m_everHadLayout && selfNeedsLayout()) + invalidateClients(); + // RenderSVGHiddenContainer overwrites layout(). We need the // layouting of RenderSVGContainer for calculating local // transformations and repaint. RenderSVGContainer::layout(); } -void RenderSVGResourceMarker::addClient(const RenderObject* object) -{ - m_marker.add(object); -} - void RenderSVGResourceMarker::invalidateClients() { - const HashSet<const RenderObject*>::const_iterator end = m_marker.end(); - for (HashSet<const RenderObject*>::const_iterator it = m_marker.begin(); it != end; ++it) - markForLayoutAndResourceInvalidation(const_cast<RenderObject*>(*it)); - - m_marker.clear(); + markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); } -void RenderSVGResourceMarker::invalidateClient(RenderObject* object) +void RenderSVGResourceMarker::invalidateClient(RenderObject* client) { - ASSERT(object); - if (!m_marker.contains(object)) - return; - - m_marker.remove(object); - markForLayoutAndResourceInvalidation(object); + ASSERT(client); + ASSERT(client->selfNeedsLayout()); + markClientForInvalidation(client, BoundariesInvalidation); } void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo) @@ -140,20 +132,11 @@ AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint& void RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform& transform) { - DEFINE_STATIC_LOCAL(HashSet<RenderSVGResourceMarker*>, currentlyDrawingMarkers, ()); - - // avoid drawing circular marker references - if (currentlyDrawingMarkers.contains(this)) - return; - - currentlyDrawingMarkers.add(this); PaintInfo info(paintInfo); info.context->save(); info.applyTransform(transform); RenderSVGContainer::paint(info, 0, 0); info.context->restore(); - - currentlyDrawingMarkers.remove(this); } AffineTransform RenderSVGResourceMarker::markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth) const diff --git a/WebCore/rendering/RenderSVGResourceMarker.h b/WebCore/rendering/RenderSVGResourceMarker.h index 75c442e..8509aca 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.h +++ b/WebCore/rendering/RenderSVGResourceMarker.h @@ -41,7 +41,6 @@ public: virtual const char* renderName() const { return "RenderSVGResourceMarker"; } - void addClient(const RenderObject*); virtual void invalidateClients(); virtual void invalidateClient(RenderObject*); @@ -74,9 +73,6 @@ private: AffineTransform viewportTransform() const; - // Save objects using this marker for invalidation. - HashSet<const RenderObject*> m_marker; - mutable AffineTransform m_localToParentTransform; FloatRect m_viewport; }; diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp index 83a64b5..2c36c96 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.cpp +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -19,6 +19,7 @@ */ #include "config.h" + #if ENABLE(SVG) #include "RenderSVGResourceMasker.h" @@ -51,37 +52,33 @@ RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement* node) RenderSVGResourceMasker::~RenderSVGResourceMasker() { + if (m_masker.isEmpty()) + return; + deleteAllValues(m_masker); m_masker.clear(); } void RenderSVGResourceMasker::invalidateClients() { - HashMap<RenderObject*, MaskerData*>::const_iterator end = m_masker.end(); - for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it) - markForLayoutAndResourceInvalidation(it->first); - - deleteAllValues(m_masker); - m_masker.clear(); m_maskBoundaries = FloatRect(); -} - -void RenderSVGResourceMasker::invalidateClient(RenderObject* object) -{ - ASSERT(object); - if (!m_masker.contains(object)) - return; + if (!m_masker.isEmpty()) { + deleteAllValues(m_masker); + m_masker.clear(); + } - delete m_masker.take(object); - markForLayoutAndResourceInvalidation(object); + markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); } -bool RenderSVGResourceMasker::childElementReferencesResource(const SVGRenderStyle* style, const String& referenceId) const +void RenderSVGResourceMasker::invalidateClient(RenderObject* client) { - if (!style->hasMasker()) - return false; + ASSERT(client); + ASSERT(client->selfNeedsLayout()); - return style->maskerResource() == referenceId; + if (m_masker.contains(client)) + delete m_masker.take(client); + + markClientForInvalidation(client, BoundariesInvalidation); } bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) @@ -102,11 +99,6 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); if (!maskElement) return false; - - // Early exit, if this resource contains a child which references ourselves. - if (containsCyclicReference(node())) - return false; - createMaskImage(maskerData, maskElement, object); } diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h index 56f657b..f6301cb 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.h +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -69,8 +69,6 @@ private: void createMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*); void calculateMaskContentRepaintRect(); - virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const; - FloatRect m_maskBoundaries; HashMap<RenderObject*, MaskerData*> m_masker; }; diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp index a2234c8..902ff02 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.cpp +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -40,43 +40,32 @@ RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement* node) RenderSVGResourcePattern::~RenderSVGResourcePattern() { - deleteAllValues(m_pattern); - m_pattern.clear(); -} - -void RenderSVGResourcePattern::invalidateClients() -{ - const HashMap<RenderObject*, PatternData*>::const_iterator end = m_pattern.end(); - for (HashMap<RenderObject*, PatternData*>::const_iterator it = m_pattern.begin(); it != end; ++it) - markForLayoutAndResourceInvalidation(it->first, false); + if (m_pattern.isEmpty()) + return; deleteAllValues(m_pattern); m_pattern.clear(); } -void RenderSVGResourcePattern::invalidateClient(RenderObject* object) +void RenderSVGResourcePattern::invalidateClients() { - ASSERT(object); - if (!m_pattern.contains(object)) - return; + if (!m_pattern.isEmpty()) { + deleteAllValues(m_pattern); + m_pattern.clear(); + } - delete m_pattern.take(object); - markForLayoutAndResourceInvalidation(object, false); + markAllClientsForInvalidation(RepaintInvalidation); } -bool RenderSVGResourcePattern::childElementReferencesResource(const SVGRenderStyle* style, const String& referenceId) const +void RenderSVGResourcePattern::invalidateClient(RenderObject* client) { - if (style->hasFill()) { - if (style->fillPaint()->matchesTargetURI(referenceId)) - return true; - } + ASSERT(client); + ASSERT(client->selfNeedsLayout()); - if (style->hasStroke()) { - if (style->strokePaint()->matchesTargetURI(referenceId)) - return true; - } + if (m_pattern.contains(client)) + delete m_pattern.take(client); - return false; + markClientForInvalidation(client, RepaintInvalidation); } bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) @@ -244,10 +233,6 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(PatternData* p if (!attributes.patternContentElement()) return 0; - // Early exit, if this resource contains a child which references ourselves. - if (containsCyclicReference(attributes.patternContentElement())) - return 0; - FloatRect objectBoundingBox = object->objectBoundingBox(); FloatRect patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); AffineTransform patternTransform = attributes.patternTransform(); diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h index ec89777..690b0de 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.h +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -67,8 +67,6 @@ private: FloatRect calculatePatternBoundariesIncludingOverflow(PatternAttributes&, const FloatRect& objectBoundingBox, const AffineTransform& viewBoxCTM, const FloatRect& patternBoundaries) const; - virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const; - HashMap<RenderObject*, PatternData*> m_pattern; }; diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index 1659e40..7ddebf2 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -26,14 +26,19 @@ #include "RenderSVGRoot.h" #include "GraphicsContext.h" +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE #include "HitTestResult.h" #endif +======= +#include "HitTestResult.h" +>>>>>>> webkit.org at r64523 #include "RenderSVGContainer.h" #include "RenderSVGResource.h" #include "RenderView.h" #include "SVGLength.h" #include "SVGRenderSupport.h" +#include "SVGResources.h" #include "SVGSVGElement.h" #include "SVGStyledElement.h" #include "TransformState.h" @@ -131,15 +136,14 @@ void RenderSVGRoot::layout() setNeedsLayout(false); } -bool RenderSVGRoot::selfWillPaint() const +bool RenderSVGRoot::selfWillPaint() { #if ENABLE(FILTERS) - const SVGRenderStyle* svgStyle = style()->svgStyle(); - RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), svgStyle->filterResource()); - if (filter) - return true; -#endif + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); + return resources && resources->filter(); +#else return false; +#endif } void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) @@ -194,10 +198,22 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) void RenderSVGRoot::destroy() { - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientDestroyed(this); RenderBox::destroy(); } +void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderBox::styleDidChange(diff, oldStyle); + SVGResourcesCache::clientStyleChanged(this, diff, style()); +} + +void RenderSVGRoot::updateFromElement() +{ + RenderBox::updateFromElement(); + SVGResourcesCache::clientUpdatedFromElement(this, style()); +} + void RenderSVGRoot::calcViewport() { SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); @@ -322,6 +338,7 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { // FIXME: CSS/HTML assumes the local point is relative to the border box, right? updateHitTestResult(result, pointInBorderBox); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE // TODO: nodeAtFloatPoint() doesn't handle region test yet. if (result.isRegionTest()) { @@ -329,6 +346,10 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re result.addRawNode(node()); } else #endif +======= + // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet. + result.addNodeToRectBasedTestResult(child->node(), _x, _y); +>>>>>>> webkit.org at r64523 return true; } } diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h index 0a08ab5..b90113c 100644 --- a/WebCore/rendering/RenderSVGRoot.h +++ b/WebCore/rendering/RenderSVGRoot.h @@ -58,6 +58,8 @@ private: virtual void paint(PaintInfo&, int parentX, int parentY); virtual void destroy(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual void updateFromElement(); virtual const AffineTransform& localToParentTransform() const; @@ -77,7 +79,7 @@ private: void calcViewport(); - bool selfWillPaint() const; + bool selfWillPaint(); IntSize parentOriginToBorderBox() const; IntSize borderOriginToContentBox() const; diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index 58348db..c4fc353 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -98,9 +98,9 @@ void RenderSVGText::layout() ASSERT(childrenInline()); forceLayoutInlineChildren(); - // Invalidate all resources of this client, if we changed something. + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) - RenderSVGResource::invalidateAllResourcesOfRenderer(this); + SVGResourcesCache::clientLayoutChanged(this); repainter.repaintAfterLayout(); setNeedsLayout(false); @@ -132,12 +132,6 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul return false; } -void RenderSVGText::destroy() -{ - RenderSVGResource::invalidateAllResourcesOfRenderer(this); - RenderSVGBlock::destroy(); -} - bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h index 6e7d03a..be19419 100644 --- a/WebCore/rendering/RenderSVGText.h +++ b/WebCore/rendering/RenderSVGText.h @@ -51,8 +51,6 @@ private: virtual bool requiresLayer() const { return false; } virtual void layout(); - virtual void destroy(); - virtual void absoluteQuads(Vector<FloatQuad>&); virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); diff --git a/WebCore/rendering/RenderScrollbar.cpp b/WebCore/rendering/RenderScrollbar.cpp index 63fce8d..817dd02 100644 --- a/WebCore/rendering/RenderScrollbar.cpp +++ b/WebCore/rendering/RenderScrollbar.cpp @@ -130,6 +130,9 @@ ScrollbarPart RenderScrollbar::partForStyleResolve() PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, PseudoId pseudoId) { + if (!m_owner) + return 0; + s_styleResolvePart = partType; s_styleResolveScrollbar = this; RefPtr<RenderStyle> result = m_owner->getUncachedPseudoStyle(pseudoId, m_owner->style()); diff --git a/WebCore/rendering/RenderScrollbar.h b/WebCore/rendering/RenderScrollbar.h index b3c00ef..8cc263a 100644 --- a/WebCore/rendering/RenderScrollbar.h +++ b/WebCore/rendering/RenderScrollbar.h @@ -49,6 +49,7 @@ public: static RenderScrollbar* scrollbarForStyleResolve(); RenderBox* owningRenderer() const { return m_owner; } + void clearOwningRenderer() { m_owner = 0; } void paintPart(GraphicsContext*, ScrollbarPart, const IntRect&); diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index 6359c09..7c54837 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -31,9 +31,13 @@ #include "Document.h" #include "FixedTableLayout.h" #include "FrameView.h" +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE #include "HitTestResult.h" #endif +======= +#include "HitTestResult.h" +>>>>>>> webkit.org at r64523 #include "HTMLNames.h" #include "RenderLayer.h" #include "RenderTableCell.h" @@ -1183,11 +1187,15 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu ty += y(); // Check kids first. +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (!hasOverflowClip() || result.intersects(xPos, yPos, overflowClipRect(tx, ty))) { #else if (!hasOverflowClip() || overflowClipRect(tx, ty).contains(xPos, yPos)) { #endif +======= + if (!hasOverflowClip() || overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos))) { +>>>>>>> webkit.org at r64523 for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { @@ -1198,6 +1206,7 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } // Check our bounds next. +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE IntRect boundsRect = IntRect(tx, ty, width(), height()); if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && result.intersects(xPos, yPos, boundsRect)) { @@ -1214,6 +1223,13 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } #endif return true; +======= + IntRect boundsRect = IntRect(tx, ty, width(), height()); + if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && boundsRect.intersects(result.rectFromPoint(xPos, yPos))) { + updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); + if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect)) + return true; +>>>>>>> webkit.org at r64523 } return false; diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index c439a13..e094f36 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -28,9 +28,13 @@ #include "CachedImage.h" #include "Document.h" +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE #include "HitTestResult.h" #endif +======= +#include "HitTestResult.h" +>>>>>>> webkit.org at r64523 #include "HTMLNames.h" #include "RenderTableCell.h" #include "RenderTableCol.h" @@ -1289,11 +1293,15 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul tx += x(); ty += y(); +<<<<<<< HEAD #ifdef ANDROID_HITTEST_WITHSIZE if (hasOverflowClip() && !result.intersects(xPos, yPos, overflowClipRect(tx, ty))) #else if (hasOverflowClip() && !overflowClipRect(tx, ty).contains(xPos, yPos)) #endif +======= + if (hasOverflowClip() && !overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos))) +>>>>>>> webkit.org at r64523 return false; for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index 5b57513..4ba2dc7 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved. * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +24,7 @@ #include "config.h" #include "RenderTextControlSingleLine.h" +#include "Chrome.h" #include "CSSStyleSelector.h" #include "Event.h" #include "EventNames.h" @@ -38,7 +40,6 @@ #include "RenderLayer.h" #include "RenderScrollbar.h" #include "RenderTheme.h" -#include "SearchPopupMenu.h" #include "SelectionController.h" #include "Settings.h" #include "SimpleFontData.h" @@ -62,7 +63,7 @@ RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node, bool placeh RenderTextControlSingleLine::~RenderTextControlSingleLine() { if (m_searchPopup) { - m_searchPopup->disconnectClient(); + m_searchPopup->popupMenu()->disconnectClient(); m_searchPopup = 0; } @@ -107,7 +108,7 @@ void RenderTextControlSingleLine::addSearchResult() const AtomicString& name = autosaveName(); if (!m_searchPopup) - m_searchPopup = SearchPopupMenu::create(this); + m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); m_searchPopup->saveRecentSearches(name, m_recentSearches); } @@ -125,7 +126,7 @@ void RenderTextControlSingleLine::showPopup() return; if (!m_searchPopup) - m_searchPopup = SearchPopupMenu::create(this); + m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); if (!m_searchPopup->enabled()) return; @@ -145,14 +146,14 @@ void RenderTextControlSingleLine::showPopup() m_searchPopup->saveRecentSearches(name, m_recentSearches); } - m_searchPopup->show(absoluteBoundingBoxRect(true), document()->view(), -1); + m_searchPopup->popupMenu()->show(absoluteBoundingBoxRect(true), document()->view(), -1); } void RenderTextControlSingleLine::hidePopup() { ASSERT(node()->isHTMLElement()); if (m_searchPopup) - m_searchPopup->hide(); + m_searchPopup->popupMenu()->hide(); } void RenderTextControlSingleLine::subtreeHasChanged() @@ -689,7 +690,7 @@ void RenderTextControlSingleLine::updateFromElement() } if (m_searchPopupIsVisible) - m_searchPopup->updateFromElement(); + m_searchPopup->popupMenu()->updateFromElement(); } void RenderTextControlSingleLine::cacheSelection(int start, int end) @@ -887,7 +888,7 @@ void RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEven const AtomicString& name = autosaveName(); if (!name.isEmpty()) { if (!m_searchPopup) - m_searchPopup = SearchPopupMenu::create(this); + m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); m_searchPopup->saveRecentSearches(name, m_recentSearches); } } diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index 8c7e844..4bc80cf 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,6 +25,7 @@ #include "PopupMenuClient.h" #include "RenderTextControl.h" +#include "SearchPopupMenu.h" #include "Timer.h" namespace WebCore { @@ -32,7 +34,6 @@ class InputElement; class InputFieldSpeechButtonElement; class SearchFieldCancelButtonElement; class SearchFieldResultsButtonElement; -class SearchPopupMenu; class SpinButtonElement; class TextControlInnerElement; diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index bebe6c8..3854e6a 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -396,7 +396,7 @@ bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& res bool inside = RenderReplaced::nodeAtPoint(request, result, x, y, tx, ty, action); // Check to see if we are really over the widget itself (and not just in the border/padding area). - if (inside && !hadResult && result.innerNode() == node()) + if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node()) result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); #ifdef ANDROID_HITTEST_WITHSIZE else if (result.isRegionTest() && !hadResult && result.innerNode() == node()) { diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp index 8e498ad..a293124 100644 --- a/WebCore/rendering/SVGInlineTextBox.cpp +++ b/WebCore/rendering/SVGInlineTextBox.cpp @@ -295,17 +295,16 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int) ASSERT(!m_paintingResource); } -bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, RenderStyle* style) +bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, RenderObject* renderer, RenderStyle* style) { + ASSERT(renderer); + ASSERT(style); ASSERT(m_paintingResourceMode != ApplyToDefaultMode); - RenderObject* parentRenderer = parent()->renderer(); - ASSERT(parentRenderer); - if (m_paintingResourceMode & ApplyToFillMode) - m_paintingResource = RenderSVGResource::fillPaintingResource(parentRenderer, style); + m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style); else if (m_paintingResourceMode & ApplyToStrokeMode) - m_paintingResource = RenderSVGResource::strokePaintingResource(parentRenderer, style); + m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style); else { // We're either called for stroking or filling. ASSERT_NOT_REACHED(); @@ -314,7 +313,7 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, Render if (!m_paintingResource) return false; - m_paintingResource->applyResource(parentRenderer, style, context, m_paintingResourceMode); + m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode); return true; } @@ -331,7 +330,7 @@ void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context) bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, TextRun& textRun, RenderStyle* style) { - bool acquiredResource = acquirePaintingResource(context, style); + bool acquiredResource = acquirePaintingResource(context, parent()->renderer(), style); #if ENABLE(SVG_FONTS) // SVG Fonts need access to the painting resource used to draw the current text chunk. @@ -508,21 +507,24 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoin if (hasDecorationFill) { m_paintingResourceMode = ApplyToFillMode; - paintDecorationWithStyle(context, textOrigin, decorationStyle, decoration); + paintDecorationWithStyle(context, textOrigin, decorationRenderer, decoration); } if (hasDecorationStroke) { m_paintingResourceMode = ApplyToStrokeMode; - paintDecorationWithStyle(context, textOrigin, decorationStyle, decoration); + paintDecorationWithStyle(context, textOrigin, decorationRenderer, decoration); } } -void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, const FloatPoint& textOrigin, RenderStyle* decorationStyle, ETextDecoration decoration) +void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, const FloatPoint& textOrigin, RenderObject* decorationRenderer, ETextDecoration decoration) { ASSERT(!m_paintingResource); ASSERT(m_paintingResourceMode != ApplyToDefaultMode); ASSERT(m_currentChunkPart.isValid()); + RenderStyle* decorationStyle = decorationRenderer->style(); + ASSERT(decorationStyle); + const Font& font = decorationStyle->font(); // The initial y value refers to overline position. @@ -534,7 +536,7 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, const context->beginPath(); context->addPath(Path::createRectangle(FloatRect(x, y, m_currentChunkPart.width, thickness))); - if (acquirePaintingResource(context, decorationStyle)) + if (acquirePaintingResource(context, decorationRenderer, decorationStyle)) releasePaintingResource(context); context->restore(); @@ -614,9 +616,15 @@ void SVGInlineTextBox::paintText(GraphicsContext* context, const FloatPoint& tex paintTextWithShadows(context, textOrigin, style, textRun, 0, startPos); // Draw text using selection style from the start to the end position of the selection + if (style != selectionStyle) + SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle); + TextRun selectionTextRun(constructTextRun(selectionStyle)); paintTextWithShadows(context, textOrigin, selectionStyle, textRun, startPos, endPos); + if (style != selectionStyle) + SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style); + // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part if (endPos < m_currentChunkPart.length && !paintSelectedTextOnly) paintTextWithShadows(context, textOrigin, style, textRun, endPos, m_currentChunkPart.length); diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h index 602fff1..7711db4 100644 --- a/WebCore/rendering/SVGInlineTextBox.h +++ b/WebCore/rendering/SVGInlineTextBox.h @@ -75,7 +75,7 @@ private: TextRun constructTextRun(RenderStyle*) const; AffineTransform buildChunkTransformation(SVGChar& firstCharacter) const; - bool acquirePaintingResource(GraphicsContext*&, RenderStyle*); + bool acquirePaintingResource(GraphicsContext*&, RenderObject*, RenderStyle*); void releasePaintingResource(GraphicsContext*&); bool prepareGraphicsContextForTextPainting(GraphicsContext*&, TextRun&, RenderStyle*); @@ -83,7 +83,7 @@ private: void computeTextMatchMarkerRect(RenderStyle*); void paintDecoration(GraphicsContext*, const FloatPoint& textOrigin, ETextDecoration, bool hasSelection); - void paintDecorationWithStyle(GraphicsContext*, const FloatPoint& textOrigin, RenderStyle*, ETextDecoration); + void paintDecorationWithStyle(GraphicsContext*, const FloatPoint& textOrigin, RenderObject*, ETextDecoration); void paintSelection(GraphicsContext*, const FloatPoint& textOrigin, RenderStyle*); void paintText(GraphicsContext*, const FloatPoint& textOrigin, RenderStyle*, RenderStyle* selectionStyle, bool hasSelection, bool paintSelectedTextOnly); void paintTextWithShadows(GraphicsContext*, const FloatPoint& textOrigin, RenderStyle*, TextRun&, int startPos, int endPos); diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 0d4a42b..34f6659 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -40,6 +40,7 @@ #include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" #include "RenderSVGRoot.h" +#include "SVGResources.h" #include "SVGStyledElement.h" #include "TransformState.h" #include <wtf/UnusedParam.h> @@ -79,10 +80,7 @@ void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, RenderBox bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo& paintInfo) { ASSERT(object); - SVGElement* svgElement = static_cast<SVGElement*>(object->node()); - ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); - SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); RenderStyle* style = object->style(); ASSERT(style); @@ -109,33 +107,22 @@ bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo paintInfo.context->beginTransparencyLayer(1); } - Document* document = object->document(); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); + if (!resources) + return true; - if (svgStyle->hasMasker()) { - AtomicString maskerId(svgStyle->maskerResource()); - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { - if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) - return false; - } else - document->accessSVGExtensions()->addPendingResource(maskerId, styledElement); + if (RenderSVGResourceMasker* masker = resources->masker()) { + if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) + return false; } - if (svgStyle->hasClipper()) { - AtomicString clipperId(svgStyle->clipperResource()); - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId)) - clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); - else - document->accessSVGExtensions()->addPendingResource(clipperId, styledElement); - } + if (RenderSVGResourceClipper* clipper = resources->clipper()) + clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); #if ENABLE(FILTERS) - if (svgStyle->hasFilter()) { - AtomicString filterId(svgStyle->filterResource()); - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId)) { - if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) - return false; - } else - document->accessSVGExtensions()->addPendingResource(filterId, styledElement); + if (RenderSVGResourceFilter* filter = resources->filter()) { + if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) + return false; } #endif @@ -157,9 +144,9 @@ void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& p ASSERT(svgStyle); #if ENABLE(FILTERS) - if (svgStyle->hasFilter()) { - AtomicString filterId(svgStyle->filterResource()); - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), filterId)) { + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); + if (resources) { + if (RenderSVGResourceFilter* filter = resources->filter()) { filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode); paintInfo.context = savedContext; } @@ -289,49 +276,46 @@ bool SVGRenderSupport::isOverflowHidden(const RenderObject* object) void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* object, FloatRect& repaintRect) { ASSERT(object); - ASSERT(object->style()); - const SVGRenderStyle* svgStyle = object->style()->svgStyle(); - if (!svgStyle) - return; - + + RenderStyle* style = object->style(); + ASSERT(style); + + const SVGRenderStyle* svgStyle = style->svgStyle(); + ASSERT(svgStyle); + RenderObject* renderer = const_cast<RenderObject*>(object); -#if ENABLE(FILTERS) - if (svgStyle->hasFilter()) { - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), svgStyle->filterResource())) - repaintRect = filter->resourceBoundingBox(renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); + if (!resources) { + svgStyle->inflateForShadow(repaintRect); + return; } + +#if ENABLE(FILTERS) + if (RenderSVGResourceFilter* filter = resources->filter()) + repaintRect = filter->resourceBoundingBox(renderer); #endif - if (svgStyle->hasClipper()) { - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object->document(), svgStyle->clipperResource())) - repaintRect.intersect(clipper->resourceBoundingBox(renderer)); - } - - if (svgStyle->hasMasker()) { - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), svgStyle->maskerResource())) - repaintRect.intersect(masker->resourceBoundingBox(renderer)); - } - + if (RenderSVGResourceClipper* clipper = resources->clipper()) + repaintRect.intersect(clipper->resourceBoundingBox(renderer)); + + if (RenderSVGResourceMasker* masker = resources->masker()) + repaintRect.intersect(masker->resourceBoundingBox(renderer)); + svgStyle->inflateForShadow(repaintRect); } -bool SVGRenderSupport::pointInClippingArea(const RenderObject* object, const FloatPoint& point) +bool SVGRenderSupport::pointInClippingArea(RenderObject* object, const FloatPoint& point) { ASSERT(object); - ASSERT(object->style()); - - Document* document = object->document(); - ASSERT(document); - - const SVGRenderStyle* svgStyle = object->style()->svgStyle(); - ASSERT(svgStyle); // We just take clippers into account to determine if a point is on the node. The Specification may // change later and we also need to check maskers. - if (svgStyle->hasClipper()) { - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, svgStyle->clipperResource())) - return clipper->hitTestClipContent(object->objectBoundingBox(), point); - } + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); + if (!resources) + return true; + + if (RenderSVGResourceClipper* clipper = resources->clipper()) + return clipper->hitTestClipContent(object->objectBoundingBox(), point); return true; } diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index 8eb486e6..371ac75 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -56,7 +56,7 @@ public: static void intersectRepaintRectWithResources(const RenderObject*, FloatRect&); // Determines whether the passed point lies in a clipping area - static bool pointInClippingArea(const RenderObject*, const FloatPoint&); + static bool pointInClippingArea(RenderObject*, const FloatPoint&); enum ContainerBoundingBoxMode { ObjectBoundingBox, diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index bec78e7..d298544 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -366,7 +366,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object) if (object.isRenderPath()) { const RenderPath& path = static_cast<const RenderPath&>(object); - if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(&path, path.style())) { + if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderPath*>(&path), path.style())) { TextStreamSeparator s(" "); ts << " [stroke={" << s; writeSVGPaintingResource(ts, strokePaintingResource); @@ -387,7 +387,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object) ts << "}]"; } - if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(&path, path.style())) { + if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderPath*>(&path), path.style())) { TextStreamSeparator s(" "); ts << " [fill={" << s; writeSVGPaintingResource(ts, fillPaintingResource); @@ -734,6 +734,8 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) const RenderStyle* style = object.style(); const SVGRenderStyle* svgStyle = style->svgStyle(); + // FIXME: We want to use SVGResourcesCache to determine which resources are present, instead of quering the resource <-> id cache. + // For now leave the DRT output as is, but later on we should change this so cycles are properly ignored in the DRT output. RenderObject& renderer = const_cast<RenderObject&>(object); if (!svgStyle->maskerResource().isEmpty()) { if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskerResource())) { diff --git a/WebCore/rendering/SVGResources.cpp b/WebCore/rendering/SVGResources.cpp index de23ce1..fa1677b 100644 --- a/WebCore/rendering/SVGResources.cpp +++ b/WebCore/rendering/SVGResources.cpp @@ -25,24 +25,128 @@ #include "RenderSVGResourceFilter.h" #include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" +#include "SVGFilterElement.h" +#include "SVGGradientElement.h" #include "SVGPaint.h" +#include "SVGPatternElement.h" #include "SVGRenderStyle.h" #include "SVGURIReference.h" namespace WebCore { SVGResources::SVGResources() - : m_clipper(0) -#if ENABLE(FILTERS) - , m_filter(0) -#endif - , m_markerStart(0) - , m_markerMid(0) - , m_markerEnd(0) - , m_masker(0) - , m_fill(0) - , m_stroke(0) + : m_clipperFilterMaskerData(0) + , m_markerData(0) + , m_fillStrokeData(0) + , m_linkedResource(0) +{ +} + +static HashSet<AtomicStringImpl*>& clipperFilterMaskerTags() { + DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ()); + if (s_tagList.isEmpty()) { + // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement + // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement + s_tagList.add(SVGNames::aTag.localName().impl()); + s_tagList.add(SVGNames::circleTag.localName().impl()); + s_tagList.add(SVGNames::ellipseTag.localName().impl()); + s_tagList.add(SVGNames::glyphTag.localName().impl()); + s_tagList.add(SVGNames::gTag.localName().impl()); + s_tagList.add(SVGNames::imageTag.localName().impl()); + s_tagList.add(SVGNames::lineTag.localName().impl()); + s_tagList.add(SVGNames::markerTag.localName().impl()); + s_tagList.add(SVGNames::maskTag.localName().impl()); + s_tagList.add(SVGNames::missing_glyphTag.localName().impl()); + s_tagList.add(SVGNames::pathTag.localName().impl()); + s_tagList.add(SVGNames::polygonTag.localName().impl()); + s_tagList.add(SVGNames::polylineTag.localName().impl()); + s_tagList.add(SVGNames::rectTag.localName().impl()); + s_tagList.add(SVGNames::svgTag.localName().impl()); + s_tagList.add(SVGNames::textTag.localName().impl()); + s_tagList.add(SVGNames::useTag.localName().impl()); + + // Not listed in the definitions is the clipPath element, the SVG spec says though: + // The "clipPath" element or any of its children can specify property "clip-path". + // So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail. + // (Already mailed SVG WG, waiting for a solution) + s_tagList.add(SVGNames::clipPathTag.localName().impl()); + + // Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed. + // (Already mailed SVG WG, waiting for a solution) + s_tagList.add(SVGNames::altGlyphTag.localName().impl()); + s_tagList.add(SVGNames::textPathTag.localName().impl()); + s_tagList.add(SVGNames::trefTag.localName().impl()); + s_tagList.add(SVGNames::tspanTag.localName().impl()); + + // Elements that we ignore, as it doesn't make any sense. + // defs, pattern, switch (FIXME: Mail SVG WG about these) + // symbol (is converted to a svg element, when referenced by use, we can safely ignore it.) + } + + return s_tagList; +} + +static HashSet<AtomicStringImpl*>& markerTags() +{ + DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ()); + if (s_tagList.isEmpty()) { + s_tagList.add(SVGNames::lineTag.localName().impl()); + s_tagList.add(SVGNames::pathTag.localName().impl()); + s_tagList.add(SVGNames::polygonTag.localName().impl()); + s_tagList.add(SVGNames::polylineTag.localName().impl()); + } + + return s_tagList; +} + +static HashSet<AtomicStringImpl*>& fillAndStrokeTags() +{ + DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ()); + if (s_tagList.isEmpty()) { + s_tagList.add(SVGNames::altGlyphTag.localName().impl()); + s_tagList.add(SVGNames::circleTag.localName().impl()); + s_tagList.add(SVGNames::ellipseTag.localName().impl()); + s_tagList.add(SVGNames::lineTag.localName().impl()); + s_tagList.add(SVGNames::pathTag.localName().impl()); + s_tagList.add(SVGNames::polygonTag.localName().impl()); + s_tagList.add(SVGNames::polylineTag.localName().impl()); + s_tagList.add(SVGNames::rectTag.localName().impl()); + s_tagList.add(SVGNames::textTag.localName().impl()); + s_tagList.add(SVGNames::textPathTag.localName().impl()); + s_tagList.add(SVGNames::trefTag.localName().impl()); + s_tagList.add(SVGNames::tspanTag.localName().impl()); + } + + return s_tagList; +} + +static HashSet<AtomicStringImpl*>& chainableResourceTags() +{ + DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ()); + if (s_tagList.isEmpty()) { + s_tagList.add(SVGNames::linearGradientTag.localName().impl()); + s_tagList.add(SVGNames::filterTag.localName().impl()); + s_tagList.add(SVGNames::patternTag.localName().impl()); + s_tagList.add(SVGNames::radialGradientTag.localName().impl()); + } + + return s_tagList; +} + +static inline String targetReferenceFromResource(SVGElement* element) +{ + String target; + if (element->hasTagName(SVGNames::patternTag)) + target = static_cast<SVGPatternElement*>(element)->href(); + else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag)) + target = static_cast<SVGGradientElement*>(element)->href(); + else if (element->hasTagName(SVGNames::filterTag)) + target = static_cast<SVGFilterElement*>(element)->href(); + else + ASSERT_NOT_REACHED(); + + return SVGURIReference::getTarget(target); } static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* document, SVGPaint* paint, AtomicString& id, bool& hasPendingResource) @@ -61,17 +165,13 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* return 0; } -static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, Node* node) +static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element) { - ASSERT(node); - if (!node->isSVGElement()) - return; - - SVGElement* svgElement = static_cast<SVGElement*>(node); - if (!svgElement->isStyled()) + ASSERT(element); + if (!element->isStyled()) return; - extensions->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); + extensions->addPendingResource(id, static_cast<SVGStyledElement*>(element)); } bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style) @@ -81,6 +181,11 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen Node* node = object->node(); ASSERT(node); + ASSERT(node->isSVGElement()); + + SVGElement* element = static_cast<SVGElement*>(node); + if (!element) + return false; Document* document = object->document(); ASSERT(document); @@ -88,77 +193,85 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen SVGDocumentExtensions* extensions = document->accessSVGExtensions(); ASSERT(extensions); - bool foundResources = false; - if (style->hasClipper()) { - AtomicString id(style->clipperResource()); - m_clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, id); - if (m_clipper) - foundResources = true; - else - registerPendingResource(extensions, id, node); - } + AtomicStringImpl* tagNameImpl = element->tagQName().localName().impl(); + if (!tagNameImpl) + return false; - if (style->hasMasker()) { - AtomicString id(style->maskerResource()); - m_masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, id); - if (m_masker) - foundResources = true; - else - registerPendingResource(extensions, id, node); - } + bool foundResources = false; + if (clipperFilterMaskerTags().contains(tagNameImpl)) { + if (style->hasClipper()) { + AtomicString id(style->clipperResource()); + if (setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id))) + foundResources = true; + else + registerPendingResource(extensions, id, element); + } #if ENABLE(FILTERS) - if (style->hasFilter()) { - AtomicString id(style->filterResource()); - m_filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, id); - if (m_filter) - foundResources = true; - else - registerPendingResource(extensions, id, node); - } + if (style->hasFilter()) { + AtomicString id(style->filterResource()); + if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id))) + foundResources = true; + else + registerPendingResource(extensions, id, element); + } #endif - if (style->hasMarkers()) { + if (style->hasMasker()) { + AtomicString id(style->maskerResource()); + if (setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id))) + foundResources = true; + else + registerPendingResource(extensions, id, element); + } + } + + if (markerTags().contains(tagNameImpl) && style->hasMarkers()) { AtomicString markerStartId(style->markerStartResource()); - m_markerStart = getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId); - if (m_markerStart) + if (setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId))) foundResources = true; else - registerPendingResource(extensions, markerStartId, node); + registerPendingResource(extensions, markerStartId, element); AtomicString markerMidId(style->markerMidResource()); - m_markerMid = getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId); - if (m_markerMid) + if (setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId))) foundResources = true; else - registerPendingResource(extensions, markerMidId, node); + registerPendingResource(extensions, markerMidId, element); AtomicString markerEndId(style->markerEndResource()); - m_markerEnd = getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId); - if (m_markerEnd) + if (setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId))) foundResources = true; else - registerPendingResource(extensions, markerEndId, node); + registerPendingResource(extensions, markerEndId, element); } - if (style->hasFill()) { - bool hasPendingResource = false; - AtomicString id; - m_fill = paintingResourceFromSVGPaint(document, style->fillPaint(), id, hasPendingResource); - if (m_fill) - foundResources = true; - else if (hasPendingResource) - registerPendingResource(extensions, id, node); + if (fillAndStrokeTags().contains(tagNameImpl)) { + if (style->hasFill()) { + bool hasPendingResource = false; + AtomicString id; + if (setFill(paintingResourceFromSVGPaint(document, style->fillPaint(), id, hasPendingResource))) + foundResources = true; + else if (hasPendingResource) + registerPendingResource(extensions, id, element); + } + + if (style->hasStroke()) { + bool hasPendingResource = false; + AtomicString id; + if (setStroke(paintingResourceFromSVGPaint(document, style->strokePaint(), id, hasPendingResource))) + foundResources = true; + else if (hasPendingResource) + registerPendingResource(extensions, id, element); + } } - if (style->hasStroke()) { - bool hasPendingResource = false; - AtomicString id; - m_stroke = paintingResourceFromSVGPaint(document, style->strokePaint(), id, hasPendingResource); - if (m_stroke) + if (chainableResourceTags().contains(tagNameImpl)) { + AtomicString id(targetReferenceFromResource(element)); + if (setLinkedResource(getRenderSVGResourceContainerById(document, id))) foundResources = true; - else if (hasPendingResource) - registerPendingResource(extensions, id, node); + else + registerPendingResource(extensions, id, element); } return foundResources; @@ -166,81 +279,115 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen void SVGResources::invalidateClient(RenderObject* object) const { - // Ordinary resources - if (m_clipper) - m_clipper->invalidateClient(object); + if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) + return; + + if (m_linkedResource) { + ASSERT(!m_clipperFilterMaskerData); + ASSERT(!m_markerData); + ASSERT(!m_fillStrokeData); + m_linkedResource->invalidateClient(object); + return; + } + + if (m_clipperFilterMaskerData) { + if (m_clipperFilterMaskerData->clipper) + m_clipperFilterMaskerData->clipper->invalidateClient(object); #if ENABLE(FILTERS) - if (m_filter) - m_filter->invalidateClient(object); + if (m_clipperFilterMaskerData->filter) + m_clipperFilterMaskerData->filter->invalidateClient(object); #endif - if (m_masker) - m_masker->invalidateClient(object); - if (m_markerStart) - m_markerStart->invalidateClient(object); - if (m_markerMid) - m_markerMid->invalidateClient(object); - if (m_markerEnd) - m_markerEnd->invalidateClient(object); - - // Paint servers - if (m_fill) - m_fill->invalidateClient(object); - if (m_stroke) - m_stroke->invalidateClient(object); + if (m_clipperFilterMaskerData->masker) + m_clipperFilterMaskerData->masker->invalidateClient(object); + } + + if (m_markerData) { + if (m_markerData->markerStart) + m_markerData->markerStart->invalidateClient(object); + if (m_markerData->markerMid) + m_markerData->markerMid->invalidateClient(object); + if (m_markerData->markerEnd) + m_markerData->markerEnd->invalidateClient(object); + } + + if (m_fillStrokeData) { + if (m_fillStrokeData->fill) + m_fillStrokeData->fill->invalidateClient(object); + if (m_fillStrokeData->stroke) + m_fillStrokeData->stroke->invalidateClient(object); + } } void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) { ASSERT(resource); + if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) + return; + + if (m_linkedResource == resource) { + ASSERT(!m_clipperFilterMaskerData); + ASSERT(!m_markerData); + ASSERT(!m_fillStrokeData); + m_linkedResource->invalidateClients(); + m_linkedResource = 0; + return; + } switch (resource->resourceType()) { case MaskerResourceType: - if (m_masker == resource) { - m_masker->invalidateClients(); - m_masker = 0; + if (!m_clipperFilterMaskerData) + break; + if (m_clipperFilterMaskerData->masker == resource) { + m_clipperFilterMaskerData->masker->invalidateClients(); + m_clipperFilterMaskerData->masker = 0; } break; case MarkerResourceType: - if (m_markerStart == resource) { - m_markerStart->invalidateClients(); - m_markerStart = 0; + if (!m_markerData) + break; + if (m_markerData->markerStart == resource) { + m_markerData->markerStart->invalidateClients(); + m_markerData->markerStart = 0; } - - if (m_markerMid == resource) { - m_markerMid->invalidateClients(); - m_markerMid = 0; + if (m_markerData->markerMid == resource) { + m_markerData->markerMid->invalidateClients(); + m_markerData->markerMid = 0; } - - if (m_markerEnd == resource) { - m_markerEnd->invalidateClients(); - m_markerEnd = 0; + if (m_markerData->markerEnd == resource) { + m_markerData->markerEnd->invalidateClients(); + m_markerData->markerEnd = 0; } break; case PatternResourceType: case LinearGradientResourceType: case RadialGradientResourceType: - if (m_fill == resource) { - m_fill->invalidateClients(); - m_fill = 0; + if (!m_fillStrokeData) + break; + if (m_fillStrokeData->fill == resource) { + m_fillStrokeData->fill->invalidateClients(); + m_fillStrokeData->fill = 0; } - - if (m_stroke == resource) { - m_stroke->invalidateClients(); - m_stroke = 0; + if (m_fillStrokeData->stroke == resource) { + m_fillStrokeData->stroke->invalidateClients(); + m_fillStrokeData->stroke = 0; } break; #if ENABLE(FILTERS) case FilterResourceType: - if (m_filter == resource) { - m_filter->invalidateClients(); - m_filter = 0; + if (!m_clipperFilterMaskerData) + break; + if (m_clipperFilterMaskerData->filter == resource) { + m_clipperFilterMaskerData->filter->invalidateClients(); + m_clipperFilterMaskerData->filter = 0; } break; #endif case ClipperResourceType: - if (m_clipper == resource) { - m_clipper->invalidateClients(); - m_clipper = 0; + if (!m_clipperFilterMaskerData) + break; + if (m_clipperFilterMaskerData->clipper == resource) { + m_clipperFilterMaskerData->clipper->invalidateClients(); + m_clipperFilterMaskerData->clipper = 0; } break; case SolidColorResourceType: @@ -250,77 +397,212 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set) { - // Ordinary resources - if (m_clipper) - set.add(m_clipper); + if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) + return; + + if (m_linkedResource) { + ASSERT(!m_clipperFilterMaskerData); + ASSERT(!m_markerData); + ASSERT(!m_fillStrokeData); + set.add(m_linkedResource); + return; + } + + if (m_clipperFilterMaskerData) { + if (m_clipperFilterMaskerData->clipper) + set.add(m_clipperFilterMaskerData->clipper); #if ENABLE(FILTERS) - if (m_filter) - set.add(m_filter); + if (m_clipperFilterMaskerData->filter) + set.add(m_clipperFilterMaskerData->filter); #endif - if (m_markerStart) - set.add(m_markerStart); - if (m_markerMid) - set.add(m_markerMid); - if (m_markerEnd) - set.add(m_markerEnd); - if (m_masker) - set.add(m_masker); - - // Paint servers - if (m_fill) - set.add(m_fill); - if (m_stroke) - set.add(m_stroke); + if (m_clipperFilterMaskerData->masker) + set.add(m_clipperFilterMaskerData->masker); + } + + if (m_markerData) { + if (m_markerData->markerStart) + set.add(m_markerData->markerStart); + if (m_markerData->markerMid) + set.add(m_markerData->markerMid); + if (m_markerData->markerEnd) + set.add(m_markerData->markerEnd); + } + + if (m_fillStrokeData) { + if (m_fillStrokeData->fill) + set.add(m_fillStrokeData->fill); + if (m_fillStrokeData->stroke) + set.add(m_fillStrokeData->stroke); + } +} + +bool SVGResources::setClipper(RenderSVGResourceClipper* clipper) +{ + if (!clipper) + return false; + + if (!m_clipperFilterMaskerData) + m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); + + m_clipperFilterMaskerData->clipper = clipper; + return true; } void SVGResources::resetClipper() { - ASSERT(m_clipper); - m_clipper = 0; + ASSERT(m_clipperFilterMaskerData); + ASSERT(m_clipperFilterMaskerData->clipper); + m_clipperFilterMaskerData->clipper = 0; } #if ENABLE(FILTERS) +bool SVGResources::setFilter(RenderSVGResourceFilter* filter) +{ + if (!filter) + return false; + + if (!m_clipperFilterMaskerData) + m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); + + m_clipperFilterMaskerData->filter = filter; + return true; +} + void SVGResources::resetFilter() { - ASSERT(m_filter); - m_filter = 0; + ASSERT(m_clipperFilterMaskerData); + ASSERT(m_clipperFilterMaskerData->filter); + m_clipperFilterMaskerData->filter = 0; } #endif +bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart) +{ + if (!markerStart) + return false; + + if (!m_markerData) + m_markerData = MarkerData::create(); + + m_markerData->markerStart = markerStart; + return true; +} + void SVGResources::resetMarkerStart() { - ASSERT(m_markerStart); - m_markerStart = 0; + ASSERT(m_markerData); + ASSERT(m_markerData->markerStart); + m_markerData->markerStart = 0; +} + +bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid) +{ + if (!markerMid) + return false; + + if (!m_markerData) + m_markerData = MarkerData::create(); + + m_markerData->markerMid = markerMid; + return true; } void SVGResources::resetMarkerMid() { - ASSERT(m_markerMid); - m_markerMid = 0; + ASSERT(m_markerData); + ASSERT(m_markerData->markerMid); + m_markerData->markerMid = 0; +} + +bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd) +{ + if (!markerEnd) + return false; + + if (!m_markerData) + m_markerData = MarkerData::create(); + + m_markerData->markerEnd = markerEnd; + return true; } void SVGResources::resetMarkerEnd() { - ASSERT(m_markerEnd); - m_markerEnd = 0; + ASSERT(m_markerData); + ASSERT(m_markerData->markerEnd); + m_markerData->markerEnd = 0; +} + +bool SVGResources::setMasker(RenderSVGResourceMasker* masker) +{ + if (!masker) + return false; + + if (!m_clipperFilterMaskerData) + m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); + + m_clipperFilterMaskerData->masker = masker; + return true; } void SVGResources::resetMasker() { - ASSERT(m_masker); - m_masker = 0; + ASSERT(m_clipperFilterMaskerData); + ASSERT(m_clipperFilterMaskerData->masker); + m_clipperFilterMaskerData->masker = 0; +} + +bool SVGResources::setFill(RenderSVGResourceContainer* fill) +{ + if (!fill) + return false; + + if (!m_fillStrokeData) + m_fillStrokeData = FillStrokeData::create(); + + m_fillStrokeData->fill = fill; + return true; } void SVGResources::resetFill() { - ASSERT(m_fill); - m_fill = 0; + ASSERT(m_fillStrokeData); + ASSERT(m_fillStrokeData->fill); + m_fillStrokeData->fill = 0; +} + +bool SVGResources::setStroke(RenderSVGResourceContainer* stroke) +{ + if (!stroke) + return false; + + if (!m_fillStrokeData) + m_fillStrokeData = FillStrokeData::create(); + + m_fillStrokeData->stroke = stroke; + return true; } void SVGResources::resetStroke() { - ASSERT(m_stroke); - m_stroke = 0; + ASSERT(m_fillStrokeData); + ASSERT(m_fillStrokeData->stroke); + m_fillStrokeData->stroke = 0; +} + +bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource) +{ + if (!linkedResource) + return false; + + m_linkedResource = linkedResource; + return true; +} + +void SVGResources::resetLinkedResource() +{ + ASSERT(m_linkedResource); + m_linkedResource = 0; } #ifndef NDEBUG @@ -334,24 +616,35 @@ void SVGResources::dump(const RenderObject* object) object->node()->showTreeForThis(); fprintf(stderr, "\n | List of resources:\n"); - if (m_clipper) - fprintf(stderr, " |-> Clipper : %p (node=%p)\n", m_clipper, m_clipper->node()); + if (m_clipperFilterMaskerData) { + if (RenderSVGResourceClipper* clipper = m_clipperFilterMaskerData->clipper) + fprintf(stderr, " |-> Clipper : %p (node=%p)\n", clipper, clipper->node()); #if ENABLE(FILTERS) - if (m_filter) - fprintf(stderr, " |-> Filter : %p (node=%p)\n", m_filter, m_filter->node()); + if (RenderSVGResourceFilter* filter = m_clipperFilterMaskerData->filter) + fprintf(stderr, " |-> Filter : %p (node=%p)\n", filter, filter->node()); #endif - if (m_markerStart) - fprintf(stderr, " |-> MarkerStart: %p (node=%p)\n", m_markerStart, m_markerStart->node()); - if (m_markerMid) - fprintf(stderr, " |-> MarkerMid : %p (node=%p)\n", m_markerMid, m_markerMid->node()); - if (m_markerEnd) - fprintf(stderr, " |-> MarkerEnd : %p (node=%p)\n", m_markerEnd, m_markerEnd->node()); - if (m_masker) - fprintf(stderr, " |-> Masker : %p (node=%p)\n", m_masker, m_masker->node()); - if (m_fill) - fprintf(stderr, " |-> Fill : %p (node=%p)\n", m_fill, m_fill->node()); - if (m_stroke) - fprintf(stderr, " |-> Stroke : %p (node=%p)\n", m_stroke, m_stroke->node()); + if (RenderSVGResourceMasker* masker = m_clipperFilterMaskerData->masker) + fprintf(stderr, " |-> Masker : %p (node=%p)\n", masker, masker->node()); + } + + if (m_markerData) { + if (RenderSVGResourceMarker* markerStart = m_markerData->markerStart) + fprintf(stderr, " |-> MarkerStart: %p (node=%p)\n", markerStart, markerStart->node()); + if (RenderSVGResourceMarker* markerMid = m_markerData->markerMid) + fprintf(stderr, " |-> MarkerMid : %p (node=%p)\n", markerMid, markerMid->node()); + if (RenderSVGResourceMarker* markerEnd = m_markerData->markerEnd) + fprintf(stderr, " |-> MarkerEnd : %p (node=%p)\n", markerEnd, markerEnd->node()); + } + + if (m_fillStrokeData) { + if (RenderSVGResourceContainer* fill = m_fillStrokeData->fill) + fprintf(stderr, " |-> Fill : %p (node=%p)\n", fill, fill->node()); + if (RenderSVGResourceContainer* stroke = m_fillStrokeData->stroke) + fprintf(stderr, " |-> Stroke : %p (node=%p)\n", stroke, stroke->node()); + } + + if (m_linkedResource) + fprintf(stderr, " |-> xlink:href : %p (node=%p)\n", m_linkedResource, m_linkedResource->node()); } #endif diff --git a/WebCore/rendering/SVGResources.h b/WebCore/rendering/SVGResources.h index 57a4140..a07a990 100644 --- a/WebCore/rendering/SVGResources.h +++ b/WebCore/rendering/SVGResources.h @@ -23,6 +23,8 @@ #if ENABLE(SVG) #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -43,18 +45,21 @@ public: bool buildCachedResources(const RenderObject*, const SVGRenderStyle*); // Ordinary resources - RenderSVGResourceClipper* clipper() const { return m_clipper; } + RenderSVGResourceClipper* clipper() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->clipper : 0; } #if ENABLE(FILTERS) - RenderSVGResourceFilter* filter() const { return m_filter; } + RenderSVGResourceFilter* filter() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->filter : 0; } #endif - RenderSVGResourceMarker* markerStart() const { return m_markerStart; } - RenderSVGResourceMarker* markerMid() const { return m_markerMid; } - RenderSVGResourceMarker* markerEnd() const { return m_markerEnd; } - RenderSVGResourceMasker* masker() const { return m_masker; } + RenderSVGResourceMarker* markerStart() const { return m_markerData ? m_markerData->markerStart : 0; } + RenderSVGResourceMarker* markerMid() const { return m_markerData ? m_markerData->markerMid : 0; } + RenderSVGResourceMarker* markerEnd() const { return m_markerData ? m_markerData->markerEnd : 0; } + RenderSVGResourceMasker* masker() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->masker : 0; } // Paint servers - RenderSVGResourceContainer* fill() const { return m_fill; } - RenderSVGResourceContainer* stroke() const { return m_stroke; } + RenderSVGResourceContainer* fill() const { return m_fillStrokeData ? m_fillStrokeData->fill : 0; } + RenderSVGResourceContainer* stroke() const { return m_fillStrokeData ? m_fillStrokeData->stroke : 0; } + + // Chainable resources - linked through xlink:href + RenderSVGResourceContainer* linkedResource() const { return m_linkedResource; } void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&); @@ -80,21 +85,92 @@ private: void resetMasker(); void resetFill(); void resetStroke(); + void resetLinkedResource(); private: - // Ordinary resources - RenderSVGResourceClipper* m_clipper; + bool setClipper(RenderSVGResourceClipper*); +#if ENABLE(FILTERS) + bool setFilter(RenderSVGResourceFilter*); +#endif + bool setMarkerStart(RenderSVGResourceMarker*); + bool setMarkerMid(RenderSVGResourceMarker*); + bool setMarkerEnd(RenderSVGResourceMarker*); + bool setMasker(RenderSVGResourceMasker*); + bool setFill(RenderSVGResourceContainer*); + bool setStroke(RenderSVGResourceContainer*); + bool setLinkedResource(RenderSVGResourceContainer*); + + // From SVG 1.1 2nd Edition + // clipper: 'container elements' and 'graphics elements' + // filter: 'container elements' and 'graphics elements' + // masker: 'container elements' and 'graphics elements' + // -> a, circle, defs, ellipse, glyph, g, image, line, marker, mask, missing-glyph, path, pattern, polygon, polyline, rect, svg, switch, symbol, text, use + struct ClipperFilterMaskerData { + ClipperFilterMaskerData() + : clipper(0) #if ENABLE(FILTERS) - RenderSVGResourceFilter* m_filter; + , filter(0) #endif - RenderSVGResourceMarker* m_markerStart; - RenderSVGResourceMarker* m_markerMid; - RenderSVGResourceMarker* m_markerEnd; - RenderSVGResourceMasker* m_masker; + , masker(0) + { + } - // Paint servers - RenderSVGResourceContainer* m_fill; - RenderSVGResourceContainer* m_stroke; + static PassOwnPtr<ClipperFilterMaskerData> create() + { + return new ClipperFilterMaskerData; + } + + RenderSVGResourceClipper* clipper; +#if ENABLE(FILTERS) + RenderSVGResourceFilter* filter; +#endif + RenderSVGResourceMasker* masker; + }; + + // From SVG 1.1 2nd Edition + // marker: line, path, polygon, polyline + struct MarkerData { + MarkerData() + : markerStart(0) + , markerMid(0) + , markerEnd(0) + { + } + + static PassOwnPtr<MarkerData> create() + { + return new MarkerData; + } + + RenderSVGResourceMarker* markerStart; + RenderSVGResourceMarker* markerMid; + RenderSVGResourceMarker* markerEnd; + }; + + // From SVG 1.1 2nd Edition + // fill: 'shapes' and 'text content elements' + // stroke: 'shapes' and 'text content elements' + // -> altGlyph, circle, ellipse, line, path, polygon, polyline, rect, text, textPath, tref, tspan + struct FillStrokeData { + FillStrokeData() + : fill(0) + , stroke(0) + { + } + + static PassOwnPtr<FillStrokeData> create() + { + return new FillStrokeData; + } + + RenderSVGResourceContainer* fill; + RenderSVGResourceContainer* stroke; + }; + + OwnPtr<ClipperFilterMaskerData> m_clipperFilterMaskerData; + OwnPtr<MarkerData> m_markerData; + OwnPtr<FillStrokeData> m_fillStrokeData; + RenderSVGResourceContainer* m_linkedResource; }; } diff --git a/WebCore/rendering/SVGResourcesCache.cpp b/WebCore/rendering/SVGResourcesCache.cpp index 46586cc..b922b44 100644 --- a/WebCore/rendering/SVGResourcesCache.cpp +++ b/WebCore/rendering/SVGResourcesCache.cpp @@ -131,17 +131,7 @@ void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifferen return; clientUpdatedFromElement(renderer, newStyle); - - // Invalidate resources in ancestor chain, if needed. - RenderObject* parent = renderer->parent(); - while (parent) { - if (parent->isSVGResourceContainer()) { - parent->toRenderSVGResourceContainer()->invalidateClients(); - break; - } - - parent = parent->parent(); - } + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false); } void SVGResourcesCache::clientUpdatedFromElement(RenderObject* renderer, const RenderStyle* newStyle) diff --git a/WebCore/rendering/SVGResourcesCycleSolver.cpp b/WebCore/rendering/SVGResourcesCycleSolver.cpp index e150144..ec2e036 100644 --- a/WebCore/rendering/SVGResourcesCycleSolver.cpp +++ b/WebCore/rendering/SVGResourcesCycleSolver.cpp @@ -94,6 +94,7 @@ bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) con return false; } +<<<<<<< HEAD static inline String targetReferenceFromResource(SVGElement* element, bool& isValid) { String target; @@ -177,6 +178,8 @@ bool SVGResourcesCycleSolver::chainableResourceContainsCycles(RenderSVGResourceC return false; } +======= +>>>>>>> webkit.org at r64523 void SVGResourcesCycleSolver::resolveCycles() { ASSERT(m_allResources.isEmpty()); @@ -221,6 +224,10 @@ void SVGResourcesCycleSolver::resolveCycles() for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it) m_allResources.add(*it); + // If we're a resource, add ourselves to the HashSet. + if (m_renderer->isSVGResourceContainer()) + m_allResources.add(m_renderer->toRenderSVGResourceContainer()); + ASSERT(!m_allResources.isEmpty()); // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer' @@ -228,22 +235,6 @@ void SVGResourcesCycleSolver::resolveCycles() end = localResources.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) { RenderSVGResourceContainer* resource = *it; - - // Special handling for resources that can be chained using xlink:href - need to detect cycles as well! - switch (resource->resourceType()) { - case PatternResourceType: - case LinearGradientResourceType: - case RadialGradientResourceType: - case FilterResourceType: - if (chainableResourceContainsCycles(resource)) { - breakCycle(resource); - continue; - } - break; - default: - break; - } - if (parentResources.contains(resource) || resourceContainsCycles(resource)) breakCycle(resource); } @@ -259,6 +250,11 @@ void SVGResourcesCycleSolver::resolveCycles() void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer* resourceLeadingToCycle) { ASSERT(resourceLeadingToCycle); + if (resourceLeadingToCycle == m_resources->linkedResource()) { + m_resources->resetLinkedResource(); + return; + } + switch (resourceLeadingToCycle->resourceType()) { case MaskerResourceType: ASSERT(resourceLeadingToCycle == m_resources->masker()); diff --git a/WebCore/rendering/SVGResourcesCycleSolver.h b/WebCore/rendering/SVGResourcesCycleSolver.h index 1f49354..e63ee63 100644 --- a/WebCore/rendering/SVGResourcesCycleSolver.h +++ b/WebCore/rendering/SVGResourcesCycleSolver.h @@ -38,7 +38,6 @@ public: private: bool resourceContainsCycles(RenderObject*) const; - bool chainableResourceContainsCycles(RenderSVGResourceContainer*) const; void breakCycle(RenderSVGResourceContainer*); RenderObject* m_renderer; diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp index 93e50cc..2a9003c 100644 --- a/WebCore/rendering/style/SVGRenderStyle.cpp +++ b/WebCore/rendering/style/SVGRenderStyle.cpp @@ -165,13 +165,14 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated. if (stroke != other->stroke) { if (stroke->width != other->stroke->width + || stroke->paint != other->stroke->paint || stroke->miterLimit != other->stroke->miterLimit || stroke->dashArray != other->stroke->dashArray || stroke->dashOffset != other->stroke->dashOffset) return StyleDifferenceLayout; - // Only these two cases remain, where we only need a repaint. - ASSERT(stroke->paint != other->stroke->paint || stroke->opacity != other->stroke->opacity); + // Only the stroke-opacity case remains, where we only need a repaint. + ASSERT(stroke->opacity != other->stroke->opacity); return StyleDifferenceRepaint; } diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index c87dd2b..c1d72e9 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -56,59 +56,237 @@ public: bool operator==(const SVGRenderStyle&) const; bool operator!=(const SVGRenderStyle& o) const { return !(*this == o); } - // SVG CSS Properties - SVG_RS_DEFINE_ATTRIBUTE(EAlignmentBaseline, AlignmentBaseline, alignmentBaseline, AB_AUTO) - SVG_RS_DEFINE_ATTRIBUTE(EDominantBaseline, DominantBaseline, dominantBaseline, DB_AUTO) - SVG_RS_DEFINE_ATTRIBUTE(EBaselineShift, BaselineShift, baselineShift, BS_BASELINE) - SVG_RS_DEFINE_ATTRIBUTE(EVectorEffect, VectorEffect, vectorEffect, VE_NONE) - - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineCap, CapStyle, capStyle, ButtCap) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(WindRule, ClipRule, clipRule, RULE_NONZERO) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EColorInterpolation, ColorInterpolation, colorInterpolation, CI_SRGB) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EColorInterpolation, ColorInterpolationFilters, colorInterpolationFilters, CI_LINEARRGB) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EColorRendering, ColorRendering, colorRendering, CR_AUTO) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(WindRule, FillRule, fillRule, RULE_NONZERO) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EImageRendering, ImageRendering, imageRendering, IR_AUTO) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineJoin, JoinStyle, joinStyle, MiterJoin) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EShapeRendering, ShapeRendering, shapeRendering, SR_AUTO) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextAnchor, TextAnchor, textAnchor, TA_START) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EWritingMode, WritingMode, writingMode, WM_LRTB) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EGlyphOrientation, GlyphOrientationHorizontal, glyphOrientationHorizontal, GO_0DEG) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EGlyphOrientation, GlyphOrientationVertical, glyphOrientationVertical, GO_AUTO) - - // SVG CSS Properties (using DataRef's) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, fill, opacity, FillOpacity, fillOpacity, 1.0f) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(SVGPaint, fill, paint, FillPaint, fillPaint, SVGPaint::defaultFill()) - - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stroke, opacity, StrokeOpacity, strokeOpacity, 1.0f) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(SVGPaint, stroke, paint, StrokePaint, strokePaint, SVGPaint::defaultStroke()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValueList, stroke, dashArray, StrokeDashArray, strokeDashArray, 0) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stroke, miterLimit, StrokeMiterLimit, strokeMiterLimit, 4.0f) + // Initial values for all the properties + static EAlignmentBaseline initialAlignmentBaseline() { return AB_AUTO; } + static EDominantBaseline initialDominantBaseline() { return DB_AUTO; } + static EBaselineShift initialBaselineShift() { return BS_BASELINE; } + static EVectorEffect initialVectorEffect() { return VE_NONE; } + static LineCap initialCapStyle() { return ButtCap; } + static WindRule initialClipRule() { return RULE_NONZERO; } + static EColorInterpolation initialColorInterpolation() { return CI_SRGB; } + static EColorInterpolation initialColorInterpolationFilters() { return CI_LINEARRGB; } + static EColorRendering initialColorRendering() { return CR_AUTO; } + static WindRule initialFillRule() { return RULE_NONZERO; } + static EImageRendering initialImageRendering() { return IR_AUTO; } + static LineJoin initialJoinStyle() { return MiterJoin; } + static EShapeRendering initialShapeRendering() { return SR_AUTO; } + static ETextAnchor initialTextAnchor() { return TA_START; } + static EWritingMode initialWritingMode() { return WM_LRTB; } + static EGlyphOrientation initialGlyphOrientationHorizontal() { return GO_0DEG; } + static EGlyphOrientation initialGlyphOrientationVertical() { return GO_AUTO; } + static float initialFillOpacity() { return 1.0f; } + static SVGPaint* initialFillPaint() { return SVGPaint::defaultFill(); } + static float initialStrokeOpacity() { return 1.0f; } + static SVGPaint* initialStrokePaint() { return SVGPaint::defaultStroke(); } + static CSSValueList* initialStrokeDashArray() { return 0; } + static float initialStrokeMiterLimit() { return 4.0f; } + static CSSValue* initialStrokeWidth() { return 0; } + static CSSValue* initialStrokeDashOffset() { return 0; }; + static CSSValue* initialKerning() { return 0; } + static float initialStopOpacity() { return 1.0f; } + static Color initialStopColor() { return Color(0, 0, 0); } + static float initialFloodOpacity() { return 1.0f; } + static Color initialFloodColor() { return Color(0, 0, 0); } + static Color initialLightingColor() { return Color(255, 255, 255); } + static CSSValue* initialBaselineShiftValue() { return 0; } + static ShadowData* initialShadow() { return 0; } + static String initialClipperResource() { return String(); } + static String initialFilterResource() { return String(); } + static String initialMaskerResource() { return String(); } + static String initialMarkerStartResource() { return String(); } + static String initialMarkerMidResource() { return String(); } + static String initialMarkerEndResource() { return String(); } + + // SVG CSS Property setters + void setAlignmentBaseline(EAlignmentBaseline val) { svg_noninherited_flags.f._alignmentBaseline = val; } + void setDominantBaseline(EDominantBaseline val) { svg_noninherited_flags.f._dominantBaseline = val; } + void setBaselineShift(EBaselineShift val) { svg_noninherited_flags.f._baselineShift = val; } + void setVectorEffect(EVectorEffect val) { svg_noninherited_flags.f._vectorEffect = val; } + void setCapStyle(LineCap val) { svg_inherited_flags._capStyle = val; } + void setClipRule(WindRule val) { svg_inherited_flags._clipRule = val; } + void setColorInterpolation(EColorInterpolation val) { svg_inherited_flags._colorInterpolation = val; } + void setColorInterpolationFilters(EColorInterpolation val) { svg_inherited_flags._colorInterpolationFilters = val; } + void setColorRendering(EColorRendering val) { svg_inherited_flags._colorRendering = val; } + void setFillRule(WindRule val) { svg_inherited_flags._fillRule = val; } + void setImageRendering(EImageRendering val) { svg_inherited_flags._imageRendering = val; } + void setJoinStyle(LineJoin val) { svg_inherited_flags._joinStyle = val; } + void setShapeRendering(EShapeRendering val) { svg_inherited_flags._shapeRendering = val; } + void setTextAnchor(ETextAnchor val) { svg_inherited_flags._textAnchor = val; } + void setWritingMode(EWritingMode val) { svg_inherited_flags._writingMode = val; } + void setGlyphOrientationHorizontal(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationHorizontal = val; } + void setGlyphOrientationVertical(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationVertical = val; } - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, stroke, width, StrokeWidth, strokeWidth, 0) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, stroke, dashOffset, StrokeDashOffset, strokeDashOffset, 0); + void setFillOpacity(float obj) + { + if (!(fill->opacity == obj)) + fill.access()->opacity = obj; + } + + void setFillPaint(PassRefPtr<SVGPaint> obj) + { + if (!(fill->paint == obj)) + fill.access()->paint = obj; + } + + void setStrokeOpacity(float obj) + { + if (!(stroke->opacity == obj)) + stroke.access()->opacity = obj; + } + + void setStrokePaint(PassRefPtr<SVGPaint> obj) + { + if (!(stroke->paint == obj)) + stroke.access()->paint = obj; + } + + void setStrokeDashArray(PassRefPtr<CSSValueList> obj) + { + if (!(stroke->dashArray == obj)) + stroke.access()->dashArray = obj; + } + + void setStrokeMiterLimit(float obj) + { + if (!(stroke->miterLimit == obj)) + stroke.access()->miterLimit = obj; + } - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, text, kerning, Kerning, kerning, 0) + void setStrokeWidth(PassRefPtr<CSSValue> obj) + { + if (!(stroke->width == obj)) + stroke.access()->width = obj; + } - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stops, opacity, StopOpacity, stopOpacity, 1.0f) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, stops, color, StopColor, stopColor, Color(0, 0, 0)) + void setStrokeDashOffset(PassRefPtr<CSSValue> obj) + { + if (!(stroke->dashOffset == obj)) + stroke.access()->dashOffset = obj; + } - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, misc, floodOpacity, FloodOpacity, floodOpacity, 1.0f) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, misc, floodColor, FloodColor, floodColor, Color(0, 0, 0)) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, misc, lightingColor, LightingColor, lightingColor, Color(255, 255, 255)) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, misc, baselineShiftValue, BaselineShiftValue, baselineShiftValue, 0) + void setKerning(PassRefPtr<CSSValue> obj) + { + if (!(text->kerning == obj)) + text.access()->kerning = obj; + } - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_OWNPTR(ShadowData, shadowSVG, shadow, Shadow, shadow, 0) + void setStopOpacity(float obj) + { + if (!(stops->opacity == obj)) + stops.access()->opacity = obj; + } - // Non-inherited resources - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, resources, clipper, ClipperResource, clipperResource, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, resources, filter, FilterResource, filterResource, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, resources, masker, MaskerResource, maskerResource, String()) + void setStopColor(Color obj) + { + if (!(stops->color == obj)) + stops.access()->color = obj; + } + + void setFloodOpacity(float obj) + { + if (!(misc->floodOpacity == obj)) + misc.access()->floodOpacity = obj; + } + + void setFloodColor(Color obj) + { + if (!(misc->floodColor == obj)) + misc.access()->floodColor = obj; + } + + void setLightingColor(Color obj) + { + if (!(misc->lightingColor == obj)) + misc.access()->lightingColor = obj; + } + + void setBaselineShiftValue(PassRefPtr<CSSValue> obj) + { + if (!(misc->baselineShiftValue == obj)) + misc.access()->baselineShiftValue = obj; + } + + void setShadow(PassOwnPtr<ShadowData> obj) { shadowSVG.access()->shadow = obj; + } + + // Setters for non-inherited resources + void setClipperResource(String obj) + { + if (!(resources->clipper == obj)) + resources.access()->clipper = obj; + } + + void setFilterResource(String obj) + { + if (!(resources->filter == obj)) + resources.access()->filter = obj; + } + + void setMaskerResource(String obj) + { + if (!(resources->masker == obj)) + resources.access()->masker = obj; + } + + // Setters for inherited resources + void setMarkerStartResource(String obj) + { + if (!(inheritedResources->markerStart == obj)) + inheritedResources.access()->markerStart = obj; + } + + void setMarkerMidResource(String obj) + { + if (!(inheritedResources->markerMid == obj)) + inheritedResources.access()->markerMid = obj; + } + + void setMarkerEndResource(String obj) + { + if (!(inheritedResources->markerEnd == obj)) + inheritedResources.access()->markerEnd = obj; + } - // Inherited resources - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerStart, MarkerStartResource, markerStartResource, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerMid, MarkerMidResource, markerMidResource, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerEnd, MarkerEndResource, markerEndResource, String()) + // Read accessors for all the properties + EAlignmentBaseline alignmentBaseline() const { return (EAlignmentBaseline) svg_noninherited_flags.f._alignmentBaseline; } + EDominantBaseline dominantBaseline() const { return (EDominantBaseline) svg_noninherited_flags.f._dominantBaseline; } + EBaselineShift baselineShift() const { return (EBaselineShift) svg_noninherited_flags.f._baselineShift; } + EVectorEffect vectorEffect() const { return (EVectorEffect) svg_noninherited_flags.f._vectorEffect; } + LineCap capStyle() const { return (LineCap) svg_inherited_flags._capStyle; } + WindRule clipRule() const { return (WindRule) svg_inherited_flags._clipRule; } + EColorInterpolation colorInterpolation() const { return (EColorInterpolation) svg_inherited_flags._colorInterpolation; } + EColorInterpolation colorInterpolationFilters() const { return (EColorInterpolation) svg_inherited_flags._colorInterpolationFilters; } + EColorRendering colorRendering() const { return (EColorRendering) svg_inherited_flags._colorRendering; } + WindRule fillRule() const { return (WindRule) svg_inherited_flags._fillRule; } + EImageRendering imageRendering() const { return (EImageRendering) svg_inherited_flags._imageRendering; } + LineJoin joinStyle() const { return (LineJoin) svg_inherited_flags._joinStyle; } + EShapeRendering shapeRendering() const { return (EShapeRendering) svg_inherited_flags._shapeRendering; } + ETextAnchor textAnchor() const { return (ETextAnchor) svg_inherited_flags._textAnchor; } + EWritingMode writingMode() const { return (EWritingMode) svg_inherited_flags._writingMode; } + EGlyphOrientation glyphOrientationHorizontal() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationHorizontal; } + EGlyphOrientation glyphOrientationVertical() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationVertical; } + float fillOpacity() const { return fill->opacity; } + SVGPaint* fillPaint() const { return fill->paint.get(); } + float strokeOpacity() const { return stroke->opacity; } + SVGPaint* strokePaint() const { return stroke->paint.get(); } + CSSValueList* strokeDashArray() const { return stroke->dashArray.get(); } + float strokeMiterLimit() const { return stroke->miterLimit; } + CSSValue* strokeWidth() const { return stroke->width.get(); } + CSSValue* strokeDashOffset() const { return stroke->dashOffset.get(); } + CSSValue* kerning() const { return text->kerning.get(); } + float stopOpacity() const { return stops->opacity; } + Color stopColor() const { return stops->color; } + float floodOpacity() const { return misc->floodOpacity; } + Color floodColor() const { return misc->floodColor; } + Color lightingColor() const { return misc->lightingColor; } + CSSValue* baselineShiftValue() const { return misc->baselineShiftValue.get(); } + ShadowData* shadow() const { return shadowSVG->shadow.get(); } + String clipperResource() const { return resources->clipper; } + String filterResource() const { return resources->filter; } + String maskerResource() const { return resources->masker; } + String markerStartResource() const { return inheritedResources->markerStart; } + String markerMidResource() const { return inheritedResources->markerMid; } + String markerEndResource() const { return inheritedResources->markerEnd; } // convenience bool hasClipper() const { return !clipperResource().isEmpty(); } diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h index 5173894..adb890c 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.h +++ b/WebCore/rendering/style/SVGRenderStyleDefs.h @@ -38,46 +38,6 @@ #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> -// Helper macros for 'SVGRenderStyle' -#define SVG_RS_DEFINE_ATTRIBUTE(Data, Type, Name, Initial) \ - void set##Type(Data val) { svg_noninherited_flags.f._##Name = val; } \ - Data Name() const { return (Data) svg_noninherited_flags.f._##Name; } \ - static Data initial##Type() { return Initial; } - -#define SVG_RS_DEFINE_ATTRIBUTE_INHERITED(Data, Type, Name, Initial) \ - void set##Type(Data val) { svg_inherited_flags._##Name = val; } \ - Data Name() const { return (Data) svg_inherited_flags._##Name; } \ - static Data initial##Type() { return Initial; } - -// "Helper" macros for SVG's RenderStyle properties -// FIXME: These are impossible to work with or debug. -#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF(Data, Group, Variable, Type, Name) \ - Data Name() const { return Group->Variable; } \ - void set##Type(Data obj) { SVG_RS_SET_VARIABLE(Group, Variable, obj) } - -#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Data, Group, Variable, Type, Name, Initial) \ - SVG_RS_DEFINE_ATTRIBUTE_DATAREF(Data, Group, Variable, Type, Name) \ - static Data initial##Type() { return Initial; } - -#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(Data, Group, Variable, Type, Name, Initial) \ - Data* Name() const { return Group->Variable.get(); } \ - void set##Type(PassRefPtr<Data> obj) { \ - if (!(Group->Variable == obj)) \ - Group.access()->Variable = obj; \ - } \ - static Data* initial##Type() { return Initial; } - -#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_OWNPTR(Data, Group, Variable, Type, Name, Initial) \ - Data* Name() const { return Group->Variable.get(); } \ - void set##Type(PassOwnPtr<Data> obj) { \ - Group.access()->Variable = obj; \ - } \ - static Data* initial##Type() { return Initial; } - -#define SVG_RS_SET_VARIABLE(Group, Variable, Value) \ - if (!(Group->Variable == Value)) \ - Group.access()->Variable = Value; - namespace WebCore { enum EBaselineShift { |