summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/rendering/svg
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/rendering/svg
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/rendering/svg')
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp43
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp41
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp19
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp42
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp48
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h17
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp59
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp137
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp68
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp71
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp61
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp218
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h22
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp33
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp239
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h66
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp136
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h11
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp19
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp114
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h46
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp45
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp69
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp79
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp350
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h45
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp93
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp111
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h23
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp116
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp72
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp180
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp154
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp81
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp53
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp50
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp238
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h38
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h12
95 files changed, 2171 insertions, 2025 deletions
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp
index 8c0a5c517a4..a53a3dcf118 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp
@@ -29,9 +29,9 @@
#include "core/rendering/svg/ReferenceFilterBuilder.h"
-#include "SVGNames.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSPrimitiveValueMappings.h"
+#include "core/css/StylePropertySet.h"
#include "core/dom/Element.h"
#include "core/fetch/DocumentResource.h"
#include "core/rendering/svg/RenderSVGResourceFilter.h"
@@ -80,10 +80,11 @@ static bool getSVGElementColorSpace(SVGElement* svgElement, ColorSpace& cs)
if (svgStyle) {
// If a layout has been performed, then we can use the fast path to get this attribute
eColorInterpolation = svgStyle->colorInterpolationFilters();
+ } else if (!svgElement->presentationAttributeStyle()) {
+ return false;
} else {
// Otherwise, use the slow path by using string comparison (used by external svg files)
- RefPtr<CSSValue> cssValue = svgElement->getPresentationAttribute(
- SVGNames::color_interpolation_filtersAttr.toString());
+ RefPtrWillBeRawPtr<CSSValue> cssValue = svgElement->presentationAttributeStyle()->getPropertyCSSValue(CSSPropertyColorInterpolationFilters);
if (cssValue.get() && cssValue->isPrimitiveValue()) {
const CSSPrimitiveValue& primitiveValue = *((CSSPrimitiveValue*)cssValue.get());
eColorInterpolation = (EColorInterpolation)primitiveValue;
@@ -110,9 +111,9 @@ static bool getSVGElementColorSpace(SVGElement* svgElement, ColorSpace& cs)
PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, RenderObject* renderer, FilterEffect* previousEffect, const ReferenceFilterOperation* filterOperation)
{
if (!renderer)
- return 0;
+ return nullptr;
- Document* document = &renderer->document();
+ TreeScope* treeScope = &renderer->node()->treeScope();
if (DocumentResourceReference* documentResourceRef = documentResourceReference(filterOperation)) {
DocumentResource* cachedSVGDocument = documentResourceRef->document();
@@ -120,25 +121,25 @@ PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, Ren
// If we have an SVG document, this is an external reference. Otherwise
// we look up the referenced node in the current document.
if (cachedSVGDocument)
- document = cachedSVGDocument->document();
+ treeScope = cachedSVGDocument->document();
}
- if (!document)
- return 0;
+ if (!treeScope)
+ return nullptr;
- Element* filter = document->getElementById(filterOperation->fragment());
+ Element* filter = treeScope->getElementById(filterOperation->fragment());
if (!filter) {
// Although we did not find the referenced filter, it might exist later
- // in the document
- document->accessSVGExtensions()->addPendingResource(filterOperation->fragment(), toElement(renderer->node()));
- return 0;
+ // in the document.
+ treeScope->document().accessSVGExtensions().addPendingResource(filterOperation->fragment(), toElement(renderer->node()));
+ return nullptr;
}
- if (!filter->isSVGElement() || !filter->hasTagName(SVGNames::filterTag))
- return 0;
+ if (!isSVGFilterElement(*filter))
+ return nullptr;
- SVGFilterElement* filterElement = toSVGFilterElement(toSVGElement(filter));
+ SVGFilterElement& filterElement = toSVGFilterElement(*filter);
// FIXME: Figure out what to do with SourceAlpha. Right now, we're
// using the alpha of the original input layer, which is obviously
@@ -148,13 +149,9 @@ PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, Ren
RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(parentFilter));
ColorSpace filterColorSpace = ColorSpaceDeviceRGB;
- bool useFilterColorSpace = getSVGElementColorSpace(filterElement, filterColorSpace);
-
- for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
- if (!node->isSVGElement())
- continue;
+ bool useFilterColorSpace = getSVGElementColorSpace(&filterElement, filterColorSpace);
- SVGElement* element = toSVGElement(node);
+ for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) {
if (!element->isFilterEffect())
continue;
@@ -165,11 +162,11 @@ PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, Ren
continue;
effectElement->setStandardAttributes(effect.get());
- effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnitsCurrentValue(), parentFilter->sourceImageRect()));
+ effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), parentFilter->sourceImageRect()));
ColorSpace colorSpace = filterColorSpace;
if (useFilterColorSpace || getSVGElementColorSpace(effectElement, colorSpace))
effect->setOperatingColorSpace(colorSpace);
- builder->add(effectElement->resultCurrentValue(), effect);
+ builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect);
}
return builder->lastEffect();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp
index ab40394a4b3..8eddc1f1e6f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp
@@ -23,7 +23,9 @@
#include "core/rendering/svg/RenderSVGBlock.h"
+#include "core/rendering/RenderView.h"
#include "core/rendering/style/ShadowList.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGElement.h"
@@ -50,7 +52,7 @@ void RenderSVGBlock::updateFromStyle()
// RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasOverflowClip(true).
// RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both
- // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText.
+ // Render(SVGText|ForeignObject) return 'NoLayer' on 'layerTypeRequired'. Fine for RenderSVGText.
//
// If we want to support overflow rules for <foreignObject> we can choose between two solutions:
// a) make RenderSVGForeignObject require layers and SVG layer aware
@@ -77,11 +79,46 @@ void RenderSVGBlock::willBeDestroyed()
void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout)
+ if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
RenderBlock::styleDidChange(diff, oldStyle);
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
+void RenderSVGBlock::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
+{
+ SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
+}
+
+const RenderObject* RenderSVGBlock::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
+LayoutRect RenderSVGBlock::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
+{
+ return SVGRenderSupport::clippedOverflowRectForRepaint(this, paintInvalidationContainer);
+}
+
+void RenderSVGBlock::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
+{
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, paintInvalidationRect, fixed);
+}
+
+bool RenderSVGBlock::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void RenderSVGBlock::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
+{
+ if (!shouldCheckForPaintInvalidationAfterLayout())
+ return;
+
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+ RenderBlockFlow::invalidateTreeAfterLayout(paintInvalidationContainer);
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h
index 6f08eb1f72f..1e21c7c639a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h
@@ -32,19 +32,33 @@ public:
virtual LayoutRect visualOverflowRect() const OVERRIDE FINAL;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE FINAL;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
+
+ virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
+ virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
+
+ virtual AffineTransform localTransform() const OVERRIDE FINAL { return m_localTransform; }
+
+ virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NoLayer; }
+
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE;
+
protected:
virtual void willBeDestroyed() OVERRIDE;
+ AffineTransform m_localTransform;
+
private:
virtual void updateFromStyle() OVERRIDE FINAL;
- virtual bool isRenderSVGBlock() const OVERRIDE FINAL { return true; };
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual bool isSVG() const OVERRIDE FINAL { return true; }
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp
index 04f28cae872..5767807922e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp
@@ -25,13 +25,15 @@
#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/frame/Settings.h"
#include "core/rendering/GraphicsContextAnnotator.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
+#include "platform/graphics/GraphicsContextCullSaver.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
namespace WebCore {
@@ -52,9 +54,8 @@ void RenderSVGContainer::layout()
ASSERT(needsLayout());
// RenderSVGRoot disables layoutState for the SVG rendering tree.
- ASSERT(!view()->layoutStateEnabled());
+ ASSERT(!view()->layoutStateCachedOffsetsEnabled());
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) || selfWillPaint());
// Allow RenderSVGViewportContainer to update its viewport.
@@ -116,7 +117,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
if (!firstChild() && !selfWillPaint())
return;
- FloatRect repaintRect = repaintRectInLocalCoordinates();
+ FloatRect repaintRect = paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(repaintRect, localToParentTransform(), paintInfo))
return;
@@ -130,10 +131,14 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
childPaintInfo.applyTransform(localToParentTransform());
SVGRenderingContext renderingContext;
+ GraphicsContextCullSaver cullSaver(*childPaintInfo.context);
bool continueRendering = true;
if (childPaintInfo.phase == PaintPhaseForeground) {
renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
continueRendering = renderingContext.isRenderingPrepared();
+
+ if (continueRendering && document().settings()->containerCullingEnabled())
+ cullSaver.cull(paintInvalidationRectInLocalCoordinates());
}
if (continueRendering) {
@@ -144,11 +149,11 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
}
// FIXME: This really should be drawn from local coordinates, but currently we hack it
- // to avoid our clip killing our outline rect. Thus we translate our
+ // to avoid our clip killing our outline rect. Thus we translate our
// outline rect into parent coords before drawing.
// FIXME: This means our focus ring won't share our rotation like it should.
// We should instead disable our clip during PaintPhaseOutline
- if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) {
+ if (paintInfo.phase == PaintPhaseForeground && style()->outlineWidth() && style()->visibility() == VISIBLE) {
IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect));
paintOutline(paintInfo, paintRectInParent);
}
@@ -157,7 +162,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call
void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
- IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
+ IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(paintInvalidationRectInLocalCoordinates()));
if (!paintRectInParent.isEmpty())
rects.append(paintRectInParent);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h
index fd4e74db96b..b7235fbaded 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h
@@ -37,12 +37,15 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderSVGContainer, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual void setNeedsBoundariesUpdate() OVERRIDE FINAL { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE FINAL { return m_needsBoundariesUpdate; }
virtual bool didTransformToRootUpdate() { return false; }
bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
@@ -51,9 +54,9 @@ protected:
virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
virtual bool isSVGContainer() const OVERRIDE FINAL { return true; }
- virtual const char* renderName() const { return "RenderSVGContainer"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGContainer"; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE FINAL;
virtual void removeChild(RenderObject*) OVERRIDE FINAL;
@@ -61,9 +64,9 @@ protected:
virtual FloatRect objectBoundingBox() const OVERRIDE FINAL { return m_objectBoundingBox; }
virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL { return m_strokeBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
// Allow RenderSVGTransformableContainer to hook in at the right time in layout()
virtual bool calculateLocalTransform() { return false; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp
index ac5c6491fc3..b9a75029ae0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp
@@ -28,9 +28,9 @@
#include "core/rendering/svg/RenderSVGEllipse.h"
-#include "SVGNames.h"
#include "core/svg/SVGCircleElement.h"
#include "core/svg/SVGEllipseElement.h"
+#include "platform/graphics/GraphicsContext.h"
namespace WebCore {
@@ -53,20 +53,22 @@ void RenderSVGEllipse::updateShapeFromElement()
m_center = FloatPoint();
m_radii = FloatSize();
- // Fallback to RenderSVGShape if shape has a non-scaling stroke.
- if (hasNonScalingStroke()) {
- RenderSVGShape::updateShapeFromElement();
- m_usePathFallback = true;
- return;
- } else
- m_usePathFallback = false;
-
calculateRadiiAndCenter();
- // Spec: "A value of zero disables rendering of the element."
- if (m_radii.width() <= 0 || m_radii.height() <= 0)
+ // Spec: "A negative value is an error. A value of zero disables rendering of the element."
+ if (m_radii.width() < 0 || m_radii.height() < 0)
return;
+ if (!m_radii.isEmpty()) {
+ // Fallback to RenderSVGShape if shape has a non-scaling stroke.
+ if (hasNonScalingStroke()) {
+ RenderSVGShape::updateShapeFromElement();
+ m_usePathFallback = true;
+ return;
+ }
+ m_usePathFallback = false;
+ }
+
m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
m_strokeBoundingBox = m_fillBoundingBox;
if (style()->svgStyle()->hasStroke())
@@ -76,21 +78,21 @@ void RenderSVGEllipse::updateShapeFromElement()
void RenderSVGEllipse::calculateRadiiAndCenter()
{
ASSERT(element());
- if (element()->hasTagName(SVGNames::circleTag)) {
- SVGCircleElement* circle = toSVGCircleElement(element());
+ if (isSVGCircleElement(*element())) {
+ SVGCircleElement& circle = toSVGCircleElement(*element());
- SVGLengthContext lengthContext(circle);
- float radius = circle->rCurrentValue().value(lengthContext);
+ SVGLengthContext lengthContext(&circle);
+ float radius = circle.r()->currentValue()->value(lengthContext);
m_radii = FloatSize(radius, radius);
- m_center = FloatPoint(circle->cxCurrentValue().value(lengthContext), circle->cyCurrentValue().value(lengthContext));
+ m_center = FloatPoint(circle.cx()->currentValue()->value(lengthContext), circle.cy()->currentValue()->value(lengthContext));
return;
}
- SVGEllipseElement* ellipse = toSVGEllipseElement(element());
+ SVGEllipseElement& ellipse = toSVGEllipseElement(*element());
- SVGLengthContext lengthContext(ellipse);
- m_radii = FloatSize(ellipse->rxCurrentValue().value(lengthContext), ellipse->ryCurrentValue().value(lengthContext));
- m_center = FloatPoint(ellipse->cxCurrentValue().value(lengthContext), ellipse->cyCurrentValue().value(lengthContext));
+ SVGLengthContext lengthContext(&ellipse);
+ m_radii = FloatSize(ellipse.rx()->currentValue()->value(lengthContext), ellipse.ry()->currentValue()->value(lengthContext));
+ m_center = FloatPoint(ellipse.cx()->currentValue()->value(lengthContext), ellipse.cy()->currentValue()->value(lengthContext));
}
void RenderSVGEllipse::fillShape(GraphicsContext* context) const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h
index f06e5c16cf0..b73b5526853 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h
@@ -37,14 +37,14 @@ public:
virtual ~RenderSVGEllipse();
private:
- virtual const char* renderName() const { return "RenderSVGEllipse"; }
-
- virtual void updateShapeFromElement();
- virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
- virtual bool shapeDependentStrokeContains(const FloatPoint&);
- virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGEllipse"; }
+
+ virtual void updateShapeFromElement() OVERRIDE;
+ virtual bool isShapeEmpty() const OVERRIDE { return m_usePathFallback ? RenderSVGShape::isShapeEmpty() : m_fillBoundingBox.isEmpty(); }
+ virtual void fillShape(GraphicsContext*) const OVERRIDE;
+ virtual void strokeShape(GraphicsContext*) const OVERRIDE;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&) OVERRIDE;
+ virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const OVERRIDE;
void calculateRadiiAndCenter();
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp
index e27e037926f..9a9459836e1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp
@@ -24,7 +24,6 @@
#include "core/rendering/svg/RenderSVGForeignObject.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/SVGRenderSupport.h"
@@ -45,6 +44,12 @@ RenderSVGForeignObject::~RenderSVGForeignObject()
{
}
+bool RenderSVGForeignObject::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+ // Disallow arbitary SVG content. Only allow proper <svg xmlns="svgNS"> subdocuments.
+ return !child->isSVG() || child->isSVGRoot();
+}
+
void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
if (paintInfo.context->paintingDisabled()
@@ -85,16 +90,6 @@ void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&)
}
}
-LayoutRect RenderSVGForeignObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
-{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
-}
-
-void RenderSVGForeignObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
-{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
-}
-
const AffineTransform& RenderSVGForeignObject::localToParentTransform() const
{
m_localToParentTransform = localTransform();
@@ -121,9 +116,8 @@ void RenderSVGForeignObject::computeLogicalHeight(LayoutUnit, LayoutUnit logical
void RenderSVGForeignObject::layout()
{
ASSERT(needsLayout());
- ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
+ ASSERT(!view()->layoutStateCachedOffsetsEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this));
SVGForeignObjectElement* foreign = toSVGForeignObjectElement(node());
@@ -138,8 +132,8 @@ void RenderSVGForeignObject::layout()
// Cache viewport boundaries
SVGLengthContext lengthContext(foreign);
- FloatPoint viewportLocation(foreign->xCurrentValue().value(lengthContext), foreign->yCurrentValue().value(lengthContext));
- m_viewport = FloatRect(viewportLocation, FloatSize(foreign->widthCurrentValue().value(lengthContext), foreign->heightCurrentValue().value(lengthContext)));
+ FloatPoint viewportLocation(foreign->x()->currentValue()->value(lengthContext), foreign->y()->currentValue()->value(lengthContext));
+ m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width()->currentValue()->value(lengthContext), foreign->height()->currentValue()->value(lengthContext)));
if (!updateCachedBoundariesInParents)
updateCachedBoundariesInParents = oldViewport != m_viewport;
@@ -165,6 +159,14 @@ void RenderSVGForeignObject::layout()
repainter.repaintAfterLayout();
}
+void RenderSVGForeignObject::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer,
+ LayoutRect& rect, bool fixed) const
+{
+ FloatRect r(rect);
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, r, fixed);
+ rect = enclosingLayoutRect(r);
+}
+
bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
// Embedded content is drawn in the foreground phase.
@@ -184,20 +186,4 @@ bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, Hit
|| RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds);
}
-bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-void RenderSVGForeignObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
-{
- SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
-}
-
-const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
-{
- return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h
index 63cdac1d35b..d57b723aa18 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h
@@ -32,38 +32,32 @@ public:
explicit RenderSVGForeignObject(SVGForeignObjectElement*);
virtual ~RenderSVGForeignObject();
- virtual const char* renderName() const { return "RenderSVGForeignObject"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGForeignObject"; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual bool requiresLayer() const { return false; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual FloatRect strokeBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(FloatPoint(), m_viewport.size()); }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return FloatRect(FloatPoint(), m_viewport.size()); }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return FloatRect(FloatPoint(), m_viewport.size()); }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual bool isSVGForeignObject() const { return true; }
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
+ virtual bool isSVGForeignObject() const OVERRIDE { return true; }
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
private:
virtual void updateLogicalWidth() OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const;
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE;
bool m_needsTransformUpdate : 1;
FloatRect m_viewport;
- AffineTransform m_localTransform;
mutable AffineTransform m_localToParentTransform;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp
index ca5f315a7bc..d9ce3bf7015 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp
@@ -21,15 +21,12 @@
#include "core/rendering/svg/RenderSVGGradientStop.h"
-#include "SVGNames.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
#include "core/svg/SVGGradientElement.h"
#include "core/svg/SVGStopElement.h"
namespace WebCore {
-using namespace SVGNames;
-
RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement* element)
: RenderObject(element)
{
@@ -42,7 +39,7 @@ RenderSVGGradientStop::~RenderSVGGradientStop()
void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderObject::styleDidChange(diff, oldStyle);
- if (diff == StyleDifferenceEqual)
+ if (diff.hasNoChange())
return;
// <stop> elements should only be allowed to make renderers under gradient elements
@@ -67,9 +64,8 @@ void RenderSVGGradientStop::layout()
SVGGradientElement* RenderSVGGradientStop::gradientElement() const
{
ContainerNode* parentNode = node()->parentNode();
- if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag))
- return toSVGGradientElement(parentNode);
- return 0;
+ ASSERT(parentNode);
+ return isSVGGradientElement(*parentNode) ? toSVGGradientElement(parentNode) : 0;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h
index e56274e3ffc..4d6fee11121 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h
@@ -34,21 +34,22 @@ public:
explicit RenderSVGGradientStop(SVGStopElement*);
virtual ~RenderSVGGradientStop();
- virtual bool isSVGGradientStop() const { return true; }
- virtual const char* renderName() const { return "RenderSVGGradientStop"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGGradientStop"; }
+ virtual bool isSVGGradientStop() const OVERRIDE { return true; }
+ virtual bool isSVG() const OVERRIDE { return true; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
// This overrides are needed to prevent ASSERTs on <svg><stop /></svg>
// RenderObject's default implementations ASSERT_NOT_REACHED()
// https://bugs.webkit.org/show_bug.cgi?id=20400
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const OVERRIDE { return LayoutRect(); }
- virtual FloatRect objectBoundingBox() const { return FloatRect(); }
- virtual FloatRect strokeBoundingBox() const { return FloatRect(); }
- virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*) const OVERRIDE { return LayoutRect(); }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return FloatRect(); }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return FloatRect(); }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return FloatRect(); }
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
private:
SVGGradientElement* gradientElement() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
index 0f1578935a5..0e5af52bb57 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
@@ -20,8 +20,7 @@
#include "config.h"
#include "core/rendering/svg/RenderSVGHiddenContainer.h"
-
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
namespace WebCore {
@@ -33,7 +32,6 @@ RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGElement* element)
void RenderSVGHiddenContainer::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
SVGRenderSupport::layoutChildren(this, selfNeedsLayout());
updateCachedBoundaries();
clearNeedsLayout();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h
index f8e57d33f1d..0616b76b719 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h
@@ -32,17 +32,17 @@ class RenderSVGHiddenContainer : public RenderSVGContainer {
public:
explicit RenderSVGHiddenContainer(SVGElement*);
- virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGHiddenContainer"; }
protected:
- virtual void layout();
+ virtual void layout() OVERRIDE;
private:
virtual bool isSVGHiddenContainer() const OVERRIDE FINAL { return true; }
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const OVERRIDE FINAL { return LayoutRect(); }
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*) const OVERRIDE FINAL { return LayoutRect(); }
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE FINAL;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp
index 9e2e4cd9414..b483670d4f2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp
@@ -29,11 +29,11 @@
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/ImageQualityController.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/PointerEventsHitRules.h"
#include "core/rendering/RenderImageResource.h"
#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
@@ -64,12 +64,12 @@ bool RenderSVGImage::updateImageViewport()
bool updatedViewport = false;
SVGLengthContext lengthContext(image);
- m_objectBoundingBox = FloatRect(image->xCurrentValue().value(lengthContext), image->yCurrentValue().value(lengthContext), image->widthCurrentValue().value(lengthContext), image->heightCurrentValue().value(lengthContext));
+ m_objectBoundingBox = FloatRect(image->x()->currentValue()->value(lengthContext), image->y()->currentValue()->value(lengthContext), image->width()->currentValue()->value(lengthContext), image->height()->currentValue()->value(lengthContext));
// Images with preserveAspectRatio=none should force non-uniform scaling. This can be achieved
// by setting the image's container size to its intrinsic size.
// See: http://www.w3.org/TR/SVG/single-page.html, 7.8 The ‘preserveAspectRatio’ attribute.
- if (image->preserveAspectRatioCurrentValue().align() == SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) {
+ if (image->preserveAspectRatio()->currentValue()->align() == SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) {
if (ImageResource* cachedImage = m_imageResource->cachedImage()) {
LayoutSize intrinsicSize = cachedImage->imageSizeForRenderer(0, style()->effectiveZoom());
if (intrinsicSize != m_imageResource->imageSize(style()->effectiveZoom())) {
@@ -93,7 +93,6 @@ void RenderSVGImage::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout());
updateImageViewport();
@@ -126,33 +125,38 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
- if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage())
+ if (paintInfo.context->paintingDisabled()
+ || paintInfo.phase != PaintPhaseForeground
+ || style()->visibility() == HIDDEN
+ || !m_imageResource->hasImage())
return;
- FloatRect boundingBox = repaintRectInLocalCoordinates();
+ FloatRect boundingBox = paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
return;
PaintInfo childPaintInfo(paintInfo);
- bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
- if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
- childPaintInfo.applyTransform(m_localTransform);
+ GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
- if (childPaintInfo.phase == PaintPhaseForeground && !m_objectBoundingBox.isEmpty()) {
- SVGRenderingContext renderingContext(this, childPaintInfo);
+ if (!m_localTransform.isIdentity()) {
+ stateSaver.save();
+ childPaintInfo.applyTransform(m_localTransform, false);
+ }
+ if (!m_objectBoundingBox.isEmpty()) {
+ // SVGRenderingContext may taint the state - make sure we're always saving.
+ SVGRenderingContext renderingContext(this, childPaintInfo, stateSaver.saved() ?
+ SVGRenderingContext::DontSaveGraphicsContext : SVGRenderingContext::SaveGraphicsContext);
- if (renderingContext.isRenderingPrepared()) {
- if (style()->svgStyle()->bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground))
- return;
+ if (renderingContext.isRenderingPrepared()) {
+ if (style()->svgStyle()->bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground))
+ return;
- paintForeground(childPaintInfo);
- }
+ paintForeground(childPaintInfo);
}
-
- if (drawsOutline)
- paintOutline(childPaintInfo, IntRect(boundingBox));
}
+
+ if (style()->outlineWidth())
+ paintOutline(childPaintInfo, IntRect(boundingBox));
}
void RenderSVGImage::paintForeground(PaintInfo& paintInfo)
@@ -162,13 +166,16 @@ void RenderSVGImage::paintForeground(PaintInfo& paintInfo)
FloatRect srcRect(0, 0, image->width(), image->height());
SVGImageElement* imageElement = toSVGImageElement(element());
- imageElement->preserveAspectRatioCurrentValue().transformRect(destRect, srcRect);
+ imageElement->preserveAspectRatio()->currentValue()->transformRect(destRect, srcRect);
- bool useLowQualityScaling = false;
+ InterpolationQuality interpolationQuality = InterpolationDefault;
if (style()->svgStyle()->bufferedRendering() != BR_STATIC)
- useLowQualityScaling = ImageQualityController::imageQualityController()->shouldPaintAtLowQuality(paintInfo.context, this, image.get(), image.get(), LayoutSize(destRect.size()));
+ interpolationQuality = ImageQualityController::imageQualityController()->chooseInterpolationQuality(paintInfo.context, this, image.get(), image.get(), LayoutSize(destRect.size()));
- paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver, DoNotRespectImageOrientation, useLowQualityScaling);
+ InterpolationQuality previousInterpolationQuality = paintInfo.context->imageInterpolationQuality();
+ paintInfo.context->setImageInterpolationQuality(interpolationQuality);
+ paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver);
+ paintInfo.context->setImageInterpolationQuality(previousInterpolationQuality);
}
void RenderSVGImage::invalidateBufferedForeground()
@@ -218,13 +225,13 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*)
invalidateBufferedForeground();
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
// this is called from paint() after the localTransform has already been applied
- IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
+ IntRect contentRect = enclosingIntRect(paintInvalidationRectInLocalCoordinates());
if (!contentRect.isEmpty())
rects.append(contentRect);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h
index e87392e04fa..644bdd15027 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h
@@ -37,9 +37,8 @@ public:
virtual ~RenderSVGImage();
bool updateImageViewport();
- virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesUpdate; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void setNeedsBoundariesUpdate() OVERRIDE { m_needsBoundariesUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
RenderImageResource* imageResource() { return m_imageResource.get(); }
@@ -47,27 +46,27 @@ public:
void paintForeground(PaintInfo&);
private:
- virtual const char* renderName() const { return "RenderSVGImage"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGImage"; }
virtual bool isSVGImage() const OVERRIDE { return true; }
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localTransform; }
- virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return m_objectBoundingBox; }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return m_objectBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return m_repaintBoundingBox; }
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
- virtual void layout();
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void layout() OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
void invalidateBufferedForeground();
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual AffineTransform localTransform() const OVERRIDE { return m_localTransform; }
bool m_needsBoundariesUpdate : 1;
bool m_needsTransformUpdate : 1;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp
index 68b1a4029cd..07c0a58c4d9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp
@@ -27,12 +27,22 @@
#include "core/rendering/svg/SVGInlineFlowBox.h"
#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGAElement.h"
namespace WebCore {
bool RenderSVGInline::isChildAllowed(RenderObject* child, RenderStyle* style) const
{
- if (SVGRenderSupport::isEmptySVGInlineText(child))
+ if (child->isText())
+ return SVGRenderSupport::isRenderableTextNode(child);
+
+ if (isSVGAElement(*node())) {
+ // Disallow direct descendant 'a'.
+ if (isSVGAElement(*child->node()))
+ return false;
+ }
+
+ if (!child->isSVGInline() && !child->isSVGInlineText())
return false;
return RenderInline::isChildAllowed(child, style);
@@ -46,7 +56,7 @@ RenderSVGInline::RenderSVGInline(Element* element)
InlineFlowBox* RenderSVGInline::createInlineFlowBox()
{
- InlineFlowBox* box = new SVGInlineFlowBox(this);
+ InlineFlowBox* box = new SVGInlineFlowBox(*this);
box->setHasVirtualLogicalHeight();
return box;
}
@@ -67,22 +77,22 @@ FloatRect RenderSVGInline::strokeBoundingBox() const
return FloatRect();
}
-FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const
+FloatRect RenderSVGInline::paintInvalidationRectInLocalCoordinates() const
{
if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
- return object->repaintRectInLocalCoordinates();
+ return object->paintInvalidationRectInLocalCoordinates();
return FloatRect();
}
-LayoutRect RenderSVGInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderSVGInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+ return SVGRenderSupport::clippedOverflowRectForRepaint(this, paintInvalidationContainer);
}
-void RenderSVGInline::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+void RenderSVGInline::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, paintInvalidationRect, fixed);
}
void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -114,7 +124,7 @@ void RenderSVGInline::willBeDestroyed()
void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout)
+ if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
RenderInline::styleDidChange(diff, oldStyle);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h
index 43634a39c22..1c09c5666f6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h
@@ -29,9 +29,10 @@ class RenderSVGInline : public RenderInline {
public:
explicit RenderSVGInline(Element*);
- virtual const char* renderName() const { return "RenderSVGInline"; }
- virtual bool requiresLayer() const OVERRIDE FINAL { return false; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGInline"; }
+ virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NoLayer; }
virtual bool isSVGInline() const OVERRIDE FINAL { return true; }
+ virtual bool isSVG() const OVERRIDE FINAL { return true; }
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
@@ -42,10 +43,10 @@ public:
// this element, since we need it for filters.
virtual FloatRect objectBoundingBox() const OVERRIDE FINAL;
virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL;
- virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL;
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE FINAL;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE FINAL;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE FINAL;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
@@ -60,6 +61,8 @@ private:
virtual void removeChild(RenderObject*) OVERRIDE FINAL;
};
+DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderSVGInline, isSVGInline());
+
}
#endif // !RenderSVGTSpan_H
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp
index e8041f8c1c2..d19fed0516d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp
@@ -89,17 +89,17 @@ void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle
return;
}
- if (diff != StyleDifferenceLayout)
+ if (!diff.needsFullLayout())
return;
// The text metrics may be influenced by style changes.
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeStyleDidChange(this);
+ textRenderer->setNeedsLayoutAndFullPaintInvalidation();
}
InlineTextBox* RenderSVGInlineText::createTextBox()
{
- InlineTextBox* box = new SVGInlineTextBox(this);
+ InlineTextBox* box = new SVGInlineTextBox(*this);
box->setHasVirtualLogicalHeight();
return box;
}
@@ -186,8 +186,7 @@ PositionWithAffinity RenderSVGInlineText::positionForPoint(const LayoutPoint& po
const SVGTextFragment& fragment = fragments.at(i);
FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) +
powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2);
@@ -226,7 +225,7 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c
return;
}
- if (style->fontDescription().textRenderingMode() == GeometricPrecision)
+ if (style->fontDescription().textRendering() == GeometricPrecision)
scalingFactor = 1;
FontDescription fontDescription(style->fontDescription());
@@ -235,7 +234,7 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c
// FIXME: We need to better handle the case when we compute very small fonts below (below 1pt).
fontDescription.setComputedSize(FontSize::getComputedSizeFromSpecifiedSize(&document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), DoNotUseSmartMinimumForFontSize));
- scaledFont = Font(fontDescription, 0, 0);
+ scaledFont = Font(fontDescription);
scaledFont.update(document.styleEngine()->fontSelector());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h
index 8c7f711a68f..b7fc9add99b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h
@@ -27,8 +27,6 @@
namespace WebCore {
-class SVGInlineTextBox;
-
class RenderSVGInlineText FINAL : public RenderText {
public:
RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
@@ -45,19 +43,20 @@ public:
FloatRect floatLinesBoundingBox() const;
private:
- virtual const char* renderName() const { return "RenderSVGInlineText"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGInlineText"; }
- virtual void setTextInternal(PassRefPtr<StringImpl>);
- virtual void styleDidChange(StyleDifference, const RenderStyle*);
+ virtual void setTextInternal(PassRefPtr<StringImpl>) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return floatLinesBoundingBox(); }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return floatLinesBoundingBox(); }
- virtual bool isSVGInlineText() const { return true; }
+ virtual bool isSVGInlineText() const OVERRIDE { return true; }
+ virtual bool isSVG() const OVERRIDE { return true; }
- virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
- virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
- virtual IntRect linesBoundingBox() const;
- virtual InlineTextBox* createTextBox();
+ virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
+ virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) OVERRIDE;
+ virtual IntRect linesBoundingBox() const OVERRIDE;
+ virtual InlineTextBox* createTextBox() OVERRIDE;
float m_scalingFactor;
Font m_scaledFont;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp
index 12da706b521..a6918a93535 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp
@@ -29,11 +29,12 @@
*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGModelObject.h"
-#include "SVGNames.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGGraphicsElement.h"
@@ -44,14 +45,19 @@ RenderSVGModelObject::RenderSVGModelObject(SVGElement* node)
{
}
-LayoutRect RenderSVGModelObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+bool RenderSVGModelObject::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isSVG() && !(child->isSVGInline() || child->isSVGInlineText());
+}
+
+LayoutRect RenderSVGModelObject::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+ return SVGRenderSupport::clippedOverflowRectForRepaint(this, paintInvalidationContainer);
}
-void RenderSVGModelObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+void RenderSVGModelObject::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, paintInvalidationRect, fixed);
}
void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -64,18 +70,6 @@ const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLay
return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
}
-// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
-// FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends
-// on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
-LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const
-{
- LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates());
- adjustRectForOutlineAndShadow(box);
-
- FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
- return containerRelativeQuad.enclosingBoundingBox();
-}
-
void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
IntRect rect = enclosingIntRect(strokeBoundingBox());
@@ -107,7 +101,7 @@ void RenderSVGModelObject::addLayerHitTestRects(LayerHitTestRects&, const Render
void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout) {
+ if (diff.needsFullLayout()) {
setNeedsBoundariesUpdate();
if (style()->hasTransform())
setNeedsTransformUpdate();
@@ -123,82 +117,53 @@ bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, co
return false;
}
-static void getElementCTM(SVGGraphicsElement* element, AffineTransform& transform)
+// The SVG addFocusRingRects() method adds rects in local coordinates so the default absoluteFocusRingQuads
+// returns incorrect values for SVG objects. Overriding this method provides access to the absolute bounds.
+void RenderSVGModelObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
{
- ASSERT(element);
- element->document().updateLayoutIgnorePendingStylesheets();
-
- SVGElement* stopAtElement = element->nearestViewportElement();
- ASSERT(stopAtElement);
+ quads.append(localToAbsoluteQuad(FloatQuad(paintInvalidationRectInLocalCoordinates())));
+}
- AffineTransform localTransform;
- Node* current = element;
+void RenderSVGModelObject::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
+{
+ // Note: This is a reduced version of RenderBox::invalidateTreeAfterLayout().
+ // FIXME: Should share code with RenderBox::invalidateTreeAfterLayout().
+ ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ ASSERT(!needsLayout());
- while (current && current->isSVGElement()) {
- SVGElement* currentElement = toSVGElement(current);
- localTransform = currentElement->renderer()->localToParentTransform();
- transform = localTransform.multiply(transform);
- // For getCTM() computation, stop at the nearest viewport element
- if (currentElement == stopAtElement)
- break;
+ if (!shouldCheckForPaintInvalidationAfterLayout())
+ return;
- current = current->parentOrShadowHostNode();
- }
-}
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
-// FloatRect::intersects does not consider horizontal or vertical lines (because of isEmpty()).
-// So special-case handling of such lines.
-static bool intersectsAllowingEmpty(const FloatRect& r, const FloatRect& other)
-{
- if (r.isEmpty() && other.isEmpty())
- return false;
- if (r.isEmpty() && !other.isEmpty()) {
- return (other.contains(r.x(), r.y()) && !other.contains(r.maxX(), r.maxY()))
- || (!other.contains(r.x(), r.y()) && other.contains(r.maxX(), r.maxY()));
- }
- if (other.isEmpty() && !r.isEmpty())
- return intersectsAllowingEmpty(other, r);
- return r.intersects(other);
-}
+ const LayoutRect oldPaintInvalidationRect = previousPaintInvalidationRect();
+ const LayoutPoint oldPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
+ const RenderLayerModelObject& newPaintInvalidationContainer = *containerForPaintInvalidation();
+ setPreviousPaintInvalidationRect(clippedOverflowRectForPaintInvalidation(&newPaintInvalidationContainer));
+ setPreviousPositionFromPaintInvalidationContainer(RenderLayer::positionFromPaintInvalidationContainer(this, &newPaintInvalidationContainer));
-// One of the element types that can cause graphics to be drawn onto the target canvas. Specifically: circle, ellipse,
-// image, line, path, polygon, polyline, rect, text and use.
-static bool isGraphicsElement(RenderObject* renderer)
-{
- return renderer->isSVGShape() || renderer->isSVGText() || renderer->isSVGImage() || renderer->node()->hasTagName(SVGNames::useTag);
-}
+ // If an ancestor container had its transform changed, then we just
+ // need to update the RenderSVGModelObject's repaint rect above. The invalidation
+ // will be handled by the container where the transform changed. This essentially
+ // means that we prune the entire branch for performance.
+ if (!SVGRenderSupport::parentTransformDidChange(this))
+ return;
-// The SVG addFocusRingRects() method adds rects in local coordinates so the default absoluteFocusRingQuads
-// returns incorrect values for SVG objects. Overriding this method provides access to the absolute bounds.
-void RenderSVGModelObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
-{
- quads.append(localToAbsoluteQuad(FloatQuad(repaintRectInLocalCoordinates())));
-}
+ // If we are set to do a full paint invalidation that means the RenderView will be
+ // issue paint invalidations. We can then skip issuing of paint invalidations for the child
+ // renderers as they'll be covered by the RenderView.
+ if (view()->doingFullRepaint()) {
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
+ return;
+ }
-bool RenderSVGModelObject::checkIntersection(RenderObject* renderer, const SVGRect& rect)
-{
- if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
- return false;
- if (!isGraphicsElement(renderer))
- return false;
- AffineTransform ctm;
- SVGGraphicsElement* svgElement = toSVGGraphicsElement(renderer->node());
- getElementCTM(svgElement, ctm);
- ASSERT(svgElement->renderer());
- return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
-}
+ const LayoutRect& newPaintInvalidationRect = previousPaintInvalidationRect();
+ const LayoutPoint& newPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
+ invalidatePaintAfterLayoutIfNeeded(containerForPaintInvalidation(),
+ shouldDoFullPaintInvalidationAfterLayout(), oldPaintInvalidationRect, oldPositionFromPaintInvalidationContainer,
+ &newPaintInvalidationRect, &newPositionFromPaintInvalidationContainer);
-bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const SVGRect& rect)
-{
- if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
- return false;
- if (!isGraphicsElement(renderer))
- return false;
- AffineTransform ctm;
- SVGGraphicsElement* svgElement = toSVGGraphicsElement(renderer->node());
- getElementCTM(svgElement, ctm);
- ASSERT(svgElement->renderer());
- return rect.contains(ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h
index c8df10aca7d..41bc62ae412 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h
@@ -32,9 +32,8 @@
#define RenderSVGModelObject_h
#include "core/rendering/RenderObject.h"
-#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/svg/SVGElement.h"
-#include "core/svg/SVGRect.h"
+#include "platform/geometry/FloatRect.h"
namespace WebCore {
@@ -49,34 +48,37 @@ class RenderSVGModelObject : public RenderObject {
public:
explicit RenderSVGModelObject(SVGElement*);
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const OVERRIDE FINAL;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+ virtual bool canHaveWhitespaceChildren() const OVERRIDE { return false; }
+
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
- static bool checkIntersection(RenderObject*, const SVGRect&);
- static bool checkEnclosure(RenderObject*, const SVGRect&);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
- virtual void computeLayerHitTestRects(LayerHitTestRects&) const OVERRIDE;
+ virtual void computeLayerHitTestRects(LayerHitTestRects&) const OVERRIDE FINAL;
SVGElement* element() const { return toSVGElement(RenderObject::node()); }
+ virtual bool isSVG() const OVERRIDE FINAL { return true; }
+
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE;
+
protected:
- virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE;
- virtual void willBeDestroyed();
+ virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE FINAL;
+ virtual void willBeDestroyed() OVERRIDE;
private:
// RenderSVGModelObject subclasses should use element() instead.
void node() const WTF_DELETED_FUNCTION;
// This method should never be called, SVG uses a different nodeAtPoint method
- bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
virtual void absoluteFocusRingQuads(Vector<FloatQuad>&) OVERRIDE FINAL;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h
index 8cec15c4c92..48b36762e04 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h
@@ -37,7 +37,7 @@ public:
private:
virtual bool isSVGPath() const OVERRIDE { return true; }
- virtual const char* renderName() const { return "RenderSVGPath"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGPath"; }
virtual void updateShapeFromElement() OVERRIDE;
FloatRect calculateUpdatedStrokeBoundingBox() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp
index dfe447156f6..5fd79e7f626 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp
@@ -28,8 +28,7 @@
#include "config.h"
#include "core/rendering/svg/RenderSVGRect.h"
-
-#include "SVGNames.h"
+#include "platform/graphics/GraphicsContext.h"
namespace WebCore {
@@ -54,19 +53,24 @@ void RenderSVGRect::updateShapeFromElement()
ASSERT(rect);
SVGLengthContext lengthContext(rect);
- // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
- if (rect->rxCurrentValue().value(lengthContext) > 0 || rect->ryCurrentValue().value(lengthContext) > 0 || hasNonScalingStroke()) {
- RenderSVGShape::updateShapeFromElement();
- m_usePathFallback = true;
- return;
- }
+ FloatSize boundingBoxSize(rect->width()->currentValue()->value(lengthContext), rect->height()->currentValue()->value(lengthContext));
- m_usePathFallback = false;
- FloatSize boundingBoxSize(rect->widthCurrentValue().value(lengthContext), rect->heightCurrentValue().value(lengthContext));
- if (boundingBoxSize.isEmpty())
+ // Spec: "A negative value is an error."
+ if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0)
return;
- m_fillBoundingBox = FloatRect(FloatPoint(rect->xCurrentValue().value(lengthContext), rect->yCurrentValue().value(lengthContext)), boundingBoxSize);
+ // Spec: "A value of zero disables rendering of the element."
+ if (!boundingBoxSize.isEmpty()) {
+ // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
+ if (rect->rx()->currentValue()->value(lengthContext) > 0 || rect->ry()->currentValue()->value(lengthContext) > 0 || hasNonScalingStroke()) {
+ RenderSVGShape::updateShapeFromElement();
+ m_usePathFallback = true;
+ return;
+ }
+ m_usePathFallback = false;
+ }
+
+ m_fillBoundingBox = FloatRect(FloatPoint(rect->x()->currentValue()->value(lengthContext), rect->y()->currentValue()->value(lengthContext)), boundingBoxSize);
// To decide if the stroke contains a point we create two rects which represent the inner and
// the outer stroke borders. A stroke contains the point, if the point is between them.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h
index 1a5d6e091e4..7ae39625755 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h
@@ -39,14 +39,14 @@ public:
virtual ~RenderSVGRect();
private:
- virtual const char* renderName() const { return "RenderSVGRect"; }
-
- virtual void updateShapeFromElement();
- virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
- virtual bool shapeDependentStrokeContains(const FloatPoint&);
- virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGRect"; }
+
+ virtual void updateShapeFromElement() OVERRIDE;
+ virtual bool isShapeEmpty() const OVERRIDE { return m_usePathFallback ? RenderSVGShape::isShapeEmpty() : m_fillBoundingBox.isEmpty(); }
+ virtual void fillShape(GraphicsContext*) const OVERRIDE;
+ virtual void strokeShape(GraphicsContext*) const OVERRIDE;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&) OVERRIDE;
+ virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const OVERRIDE;
private:
FloatRect m_innerStrokeRect;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp
index 4dd3ae01c90..0c67bc8d070 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp
@@ -24,8 +24,8 @@
#include "core/rendering/svg/RenderSVGResource.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/svg/RenderSVGResourceClipper.h"
#include "core/rendering/svg/RenderSVGResourceFilter.h"
#include "core/rendering/svg/RenderSVGResourceMasker.h"
@@ -35,22 +35,25 @@
namespace WebCore {
-static inline bool inheritColorFromParentStyleIfNeeded(RenderObject* object, bool applyToFill, Color& color)
+static inline bool inheritColorFromParentStyle(RenderObject* object, bool applyToFill, Color& color)
{
- if (color.isValid())
- return true;
if (!object->parent() || !object->parent()->style())
return false;
const SVGRenderStyle* parentSVGStyle = object->parent()->style()->svgStyle();
+ SVGPaint::SVGPaintType paintType = applyToFill ? parentSVGStyle->fillPaintType() : parentSVGStyle->strokePaintType();
+ if (paintType != SVGPaint::SVG_PAINTTYPE_RGBCOLOR && paintType != SVGPaint::SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR)
+ return false;
color = applyToFill ? parentSVGStyle->fillPaintColor() : parentSVGStyle->strokePaintColor();
return true;
}
-static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, bool& hasFallback)
{
ASSERT(object);
ASSERT(style);
+ hasFallback = false;
+
// If we have no style at all, ignore it.
const SVGRenderStyle* svgStyle = style->svgStyle();
if (!svgStyle)
@@ -78,10 +81,10 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
bool applyToFill = mode == ApplyToFillMode;
SVGPaint::SVGPaintType paintType = applyToFill ? svgStyle->fillPaintType() : svgStyle->strokePaintType();
- if (paintType == SVGPaint::SVG_PAINTTYPE_NONE)
- return 0;
+ ASSERT(paintType != SVGPaint::SVG_PAINTTYPE_NONE);
Color color;
+ bool hasColor = false;
switch (paintType) {
case SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR:
case SVGPaint::SVG_PAINTTYPE_RGBCOLOR:
@@ -90,6 +93,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR:
case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR:
color = applyToFill ? svgStyle->fillPaintColor() : svgStyle->strokePaintColor();
+ hasColor = true;
default:
break;
}
@@ -101,15 +105,15 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
// For SVG_PAINTTYPE_CURRENTCOLOR, 'color' already contains the 'visitedColor'.
if (visitedPaintType < SVGPaint::SVG_PAINTTYPE_URI_NONE && visitedPaintType != SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) {
const Color& visitedColor = applyToFill ? svgStyle->visitedLinkFillPaintColor() : svgStyle->visitedLinkStrokePaintColor();
- if (visitedColor.isValid())
- color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
+ color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
+ hasColor = true;
}
}
// If the primary resource is just a color, return immediately.
RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource();
if (paintType < SVGPaint::SVG_PAINTTYPE_URI_NONE) {
- if (!inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+ if (!hasColor && !inheritColorFromParentStyle(object, applyToFill, color))
return 0;
colorResource->setColor(color);
@@ -119,7 +123,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
// If no resources are associated with the given renderer, return the color resource.
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
if (!resources) {
- if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || !inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+ if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || (!hasColor && !inheritColorFromParentStyle(object, applyToFill, color)))
return 0;
colorResource->setColor(color);
@@ -129,7 +133,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
// If the requested resource is not available, return the color resource.
RenderSVGResource* uriResource = mode == ApplyToFillMode ? resources->fill() : resources->stroke();
if (!uriResource) {
- if (!inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+ if (!hasColor && !inheritColorFromParentStyle(object, applyToFill, color))
return 0;
colorResource->setColor(color);
@@ -137,19 +141,22 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
}
// The paint server resource exists, though it may be invalid (pattern with width/height=0). Pass the fallback color to our caller
- // so it can use the solid color painting resource, if applyResource() on the URI resource failed.
- fallbackColor = color;
+ // via sharedSolidPaintingResource so it can use the solid color painting resource, if applyResource() on the URI resource failed.
+ if (hasColor) {
+ colorResource->setColor(color);
+ hasFallback = true;
+ }
return uriResource;
}
-RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, bool& hasFallback)
{
- return requestPaintingResource(ApplyToFillMode, object, style, fallbackColor);
+ return requestPaintingResource(ApplyToFillMode, object, style, hasFallback);
}
-RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, bool& hasFallback)
{
- return requestPaintingResource(ApplyToStrokeMode, object, style, fallbackColor);
+ return requestPaintingResource(ApplyToStrokeMode, object, style, hasFallback);
}
RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
@@ -176,13 +183,28 @@ static inline void removeFromCacheAndInvalidateDependencies(RenderObject* object
if (!object->node() || !object->node()->isSVGElement())
return;
- HashSet<SVGElement*>* dependencies = object->document().accessSVGExtensions()->setOfElementsReferencingTarget(toSVGElement(object->node()));
+ SVGElementSet* dependencies = object->document().accessSVGExtensions().setOfElementsReferencingTarget(toSVGElement(object->node()));
if (!dependencies)
return;
- HashSet<SVGElement*>::iterator end = dependencies->end();
- for (HashSet<SVGElement*>::iterator it = dependencies->begin(); it != end; ++it) {
- if (RenderObject* renderer = (*it)->renderer())
+
+ // We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive
+ // reference graph adjustments on changes, so we need to break possible cycles here.
+ // This strong reference is safe, as it is guaranteed that this set will be emptied
+ // at the end of recursion.
+ typedef WillBeHeapHashSet<RawPtrWillBeMember<SVGElement> > SVGElementSet;
+ DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<SVGElementSet>, invalidatingDependencies, (adoptPtrWillBeNoop(new SVGElementSet)));
+
+ SVGElementSet::iterator end = dependencies->end();
+ for (SVGElementSet::iterator it = dependencies->begin(); it != end; ++it) {
+ if (RenderObject* renderer = (*it)->renderer()) {
+ if (UNLIKELY(!invalidatingDependencies->add(*it).isNewEntry)) {
+ // Reference cycle: we are in process of invalidating this dependant.
+ continue;
+ }
+
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, needsLayout);
+ invalidatingDependencies->remove(*it);
+ }
}
}
@@ -192,7 +214,7 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject*
ASSERT(object->node());
if (needsLayout && !object->documentBeingDestroyed())
- object->setNeedsLayout();
+ object->setNeedsLayoutAndFullPaintInvalidation();
removeFromCacheAndInvalidateDependencies(object, needsLayout);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h
index 676562dd01c..d1d3a89926b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h
@@ -43,9 +43,8 @@ enum RenderSVGResourceMode {
ApplyToStrokeMode = 1 << 2,
ApplyToTextMode = 1 << 3 // used in combination with ApplyTo{Fill|Stroke}Mode
};
+typedef unsigned RenderSVGResourceModeFlags;
-class Color;
-class FloatRect;
class GraphicsContext;
class Path;
class RenderObject;
@@ -75,8 +74,9 @@ public:
}
// Helper utilities used in the render tree to access resources used for painting shapes/text (gradients & patterns & solid colors only)
- static RenderSVGResource* fillPaintingResource(RenderObject*, const RenderStyle*, Color& fallbackColor);
- static RenderSVGResource* strokePaintingResource(RenderObject*, const RenderStyle*, Color& fallbackColor);
+ // If hasFallback gets set to true, the sharedSolidPaintingResource is set to a fallback color.
+ static RenderSVGResource* fillPaintingResource(RenderObject*, const RenderStyle*, bool& hasFallback);
+ static RenderSVGResource* strokePaintingResource(RenderObject*, const RenderStyle*, bool& hasFallback);
static RenderSVGResourceSolidColor* sharedSolidPaintingResource();
static void markForLayoutAndParentResourceInvalidation(RenderObject*, bool needsLayout = true);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
index b98db0f7c86..62db92f8c1a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
@@ -24,15 +24,16 @@
#include "core/rendering/svg/RenderSVGResourceClipper.h"
-#include "RuntimeEnabledFeatures.h"
-#include "SVGNames.h"
-#include "core/frame/Frame.h"
+#include "core/SVGNames.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/HitTestResult.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGUseElement.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/DisplayList.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "wtf/TemporaryChange.h"
@@ -78,7 +79,7 @@ bool RenderSVGResourceClipper::applyStatefulResource(RenderObject* object, Graph
clearInvalidationMask();
- return applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context, clipperContext);
+ return applyClippingToContext(object, object->objectBoundingBox(), object->paintInvalidationRectInLocalCoordinates(), context, clipperContext);
}
bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
@@ -89,16 +90,16 @@ bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
WindRule clipRule = RULE_NONZERO;
Path clipPath = Path();
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
+ for (Element* childElement = ElementTraversal::firstWithin(*element()); childElement; childElement = ElementTraversal::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
if (!renderer)
continue;
// Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts.
if (renderer->isSVGText())
return false;
- if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGGraphicsElement())
+ if (!childElement->isSVGElement() || !toSVGElement(childElement)->isSVGGraphicsElement())
continue;
- SVGGraphicsElement* styled = toSVGGraphicsElement(childNode);
+ SVGGraphicsElement* styled = toSVGGraphicsElement(childElement);
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
@@ -127,7 +128,7 @@ bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
}
}
// Only one visible shape/path was found. Directly continue clipping and transform the content to userspace if necessary.
- if (toSVGClipPathElement(element())->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
@@ -148,7 +149,6 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
const FloatRect& repaintRect, GraphicsContext* context, ClipperContext& clipperContext)
{
ASSERT(target);
- ASSERT(target->node());
ASSERT(context);
ASSERT(clipperContext.state == ClipperContext::NotAppliedState);
ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
@@ -161,8 +161,8 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
// When drawing a clip for non-SVG elements, the CTM does not include the zoom factor.
// In this case, we need to apply the zoom scale explicitly - but only for clips with
// userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolved lengths).
- if (!target->node()->isSVGElement()
- && toSVGClipPathElement(element())->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
+ if (!target->isSVG()
+ && toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
ASSERT(style());
animatedLocalTransform.scale(style()->effectiveZoom());
}
@@ -238,7 +238,7 @@ void RenderSVGResourceClipper::drawClipMaskContent(GraphicsContext* context, con
ASSERT(context);
AffineTransform contentTransformation;
- SVGUnitTypes::SVGUnitType contentUnits = toSVGClipPathElement(element())->clipPathUnitsCurrentValue();
+ SVGUnitTypes::SVGUnitType contentUnits = toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue();
if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y());
contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
@@ -258,7 +258,10 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
ASSERT(context);
ASSERT(frame());
- context->beginRecording(repaintRectInLocalCoordinates());
+ // Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection
+ // with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and
+ // userSpaceOnUse units (http://crbug.com/294900).
+ context->beginRecording(strokeBoundingBox());
// Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints:
// - fill-opacity/stroke-opacity/opacity set to 1
@@ -268,9 +271,9 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
PaintBehavior oldBehavior = frame()->view()->paintBehavior();
frame()->view()->setPaintBehavior(oldBehavior | PaintBehaviorRenderingSVGMask);
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
RenderStyle* style = renderer->style();
@@ -278,13 +281,13 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
continue;
WindRule newClipRule = style->svgStyle()->clipRule();
- bool isUseElement = childNode->hasTagName(SVGNames::useTag);
+ bool isUseElement = isSVGUseElement(*childElement);
if (isUseElement) {
- SVGUseElement* useElement = toSVGUseElement(childNode);
- renderer = useElement->rendererClipChild();
+ SVGUseElement& useElement = toSVGUseElement(*childElement);
+ renderer = useElement.rendererClipChild();
if (!renderer)
continue;
- if (!useElement->hasAttribute(SVGNames::clip_ruleAttr))
+ if (!useElement.hasAttribute(SVGNames::clip_ruleAttr))
newClipRule = renderer->style()->svgStyle()->clipRule();
}
@@ -295,7 +298,7 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
context->setFillRule(newClipRule);
if (isUseElement)
- renderer = childNode->renderer();
+ renderer = childElement->renderer();
SVGRenderingContext::renderSubtree(context, renderer, contentTransformation);
}
@@ -308,16 +311,16 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
void RenderSVGResourceClipper::calculateClipContentRepaintRect()
{
// This is a rough heuristic to appraise the clip size and doesn't consider clip on clip.
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
- if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag))
+ if (!renderer->isSVGShape() && !renderer->isSVGText() && !isSVGUseElement(*childElement))
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
- m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+ m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->paintInvalidationRectInLocalCoordinates()));
}
m_clipBoundaries = toSVGClipPathElement(element())->animatedLocalTransform().mapRect(m_clipBoundaries);
}
@@ -329,7 +332,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
return false;
SVGClipPathElement* clipPathElement = toSVGClipPathElement(element());
- if (clipPathElement->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (clipPathElement->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
@@ -338,11 +341,11 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
point = clipPathElement->animatedLocalTransform().inverse().mapPoint(point);
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
- if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag))
+ if (!renderer->isSVGShape() && !renderer->isSVGText() && !isSVGUseElement(*childElement))
continue;
IntPoint hitPoint;
HitTestResult result(hitPoint);
@@ -353,7 +356,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
return false;
}
-FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
+FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject* object)
{
// Resource was not layouted yet. Give back the boundingBox of the object.
if (selfNeedsLayout())
@@ -362,7 +365,7 @@ FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
if (m_clipBoundaries.isEmpty())
calculateClipContentRepaintRect();
- if (toSVGClipPathElement(element())->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
FloatRect objectBoundingBox = object->objectBoundingBox();
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h
index ae89b1e3df5..75a805859ff 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h
@@ -45,13 +45,13 @@ public:
explicit RenderSVGResourceClipper(SVGClipPathElement*);
virtual ~RenderSVGResourceClipper();
- virtual const char* renderName() const { return "RenderSVGResourceClipper"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceClipper"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE FINAL;
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) OVERRIDE FINAL;
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) OVERRIDE;
// FIXME: Filters are also stateful resources that could benefit from having their state managed
// on the caller stack instead of the current hashmap. We should look at refactoring these
@@ -64,13 +64,13 @@ public:
// FIXME: We made applyClippingToContext public because we cannot call applyResource on HTML elements (it asserts on RenderObject::objectBoundingBox)
bool applyClippingToContext(RenderObject*, const FloatRect&, const FloatRect&, GraphicsContext*, ClipperContext&);
- FloatRect resourceBoundingBox(RenderObject*);
+ FloatRect resourceBoundingBox(const RenderObject*);
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
bool hitTestClipContent(const FloatRect&, const FloatPoint&);
- SVGUnitTypes::SVGUnitType clipPathUnits() const { return toSVGClipPathElement(element())->clipPathUnitsCurrentValue(); }
+ SVGUnitTypes::SVGUnitType clipPathUnits() const { return toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue(); }
static const RenderSVGResourceType s_resourceType;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
index 55405a77a08..8434f4fe4ee 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
@@ -21,7 +21,6 @@
#include "core/rendering/svg/RenderSVGResourceContainer.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/SVGRenderingContext.h"
@@ -32,7 +31,7 @@
namespace WebCore {
-static inline SVGDocumentExtensions* svgExtensionsFromElement(SVGElement* element)
+static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement* element)
{
ASSERT(element);
return element->document().accessSVGExtensions();
@@ -51,7 +50,7 @@ RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement* node)
RenderSVGResourceContainer::~RenderSVGResourceContainer()
{
if (m_registered)
- svgExtensionsFromElement(element())->removeResource(m_id);
+ svgExtensionsFromElement(element()).removeResource(m_id);
}
void RenderSVGResourceContainer::layout()
@@ -62,7 +61,6 @@ void RenderSVGResourceContainer::layout()
if (m_isInLayout)
return;
- LayoutRectRecorder recorder(*this);
TemporaryChange<bool> inLayoutChange(m_isInLayout, true);
RenderSVGHiddenContainer::layout();
@@ -92,8 +90,8 @@ void RenderSVGResourceContainer::idChanged()
removeAllClientsFromCache();
// Remove old id, that is guaranteed to be present in cache.
- SVGDocumentExtensions* extensions = svgExtensionsFromElement(element());
- extensions->removeResource(m_id);
+ SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
+ extensions.removeResource(m_id);
m_id = element()->getIdAttribute();
registerResource();
@@ -150,10 +148,10 @@ void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client,
break;
case RepaintInvalidation:
if (client->view()) {
- if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInLayout())
- client->setShouldDoFullRepaintAfterLayout(true);
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInPerformLayout())
+ client->setShouldDoFullPaintInvalidationAfterLayout(true);
else
- client->repaint();
+ client->paintInvalidationForWholeRenderer();
}
break;
case ParentOnlyInvalidation:
@@ -202,7 +200,7 @@ void RenderSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutSc
if (selfNeedsLayout())
return;
- setNeedsLayout(MarkContainingBlockChain, layoutScope);
+ setNeedsLayoutAndFullPaintInvalidation(MarkContainingBlockChain, layoutScope);
if (everHadLayout())
removeAllClientsFromCache();
@@ -210,33 +208,36 @@ void RenderSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutSc
void RenderSVGResourceContainer::registerResource()
{
- SVGDocumentExtensions* extensions = svgExtensionsFromElement(element());
- if (!extensions->hasPendingResource(m_id)) {
- extensions->addResource(m_id, this);
+ SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
+ if (!extensions.hasPendingResource(m_id)) {
+ extensions.addResource(m_id, this);
return;
}
- OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions->removePendingResource(m_id));
+ OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions.removePendingResource(m_id));
// Cache us with the new id.
- extensions->addResource(m_id, this);
+ extensions.addResource(m_id, this);
// Update cached resources of pending clients.
const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();
for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) {
ASSERT((*it)->hasPendingResources());
- extensions->clearHasPendingResourcesIfPossible(*it);
+ extensions.clearHasPendingResourcesIfPossible(*it);
RenderObject* renderer = (*it)->renderer();
if (!renderer)
continue;
- SVGResourcesCache::clientStyleChanged(renderer, StyleDifferenceLayout, renderer->style());
- renderer->setNeedsLayout();
+
+ StyleDifference diff;
+ diff.setNeedsFullLayout();
+ SVGResourcesCache::clientStyleChanged(renderer, diff, renderer->style());
+ renderer->setNeedsLayoutAndFullPaintInvalidation();
}
}
-bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
+static bool shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
{
- ASSERT_UNUSED(object, object);
+ ASSERT(object);
// This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline());
@@ -251,6 +252,26 @@ bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* obj
return true;
}
+AffineTransform RenderSVGResourceContainer::computeResourceSpaceTransform(RenderObject* object, const AffineTransform& baseTransform, const SVGRenderStyle* svgStyle, unsigned short resourceMode)
+{
+ AffineTransform computedSpaceTransform = baseTransform;
+ if (resourceMode & ApplyToTextMode) {
+ // Depending on the font scaling factor, we may need to apply an
+ // additional transform (scale-factor) the paintserver, since text
+ // painting removes the scale factor from the context. (See
+ // SVGInlineTextBox::paintTextWithShadows.)
+ AffineTransform additionalTextTransformation;
+ if (shouldTransformOnTextPainting(object, additionalTextTransformation))
+ computedSpaceTransform = additionalTextTransformation * computedSpaceTransform;
+ }
+ if (resourceMode & ApplyToStrokeMode) {
+ // Non-scaling stroke needs to reset the transform back to the host transform.
+ if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
+ computedSpaceTransform = transformOnNonScalingStroke(object, computedSpaceTransform);
+ }
+ return computedSpaceTransform;
+}
+
// FIXME: This does not belong here.
AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
{
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h
index 71d3c6f0cf1..52b50c394a3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h
@@ -33,12 +33,11 @@ public:
explicit RenderSVGResourceContainer(SVGElement*);
virtual ~RenderSVGResourceContainer();
- virtual void layout();
+ virtual void layout() OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
virtual bool isSVGResourceContainer() const OVERRIDE FINAL { return true; }
- static bool shouldTransformOnTextPainting(RenderObject*, AffineTransform&);
static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform);
void idChanged();
@@ -64,6 +63,8 @@ protected:
void clearInvalidationMask() { m_invalidationMask = 0; }
+ static AffineTransform computeResourceSpaceTransform(RenderObject*, const AffineTransform& baseTransform, const SVGRenderStyle*, unsigned short resourceMode);
+
bool m_isInLayout;
private:
@@ -86,21 +87,21 @@ private:
HashSet<RenderLayer*> m_clientLayers;
};
-inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document& document, const AtomicString& id)
+inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(TreeScope& treeScope, const AtomicString& id)
{
if (id.isEmpty())
return 0;
- if (RenderSVGResourceContainer* renderResource = document.accessSVGExtensions()->resourceById(id))
+ if (RenderSVGResourceContainer* renderResource = treeScope.document().accessSVGExtensions().resourceById(id))
return renderResource;
return 0;
}
template<typename Renderer>
-Renderer* getRenderSVGResourceById(Document& document, const AtomicString& id)
+Renderer* getRenderSVGResourceById(TreeScope& treeScope, const AtomicString& id)
{
- if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id))
+ if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(treeScope, id))
return container->cast<Renderer>();
return 0;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
index 840c563c4c2..80f0a30a0c2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
@@ -30,9 +30,9 @@
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
+#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
#include "platform/graphics/filters/SourceAlpha.h"
#include "platform/graphics/filters/SourceGraphic.h"
-#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
using namespace std;
@@ -50,6 +50,11 @@ RenderSVGResourceFilter::~RenderSVGResourceFilter()
m_filter.clear();
}
+bool RenderSVGResourceFilter::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isSVGResourceFilterPrimitive();
+}
+
void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation)
{
m_filter.clear();
@@ -77,11 +82,7 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter*
// Add effects to the builder
RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(SourceGraphic::create(filter), SourceAlpha::create(filter));
- for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
- if (!node->isSVGElement())
- continue;
-
- SVGElement* element = toSVGElement(node);
+ for (SVGElement* element = Traversal<SVGElement>::firstChild(*filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) {
if (!element->isFilterEffect() || !element->renderer())
continue;
@@ -89,46 +90,40 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter*
RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter);
if (!effect) {
builder->clearEffects();
- return 0;
+ return nullptr;
}
builder->appendEffectToEffectReferences(effect, effectElement->renderer());
effectElement->setStandardAttributes(effect.get());
- effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnitsCurrentValue(), targetBoundingBox));
+ effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->currentValue()->enumValue(), targetBoundingBox));
effect->setOperatingColorSpace(
effectElement->renderer()->style()->svgStyle()->colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
- builder->add(effectElement->resultCurrentValue(), effect);
+ builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect);
}
return builder.release();
}
-bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
+void RenderSVGResourceFilter::adjustScaleForMaximumImageSize(const FloatSize& size, FloatSize& filterScale)
{
- bool matchesFilterSize = true;
- if (size.width() > kMaxFilterSize) {
- scale.setWidth(scale.width() * kMaxFilterSize / size.width());
- matchesFilterSize = false;
- }
- if (size.height() > kMaxFilterSize) {
- scale.setHeight(scale.height() * kMaxFilterSize / size.height());
- matchesFilterSize = false;
- }
+ FloatSize scaledSize(size);
+ scaledSize.scale(filterScale.width(), filterScale.height());
+ float scaledArea = scaledSize.width() * scaledSize.height();
+
+ if (scaledArea <= FilterEffect::maxFilterArea())
+ return;
- return matchesFilterSize;
+ // If area of scaled size is bigger than the upper limit, adjust the scale
+ // to fit.
+ filterScale.scale(sqrt(FilterEffect::maxFilterArea() / scaledArea));
}
-static bool createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform,
- OwnPtr<ImageBuffer>& imageBuffer, bool accelerated)
+static bool createImageBuffer(const Filter* filter, OwnPtr<ImageBuffer>& imageBuffer)
{
- IntRect paintRect = SVGRenderingContext::calculateImageBufferRect(targetRect, absoluteTransform);
+ IntRect paintRect = filter->sourceImageRect();
// Don't create empty ImageBuffers.
if (paintRect.isEmpty())
return false;
- OwnPtr<ImageBufferSurface> surface;
- if (accelerated)
- surface = adoptPtr(new AcceleratedImageBufferSurface(paintRect.size()));
- if (!accelerated || !surface->isValid())
- surface = adoptPtr(new UnacceleratedImageBufferSurface(paintRect.size()));
+ OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSurface(paintRect.size()));
if (!surface->isValid())
return false;
OwnPtr<ImageBuffer> image = ImageBuffer::create(surface.release());
@@ -137,12 +132,71 @@ static bool createImageBuffer(const FloatRect& targetRect, const AffineTransform
ASSERT(imageContext);
imageContext->translate(-paintRect.x(), -paintRect.y());
- imageContext->concatCTM(absoluteTransform);
-
+ imageContext->concatCTM(filter->absoluteTransform());
imageBuffer = image.release();
return true;
}
+static void beginDeferredFilter(GraphicsContext* context, FilterData* filterData, SVGFilterElement* filterElement)
+{
+ SkiaImageFilterBuilder builder(context);
+ RefPtr<ImageFilter> imageFilter = builder.build(filterData->builder->lastEffect(), ColorSpaceDeviceRGB);
+ // FIXME: Remove the cache when impl-size painting is enabled on every platform and the non impl-side painting path is removed
+ if (!context->isRecordingCanvas()) // Recording canvases do not use the cache
+ filterData->filter->enableCache();
+ FloatRect boundaries = enclosingIntRect(filterData->boundaries);
+ context->save();
+ float scaledArea = boundaries.width() * boundaries.height();
+
+ // If area of scaled size is bigger than the upper limit, adjust the scale
+ // to fit.
+ if (scaledArea > FilterEffect::maxFilterArea()) {
+ float scale = sqrtf(FilterEffect::maxFilterArea() / scaledArea);
+ context->scale(scale, scale);
+ }
+ // Clip drawing of filtered image to primitive boundaries.
+ context->clipRect(boundaries);
+ if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
+ // Get boundaries in device coords.
+ // FIXME: See crbug.com/382491. Is the use of getCTM OK here, given it does not include device
+ // zoom or High DPI adjustments?
+ FloatSize size = context->getCTM().mapSize(boundaries.size());
+ // Compute the scale amount required so that the resulting offscreen is exactly filterResX by filterResY pixels.
+ float filterResScaleX = filterElement->filterResX()->currentValue()->value() / size.width();
+ float filterResScaleY = filterElement->filterResY()->currentValue()->value() / size.height();
+ // Scale the CTM so the primitive is drawn to filterRes.
+ context->scale(filterResScaleX, filterResScaleY);
+ // Create a resize filter with the inverse scale.
+ AffineTransform resizeMatrix;
+ resizeMatrix.scale(1 / filterResScaleX, 1 / filterResScaleY);
+ imageFilter = builder.buildTransform(resizeMatrix, imageFilter.get());
+ }
+ // If the CTM contains rotation or shearing, apply the filter to
+ // the unsheared/unrotated matrix, and do the shearing/rotation
+ // as a final pass.
+ AffineTransform ctm = context->getCTM();
+ if (ctm.b() || ctm.c()) {
+ AffineTransform scaleAndTranslate;
+ scaleAndTranslate.translate(ctm.e(), ctm.f());
+ scaleAndTranslate.scale(ctm.xScale(), ctm.yScale());
+ ASSERT(scaleAndTranslate.isInvertible());
+ AffineTransform shearAndRotate = scaleAndTranslate.inverse();
+ shearAndRotate.multiply(ctm);
+ context->setCTM(scaleAndTranslate);
+ imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get());
+ }
+ context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get());
+}
+
+static void endDeferredFilter(GraphicsContext* context, FilterData* filterData)
+{
+ context->endLayer();
+ context->restore();
+ // FIXME: Remove the cache when impl-size painting is enabled on every platform and the non impl-side painting path is removed
+ if (!context->isRecordingCanvas()) // Recording canvases do not use the cache
+ filterData->filter->disableCache();
+}
+
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(object);
@@ -151,10 +205,16 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
clearInvalidationMask();
+ bool deferredFiltersEnabled = object->document().settings()->deferredFiltersEnabled();
if (m_filter.contains(object)) {
FilterData* filterData = m_filter.get(object);
if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
filterData->state = FilterData::CycleDetected;
+ if (deferredFiltersEnabled && filterData->state == FilterData::Built) {
+ SVGFilterElement* filterElement = toSVGFilterElement(element());
+ beginDeferredFilter(context, filterData, filterElement);
+ return true;
+ }
return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
}
@@ -162,64 +222,65 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
FloatRect targetBoundingBox = object->objectBoundingBox();
SVGFilterElement* filterElement = toSVGFilterElement(element());
- filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnitsCurrentValue(), targetBoundingBox);
+ filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox);
if (filterData->boundaries.isEmpty())
return false;
// Determine absolute transformation matrix for filter.
AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform);
+ SVGRenderingContext::calculateDeviceSpaceTransformation(object, absoluteTransform);
if (!absoluteTransform.isInvertible())
return false;
- // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
- filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);
+ // Filters cannot handle a full transformation, only scales in each direction.
+ FloatSize filterScale;
+
+ // Calculate the scale factor for the filter.
+ // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
+ if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
+ // If resolution is specified, scale to match it.
+ filterScale = FloatSize(
+ filterElement->filterResX()->currentValue()->value() / filterData->boundaries.width(),
+ filterElement->filterResY()->currentValue()->value() / filterData->boundaries.height());
+ } else {
+ // Otherwise, use the scale of the absolute transform.
+ filterScale = FloatSize(absoluteTransform.xScale(), absoluteTransform.yScale());
+ }
+ // The size of the scaled filter boundaries shouldn't be bigger than kMaxFilterSize.
+ // Intermediate filters are limited by the filter boundaries so they can't be bigger than this.
+ adjustScaleForMaximumImageSize(filterData->boundaries.size(), filterScale);
- // Determine absolute boundaries of the filter and the drawing region.
- FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
filterData->drawingRegion = object->strokeBoundingBox();
filterData->drawingRegion.intersect(filterData->boundaries);
- FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(filterData->drawingRegion);
+ FloatRect absoluteDrawingRegion = filterData->drawingRegion;
+ if (!deferredFiltersEnabled)
+ absoluteDrawingRegion.scale(filterScale.width(), filterScale.height());
+
+ IntRect intDrawingRegion = enclosingIntRect(absoluteDrawingRegion);
// Create the SVGFilter object.
- bool primitiveBoundingBoxMode = filterElement->primitiveUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
- filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
+ bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ filterData->shearFreeAbsoluteTransform = AffineTransform();
+ if (!deferredFiltersEnabled)
+ filterData->shearFreeAbsoluteTransform.scale(filterScale.width(), filterScale.height());
+ filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
// Create all relevant filter primitives.
filterData->builder = buildPrimitives(filterData->filter.get());
if (!filterData->builder)
return false;
- // Calculate the scale factor for the use of filterRes.
- // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
- FloatSize scale(1, 1);
- if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
- scale.setWidth(filterElement->filterResXCurrentValue() / absoluteFilterBoundaries.width());
- scale.setHeight(filterElement->filterResYCurrentValue() / absoluteFilterBoundaries.height());
- }
-
- if (scale.isEmpty())
- return false;
-
- // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
- FloatRect tempSourceRect = absoluteDrawingRegion;
- tempSourceRect.scale(scale.width(), scale.height());
- fitsInMaximumImageSize(tempSourceRect.size(), scale);
-
- // Set the scale level in SVGFilter.
- filterData->filter->setFilterResolution(scale);
-
FilterEffect* lastEffect = filterData->builder->lastEffect();
if (!lastEffect)
return false;
lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
- FloatRect subRegion = lastEffect->maxEffectRect();
- // At least one FilterEffect has a too big image size,
- // recalculate the effect sizes with new scale factors.
- if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
- filterData->filter->setFilterResolution(scale);
- lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
+
+ if (deferredFiltersEnabled) {
+ FilterData* data = filterData.get();
+ m_filter.set(object, filterData.release());
+ beginDeferredFilter(context, data, filterElement);
+ return true;
}
// If the drawingRegion is empty, we have something like <g filter=".."/>.
@@ -231,23 +292,14 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
return false;
}
- // Change the coordinate transformation applied to the filtered element to reflect the resolution of the filter.
- AffineTransform effectiveTransform;
- effectiveTransform.scale(scale.width(), scale.height());
- effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);
-
OwnPtr<ImageBuffer> sourceGraphic;
- bool isAccelerated = object->document().settings()->acceleratedFiltersEnabled();
- if (!createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, isAccelerated)) {
+ if (!createImageBuffer(filterData->filter.get(), sourceGraphic)) {
ASSERT(!m_filter.contains(object));
filterData->savedContext = context;
m_filter.set(object, filterData.release());
return false;
}
- // Set the rendering mode from the page's settings.
- filterData->filter->setIsAccelerated(isAccelerated);
-
GraphicsContext* sourceGraphicContext = sourceGraphic->context();
ASSERT(sourceGraphicContext);
@@ -272,6 +324,12 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
if (!filterData)
return;
+ if (object->document().settings()->deferredFiltersEnabled() && (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Built)) {
+ endDeferredFilter(context, filterData);
+ filterData->state = FilterData::Built;
+ return;
+ }
+
switch (filterData->state) {
case FilterData::MarkedForRemoval:
m_filter.remove(object);
@@ -319,22 +377,16 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
ImageBuffer* resultImage = lastEffect->asImageBuffer();
if (resultImage) {
- context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());
-
- context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
- context->drawImageBuffer(resultImage, lastEffect->absolutePaintRect());
- context->scale(filterData->filter->filterResolution());
-
- context->concatCTM(filterData->shearFreeAbsoluteTransform);
+ context->drawImageBuffer(resultImage, filterData->filter->mapAbsoluteRectToLocalRect(lastEffect->absolutePaintRect()));
}
}
filterData->sourceGraphicBuffer.clear();
}
-FloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object)
+FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject* object)
{
if (SVGFilterElement* element = toSVGFilterElement(this->element()))
- return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnitsCurrentValue(), object->objectBoundingBox());
+ return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnits()->currentValue()->enumValue(), object->objectBoundingBox());
return FloatRect();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h
index 6455b039284..1c679130ccc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h
@@ -60,30 +60,32 @@ public:
explicit RenderSVGResourceFilter(SVGFilterElement*);
virtual ~RenderSVGResourceFilter();
- virtual const char* renderName() const { return "RenderSVGResourceFilter"; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceFilter"; }
virtual bool isSVGResourceFilter() const OVERRIDE { return true; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE;
- FloatRect resourceBoundingBox(RenderObject*);
+ FloatRect resourceBoundingBox(const RenderObject*);
PassRefPtr<SVGFilterBuilder> buildPrimitives(SVGFilter*);
- SVGUnitTypes::SVGUnitType filterUnits() const { return toSVGFilterElement(element())->filterUnitsCurrentValue(); }
- SVGUnitTypes::SVGUnitType primitiveUnits() const { return toSVGFilterElement(element())->primitiveUnitsCurrentValue(); }
+ SVGUnitTypes::SVGUnitType filterUnits() const { return toSVGFilterElement(element())->filterUnits()->currentValue()->enumValue(); }
+ SVGUnitTypes::SVGUnitType primitiveUnits() const { return toSVGFilterElement(element())->primitiveUnits()->currentValue()->enumValue(); }
void primitiveAttributeChanged(RenderObject*, const QualifiedName&);
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
FloatRect drawingRegion(RenderObject*) const;
private:
- bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
+ void adjustScaleForMaximumImageSize(const FloatSize&, FloatSize&);
typedef HashMap<RenderObject*, OwnPtr<FilterData> > FilterMap;
FilterMap m_filter;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
index e34449d35ea..f7fce429304 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
@@ -40,16 +40,17 @@ void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, cons
return;
ASSERT(filter->isSVGResourceFilter());
- if (diff == StyleDifferenceEqual || !oldStyle)
+ if (diff.hasNoChange() || !oldStyle)
return;
const SVGRenderStyle* newStyle = this->style()->svgStyle();
- if (element()->hasTagName(SVGNames::feFloodTag)) {
+ ASSERT(element());
+ if (isSVGFEFloodElement(*element())) {
if (newStyle->floodColor() != oldStyle->svgStyle()->floodColor())
toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
if (newStyle->floodOpacity() != oldStyle->svgStyle()->floodOpacity())
toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
- } else if (element()->hasTagName(SVGNames::feDiffuseLightingTag) || element()->hasTagName(SVGNames::feSpecularLightingTag)) {
+ } else if (isSVGFEDiffuseLightingElement(*element()) || isSVGFESpecularLightingElement(*element())) {
if (newStyle->lightingColor() != oldStyle->svgStyle()->lightingColor())
toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
index 704df3d4075..b2a293d68fe 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
@@ -38,10 +38,12 @@ public:
{
}
- virtual void styleDidChange(StyleDifference, const RenderStyle*);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE { return false; }
- virtual const char* renderName() const { return "RenderSVGResourceFilterPrimitive"; }
- virtual bool isSVGResourceFilterPrimitive() const { return true; }
+ virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceFilterPrimitive"; }
+ virtual bool isSVGResourceFilterPrimitive() const OVERRIDE { return true; }
inline void primitiveAttributeChanged(const QualifiedName& attribute)
{
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
index 4e432a56082..6f44a65b116 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
@@ -81,12 +81,10 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
return false;
- OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).iterator->value;
+ OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).storedValue->value;
if (!gradientData)
gradientData = adoptPtr(new GradientData);
- bool isPaintingText = resourceMode & ApplyToTextMode;
-
// Create gradient object
if (!gradientData->gradient) {
buildGradient(gradientData.get());
@@ -101,36 +99,29 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
calculateGradientTransform(gradientTransform);
gradientData->userspaceTransform *= gradientTransform;
- if (isPaintingText) {
- // Depending on font scaling factor, we may need to rescale the gradient here since
- // text painting removes the scale factor from the context.
- AffineTransform additionalTextTransform;
- if (shouldTransformOnTextPainting(object, additionalTextTransform))
- gradientData->userspaceTransform *= additionalTextTransform;
- }
- gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
}
if (!gradientData->gradient)
return false;
+ const SVGRenderStyle* svgStyle = style->svgStyle();
+ ASSERT(svgStyle);
+
+ AffineTransform computedGradientSpaceTransform = computeResourceSpaceTransform(object, gradientData->userspaceTransform, svgStyle, resourceMode);
+ gradientData->gradient->setGradientSpaceTransform(computedGradientSpaceTransform);
+
// Draw gradient
context->save();
- if (isPaintingText)
+ if (resourceMode & ApplyToTextMode)
context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFill : TextModeStroke);
- const SVGRenderStyle* svgStyle = style->svgStyle();
- ASSERT(svgStyle);
-
if (resourceMode & ApplyToFillMode) {
- context->setAlpha(svgStyle->fillOpacity());
+ context->setAlphaAsFloat(svgStyle->fillOpacity());
context->setFillGradient(gradientData->gradient);
context->setFillRule(svgStyle->fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
- if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
- gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(object, gradientData->userspaceTransform));
- context->setAlpha(svgStyle->strokeOpacity());
+ context->setAlphaAsFloat(svgStyle->strokeOpacity());
context->setStrokeGradient(gradientData->gradient);
SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
index ba1c3d27884..b829e403004 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
@@ -33,15 +33,15 @@ public:
explicit RenderSVGResourceLinearGradient(SVGLinearGradientElement*);
virtual ~RenderSVGResourceLinearGradient();
- virtual const char* renderName() const { return "RenderSVGResourceLinearGradient"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceLinearGradient"; }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
- virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
- virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
- virtual bool collectGradientAttributes(SVGGradientElement*);
- virtual void buildGradient(GradientData*) const;
+ virtual SVGUnitTypes::SVGUnitType gradientUnits() const OVERRIDE { return m_attributes.gradientUnits(); }
+ virtual void calculateGradientTransform(AffineTransform& transform) OVERRIDE { transform = m_attributes.gradientTransform(); }
+ virtual bool collectGradientAttributes(SVGGradientElement*) OVERRIDE;
+ virtual void buildGradient(GradientData*) const OVERRIDE;
FloatPoint startPoint(const LinearGradientAttributes&) const;
FloatPoint endPoint(const LinearGradientAttributes&) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
index d3de3b7cc64..be93b479b2d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
@@ -23,7 +23,7 @@
#include "core/rendering/svg/RenderSVGResourceMarker.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/svg/RenderSVGContainer.h"
#include "core/rendering/svg/SVGRenderSupport.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
@@ -49,13 +49,8 @@ void RenderSVGResourceMarker::layout()
if (m_isInLayout)
return;
- LayoutRectRecorder recorder(*this);
TemporaryChange<bool> inLayoutChange(m_isInLayout, true);
- // Invalidate all resources if our layout changed.
- if (everHadLayout() && selfNeedsLayout())
- removeAllClientsFromCache();
-
// RenderSVGHiddenContainer overwrites layout(). We need the
// layouting of RenderSVGContainer for calculating local
// transformations and repaint.
@@ -83,7 +78,7 @@ void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo)
FloatRect RenderSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const
{
- FloatRect coordinates = RenderSVGContainer::repaintRectInLocalCoordinates();
+ FloatRect coordinates = RenderSVGContainer::paintInvalidationRectInLocalCoordinates();
// Map repaint rect into parent coordinate space, in which the marker boundaries have to be evaluated
coordinates = localToParentTransform().mapRect(coordinates);
@@ -105,7 +100,7 @@ FloatPoint RenderSVGResourceMarker::referencePoint() const
ASSERT(marker);
SVGLengthContext lengthContext(marker);
- return FloatPoint(marker->refXCurrentValue().value(lengthContext), marker->refYCurrentValue().value(lengthContext));
+ return FloatPoint(marker->refX()->currentValue()->value(lengthContext), marker->refY()->currentValue()->value(lengthContext));
}
float RenderSVGResourceMarker::angle() const
@@ -114,8 +109,8 @@ float RenderSVGResourceMarker::angle() const
ASSERT(marker);
float angle = -1;
- if (marker->orientTypeCurrentValue() == SVGMarkerOrientAngle)
- angle = marker->orientAngleCurrentValue().value();
+ if (marker->orientType()->currentValue()->enumValue() == SVGMarkerOrientAngle)
+ angle = marker->orientAngle()->currentValue()->value();
return angle;
}
@@ -126,7 +121,7 @@ AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint&
ASSERT(marker);
float markerAngle = angle();
- bool useStrokeWidth = marker->markerUnitsCurrentValue() == SVGMarkerUnitsStrokeWidth;
+ bool useStrokeWidth = marker->markerUnits()->currentValue()->enumValue() == SVGMarkerUnitsStrokeWidth;
AffineTransform transform;
transform.translate(origin.x(), origin.y());
@@ -142,12 +137,15 @@ void RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform&
// An empty viewBox disables rendering.
SVGMarkerElement* marker = toSVGMarkerElement(element());
ASSERT(marker);
- if (marker->hasAttribute(SVGNames::viewBoxAttr) && marker->viewBoxCurrentValue().isValid() && marker->viewBoxCurrentValue().isEmpty())
+ if (marker->hasAttribute(SVGNames::viewBoxAttr) && marker->viewBox()->currentValue()->isValid() && marker->viewBox()->currentValue()->value().isEmpty())
return;
PaintInfo info(paintInfo);
- GraphicsContextStateSaver stateSaver(*info.context);
- info.applyTransform(transform);
+ GraphicsContextStateSaver stateSaver(*info.context, false);
+ if (!transform.isIdentity()) {
+ stateSaver.save();
+ info.applyTransform(transform, false);
+ }
RenderSVGContainer::paint(info, IntPoint());
}
@@ -181,8 +179,8 @@ void RenderSVGResourceMarker::calcViewport()
ASSERT(marker);
SVGLengthContext lengthContext(marker);
- float w = marker->markerWidthCurrentValue().value(lengthContext);
- float h = marker->markerHeightCurrentValue().value(lengthContext);
+ float w = marker->markerWidth()->currentValue()->value(lengthContext);
+ float h = marker->markerHeight()->currentValue()->value(lengthContext);
m_viewport = FloatRect(0, 0, w, h);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h
index 625b37a652a..ba31fb21e45 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h
@@ -28,7 +28,6 @@
namespace WebCore {
-class AffineTransform;
class RenderObject;
class RenderSVGResourceMarker FINAL : public RenderSVGResourceContainer {
@@ -36,30 +35,30 @@ public:
explicit RenderSVGResourceMarker(SVGMarkerElement*);
virtual ~RenderSVGResourceMarker();
- virtual const char* renderName() const { return "RenderSVGResourceMarker"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceMarker"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
void draw(PaintInfo&, const AffineTransform&);
// Calculates marker boundaries, mapped to the target element's coordinate space
FloatRect markerBoundaries(const AffineTransform& markerTransformation) const;
- virtual void applyViewportClip(PaintInfo&);
- virtual void layout();
- virtual void calcViewport();
+ virtual void applyViewportClip(PaintInfo&) OVERRIDE;
+ virtual void layout() OVERRIDE;
+ virtual void calcViewport() OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const;
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE;
AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) { return false; }
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) OVERRIDE { return false; }
FloatPoint referencePoint() const;
float angle() const;
- SVGMarkerUnitsType markerUnits() const { return toSVGMarkerElement(element())->markerUnitsCurrentValue(); }
+ SVGMarkerUnitsType markerUnits() const { return toSVGMarkerElement(element())->markerUnits()->currentValue()->enumValue(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
index 43c64ca081d..98a6d4c7639 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
@@ -66,8 +66,8 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
clearInvalidationMask();
- FloatRect repaintRect = object->repaintRectInLocalCoordinates();
- if (repaintRect.isEmpty() || !element()->hasChildNodes())
+ FloatRect repaintRect = object->paintInvalidationRectInLocalCoordinates();
+ if (repaintRect.isEmpty() || !element()->hasChildren())
return false;
// Content layer start.
@@ -85,7 +85,7 @@ void RenderSVGResourceMasker::postApplyResource(RenderObject* object, GraphicsCo
ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
- FloatRect repaintRect = object->repaintRectInLocalCoordinates();
+ FloatRect repaintRect = object->paintInvalidationRectInLocalCoordinates();
const SVGRenderStyle* svgStyle = style()->svgStyle();
ASSERT(svgStyle);
@@ -115,7 +115,7 @@ void RenderSVGResourceMasker::drawMaskForRenderer(GraphicsContext* context, cons
ASSERT(context);
AffineTransform contentTransformation;
- SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnitsCurrentValue();
+ SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue();
if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y());
contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
@@ -133,10 +133,13 @@ PassRefPtr<DisplayList> RenderSVGResourceMasker::asDisplayList(GraphicsContext*
{
ASSERT(context);
- context->beginRecording(repaintRectInLocalCoordinates());
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ // Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection
+ // with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and
+ // userSpaceOnUse units (http://crbug.com/294900).
+ context->beginRecording(strokeBoundingBox());
+ for (Element* childElement = ElementTraversal::firstWithin(*element()); childElement; childElement = ElementTraversal::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!childElement->isSVGElement() || !renderer)
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
@@ -150,24 +153,24 @@ PassRefPtr<DisplayList> RenderSVGResourceMasker::asDisplayList(GraphicsContext*
void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
{
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
- m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+ m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->paintInvalidationRectInLocalCoordinates()));
}
}
-FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object)
+FloatRect RenderSVGResourceMasker::resourceBoundingBox(const RenderObject* object)
{
SVGMaskElement* maskElement = toSVGMaskElement(element());
ASSERT(maskElement);
FloatRect objectBoundingBox = object->objectBoundingBox();
- FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(maskElement, maskElement->maskUnitsCurrentValue(), objectBoundingBox);
+ FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(maskElement, maskElement->maskUnits()->currentValue()->enumValue(), objectBoundingBox);
// Resource was not layouted yet. Give back clipping rect of the mask.
if (selfNeedsLayout())
@@ -177,7 +180,7 @@ FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object)
calculateMaskContentRepaintRect();
FloatRect maskRect = m_maskContentBoundaries;
- if (maskElement->maskContentUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (maskElement->maskContentUnits()->currentValue()->value() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h
index 2af52752127..e05fc0d9b95 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h
@@ -25,7 +25,6 @@
#include "core/svg/SVGUnitTypes.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntSize.h"
-#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageBuffer.h"
#include "wtf/HashMap.h"
@@ -34,24 +33,25 @@
namespace WebCore {
class DisplayList;
+class GraphicsContext;
class RenderSVGResourceMasker FINAL : public RenderSVGResourceContainer {
public:
explicit RenderSVGResourceMasker(SVGMaskElement*);
virtual ~RenderSVGResourceMasker();
- virtual const char* renderName() const { return "RenderSVGResourceMasker"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceMasker"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) OVERRIDE;
- FloatRect resourceBoundingBox(RenderObject*);
+ FloatRect resourceBoundingBox(const RenderObject*);
- SVGUnitTypes::SVGUnitType maskUnits() const { return toSVGMaskElement(element())->maskUnitsCurrentValue(); }
- SVGUnitTypes::SVGUnitType maskContentUnits() const { return toSVGMaskElement(element())->maskContentUnitsCurrentValue(); }
+ SVGUnitTypes::SVGUnitType maskUnits() const { return toSVGMaskElement(element())->maskUnits()->currentValue()->enumValue(); }
+ SVGUnitTypes::SVGUnitType maskContentUnits() const { return toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
index c107a793f4a..401a29057a8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
@@ -53,6 +53,7 @@ void RenderSVGResourcePattern::removeClientFromCache(RenderObject* client, bool
PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsigned short resourceMode)
{
+ ASSERT(object);
PatternData* currentData = m_patternMap.get(object);
if (currentData && currentData->pattern)
return currentData;
@@ -84,19 +85,18 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
return 0;
AffineTransform absoluteTransformIgnoringRotation;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation);
+ SVGRenderingContext::calculateDeviceSpaceTransformation(object, absoluteTransformIgnoringRotation);
// Ignore 2D rotation, as it doesn't affect the size of the tile.
SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
FloatRect absoluteTileBoundaries = absoluteTransformIgnoringRotation.mapRect(tileBoundaries);
- FloatRect clampedAbsoluteTileBoundaries;
// Scale the tile size to match the scale level of the patternTransform.
absoluteTileBoundaries.scale(static_cast<float>(m_attributes.patternTransform().xScale()),
static_cast<float>(m_attributes.patternTransform().yScale()));
// Build tile image.
- OwnPtr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
+ OwnPtr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform);
if (!tileImage)
return 0;
@@ -117,18 +117,10 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
if (!patternTransform.isIdentity())
patternData->transform = patternTransform * patternData->transform;
- // Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows.
- if (resourceMode & ApplyToTextMode) {
- AffineTransform additionalTextTransformation;
- if (shouldTransformOnTextPainting(object, additionalTextTransformation))
- patternData->transform *= additionalTextTransformation;
- }
- patternData->pattern->setPatternSpaceTransform(patternData->transform);
-
// Various calls above may trigger invalidations in some fringe cases (ImageBuffer allocation
// failures in the SVG image cache for example). To avoid having our PatternData deleted by
// removeAllClientsFromCache(), we only make it visible in the cache at the very end.
- return m_patternMap.set(object, patternData.release()).iterator->value.get();
+ return m_patternMap.set(object, patternData.release()).storedValue->value.get();
}
bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
@@ -150,20 +142,21 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
if (!patternData)
return false;
- // Draw pattern
- context->save();
-
const SVGRenderStyle* svgStyle = style->svgStyle();
ASSERT(svgStyle);
+ AffineTransform computedPatternSpaceTransform = computeResourceSpaceTransform(object, patternData->transform, svgStyle, resourceMode);
+ patternData->pattern->setPatternSpaceTransform(computedPatternSpaceTransform);
+
+ // Draw pattern
+ context->save();
+
if (resourceMode & ApplyToFillMode) {
- context->setAlpha(svgStyle->fillOpacity());
+ context->setAlphaAsFloat(svgStyle->fillOpacity());
context->setFillPattern(patternData->pattern);
context->setFillRule(svgStyle->fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
- if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
- patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform));
- context->setAlpha(svgStyle->strokeOpacity());
+ context->setAlphaAsFloat(svgStyle->strokeOpacity());
context->setStrokePattern(patternData->pattern);
SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
}
@@ -235,10 +228,9 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes,
const FloatRect& tileBoundaries,
const FloatRect& absoluteTileBoundaries,
- const AffineTransform& tileImageTransform,
- FloatRect& clampedAbsoluteTileBoundaries) const
+ const AffineTransform& tileImageTransform) const
{
- clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
+ FloatRect clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
IntSize imageSize(roundedIntSize(clampedAbsoluteTileBoundaries.size()));
if (imageSize.isEmpty())
@@ -250,11 +242,12 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
GraphicsContext* tileImageContext = tileImage->context();
ASSERT(tileImageContext);
IntSize unclampedImageSize(roundedIntSize(absoluteTileBoundaries.size()));
- tileImageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTileBoundaries.width(), unclampedImageSize.height() / absoluteTileBoundaries.height()));
+ tileImageContext->scale(unclampedImageSize.width() / absoluteTileBoundaries.width(), unclampedImageSize.height() / absoluteTileBoundaries.height());
// The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation).
- tileImageContext->scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
- clampedAbsoluteTileBoundaries.height() / tileBoundaries.height()));
+ tileImageContext->scale(
+ clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
+ clampedAbsoluteTileBoundaries.height() / tileBoundaries.height());
// Apply tile image transformations.
if (!tileImageTransform.isIdentity())
@@ -265,12 +258,12 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
contentTransformation = tileImageTransform;
// Draw the content into the ImageBuffer.
- for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) {
- if (!node->isSVGElement() || !node->renderer())
+ for (Element* element = ElementTraversal::firstWithin(*attributes.patternContentElement()); element; element = ElementTraversal::nextSibling(*element)) {
+ if (!element->isSVGElement() || !element->renderer())
continue;
- if (node->renderer()->needsLayout())
+ if (element->renderer()->needsLayout())
return nullptr;
- SVGRenderingContext::renderSubtree(tileImage->context(), node->renderer(), contentTransformation);
+ SVGRenderingContext::renderSubtree(tileImage->context(), element->renderer(), contentTransformation);
}
return tileImage.release();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h
index 56a8318e06d..d6b4f12e577 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h
@@ -46,23 +46,22 @@ class RenderSVGResourcePattern FINAL : public RenderSVGResourceContainer {
public:
explicit RenderSVGResourcePattern(SVGPatternElement*);
- virtual const char* renderName() const { return "RenderSVGResourcePattern"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourcePattern"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE;
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
private:
bool buildTileImageTransform(RenderObject*, const PatternAttributes&, const SVGPatternElement*, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const;
PassOwnPtr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries,
- const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform,
- FloatRect& clampedAbsoluteTileBoundaries) const;
+ const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform) const;
PatternData* buildPattern(RenderObject*, unsigned short resourceMode);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
index 43ee07601e0..1f9145a02bd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
@@ -33,15 +33,15 @@ public:
explicit RenderSVGResourceRadialGradient(SVGRadialGradientElement*);
virtual ~RenderSVGResourceRadialGradient();
- virtual const char* renderName() const { return "RenderSVGResourceRadialGradient"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceRadialGradient"; }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
- virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
- virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
- virtual bool collectGradientAttributes(SVGGradientElement*);
- virtual void buildGradient(GradientData*) const;
+ virtual SVGUnitTypes::SVGUnitType gradientUnits() const OVERRIDE { return m_attributes.gradientUnits(); }
+ virtual void calculateGradientTransform(AffineTransform& transform) OVERRIDE { transform = m_attributes.gradientTransform(); }
+ virtual bool collectGradientAttributes(SVGGradientElement*) OVERRIDE;
+ virtual void buildGradient(GradientData*) const OVERRIDE;
FloatPoint centerPoint(const RadialGradientAttributes&) const;
FloatPoint focalPoint(const RadialGradientAttributes&) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
index a79ad3ad916..fac2a846c9a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
@@ -21,8 +21,8 @@
#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/svg/RenderSVGShape.h"
#include "core/rendering/svg/SVGRenderSupport.h"
@@ -56,9 +56,9 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl
if (resourceMode & ApplyToFillMode) {
if (!isRenderingMask && svgStyle)
- context->setAlpha(svgStyle->fillOpacity());
+ context->setAlphaAsFloat(svgStyle->fillOpacity());
else
- context->setAlpha(1);
+ context->setAlphaAsFloat(1);
context->setFillColor(m_color);
if (!isRenderingMask)
context->setFillRule(svgStyle ? svgStyle->fillRule() : RULE_NONZERO);
@@ -68,7 +68,7 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl
} else if (resourceMode & ApplyToStrokeMode) {
// When rendering the mask for a RenderSVGResourceClipper, the stroke code path is never hit.
ASSERT(!isRenderingMask);
- context->setAlpha(svgStyle ? svgStyle->strokeOpacity() : 1);
+ context->setAlphaAsFloat(svgStyle ? svgStyle->strokeOpacity() : 1);
context->setStrokeColor(m_color);
if (style)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
index 85937ce9ef1..3583a0d1aec 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
@@ -26,18 +26,18 @@
namespace WebCore {
-class RenderSVGResourceSolidColor : public RenderSVGResource {
+class RenderSVGResourceSolidColor FINAL : public RenderSVGResource {
public:
RenderSVGResourceSolidColor();
virtual ~RenderSVGResourceSolidColor();
- virtual void removeAllClientsFromCache(bool = true) { }
- virtual void removeClientFromCache(RenderObject*, bool = true) { }
+ virtual void removeAllClientsFromCache(bool = true) OVERRIDE { }
+ virtual void removeClientFromCache(RenderObject*, bool = true) OVERRIDE { }
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE;
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
const Color& color() const { return m_color; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp
index a4355cd4d9a..d88947d3574 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp
@@ -25,19 +25,21 @@
#include "core/rendering/svg/RenderSVGRoot.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderPart.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGElement.h"
#include "core/svg/SVGSVGElement.h"
#include "core/svg/graphics/SVGImage.h"
+#include "platform/LengthFunctions.h"
#include "platform/graphics/GraphicsContext.h"
using namespace std;
@@ -49,6 +51,7 @@ RenderSVGRoot::RenderSVGRoot(SVGElement* node)
, m_objectBoundingBoxValid(false)
, m_isLayoutSizeChanged(false)
, m_needsBoundariesOrTransformUpdate(true)
+ , m_hasBoxDecorations(false)
{
}
@@ -56,19 +59,13 @@ RenderSVGRoot::~RenderSVGRoot()
{
}
-void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
{
// Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing
// SVG needs to specify how to calculate some intrinsic sizing properties to enable inclusion within other languages.
// The intrinsic width and height of the viewport of SVG content must be determined from the ‘width’ and ‘height’ attributes.
- // If either of these are not specified, a value of '100%' must be assumed. Note: the ‘width’ and ‘height’ attributes are not
- // the same as the CSS width and height properties. Specifically, percentage values do not provide an intrinsic width or height,
- // and do not indicate a percentage of the containing block. Rather, once the viewport is established, they indicate the portion
- // of the viewport that is actually covered by image data.
SVGSVGElement* svg = toSVGSVGElement(node());
ASSERT(svg);
- Length intrinsicWidthAttribute = svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties);
- Length intrinsicHeightAttribute = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
// The intrinsic aspect ratio of the viewport of SVG content is necessary for example, when including SVG from an ‘object’
// element in HTML styled with CSS. It is possible (indeed, common) for an SVG graphic to have an intrinsic aspect ratio but
@@ -77,33 +74,21 @@ void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, d
// - If the ‘width’ and ‘height’ of the rootmost ‘svg’ element are both specified with unit identifiers (in, mm, cm, pt, pc,
// px, em, ex) or in user units, then the aspect ratio is calculated from the ‘width’ and ‘height’ attributes after
// resolving both values to user units.
- if (intrinsicWidthAttribute.isFixed() || intrinsicHeightAttribute.isFixed()) {
- if (intrinsicWidthAttribute.isFixed())
- intrinsicSize.setWidth(floatValueForLength(intrinsicWidthAttribute, 0, 0));
- if (intrinsicHeightAttribute.isFixed())
- intrinsicSize.setHeight(floatValueForLength(intrinsicHeightAttribute, 0, 0));
- if (!intrinsicSize.isEmpty())
- intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
- return;
- }
+ intrinsicSize.setWidth(floatValueForLength(svg->intrinsicWidth(), 0));
+ intrinsicSize.setHeight(floatValueForLength(svg->intrinsicHeight(), 0));
- // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
- // aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
- // fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
- // calculated and is considered unspecified.
- intrinsicSize = svg->viewBoxCurrentValue().size();
if (!intrinsicSize.isEmpty()) {
- // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
- intrinsicSize = FloatSize();
- return;
- }
-
- // If our intrinsic size is in percentage units, return those to the caller through the intrinsicSize. Notify the caller
- // about the special situation, by setting isPercentageIntrinsicSize=true, so it knows how to interpret the return values.
- if (intrinsicWidthAttribute.isPercent() && intrinsicHeightAttribute.isPercent()) {
- isPercentageIntrinsicSize = true;
- intrinsicSize = FloatSize(intrinsicWidthAttribute.percent(), intrinsicHeightAttribute.percent());
+ } else {
+ // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
+ // aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
+ // fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
+ // calculated and is considered unspecified.
+ FloatSize viewBoxSize = svg->viewBox()->currentValue()->value().size();
+ if (!viewBoxSize.isEmpty()) {
+ // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
+ intrinsicRatio = viewBoxSize.width() / static_cast<double>(viewBoxSize.height());
+ }
}
}
@@ -117,20 +102,20 @@ bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const
if (!node())
return false;
- Frame* frame = node()->document().frame();
+ LocalFrame* frame = node()->document().frame();
if (!frame)
return false;
// If our frame has an owner renderer, we're embedded through eg. object/embed/iframe,
- // but we only negotiate if we're in an SVG document.
- if (!frame->ownerRenderer())
+ // but we only negotiate if we're in an SVG document inside a embedded object (object/embed).
+ if (!frame->ownerRenderer() || !frame->ownerRenderer()->isEmbeddedObject())
return false;
return frame->document()->isSVGDocument();
}
-static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView)
+static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize)
{
- return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1));
+ return static_cast<LayoutUnit>(valueForLength(length, maxSize) * (length.isFixed() ? scale : 1));
}
LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
@@ -142,15 +127,14 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred sho
if (!m_containerSize.isEmpty())
return m_containerSize.width();
+ if (isEmbeddedThroughFrameContainingSVGDocument())
+ return containingBlock()->availableLogicalWidth();
+
if (style()->logicalWidth().isSpecified() || style()->logicalMaxWidth().isSpecified())
return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
- if (svg->widthAttributeEstablishesViewport())
- return resolveLengthAttributeForSVG(svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style()->effectiveZoom(), containingBlock()->availableLogicalWidth(), view());
-
- // SVG embedded through object/embed/iframe.
- if (isEmbeddedThroughFrameContainingSVGDocument())
- return document().frame()->ownerRenderer()->availableLogicalWidth();
+ if (svg->hasIntrinsicWidth())
+ return resolveLengthAttributeForSVG(svg->intrinsicWidth(), style()->effectiveZoom(), containingBlock()->availableLogicalWidth().toFloat());
// SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
@@ -165,27 +149,14 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
if (!m_containerSize.isEmpty())
return m_containerSize.height();
+ if (isEmbeddedThroughFrameContainingSVGDocument())
+ return containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding);
+
if (style()->logicalHeight().isSpecified() || style()->logicalMaxHeight().isSpecified())
return RenderReplaced::computeReplacedLogicalHeight();
- if (svg->heightAttributeEstablishesViewport()) {
- Length height = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
- if (height.isPercent()) {
- RenderBlock* cb = containingBlock();
- ASSERT(cb);
- while (cb->isAnonymous()) {
- cb = cb->containingBlock();
- cb->addPercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
- }
- } else
- RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
-
- return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding), view());
- }
-
- // SVG embedded through object/embed/iframe.
- if (isEmbeddedThroughFrameContainingSVGDocument())
- return document().frame()->ownerRenderer()->availableLogicalHeight(IncludeMarginBorderPadding);
+ if (svg->hasIntrinsicHeight())
+ return resolveLengthAttributeForSVG(svg->intrinsicHeight(), style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding).toFloat());
// SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
return RenderReplaced::computeReplacedLogicalHeight();
@@ -195,13 +166,11 @@ void RenderSVGRoot::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
-
// Arbitrary affine transforms are incompatible with LayoutState.
- LayoutStateDisabler layoutStateDisabler(view());
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
bool needsLayout = selfNeedsLayout();
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout);
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout() && needsLayout);
LayoutSize oldSize = size();
updateLogicalWidth();
@@ -222,13 +191,34 @@ void RenderSVGRoot::layout()
m_needsBoundariesOrTransformUpdate = false;
}
- updateLayerTransform();
+ m_overflow.clear();
+ addVisualEffectOverflow();
- repainter.repaintAfterLayout();
+ if (!shouldApplyViewportClip()) {
+ FloatRect contentRepaintRect = paintInvalidationRectInLocalCoordinates();
+ contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect);
+ addVisualOverflow(enclosingLayoutRect(contentRepaintRect));
+ }
+ updateLayerTransformAfterLayout();
+ m_hasBoxDecorations = isDocumentElement() ? calculateHasBoxDecorations() : hasBoxDecorations();
+ invalidateBackgroundObscurationStatus();
+
+ repainter.repaintAfterLayout();
clearNeedsLayout();
}
+bool RenderSVGRoot::shouldApplyViewportClip() const
+{
+ // the outermost svg is clipped if auto, and svg document roots are always clipped
+ // When the svg is stand-alone (isDocumentElement() == true) the viewport clipping should always
+ // be applied, noting that the window scrollbars should be hidden if overflow=hidden.
+ return style()->overflowX() == OHIDDEN
+ || style()->overflowX() == OAUTO
+ || style()->overflowX() == OSCROLL
+ || this->isDocumentElement();
+}
+
void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// An empty viewport disables rendering.
@@ -239,6 +229,10 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
if (paintInfo.context->paintingDisabled())
return;
+ // SVG outlines are painted during PaintPhaseForeground.
+ if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline)
+ return;
+
// An empty viewBox also disables rendering.
// (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute)
SVGSVGElement* svg = toSVGSVGElement(node());
@@ -257,8 +251,9 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
PaintInfo childPaintInfo(paintInfo);
childPaintInfo.context->save();
- // Apply initial viewport clip - not affected by overflow handling
- childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion)));
+ // Apply initial viewport clip
+ if (shouldApplyViewportClip())
+ childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset)));
// Convert from container offsets (html renderers) to a relative transform (svg renderers).
// Transform from our paint container's coordinate system to our local coords.
@@ -292,13 +287,22 @@ void RenderSVGRoot::willBeDestroyed()
void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout)
+ if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
+ if (diff.needsRepaint()) {
+ // Box decorations may have appeared/disappeared - recompute status.
+ m_hasBoxDecorations = calculateHasBoxDecorations();
+ }
RenderReplaced::styleDidChange(diff, oldStyle);
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
+bool RenderSVGRoot::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isSVG() && !(child->isSVGInline() || child->isSVGInlineText());
+}
+
void RenderSVGRoot::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderReplaced::addChild(child, beforeChild);
@@ -330,12 +334,13 @@ void RenderSVGRoot::buildLocalToBorderBoxTransform()
SVGSVGElement* svg = toSVGSVGElement(node());
ASSERT(svg);
float scale = style()->effectiveZoom();
- SVGPoint translate = svg->currentTranslate();
+ FloatPoint translate = svg->currentTranslate();
LayoutSize borderAndPadding(borderLeft() + paddingLeft(), borderTop() + paddingTop());
m_localToBorderBoxTransform = svg->viewBoxToViewTransform(contentWidth() / scale, contentHeight() / scale);
- if (borderAndPadding.isEmpty() && scale == 1 && translate == SVGPoint::zero())
+ AffineTransform viewToBorderBoxTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y());
+ if (viewToBorderBoxTransform.isIdentity())
return;
- m_localToBorderBoxTransform = AffineTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()) * m_localToBorderBoxTransform;
+ m_localToBorderBoxTransform = viewToBorderBoxTransform * m_localToBorderBoxTransform;
}
const AffineTransform& RenderSVGRoot::localToParentTransform() const
@@ -349,23 +354,53 @@ const AffineTransform& RenderSVGRoot::localToParentTransform() const
return m_localToParentTransform;
}
-LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderSVGRoot::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+ // This is an open-coded aggregate of SVGRenderSupport::clippedOverflowRectForPaintInvalidation,
+ // RenderSVGRoot::computeFloatRectForPaintInvalidation and RenderReplaced::clippedOverflowRectForPaintInvalidation.
+ // The reason for this is to optimize/minimize the repaint rect when the box is not "decorated"
+ // (does not have background/border/etc.)
+
+ // Return early for any cases where we don't actually paint.
+ if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+ return LayoutRect();
+
+ // Compute the repaint rect of the content of the SVG in the border-box coordinate space.
+ FloatRect contentRepaintRect = paintInvalidationRectInLocalCoordinates();
+ contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect);
+
+ // Apply initial viewport clip, overflow:visible content is added to visualOverflow
+ // but the most common case is that overflow is hidden, so always intersect.
+ contentRepaintRect.intersect(pixelSnappedBorderBoxRect());
+
+ LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect);
+ // If the box is decorated or is overflowing, extend it to include the border-box and overflow.
+ if (m_hasBoxDecorations || hasRenderOverflow()) {
+ // The selectionRect can project outside of the overflowRect, so take their union
+ // for repainting to avoid selection painting glitches.
+ LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect());
+ repaintRect.unite(decoratedRepaintRect);
+ }
+
+ // Compute the repaint rect in the parent coordinate space.
+ LayoutRect rect = enclosingIntRect(repaintRect);
+ RenderReplaced::mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect);
+ return rect;
}
-void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+void RenderSVGRoot::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
{
// Apply our local transforms (except for x/y translation), then our shadow,
// and then call RenderBox's method to handle all the normal CSS Box model bits
- repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect);
+ paintInvalidationRect = m_localToBorderBoxTransform.mapRect(paintInvalidationRect);
- // Apply initial viewport clip - not affected by overflow settings
- repaintRect.intersect(pixelSnappedBorderBoxRect());
+ // Apply initial viewport clip
+ if (shouldApplyViewportClip())
+ paintInvalidationRect.intersect(pixelSnappedBorderBoxRect());
- LayoutRect rect = enclosingIntRect(repaintRect);
- RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed);
- repaintRect = rect;
+ LayoutRect rect = enclosingIntRect(paintInvalidationRect);
+ RenderReplaced::mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, fixed);
+ paintInvalidationRect = rect;
}
// This method expects local CSS box coordinates.
@@ -374,7 +409,9 @@ void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* rep
void RenderSVGRoot::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
{
ASSERT(mode & ~IsFixed); // We should have no fixed content in the SVG rendering tree.
- ASSERT(mode & UseTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
+ // We used to have this ASSERT here, but we removed it when enabling layer squashing.
+ // See http://crbug.com/364901
+ // ASSERT(mode & UseTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
RenderReplaced::mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
}
@@ -388,7 +425,6 @@ void RenderSVGRoot::updateCachedBoundaries()
{
SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
- m_repaintBoundingBox.inflate(borderAndPaddingWidth());
}
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
@@ -412,11 +448,11 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
}
// If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit.
- if (hitTestAction == HitTestBlockBackground && visibleToHitTestRequest(request)) {
- // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase,
- // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need
- // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able
- // to detect these hits anymore.
+ if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && visibleToHitTestRequest(request)) {
+ // Only return true here, if the last hit testing phase 'BlockBackground' (or 'ChildBlockBackground' - depending on context) is executed.
+ // If we'd return true in the 'Foreground' phase, hit testing would stop immediately. For SVG only trees this doesn't matter.
+ // Though when we have a <foreignObject> subtree we need to be able to detect hits on the background of a <div> element.
+ // If we'd return true here in the 'Foreground' phase, we are not able to detect these hits anymore.
LayoutRect boundsRect(accumulatedOffset + location(), size());
if (locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, pointInBorderBox);
@@ -428,27 +464,4 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
return false;
}
-bool RenderSVGRoot::hasRelativeDimensions() const
-{
- SVGSVGElement* svg = toSVGSVGElement(node());
- ASSERT(svg);
-
- return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent() || svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
-bool RenderSVGRoot::hasRelativeIntrinsicLogicalWidth() const
-{
- SVGSVGElement* svg = toSVGSVGElement(node());
- ASSERT(svg);
- return svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
-bool RenderSVGRoot::hasRelativeLogicalHeight() const
-{
- SVGSVGElement* svg = toSVGSVGElement(node());
- ASSERT(svg);
-
- return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h
index f907222eb81..b38d51cbde8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h
@@ -24,12 +24,10 @@
#define RenderSVGRoot_h
#include "core/rendering/RenderReplaced.h"
-#include "core/rendering/svg/SVGRenderSupport.h"
#include "platform/geometry/FloatRect.h"
namespace WebCore {
-class AffineTransform;
class SVGElement;
class RenderSVGRoot FINAL : public RenderReplaced {
@@ -40,66 +38,77 @@ public:
bool isEmbeddedThroughSVGImage() const;
bool isEmbeddedThroughFrameContainingSVGDocument() const;
- virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+ virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const OVERRIDE;
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderSVGRoot, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
- virtual void setNeedsBoundariesUpdate() { m_needsBoundariesOrTransformUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesOrTransformUpdate; }
- virtual void setNeedsTransformUpdate() { m_needsBoundariesOrTransformUpdate = true; }
+ virtual void setNeedsBoundariesUpdate() OVERRIDE { m_needsBoundariesOrTransformUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsBoundariesOrTransformUpdate = true; }
IntSize containerSize() const { return m_containerSize; }
- void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; }
-
- virtual bool hasRelativeDimensions() const OVERRIDE;
- virtual bool hasRelativeIntrinsicLogicalWidth() const OVERRIDE;
- virtual bool hasRelativeLogicalHeight() const OVERRIDE;
+ void setContainerSize(const IntSize& containerSize)
+ {
+ // SVGImage::draw() does a view layout prior to painting,
+ // and we need that layout to know of the new size otherwise
+ // the rendering may be incorrectly using the old size.
+ if (m_containerSize != containerSize)
+ setNeedsLayoutAndFullPaintInvalidation();
+ m_containerSize = containerSize;
+ }
// localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates.
const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; }
private:
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ virtual RenderObjectChildList* virtualChildren() OVERRIDE { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const OVERRIDE { return children(); }
- virtual bool isSVGRoot() const { return true; }
- virtual const char* renderName() const { return "RenderSVGRoot"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGRoot"; }
+ virtual bool isSVGRoot() const OVERRIDE { return true; }
+ virtual bool isSVG() const OVERRIDE { return true; }
virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const OVERRIDE;
- virtual LayoutUnit computeReplacedLogicalHeight() const;
- virtual void layout();
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+ virtual LayoutUnit computeReplacedLogicalHeight() const OVERRIDE;
+ virtual void layout() OVERRIDE;
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual void willBeDestroyed();
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void willBeDestroyed() OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
virtual void removeChild(RenderObject*) OVERRIDE;
+ virtual bool canHaveWhitespaceChildren() const OVERRIDE { return false; }
virtual void insertedIntoTree() OVERRIDE;
virtual void willBeRemovedFromTree() OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const;
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return m_objectBoundingBox; }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return m_strokeBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return m_repaintBoundingBox; }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const OVERRIDE;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const OVERRIDE;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual bool canBeSelectionLeaf() const { return false; }
- virtual bool canHaveChildren() const { return true; }
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return false; }
+ virtual bool canHaveChildren() const OVERRIDE { return true; }
+ bool shouldApplyViewportClip() const;
void updateCachedBoundaries();
void buildLocalToBorderBoxTransform();
@@ -113,6 +122,7 @@ private:
AffineTransform m_localToBorderBoxTransform;
bool m_isLayoutSizeChanged : 1;
bool m_needsBoundariesOrTransformUpdate : 1;
+ bool m_hasBoxDecorations : 1;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderSVGRoot, isSVGRoot());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp
index 04298f7e49d..dfd09e70aef 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp
@@ -26,17 +26,16 @@
*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGShape.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestRequest.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/PointerEventsHitRules.h"
#include "core/rendering/svg/RenderSVGResourceMarker.h"
#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
#include "core/rendering/svg/SVGPathData.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
@@ -63,7 +62,7 @@ void RenderSVGShape::updateShapeFromElement()
{
m_path.clear();
m_path = adoptPtr(new Path);
- ASSERT(RenderSVGShape::isEmpty());
+ ASSERT(RenderSVGShape::isShapeEmpty());
updatePathFromGraphicsElement(toSVGGraphicsElement(element()), path());
processMarkerPositions();
@@ -72,11 +71,6 @@ void RenderSVGShape::updateShapeFromElement()
m_strokeBoundingBox = calculateStrokeBoundingBox();
}
-bool RenderSVGShape::isEmpty() const
-{
- return path().isEmpty();
-}
-
void RenderSVGShape::fillShape(GraphicsContext* context) const
{
context->fillPath(path());
@@ -119,8 +113,8 @@ bool RenderSVGShape::fillContains(const FloatPoint& point, bool requiresFill, co
if (!m_fillBoundingBox.contains(point))
return false;
- Color fallbackColor;
- if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), fallbackColor))
+ bool hasFallback;
+ if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), hasFallback))
return false;
return shapeDependentFillContains(point, fillRule);
@@ -131,8 +125,8 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
if (!strokeBoundingBox().contains(point))
return false;
- Color fallbackColor;
- if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), fallbackColor))
+ bool hasFallback;
+ if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), hasFallback))
return false;
return shapeDependentStrokeContains(point);
@@ -140,7 +134,6 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
void RenderSVGShape::layout()
{
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout());
bool updateCachedBoundariesInParents = false;
@@ -201,7 +194,7 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const
if (!style()->svgStyle()->hasMarkers())
return false;
- if (!toSVGGraphicsElement(element())->supportsMarkers())
+ if (!SVGResources::supportsMarkers(*toSVGGraphicsElement(element())))
return false;
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
@@ -213,13 +206,12 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const
void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context)
{
- Color fallbackColor;
- if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) {
- if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode))
+ bool hasFallback;
+ if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, hasFallback)) {
+ if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode)) {
fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
- else if (fallbackColor.isValid()) {
+ } else if (hasFallback) {
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
if (fallbackResource->applyResource(this, style, context, ApplyToFillMode))
fallbackResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
}
@@ -228,13 +220,12 @@ void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context)
void RenderSVGShape::strokeShape(RenderStyle* style, GraphicsContext* context)
{
- Color fallbackColor;
- if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor)) {
- if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode))
+ bool hasFallback;
+ if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, hasFallback)) {
+ if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode)) {
strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
- else if (fallbackColor.isValid()) {
+ } else if (hasFallback) {
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode))
fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
}
@@ -244,68 +235,67 @@ void RenderSVGShape::strokeShape(RenderStyle* style, GraphicsContext* context)
void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
-
- if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || isEmpty())
+ if (paintInfo.context->paintingDisabled()
+ || paintInfo.phase != PaintPhaseForeground
+ || style()->visibility() == HIDDEN
+ || isShapeEmpty())
return;
- FloatRect boundingBox = repaintRectInLocalCoordinates();
+
+ FloatRect boundingBox = paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
return;
PaintInfo childPaintInfo(paintInfo);
- bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
- if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
- childPaintInfo.applyTransform(m_localTransform);
-
- if (childPaintInfo.phase == PaintPhaseForeground) {
- SVGRenderingContext renderingContext(this, childPaintInfo);
-
- if (renderingContext.isRenderingPrepared()) {
- const SVGRenderStyle* svgStyle = style()->svgStyle();
- if (svgStyle->shapeRendering() == SR_CRISPEDGES)
- childPaintInfo.context->setShouldAntialias(false);
-
- for (int i = 0; i < 3; i++) {
- switch (svgStyle->paintOrderType(i)) {
- case PT_FILL:
- fillShape(this->style(), childPaintInfo.context);
- break;
- case PT_STROKE:
- if (svgStyle->hasVisibleStroke()) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
- AffineTransform nonScalingTransform;
-
- if (hasNonScalingStroke()) {
- AffineTransform nonScalingTransform = nonScalingStrokeTransform();
- if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
- return;
- }
-
- strokeShape(this->style(), childPaintInfo.context);
- }
- break;
- case PT_MARKERS:
- if (!m_markerPositions.isEmpty())
- drawMarkers(childPaintInfo);
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
+
+ GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+ childPaintInfo.applyTransform(m_localTransform);
+
+ SVGRenderingContext renderingContext(this, childPaintInfo);
+
+ if (renderingContext.isRenderingPrepared()) {
+ const SVGRenderStyle* svgStyle = style()->svgStyle();
+ if (svgStyle->shapeRendering() == SR_CRISPEDGES)
+ childPaintInfo.context->setShouldAntialias(false);
+
+ for (int i = 0; i < 3; i++) {
+ switch (svgStyle->paintOrderType(i)) {
+ case PT_FILL:
+ fillShape(this->style(), childPaintInfo.context);
+ break;
+ case PT_STROKE:
+ if (svgStyle->hasVisibleStroke()) {
+ GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
+ AffineTransform nonScalingTransform;
+
+ if (hasNonScalingStroke()) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
+ return;
}
+
+ strokeShape(this->style(), childPaintInfo.context);
}
+ break;
+ case PT_MARKERS:
+ if (!m_markerPositions.isEmpty())
+ drawMarkers(childPaintInfo);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
}
}
-
- if (drawsOutline)
- paintOutline(childPaintInfo, IntRect(boundingBox));
}
+
+ if (style()->outlineWidth())
+ paintOutline(childPaintInfo, IntRect(boundingBox));
}
// This method is called from inside paintOutline() since we call paintOutline()
// while transformed to our coord system, return local coords
void RenderSVGShape::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
- IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates());
+ IntRect rect = enclosingIntRect(paintInvalidationRectInLocalCoordinates());
if (!rect.isEmpty())
rects.append(rect);
}
@@ -417,7 +407,7 @@ FloatRect RenderSVGShape::calculateStrokeBoundingBox() const
void RenderSVGShape::updateRepaintBoundingBox()
{
m_repaintBoundingBox = strokeBoundingBox();
- if (strokeWidth() < 1.0f)
+ if (strokeWidth() < 1.0f && !m_repaintBoundingBox.isEmpty())
m_repaintBoundingBox.inflate(1);
SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
}
@@ -425,13 +415,13 @@ void RenderSVGShape::updateRepaintBoundingBox()
float RenderSVGShape::strokeWidth() const
{
SVGLengthContext lengthContext(element());
- return style()->svgStyle()->strokeWidth().value(lengthContext);
+ return style()->svgStyle()->strokeWidth()->value(lengthContext);
}
bool RenderSVGShape::hasSmoothStroke() const
{
const SVGRenderStyle* svgStyle = style()->svgStyle();
- return svgStyle->strokeDashArray().isEmpty()
+ return svgStyle->strokeDashArray()->isEmpty()
&& svgStyle->strokeMiterLimit() == svgStyle->initialStrokeMiterLimit()
&& svgStyle->joinStyle() == svgStyle->initialJoinStyle()
&& svgStyle->capStyle() == svgStyle->initialCapStyle();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h
index f800b2db555..12a703f063b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h
@@ -38,9 +38,6 @@ namespace WebCore {
class FloatPoint;
class GraphicsContextStateSaver;
class PointerEventsHitRules;
-class RenderSVGContainer;
-class RenderSVGPath;
-class RenderSVGResource;
class SVGGraphicsElement;
class RenderSVGShape : public RenderSVGModelObject {
@@ -51,7 +48,6 @@ public:
void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
virtual void setNeedsBoundariesUpdate() OVERRIDE FINAL { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE FINAL { return m_needsBoundariesUpdate; }
virtual void setNeedsTransformUpdate() OVERRIDE FINAL { m_needsTransformUpdate = true; }
virtual void fillShape(GraphicsContext*) const;
virtual void strokeShape(GraphicsContext*) const;
@@ -66,7 +62,7 @@ public:
protected:
virtual void updateShapeFromElement();
- virtual bool isEmpty() const;
+ virtual bool isShapeEmpty() const { return path().isEmpty(); }
virtual bool shapeDependentStrokeContains(const FloatPoint&);
virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
float strokeWidth() const;
@@ -85,12 +81,12 @@ private:
bool fillContains(const FloatPoint&, bool requiresFill = true, const WindRule fillRule = RULE_NONZERO);
bool strokeContains(const FloatPoint&, bool requiresStroke = true);
- virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
virtual const AffineTransform& localToParentTransform() const OVERRIDE FINAL { return m_localTransform; }
virtual AffineTransform localTransform() const OVERRIDE FINAL { return m_localTransform; }
virtual bool isSVGShape() const OVERRIDE FINAL { return true; }
- virtual const char* renderName() const { return "RenderSVGShape"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGShape"; }
virtual void layout() OVERRIDE FINAL;
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
@@ -116,7 +112,6 @@ private:
private:
FloatRect m_repaintBoundingBox;
- FloatRect m_repaintBoundingBoxExcludingShadow;
AffineTransform m_localTransform;
OwnPtr<Path> m_path;
Vector<MarkerPosition> m_markerPositions;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp
index 5f34538620b..30c06454d59 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp
@@ -24,6 +24,9 @@
#include "core/rendering/svg/RenderSVGTSpan.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGAltGlyphElement.h"
+
namespace WebCore {
RenderSVGTSpan::RenderSVGTSpan(Element* element)
@@ -31,4 +34,20 @@ RenderSVGTSpan::RenderSVGTSpan(Element* element)
{
}
+bool RenderSVGTSpan::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ // Always allow text (except empty textnodes and <br>).
+ if (child->isText())
+ return SVGRenderSupport::isRenderableTextNode(child);
+
+#if ENABLE(SVG_FONTS)
+ // Only allow other types of children if this is not an 'altGlyph'.
+ ASSERT(node());
+ if (isSVGAltGlyphElement(*node()))
+ return false;
+#endif
+
+ return child->isSVGInline() && !child->isSVGTextPath();
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h
index ba8cb31e1e0..7875119a34f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h
@@ -28,7 +28,10 @@ namespace WebCore {
class RenderSVGTSpan FINAL : public RenderSVGInline {
public:
explicit RenderSVGTSpan(Element*);
- virtual const char* renderName() const { return "RenderSVGTSpan"; }
+
+ virtual bool isChildAllowed(RenderObject* child, RenderStyle*) const OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGTSpan"; }
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp
index ba45ce98f18..8536029524b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp
@@ -30,10 +30,11 @@
#include "core/rendering/HitTestRequest.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/PointerEventsHitRules.h"
#include "core/rendering/style/ShadowList.h"
+#include "core/rendering/svg/RenderSVGInline.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGResource.h"
#include "core/rendering/svg/RenderSVGRoot.h"
@@ -70,7 +71,7 @@ RenderSVGText::~RenderSVGText()
bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const
{
- return child->isInline() && !SVGRenderSupport::isEmptySVGInlineText(child);
+ return child->isSVGInline() || (child->isText() && SVGRenderSupport::isRenderableTextNode(child));
}
RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start)
@@ -93,33 +94,13 @@ const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObje
return toRenderSVGText(start);
}
-LayoutRect RenderSVGText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
-{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
-}
-
-void RenderSVGText::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+void RenderSVGText::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, bool fixed) const
{
FloatRect repaintRect = rect;
- computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+ computeFloatRectForPaintInvalidation(paintInvalidationContainer, repaintRect, fixed);
rect = enclosingLayoutRect(repaintRect);
}
-void RenderSVGText::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
-{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
-}
-
-void RenderSVGText::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
-{
- SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
-}
-
-const RenderObject* RenderSVGText::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
-{
- return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
-}
-
static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes)
{
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
@@ -128,14 +109,15 @@ static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLay
}
}
-static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGInlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
+static inline bool findPreviousAndNextAttributes(RenderSVGText* root, RenderSVGInlineText* locateElement, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
{
- ASSERT(start);
+ ASSERT(root);
ASSERT(locateElement);
- // FIXME: Make this iterative.
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- RenderSVGInlineText* text = toRenderSVGInlineText(child);
+ bool stopAfterNext = false;
+ RenderObject* current = root->firstChild();
+ while (current) {
+ if (current->isSVGInlineText()) {
+ RenderSVGInlineText* text = toRenderSVGInlineText(current);
if (locateElement != text) {
if (stopAfterNext) {
next = text->layoutAttributes();
@@ -143,20 +125,19 @@ static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGI
}
previous = text->layoutAttributes();
+ } else {
+ stopAfterNext = true;
+ }
+ } else if (current->isSVGInline()) {
+ // Descend into text content (if possible).
+ if (RenderObject* child = toRenderSVGInline(current)->firstChild()) {
+ current = child;
continue;
}
-
- stopAfterNext = true;
- continue;
}
- if (!child->isSVGInline())
- continue;
-
- if (findPreviousAndNextAttributes(child, locateElement, stopAfterNext, previous, next))
- return true;
+ current = current->nextInPreOrderAfterChildren(root);
}
-
return false;
}
@@ -201,11 +182,10 @@ void RenderSVGText::subtreeChildWasAdded(RenderObject* child)
attributes = newLayoutAttributes[i];
if (m_layoutAttributes.find(attributes) == kNotFound) {
// Every time this is invoked, there's only a single new entry in the newLayoutAttributes list, compared to the old in m_layoutAttributes.
- bool stopAfterNext = false;
SVGTextLayoutAttributes* previous = 0;
SVGTextLayoutAttributes* next = 0;
ASSERT_UNUSED(child, attributes->context() == child);
- findPreviousAndNextAttributes(this, attributes->context(), stopAfterNext, previous, next);
+ findPreviousAndNextAttributes(this, attributes->context(), previous, next);
if (previous)
m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(previous->context());
@@ -258,11 +238,10 @@ void RenderSVGText::subtreeChildWillBeRemoved(RenderObject* child, Vector<SVGTex
// This logic requires that the 'text' child is still inserted in the tree.
RenderSVGInlineText* text = toRenderSVGInlineText(child);
- bool stopAfterNext = false;
SVGTextLayoutAttributes* previous = 0;
SVGTextLayoutAttributes* next = 0;
if (!documentBeingDestroyed())
- findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next);
+ findPreviousAndNextAttributes(this, text, previous, next);
if (previous)
affectedAttributes.append(previous);
@@ -288,9 +267,8 @@ void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*
m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(affectedAttributes[i]->context());
}
-void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
+void RenderSVGText::subtreeStyleDidChange()
{
- ASSERT(text);
if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
return;
@@ -299,7 +277,7 @@ void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
// Only update the metrics cache, but not the text positioning element cache
// nor the layout attributes cached in the leaf #text renderers.
FontCachePurgePreventer fontCachePurgePreventer;
- for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
+ for (RenderObject* descendant = firstChild(); descendant; descendant = descendant->nextInPreOrder(this)) {
if (descendant->isSVGInlineText())
m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGInlineText(descendant));
}
@@ -344,7 +322,9 @@ static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayout
void RenderSVGText::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
+
+ subtreeStyleDidChange();
+
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this));
bool updateCachedBoundariesInParents = false;
@@ -408,7 +388,16 @@ void RenderSVGText::layout()
// FIXME: We need to find a way to only layout the child boxes, if needed.
FloatRect oldBoundaries = objectBoundingBox();
ASSERT(childrenInline());
- forceLayoutInlineChildren();
+
+ rebuildFloatsFromIntruding();
+
+ LayoutUnit beforeEdge = borderBefore() + paddingBefore();
+ LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+ setLogicalHeight(beforeEdge);
+
+ LayoutUnit repaintLogicalTop = 0;
+ LayoutUnit repaintLogicalBottom = 0;
+ layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom, afterEdge);
if (m_needsReordering)
m_needsReordering = false;
@@ -430,7 +419,7 @@ void RenderSVGText::layout()
RootInlineBox* RenderSVGText::createRootInlineBox()
{
- RootInlineBox* box = new SVGRootInlineBox(this);
+ RootInlineBox* box = new SVGRootInlineBox(*this);
box->setHasVirtualLogicalHeight();
return box;
}
@@ -458,12 +447,6 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul
return false;
}
-bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInContents)
{
RootInlineBox* rootBox = firstRootBox();
@@ -477,7 +460,7 @@ PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInC
if (!closestBox)
return createPositionWithAffinity(0, DOWNSTREAM);
- return closestBox->renderer()->positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
+ return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
}
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
@@ -491,14 +474,23 @@ void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
return;
if (paintInfo.phase != PaintPhaseForeground
- && paintInfo.phase != PaintPhaseSelfOutline
&& paintInfo.phase != PaintPhaseSelection)
return;
PaintInfo blockInfo(paintInfo);
- GraphicsContextStateSaver stateSaver(*blockInfo.context);
- blockInfo.applyTransform(localToParentTransform());
+ GraphicsContextStateSaver stateSaver(*blockInfo.context, false);
+ const AffineTransform& localTransform = localToParentTransform();
+ if (!localTransform.isIdentity()) {
+ stateSaver.save();
+ blockInfo.applyTransform(localTransform, false);
+ }
RenderBlock::paint(blockInfo, LayoutPoint());
+
+ // Paint the outlines, if any
+ if (paintInfo.phase == PaintPhaseForeground) {
+ blockInfo.phase = PaintPhaseSelfOutline;
+ RenderBlock::paint(blockInfo, LayoutPoint());
+ }
}
FloatRect RenderSVGText::strokeBoundingBox() const
@@ -511,11 +503,11 @@ FloatRect RenderSVGText::strokeBoundingBox() const
ASSERT(node());
ASSERT(node()->isSVGElement());
SVGLengthContext lengthContext(toSVGElement(node()));
- strokeBoundaries.inflate(svgStyle->strokeWidth().value(lengthContext));
+ strokeBoundaries.inflate(svgStyle->strokeWidth()->value(lengthContext));
return strokeBoundaries;
}
-FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
+FloatRect RenderSVGText::paintInvalidationRectInLocalCoordinates() const
{
FloatRect repaintRect = strokeBoundingBox();
SVGRenderSupport::intersectRepaintRectWithResources(this, repaintRect);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h
index 56fb0db8e49..dfac5394a68 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h
@@ -37,12 +37,12 @@ public:
explicit RenderSVGText(SVGTextElement*);
virtual ~RenderSVGText();
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; }
- virtual FloatRect repaintRectInLocalCoordinates() const;
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE;
static RenderSVGText* locateRenderSVGTextAncestor(RenderObject*);
static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject*);
@@ -53,42 +53,35 @@ public:
void subtreeChildWasAdded(RenderObject*);
void subtreeChildWillBeRemoved(RenderObject*, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
void subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
- void subtreeStyleDidChange(RenderSVGInlineText*);
+ void subtreeStyleDidChange();
void subtreeTextDidChange(RenderSVGInlineText*);
private:
- virtual const char* renderName() const { return "RenderSVGText"; }
- virtual bool isSVGText() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGText"; }
+ virtual bool isSVGText() const OVERRIDE { return true; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
+ virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
- virtual bool requiresLayer() const { return false; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
virtual void removeChild(RenderObject*) OVERRIDE;
virtual void willBeDestroyed() OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return frameRect(); }
- virtual FloatRect strokeBoundingBox() const;
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return frameRect(); }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
- virtual AffineTransform localTransform() const { return m_localTransform; }
- virtual RootInlineBox* createRootInlineBox();
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localTransform; }
+ virtual RootInlineBox* createRootInlineBox() OVERRIDE;
- virtual RenderBlock* firstLineBlock() const;
- virtual void updateFirstLetter();
+ virtual RenderBlock* firstLineBlock() const OVERRIDE;
+ virtual void updateFirstLetter() OVERRIDE;
bool shouldHandleSubtreeMutations() const;
@@ -96,7 +89,6 @@ private:
bool m_needsPositioningValuesUpdate : 1;
bool m_needsTransformUpdate : 1;
bool m_needsTextMetricsUpdate : 1;
- AffineTransform m_localTransform;
SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder;
Vector<SVGTextLayoutAttributes*> m_layoutAttributes;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp
index aec2da5ac29..f9deafa7276 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp
@@ -21,8 +21,8 @@
#include "core/rendering/svg/RenderSVGTextPath.h"
-#include "SVGNames.h"
#include "core/rendering/svg/SVGPathData.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/svg/SVGPathElement.h"
#include "core/svg/SVGTextPathElement.h"
@@ -33,30 +33,45 @@ RenderSVGTextPath::RenderSVGTextPath(Element* element)
{
}
+bool RenderSVGTextPath::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ if (child->isText())
+ return SVGRenderSupport::isRenderableTextNode(child);
+
+#if ENABLE(SVG_FONTS)
+ // 'altGlyph' is supported by the content model for 'textPath', but...
+ ASSERT(child->node());
+ if (isSVGAltGlyphElement(*child->node()))
+ return false;
+#endif
+
+ return child->isSVGInline() && !child->isSVGTextPath();
+}
+
Path RenderSVGTextPath::layoutPath() const
{
SVGTextPathElement* textPathElement = toSVGTextPathElement(node());
- Element* targetElement = SVGURIReference::targetElementFromIRIString(textPathElement->hrefCurrentValue(), textPathElement->document());
- if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag))
+ Element* targetElement = SVGURIReference::targetElementFromIRIString(textPathElement->href()->currentValue()->value(), textPathElement->treeScope());
+ if (!isSVGPathElement(targetElement))
return Path();
- SVGPathElement* pathElement = toSVGPathElement(targetElement);
+ SVGPathElement& pathElement = toSVGPathElement(*targetElement);
Path pathData;
- updatePathFromGraphicsElement(pathElement, pathData);
+ updatePathFromGraphicsElement(&pathElement, pathData);
// Spec: The transform attribute on the referenced 'path' element represents a
// supplemental transformation relative to the current user coordinate system for
// the current 'text' element, including any adjustments to the current user coordinate
// system due to a possible transform attribute on the current 'text' element.
// http://www.w3.org/TR/SVG/text.html#TextPathElement
- pathData.transform(pathElement->animatedLocalTransform());
+ pathData.transform(pathElement.animatedLocalTransform());
return pathData;
}
float RenderSVGTextPath::startOffset() const
{
- return toSVGTextPathElement(node())->startOffsetCurrentValue().valueAsPercentage();
+ return toSVGTextPathElement(node())->startOffset()->currentValue()->valueAsPercentage();
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h
index 6e14b5528f6..6d98871341f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h
@@ -32,10 +32,12 @@ public:
Path layoutPath() const;
float startOffset() const;
- virtual bool isSVGTextPath() const { return true; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+ virtual bool isSVGTextPath() const OVERRIDE { return true; }
private:
- virtual const char* renderName() const { return "RenderSVGTextPath"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGTextPath"; }
Path m_layoutPath;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
index 52516c4c268..841bec55ec1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
@@ -23,8 +23,8 @@
#include "core/rendering/svg/RenderSVGTransformableContainer.h"
-#include "SVGNames.h"
#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGGElement.h"
#include "core/svg/SVGGraphicsElement.h"
#include "core/svg/SVGUseElement.h"
@@ -37,25 +37,60 @@ RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElem
{
}
+static bool hasValidPredecessor(const Node* node)
+{
+ ASSERT(node);
+ while ((node = node->previousSibling())) {
+ if (node->isSVGElement() && toSVGElement(node)->isValid())
+ return true;
+ }
+ return false;
+}
+
+bool RenderSVGTransformableContainer::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+ ASSERT(element());
+ if (isSVGSwitchElement(*element())) {
+ Node* node = child->node();
+ // Reject non-SVG/non-valid elements.
+ if (!node->isSVGElement() || !toSVGElement(node)->isValid())
+ return false;
+ // Reject this child if it isn't the first valid node.
+ if (hasValidPredecessor(node))
+ return false;
+ } else if (isSVGAElement(*element())) {
+ // http://www.w3.org/2003/01/REC-SVG11-20030114-errata#linking-text-environment
+ // The 'a' element may contain any element that its parent may contain, except itself.
+ if (isSVGAElement(*child->node()))
+ return false;
+ if (parent() && parent()->isSVG())
+ return parent()->isChildAllowed(child, style);
+ }
+ return RenderSVGContainer::isChildAllowed(child, style);
+}
+
bool RenderSVGTransformableContainer::calculateLocalTransform()
{
SVGGraphicsElement* element = toSVGGraphicsElement(this->element());
+ ASSERT(element);
// If we're either the renderer for a <use> element, or for any <g> element inside the shadow
// tree, that was created during the use/symbol/svg expansion in SVGUseElement. These containers
// need to respect the translations induced by their corresponding use elements x/y attributes.
SVGUseElement* useElement = 0;
- if (element->hasTagName(SVGNames::useTag))
+ if (isSVGUseElement(*element)) {
useElement = toSVGUseElement(element);
- else if (element->isInShadowTree() && element->hasTagName(SVGNames::gTag)) {
+ } else if (isSVGGElement(*element) && toSVGGElement(element)->inUseShadowTree()) {
SVGElement* correspondingElement = element->correspondingElement();
- if (correspondingElement && correspondingElement->hasTagName(SVGNames::useTag))
+ if (isSVGUseElement(correspondingElement))
useElement = toSVGUseElement(correspondingElement);
}
if (useElement) {
SVGLengthContext lengthContext(useElement);
- FloatSize translation(useElement->xCurrentValue().value(lengthContext), useElement->yCurrentValue().value(lengthContext));
+ FloatSize translation(
+ useElement->x()->currentValue()->value(lengthContext),
+ useElement->y()->currentValue()->value(lengthContext));
if (translation != m_lastTranslation)
m_needsTransformUpdate = true;
m_lastTranslation = translation;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h
index 6aa752aa95d..4b03d8a330d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h
@@ -30,14 +30,16 @@ class RenderSVGTransformableContainer FINAL : public RenderSVGContainer {
public:
explicit RenderSVGTransformableContainer(SVGGraphicsElement*);
- virtual bool isSVGTransformableContainer() const { return true; }
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
- virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+ virtual bool isSVGTransformableContainer() const OVERRIDE { return true; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localTransform; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
+ virtual bool didTransformToRootUpdate() OVERRIDE { return m_didTransformToRootUpdate; }
private:
- virtual bool calculateLocalTransform();
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual bool calculateLocalTransform() OVERRIDE;
+ virtual AffineTransform localTransform() const OVERRIDE { return m_localTransform; }
bool m_needsTransformUpdate : 1;
bool m_didTransformToRootUpdate : 1;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
index 05234c18b57..4b4d3d5d4c3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
@@ -21,11 +21,10 @@
*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGViewportContainer.h"
-#include "SVGNames.h"
-#include "core/svg/SVGElementInstance.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/svg/SVGSVGElement.h"
#include "core/svg/SVGUseElement.h"
#include "platform/graphics/GraphicsContext.h"
@@ -42,7 +41,8 @@ RenderSVGViewportContainer::RenderSVGViewportContainer(SVGElement* node)
void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
{
- if (!element()->hasTagName(SVGNames::svgTag))
+ ASSERT(element());
+ if (!isSVGSVGElement(*element()))
return;
m_isLayoutSizeChanged = toSVGSVGElement(element())->hasRelativeLengths() && selfNeedsLayout();
@@ -57,59 +57,14 @@ void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
void RenderSVGViewportContainer::calcViewport()
{
SVGElement* element = this->element();
- if (!element->hasTagName(SVGNames::svgTag))
+ ASSERT(element);
+ if (!isSVGSVGElement(*element))
return;
SVGSVGElement* svg = toSVGSVGElement(element);
FloatRect oldViewport = m_viewport;
SVGLengthContext lengthContext(element);
- m_viewport = FloatRect(svg->xCurrentValue().value(lengthContext), svg->yCurrentValue().value(lengthContext), svg->widthCurrentValue().value(lengthContext), svg->heightCurrentValue().value(lengthContext));
-
- SVGElement* correspondingElement = svg->correspondingElement();
- if (correspondingElement && svg->isInShadowTree()) {
- const HashSet<SVGElementInstance*>& instances = correspondingElement->instancesForElement();
- ASSERT(!instances.isEmpty());
-
- SVGUseElement* useElement = 0;
- const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
- for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
- const SVGElementInstance* instance = (*it);
- ASSERT(instance->correspondingElement()->hasTagName(SVGNames::svgTag) || instance->correspondingElement()->hasTagName(SVGNames::symbolTag));
- if (instance->shadowTreeElement() == svg) {
- ASSERT(correspondingElement == instance->correspondingElement());
- useElement = instance->directUseElement();
- if (!useElement)
- useElement = instance->correspondingUseElement();
- break;
- }
- }
-
- ASSERT(useElement);
- bool isSymbolElement = correspondingElement->hasTagName(SVGNames::symbolTag);
-
- // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
- // If attributes width and/or height are provided on the 'use' element, then these attributes
- // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
- // the generated 'svg' element will use values of 100% for these attributes.
-
- // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
- // values will override the corresponding attributes on the 'svg' in the generated tree.
-
- SVGLengthContext lengthContext(element);
- if (useElement->hasAttribute(SVGNames::widthAttr))
- m_viewport.setWidth(useElement->widthCurrentValue().value(lengthContext));
- else if (isSymbolElement && svg->hasAttribute(SVGNames::widthAttr)) {
- SVGLength containerWidth(LengthModeWidth, "100%");
- m_viewport.setWidth(containerWidth.value(lengthContext));
- }
-
- if (useElement->hasAttribute(SVGNames::heightAttr))
- m_viewport.setHeight(useElement->heightCurrentValue().value(lengthContext));
- else if (isSymbolElement && svg->hasAttribute(SVGNames::heightAttr)) {
- SVGLength containerHeight(LengthModeHeight, "100%");
- m_viewport.setHeight(containerHeight.value(lengthContext));
- }
- }
+ m_viewport = FloatRect(svg->x()->currentValue()->value(lengthContext), svg->y()->currentValue()->value(lengthContext), svg->width()->currentValue()->value(lengthContext), svg->height()->currentValue()->value(lengthContext));
if (oldViewport != m_viewport) {
setNeedsBoundariesUpdate();
@@ -130,7 +85,8 @@ bool RenderSVGViewportContainer::calculateLocalTransform()
AffineTransform RenderSVGViewportContainer::viewportTransform() const
{
- if (element()->hasTagName(SVGNames::svgTag)) {
+ ASSERT(element());
+ if (isSVGSVGElement(*element())) {
SVGSVGElement* svg = toSVGSVGElement(element());
return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
}
@@ -149,11 +105,10 @@ bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& poi
void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
+ ASSERT(element());
// An empty viewBox disables rendering.
- if (element()->hasTagName(SVGNames::svgTag)) {
- if (toSVGSVGElement(element())->hasEmptyViewBox())
- return;
- }
+ if (isSVGSVGElement(*element()) && toSVGSVGElement(*element()).hasEmptyViewBox())
+ return;
RenderSVGContainer::paint(paintInfo, paintOffset);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h
index b1b79ed5e31..679bd051dc7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h
@@ -35,25 +35,25 @@ public:
FloatRect viewport() const { return m_viewport; }
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
- virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+ virtual bool didTransformToRootUpdate() OVERRIDE { return m_didTransformToRootUpdate; }
- virtual void determineIfLayoutSizeChanged();
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void determineIfLayoutSizeChanged() OVERRIDE;
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
private:
- virtual bool isSVGViewportContainer() const { return true; }
- virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+ virtual bool isSVGViewportContainer() const OVERRIDE { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGViewportContainer"; }
AffineTransform viewportTransform() const;
- virtual const AffineTransform& localToParentTransform() const { return m_localToParentTransform; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localToParentTransform; }
- virtual void calcViewport();
- virtual bool calculateLocalTransform();
+ virtual void calcViewport() OVERRIDE;
+ virtual bool calculateLocalTransform() OVERRIDE;
- virtual void applyViewportClip(PaintInfo&);
- virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent);
+ virtual void applyViewportClip(PaintInfo&) OVERRIDE;
+ virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent) OVERRIDE;
FloatRect m_viewport;
mutable AffineTransform m_localToParentTransform;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp
index c4f5cdb1203..d4a861c3db2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp
@@ -23,8 +23,6 @@
#include "config.h"
#include "core/rendering/svg/SVGInlineFlowBox.h"
-#include "core/dom/DocumentMarkerController.h"
-#include "core/dom/RenderedDocumentMarker.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/SVGInlineTextBox.h"
#include "core/rendering/svg/SVGRenderingContext.h"
@@ -47,22 +45,15 @@ void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo)
}
}
-void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
- RenderObject* boxRenderer = renderer();
- ASSERT(boxRenderer);
-
- SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext);
+ SVGRenderingContext renderingContext(&renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer()));
-
- child->paint(paintInfo, LayoutPoint(), 0, 0);
- }
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->paint(paintInfo, paintOffset, 0, 0);
}
}
@@ -77,66 +68,4 @@ FloatRect SVGInlineFlowBox::calculateBoundaries() const
return childRect;
}
-void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer)
-{
- ASSERT(textRenderer);
-
- Node* node = textRenderer->node();
- if (!node || !node->inDocument())
- return;
-
- RenderStyle* style = textRenderer->style();
- ASSERT(style);
-
- AffineTransform fragmentTransform;
- Document& document = textRenderer->document();
- Vector<DocumentMarker*> markers = document.markers()->markersFor(textRenderer->node());
-
- Vector<DocumentMarker*>::iterator markerEnd = markers.end();
- for (Vector<DocumentMarker*>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) {
- DocumentMarker* marker = *markerIt;
-
- // SVG is only interessted in the TextMatch marker, for now.
- if (marker->type() != DocumentMarker::TextMatch)
- continue;
-
- FloatRect markerRect;
- for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if (!box->isSVGInlineTextBox())
- continue;
-
- SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
-
- int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0);
- int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len());
-
- if (markerStartPosition >= markerEndPosition)
- continue;
-
- int fragmentStartPosition = 0;
- int fragmentEndPosition = 0;
-
- const Vector<SVGTextFragment>& fragments = textBox->textFragments();
- unsigned textFragmentsSize = fragments.size();
- for (unsigned i = 0; i < textFragmentsSize; ++i) {
- const SVGTextFragment& fragment = fragments.at(i);
-
- fragmentStartPosition = markerStartPosition;
- fragmentEndPosition = markerEndPosition;
- if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
- continue;
-
- FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
- fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
-
- markerRect.unite(fragmentRect);
- }
- }
-
- toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox());
- }
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h
index e76a9ccdafc..0d66044e42b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h
@@ -25,26 +25,22 @@
namespace WebCore {
-class RenderSVGInlineText;
-
class SVGInlineFlowBox FINAL : public InlineFlowBox {
public:
- SVGInlineFlowBox(RenderObject* obj)
+ SVGInlineFlowBox(RenderObject& obj)
: InlineFlowBox(obj)
, m_logicalHeight(0)
{
}
- virtual bool isSVGInlineFlowBox() const { return true; }
- virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+ virtual bool isSVGInlineFlowBox() const OVERRIDE { return true; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return m_logicalHeight; }
void setLogicalHeight(float h) { m_logicalHeight = h; }
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
-
- virtual FloatRect calculateBoundaries() const;
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
- static void computeTextMatchMarkerRectForRenderer(RenderSVGInlineText*);
+ virtual FloatRect calculateBoundaries() const OVERRIDE;
private:
float m_logicalHeight;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp
index 6c593827328..a5dc2fc742c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp
@@ -22,11 +22,17 @@
#include "config.h"
#include "core/rendering/svg/SVGInlineTextBox.h"
-#include "core/frame/Frame.h"
+#include "core/dom/DocumentMarkerController.h"
+#include "core/dom/RenderedDocumentMarker.h"
+#include "core/editing/Editor.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/InlineFlowBox.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/PointerEventsHitRules.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderTheme.h"
#include "core/rendering/style/ShadowList.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGResource.h"
@@ -35,7 +41,7 @@
#include "core/rendering/svg/SVGTextRunRenderingContext.h"
#include "platform/FloatConversion.h"
#include "platform/fonts/FontCache.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
using namespace std;
@@ -44,17 +50,16 @@ namespace WebCore {
struct ExpectedSVGInlineTextBoxSize : public InlineTextBox {
float float1;
- uint32_t bitfields : 5;
+ uint32_t bitfields : 1;
void* pointer;
Vector<SVGTextFragment> vector;
};
COMPILE_ASSERT(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize), SVGInlineTextBox_is_not_of_expected_size);
-SVGInlineTextBox::SVGInlineTextBox(RenderObject* object)
+SVGInlineTextBox::SVGInlineTextBox(RenderObject& object)
: InlineTextBox(object)
, m_logicalHeight(0)
- , m_paintingResourceMode(ApplyToDefaultMode)
, m_startsNewTextChunk(false)
, m_paintingResource(0)
{
@@ -84,13 +89,12 @@ int SVGInlineTextBox::offsetForPosition(float, bool) const
int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
{
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- RenderStyle* style = textRenderer->style();
+ RenderStyle* style = textRenderer.style();
ASSERT(style);
TextRun textRun = constructTextRun(style, fragment);
@@ -102,7 +106,7 @@ int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
if (!fragmentTransform.isIdentity())
textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
- return fragment.characterOffset - start() + textRenderer->scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
+ return fragment.characterOffset - start() + textRenderer.scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
float SVGInlineTextBox::positionForOffset(int) const
@@ -119,13 +123,12 @@ FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
FontCachePurgePreventer fontCachePurgePreventer;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = textRenderer->scaledFont();
+ const Font& scaledFont = textRenderer.scaledFont();
const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
FloatPoint textOrigin(fragment.x, fragment.y);
if (scalingFactor != 1)
@@ -149,10 +152,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
if (startPosition >= endPosition)
return LayoutRect();
- RenderText* text = textRenderer();
- ASSERT(text);
-
- RenderStyle* style = text->style();
+ RenderStyle* style = textRenderer().style();
ASSERT(style);
AffineTransform fragmentTransform;
@@ -171,8 +171,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
selectionRect.unite(fragmentRect);
}
@@ -180,25 +179,24 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
return enclosingIntRect(selectionRect);
}
-static inline bool textShouldBePainted(RenderSVGInlineText* textRenderer)
+static inline bool textShouldBePainted(RenderSVGInlineText& textRenderer)
{
// Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
// If the absolute font size on screen is below x=0.5, don't render anything.
- return textRenderer->scaledFont().pixelSize();
+ return textRenderer.scaledFont().fontDescription().computedPixelSize();
}
void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
{
- ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
+ ASSERT(paintInfo.shouldPaintWithinRoot(&renderer()));
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(truncation() == cNoTruncation);
- if (renderer()->style()->visibility() != VISIBLE)
+ if (renderer().style()->visibility() != VISIBLE)
return;
- RenderObject* parentRenderer = parent()->renderer();
- ASSERT(parentRenderer);
- ASSERT(!parentRenderer->document().printing());
+ RenderObject& parentRenderer = parent()->renderer();
+ ASSERT(!parentRenderer.document().printing());
// Determine whether or not we're selected.
bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
@@ -206,25 +204,17 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
if (!hasSelection || paintSelectedTextOnly)
return;
- Color backgroundColor = renderer()->selectionBackgroundColor();
- if (!backgroundColor.isValid() || !backgroundColor.alpha())
+ Color backgroundColor = renderer().selectionBackgroundColor();
+ if (!backgroundColor.alpha())
return;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
if (!textShouldBePainted(textRenderer))
return;
- RenderStyle* style = parentRenderer->style();
+ RenderStyle* style = parentRenderer.style();
ASSERT(style);
- RenderStyle* selectionStyle = style;
- if (hasSelection) {
- selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
- if (!selectionStyle)
- selectionStyle = style;
- }
-
int startPosition, endPosition;
selectionStartEnd(startPosition, endPosition);
@@ -248,41 +238,39 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
paintInfo.context->setFillColor(backgroundColor);
paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor);
-
- m_paintingResourceMode = ApplyToDefaultMode;
}
ASSERT(!m_paintingResource);
}
-void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
- ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
+ ASSERT(paintInfo.shouldPaintWithinRoot(&renderer()));
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(truncation() == cNoTruncation);
- if (renderer()->style()->visibility() != VISIBLE)
+ if (renderer().style()->visibility() != VISIBLE)
return;
// Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
// If we ever need that for SVG, it's very easy to refactor and reuse the code.
- RenderObject* parentRenderer = parent()->renderer();
- ASSERT(parentRenderer);
+ RenderObject& parentRenderer = parent()->renderer();
bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
- bool hasSelection = !parentRenderer->document().printing() && selectionState() != RenderObject::SelectionNone;
+ bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone;
if (!hasSelection && paintSelectedTextOnly)
return;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
if (!textShouldBePainted(textRenderer))
return;
- RenderStyle* style = parentRenderer->style();
+ RenderStyle* style = parentRenderer.style();
ASSERT(style);
+ paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer.scaledFont(), true);
+
const SVGRenderStyle* svgStyle = style->svgStyle();
ASSERT(svgStyle);
@@ -291,7 +279,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
RenderStyle* selectionStyle = style;
if (hasSelection) {
- selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
+ selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION);
if (selectionStyle) {
const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle();
ASSERT(svgSelectionStyle);
@@ -300,11 +288,12 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
hasFill = svgSelectionStyle->hasFill();
if (!hasVisibleStroke)
hasVisibleStroke = svgSelectionStyle->hasVisibleStroke();
- } else
+ } else {
selectionStyle = style;
+ }
}
- if (textRenderer->frame() && textRenderer->frame()->view() && textRenderer->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
+ if (textRenderer.frame() && textRenderer.frame()->view() && textRenderer.frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
hasFill = true;
hasVisibleStroke = false;
}
@@ -315,10 +304,12 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
SVGTextFragment& fragment = m_textFragments.at(i);
ASSERT(!m_paintingResource);
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
+ if (!fragmentTransform.isIdentity()) {
+ stateSaver.save();
paintInfo.context->concatCTM(fragmentTransform);
+ }
// Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations.
unsigned decorations = style->textDecorationsInEffect();
@@ -332,15 +323,15 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
case PT_FILL:
// Fill text
if (hasFill) {
- m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode;
- paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ paintText(paintInfo.context, style, selectionStyle, fragment,
+ ApplyToFillMode | ApplyToTextMode, hasSelection, paintSelectedTextOnly);
}
break;
case PT_STROKE:
// Stroke text
if (hasVisibleStroke) {
- m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
- paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ paintText(paintInfo.context, style, selectionStyle, fragment,
+ ApplyToStrokeMode | ApplyToTextMode, hasSelection, paintSelectedTextOnly);
}
break;
case PT_MARKERS:
@@ -355,25 +346,29 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
// Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text.
if (decorations & TextDecorationLineThrough)
paintDecoration(paintInfo.context, TextDecorationLineThrough, fragment);
-
- m_paintingResourceMode = ApplyToDefaultMode;
}
+ // finally, paint the outline if any
+ if (style->hasOutline() && parentRenderer.isRenderInline())
+ toRenderInline(parentRenderer).paintOutline(paintInfo, paintOffset);
+
ASSERT(!m_paintingResource);
}
-bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderObject* renderer, RenderStyle* style)
+bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor,
+ RenderObject* renderer, RenderStyle* style, RenderSVGResourceModeFlags resourceMode)
{
+ // Callers must save the context state before calling when scalingFactor is not 1.
ASSERT(scalingFactor);
ASSERT(renderer);
ASSERT(style);
- ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
+ ASSERT(resourceMode != ApplyToDefaultMode);
- Color fallbackColor;
- if (m_paintingResourceMode & ApplyToFillMode)
- m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, fallbackColor);
- else if (m_paintingResourceMode & ApplyToStrokeMode)
- m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, fallbackColor);
+ bool hasFallback = false;
+ if (resourceMode & ApplyToFillMode)
+ m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, hasFallback);
+ else if (resourceMode & ApplyToStrokeMode)
+ m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, hasFallback);
else {
// We're either called for stroking or filling.
ASSERT_NOT_REACHED();
@@ -382,36 +377,32 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float
if (!m_paintingResource)
return false;
- if (!m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode)) {
- if (fallbackColor.isValid()) {
- RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
-
- m_paintingResource = fallbackResource;
- m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode);
+ if (!m_paintingResource->applyResource(renderer, style, context, resourceMode)) {
+ if (hasFallback) {
+ m_paintingResource = RenderSVGResource::sharedSolidPaintingResource();
+ m_paintingResource->applyResource(renderer, style, context, resourceMode);
}
}
- if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode)
+ if (scalingFactor != 1 && resourceMode & ApplyToStrokeMode)
context->setStrokeThickness(context->strokeThickness() * scalingFactor);
return true;
}
-void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path)
+void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path,
+ RenderSVGResourceModeFlags resourceMode)
{
ASSERT(m_paintingResource);
- RenderObject* parentRenderer = parent()->renderer();
- ASSERT(parentRenderer);
-
- m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode, path, /*RenderSVGShape*/ 0);
+ m_paintingResource->postApplyResource(&parent()->renderer(), context, resourceMode, path, 0);
m_paintingResource = 0;
}
-bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, TextRun& textRun, RenderStyle* style)
+bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context,
+ float scalingFactor, TextRun& textRun, RenderStyle* style, RenderSVGResourceModeFlags resourceMode)
{
- bool acquiredResource = acquirePaintingResource(context, scalingFactor, parent()->renderer(), style);
+ bool acquiredResource = acquirePaintingResource(context, scalingFactor, &parent()->renderer(), style, resourceMode);
if (!acquiredResource)
return false;
@@ -425,9 +416,10 @@ bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c
return true;
}
-void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun)
+void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context,
+ TextRun& textRun, RenderSVGResourceModeFlags resourceMode)
{
- releasePaintingResource(context, /* path */0);
+ releasePaintingResource(context, 0, resourceMode);
#if ENABLE(SVG_FONTS)
TextRun::RenderingContext* renderingContext = textRun.renderingContext();
@@ -439,10 +431,8 @@ void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*&
TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const
{
ASSERT(style);
- ASSERT(textRenderer());
- RenderText* text = textRenderer();
- ASSERT(text);
+ RenderText* text = &textRenderer();
// FIXME(crbug.com/264211): This should not be necessary but can occur if we
// layout during layout. Remove this when 264211 is fixed.
@@ -523,7 +513,7 @@ static inline float thicknessForDecoration(TextDecoration, const Font& font)
{
// FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
// Compatible with Batik/Opera
- return font.size() / 20.0f;
+ return font.fontDescription().computedSize() / 20.0f;
}
static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowBox* parentBox)
@@ -531,7 +521,7 @@ static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB
// Lookup first render object in parent hierarchy which has text-decoration set.
RenderObject* renderer = 0;
while (parentBox) {
- renderer = parentBox->renderer();
+ renderer = &parentBox->renderer();
if (renderer->style() && renderer->style()->textDecoration() != TextDecorationNone)
break;
@@ -545,7 +535,7 @@ static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB
void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment)
{
- if (textRenderer()->style()->textDecorationsInEffect() == TextDecorationNone)
+ if (textRenderer().style()->textDecorationsInEffect() == TextDecorationNone)
return;
// Find out which render style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours.
@@ -559,24 +549,29 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
const SVGRenderStyle* svgDecorationStyle = decorationStyle->svgStyle();
ASSERT(svgDecorationStyle);
- bool hasDecorationFill = svgDecorationStyle->hasFill();
- bool hasVisibleDecorationStroke = svgDecorationStyle->hasVisibleStroke();
-
- if (hasDecorationFill) {
- m_paintingResourceMode = ApplyToFillMode;
- paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
- }
-
- if (hasVisibleDecorationStroke) {
- m_paintingResourceMode = ApplyToStrokeMode;
- paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
+ for (int i = 0; i < 3; i++) {
+ switch (svgDecorationStyle->paintOrderType(i)) {
+ case PT_FILL:
+ if (svgDecorationStyle->hasFill())
+ paintDecorationWithStyle(context, decoration, fragment, decorationRenderer, ApplyToFillMode);
+ break;
+ case PT_STROKE:
+ if (svgDecorationStyle->hasVisibleStroke())
+ paintDecorationWithStyle(context, decoration, fragment, decorationRenderer, ApplyToStrokeMode);
+ break;
+ case PT_MARKERS:
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
}
}
-void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer)
+void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration,
+ const SVGTextFragment& fragment, RenderObject* decorationRenderer, RenderSVGResourceModeFlags resourceMode)
{
ASSERT(!m_paintingResource);
- ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
+ ASSERT(resourceMode != ApplyToDefaultMode);
RenderStyle* decorationStyle = decorationRenderer->style();
ASSERT(decorationStyle);
@@ -596,11 +591,12 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe
float width = fragment.width;
const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
- GraphicsContextStateSaver stateSaver(*context);
+ GraphicsContextStateSaver stateSaver(*context, false);
if (scalingFactor != 1) {
+ stateSaver.save();
width *= scalingFactor;
decorationOrigin.scale(scalingFactor, scalingFactor);
- context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+ context->scale(1 / scalingFactor, 1 / scalingFactor);
}
decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness));
@@ -608,19 +604,22 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe
Path path;
path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness)));
- if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle))
- releasePaintingResource(context, &path);
+ // acquirePaintingResource also modifies state if the scalingFactor is non-identity.
+ // Above we have saved the state for this case.
+ if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle, resourceMode))
+ releasePaintingResource(context, &path, resourceMode);
}
-void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
+void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style,
+ TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition,
+ RenderSVGResourceModeFlags resourceMode)
{
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = textRenderer->scaledFont();
+ const Font& scaledFont = textRenderer.scaledFont();
const ShadowList* shadowList = style->textShadow();
// Text shadows are disabled when printing. http://crbug.com/258321
@@ -633,28 +632,28 @@ void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
textOrigin.scale(scalingFactor, scalingFactor);
textSize.scale(scalingFactor);
context->save();
- context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+ context->scale(1 / scalingFactor, 1 / scalingFactor);
}
if (hasShadow) {
- DrawLooper drawLooper;
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
for (size_t i = shadowList->shadows().size(); i--; ) {
const ShadowData& shadow = shadowList->shadows()[i];
FloatSize offset(shadow.x(), shadow.y());
- drawLooper.addShadow(offset, shadow.blur(), shadow.color(),
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowRespectsAlpha);
+ drawLooperBuilder->addShadow(offset, shadow.blur(), shadow.color(),
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowRespectsAlpha);
}
- drawLooper.addUnmodifiedContent();
- context->setDrawLooper(drawLooper);
+ drawLooperBuilder->addUnmodifiedContent();
+ context->setDrawLooper(drawLooperBuilder.release());
}
- if (prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style)) {
+ if (prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style, resourceMode)) {
TextRunPaintInfo textRunPaintInfo(textRun);
textRunPaintInfo.from = startPosition;
textRunPaintInfo.to = endPosition;
textRunPaintInfo.bounds = FloatRect(textOrigin, textSize);
scaledFont.drawText(context, textRunPaintInfo, textOrigin);
- restoreGraphicsContextAfterTextPainting(context, textRun);
+ restoreGraphicsContextAfterTextPainting(context, textRun, resourceMode);
}
if (scalingFactor != 1)
@@ -663,7 +662,9 @@ void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
context->clearShadow();
}
-void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, RenderStyle* selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
+void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style,
+ RenderStyle* selectionStyle, const SVGTextFragment& fragment,
+ RenderSVGResourceModeFlags resourceMode, bool hasSelection, bool paintSelectedTextOnly)
{
ASSERT(style);
ASSERT(selectionStyle);
@@ -678,40 +679,104 @@ void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, R
// Fast path if there is no selection, just draw the whole chunk part using the regular style
TextRun textRun = constructTextRun(style, fragment);
if (!hasSelection || startPosition >= endPosition) {
- paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length);
+ paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length, resourceMode);
return;
}
// Eventually draw text using regular style until the start position of the selection
if (startPosition > 0 && !paintSelectedTextOnly)
- paintTextWithShadows(context, style, textRun, fragment, 0, startPosition);
+ paintTextWithShadows(context, style, textRun, fragment, 0, startPosition, resourceMode);
// Draw text using selection style from the start to the end position of the selection
- if (style != selectionStyle)
- SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle);
+ if (style != selectionStyle) {
+ StyleDifference diff;
+ diff.setNeedsRepaintObject();
+ SVGResourcesCache::clientStyleChanged(&parent()->renderer(), diff, selectionStyle);
+ }
- TextRun selectionTextRun = constructTextRun(selectionStyle, fragment);
- paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition);
+ paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition, resourceMode);
- if (style != selectionStyle)
- SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style);
+ if (style != selectionStyle) {
+ StyleDifference diff;
+ diff.setNeedsRepaintObject();
+ SVGResourcesCache::clientStyleChanged(&parent()->renderer(), diff, selectionStyle);
+ }
// Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
- paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length);
+ paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length, resourceMode);
+}
+
+void SVGInlineTextBox::paintDocumentMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&, bool)
+{
+ // SVG does not have support for generic document markers (e.g., spellchecking, etc).
+}
+
+void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const FloatPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font)
+{
+ // SVG is only interested in the TextMatch markers.
+ if (marker->type() != DocumentMarker::TextMatch)
+ return;
+
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
+
+ FloatRect markerRect;
+ AffineTransform fragmentTransform;
+ for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextTextBox()) {
+ if (!box->isSVGInlineTextBox())
+ continue;
+
+ SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
+
+ int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0);
+ int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len());
+
+ if (markerStartPosition >= markerEndPosition)
+ continue;
+
+ const Vector<SVGTextFragment>& fragments = textBox->textFragments();
+ unsigned textFragmentsSize = fragments.size();
+ for (unsigned i = 0; i < textFragmentsSize; ++i) {
+ const SVGTextFragment& fragment = fragments.at(i);
+
+ int fragmentStartPosition = markerStartPosition;
+ int fragmentEndPosition = markerEndPosition;
+ if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
+ continue;
+
+ FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
+ fragment.buildFragmentTransform(fragmentTransform);
+
+ // Draw the marker highlight.
+ if (renderer().frame()->editor().markedTextMatchesAreHighlighted()) {
+ Color color = marker->activeMatch() ?
+ RenderTheme::theme().platformActiveTextSearchHighlightColor() :
+ RenderTheme::theme().platformInactiveTextSearchHighlightColor();
+ GraphicsContextStateSaver stateSaver(*context);
+ if (!fragmentTransform.isIdentity())
+ context->concatCTM(fragmentTransform);
+ context->setFillColor(color);
+ context->fillRect(fragmentRect, color);
+ }
+
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ markerRect.unite(fragmentRect);
+ }
+ }
+
+ toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsoluteQuad(markerRect).enclosingBoundingBox());
}
FloatRect SVGInlineTextBox::calculateBoundaries() const
{
FloatRect textRect;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor;
+ float baseline = textRenderer.scaledFont().fontMetrics().floatAscent() / scalingFactor;
AffineTransform fragmentTransform;
unsigned textFragmentsSize = m_textFragments.size();
@@ -719,8 +784,7 @@ FloatRect SVGInlineTextBox::calculateBoundaries() const
const SVGTextFragment& fragment = m_textFragments.at(i);
FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
textRect.unite(fragmentRect);
}
@@ -733,18 +797,18 @@ bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
// FIXME: integrate with InlineTextBox::nodeAtPoint better.
ASSERT(!isLineBreak());
- PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, renderer()->style()->pointerEvents());
- bool isVisible = renderer()->style()->visibility() == VISIBLE;
+ PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, renderer().style()->pointerEvents());
+ bool isVisible = renderer().style()->visibility() == VISIBLE;
if (isVisible || !hitRules.requireVisible) {
if (hitRules.canHitBoundingBox
- || (hitRules.canHitStroke && (renderer()->style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
- || (hitRules.canHitFill && (renderer()->style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
+ || (hitRules.canHitStroke && (renderer().style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
+ || (hitRules.canHitFill && (renderer().style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
FloatPoint boxOrigin(x(), y());
boxOrigin.moveBy(accumulatedOffset);
FloatRect rect(boxOrigin, size());
if (locationInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+ renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+ if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect))
return true;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h
index ccec860b863..2a5cb1bcd0e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h
@@ -23,38 +23,38 @@
#define SVGInlineTextBox_h
#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/svg/RenderSVGResource.h"
#include "core/rendering/svg/SVGTextLayoutEngine.h"
namespace WebCore {
class RenderSVGResource;
-class SVGRootInlineBox;
class SVGInlineTextBox FINAL : public InlineTextBox {
public:
- SVGInlineTextBox(RenderObject*);
+ SVGInlineTextBox(RenderObject&);
- virtual bool isSVGInlineTextBox() const { return true; }
+ virtual bool isSVGInlineTextBox() const OVERRIDE { return true; }
- virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return m_logicalHeight; }
void setLogicalHeight(float height) { m_logicalHeight = height; }
- virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
- virtual float positionForOffset(int offset) const;
+ virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const OVERRIDE;
+ virtual float positionForOffset(int offset) const OVERRIDE;
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual LayoutRect localSelectionRect(int startPosition, int endPosition);
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+ virtual LayoutRect localSelectionRect(int startPosition, int endPosition) OVERRIDE;
bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const;
- virtual FloatRect calculateBoundaries() const;
+ virtual FloatRect calculateBoundaries() const OVERRIDE;
void clearTextFragments() { m_textFragments.clear(); }
Vector<SVGTextFragment>& textFragments() { return m_textFragments; }
const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; }
- virtual void dirtyLineBoxes() OVERRIDE FINAL;
+ virtual void dirtyLineBoxes() OVERRIDE;
bool startsNewTextChunk() const { return m_startsNewTextChunk; }
void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; }
@@ -65,23 +65,30 @@ public:
private:
TextRun constructTextRun(RenderStyle*, const SVGTextFragment&) const;
- bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderObject*, RenderStyle*);
- void releasePaintingResource(GraphicsContext*&, const Path*);
+ bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderObject*,
+ RenderStyle*, RenderSVGResourceModeFlags);
+ void releasePaintingResource(GraphicsContext*&, const Path*, RenderSVGResourceModeFlags);
- bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&, RenderStyle*);
- void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&);
+ bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&,
+ RenderStyle*, RenderSVGResourceModeFlags);
+ void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&, RenderSVGResourceModeFlags);
void paintDecoration(GraphicsContext*, TextDecoration, const SVGTextFragment&);
- void paintDecorationWithStyle(GraphicsContext*, TextDecoration, const SVGTextFragment&, RenderObject* decorationRenderer);
- void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition);
- void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly);
+ void paintDecorationWithStyle(GraphicsContext*, TextDecoration, const SVGTextFragment&,
+ RenderObject* decorationRenderer, RenderSVGResourceModeFlags);
+ void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&,
+ int startPosition, int endPosition, RenderSVGResourceModeFlags);
+ void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&,
+ RenderSVGResourceModeFlags, bool hasSelection, bool paintSelectedTextOnly);
+
+ virtual void paintDocumentMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&, bool) OVERRIDE FINAL;
+ virtual void paintTextMatchMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&) OVERRIDE FINAL;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
private:
float m_logicalHeight;
- unsigned m_paintingResourceMode : 4;
- unsigned m_startsNewTextChunk : 1;
+ bool m_startsNewTextChunk : 1;
RenderSVGResource* m_paintingResource;
Vector<SVGTextFragment> m_textFragments;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h
index aebd83b3e1a..1b31b98b87f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h
@@ -26,8 +26,6 @@
namespace WebCore {
-class RenderSVGResourceMarker;
-
enum SVGMarkerType {
StartMarker,
MidMarker,
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp
index f42f6410e57..5a18ba50295 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/svg/SVGPathData.h"
-#include "SVGNames.h"
+#include "core/SVGNames.h"
#include "core/svg/SVGCircleElement.h"
#include "core/svg/SVGEllipseElement.h"
#include "core/svg/SVGLineElement.h"
@@ -34,14 +34,16 @@
namespace WebCore {
+using namespace SVGNames;
+
static void updatePathFromCircleElement(SVGElement* element, Path& path)
{
SVGCircleElement* circle = toSVGCircleElement(element);
SVGLengthContext lengthContext(element);
- float r = circle->rCurrentValue().value(lengthContext);
+ float r = circle->r()->currentValue()->value(lengthContext);
if (r > 0)
- path.addEllipse(FloatRect(circle->cxCurrentValue().value(lengthContext) - r, circle->cyCurrentValue().value(lengthContext) - r, r * 2, r * 2));
+ path.addEllipse(FloatRect(circle->cx()->currentValue()->value(lengthContext) - r, circle->cy()->currentValue()->value(lengthContext) - r, r * 2, r * 2));
}
static void updatePathFromEllipseElement(SVGElement* element, Path& path)
@@ -49,13 +51,16 @@ static void updatePathFromEllipseElement(SVGElement* element, Path& path)
SVGEllipseElement* ellipse = toSVGEllipseElement(element);
SVGLengthContext lengthContext(element);
- float rx = ellipse->rxCurrentValue().value(lengthContext);
- if (rx <= 0)
+ float rx = ellipse->rx()->currentValue()->value(lengthContext);
+ if (rx < 0)
+ return;
+ float ry = ellipse->ry()->currentValue()->value(lengthContext);
+ if (ry < 0)
return;
- float ry = ellipse->ryCurrentValue().value(lengthContext);
- if (ry <= 0)
+ if (!rx && !ry)
return;
- path.addEllipse(FloatRect(ellipse->cxCurrentValue().value(lengthContext) - rx, ellipse->cyCurrentValue().value(lengthContext) - ry, rx * 2, ry * 2));
+
+ path.addEllipse(FloatRect(ellipse->cx()->currentValue()->value(lengthContext) - rx, ellipse->cy()->currentValue()->value(lengthContext) - ry, rx * 2, ry * 2));
}
static void updatePathFromLineElement(SVGElement* element, Path& path)
@@ -63,8 +68,8 @@ static void updatePathFromLineElement(SVGElement* element, Path& path)
SVGLineElement* line = toSVGLineElement(element);
SVGLengthContext lengthContext(element);
- path.moveTo(FloatPoint(line->x1CurrentValue().value(lengthContext), line->y1CurrentValue().value(lengthContext)));
- path.addLineTo(FloatPoint(line->x2CurrentValue().value(lengthContext), line->y2CurrentValue().value(lengthContext)));
+ path.moveTo(FloatPoint(line->x1()->currentValue()->value(lengthContext), line->y1()->currentValue()->value(lengthContext)));
+ path.addLineTo(FloatPoint(line->x2()->currentValue()->value(lengthContext), line->y2()->currentValue()->value(lengthContext)));
}
static void updatePathFromPathElement(SVGElement* element, Path& path)
@@ -72,32 +77,26 @@ static void updatePathFromPathElement(SVGElement* element, Path& path)
buildPathFromByteStream(toSVGPathElement(element)->pathByteStream(), path);
}
-static void updatePathFromPolygonElement(SVGElement* element, Path& path)
+static void updatePathFromPolylineElement(SVGElement* element, Path& path)
{
- SVGPointList& points = toSVGPolygonElement(element)->pointsCurrentValue();
- if (points.isEmpty())
+ RefPtr<SVGPointList> points = toSVGPolyElement(element)->points()->currentValue();
+ if (points->isEmpty())
return;
- path.moveTo(points.first());
-
- unsigned size = points.size();
- for (unsigned i = 1; i < size; ++i)
- path.addLineTo(points.at(i));
+ SVGPointList::ConstIterator it = points->begin();
+ SVGPointList::ConstIterator itEnd = points->end();
+ ASSERT(it != itEnd);
+ path.moveTo(it->value());
+ ++it;
- path.closeSubpath();
+ for (; it != itEnd; ++it)
+ path.addLineTo(it->value());
}
-static void updatePathFromPolylineElement(SVGElement* element, Path& path)
+static void updatePathFromPolygonElement(SVGElement* element, Path& path)
{
- SVGPointList& points = toSVGPolylineElement(element)->pointsCurrentValue();
- if (points.isEmpty())
- return;
-
- path.moveTo(points.first());
-
- unsigned size = points.size();
- for (unsigned i = 1; i < size; ++i)
- path.addLineTo(points.at(i));
+ updatePathFromPolylineElement(element, path);
+ path.closeSubpath();
}
static void updatePathFromRectElement(SVGElement* element, Path& path)
@@ -105,19 +104,21 @@ static void updatePathFromRectElement(SVGElement* element, Path& path)
SVGRectElement* rect = toSVGRectElement(element);
SVGLengthContext lengthContext(element);
- float width = rect->widthCurrentValue().value(lengthContext);
- if (width <= 0)
+ float width = rect->width()->currentValue()->value(lengthContext);
+ if (width < 0)
+ return;
+ float height = rect->height()->currentValue()->value(lengthContext);
+ if (height < 0)
return;
- float height = rect->heightCurrentValue().value(lengthContext);
- if (height <= 0)
+ if (!width && !height)
return;
- float x = rect->xCurrentValue().value(lengthContext);
- float y = rect->yCurrentValue().value(lengthContext);
- bool hasRx = rect->rxCurrentValue().value(lengthContext) > 0;
- bool hasRy = rect->ryCurrentValue().value(lengthContext) > 0;
+ float x = rect->x()->currentValue()->value(lengthContext);
+ float y = rect->y()->currentValue()->value(lengthContext);
+ float rx = rect->rx()->currentValue()->value(lengthContext);
+ float ry = rect->ry()->currentValue()->value(lengthContext);
+ bool hasRx = rx > 0;
+ bool hasRy = ry > 0;
if (hasRx || hasRy) {
- float rx = rect->rxCurrentValue().value(lengthContext);
- float ry = rect->ryCurrentValue().value(lengthContext);
if (!hasRx)
rx = ry;
else if (!hasRy)
@@ -139,13 +140,13 @@ void updatePathFromGraphicsElement(SVGElement* element, Path& path)
static HashMap<StringImpl*, PathUpdateFunction>* map = 0;
if (!map) {
map = new HashMap<StringImpl*, PathUpdateFunction>;
- map->set(SVGNames::circleTag.localName().impl(), updatePathFromCircleElement);
- map->set(SVGNames::ellipseTag.localName().impl(), updatePathFromEllipseElement);
- map->set(SVGNames::lineTag.localName().impl(), updatePathFromLineElement);
- map->set(SVGNames::pathTag.localName().impl(), updatePathFromPathElement);
- map->set(SVGNames::polygonTag.localName().impl(), updatePathFromPolygonElement);
- map->set(SVGNames::polylineTag.localName().impl(), updatePathFromPolylineElement);
- map->set(SVGNames::rectTag.localName().impl(), updatePathFromRectElement);
+ map->set(circleTag.localName().impl(), updatePathFromCircleElement);
+ map->set(ellipseTag.localName().impl(), updatePathFromEllipseElement);
+ map->set(lineTag.localName().impl(), updatePathFromLineElement);
+ map->set(pathTag.localName().impl(), updatePathFromPathElement);
+ map->set(polygonTag.localName().impl(), updatePathFromPolygonElement);
+ map->set(polylineTag.localName().impl(), updatePathFromPolylineElement);
+ map->set(rectTag.localName().impl(), updatePathFromRectElement);
}
if (PathUpdateFunction pathUpdateFunction = map->get(element->localName().impl()))
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp
index cfc4a641f7f..56c9e2cffdd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp
@@ -23,9 +23,9 @@
*/
#include "config.h"
-
#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/SubtreeLayoutScope.h"
@@ -51,8 +51,8 @@ LayoutRect SVGRenderSupport::clippedOverflowRectForRepaint(const RenderObject* o
// Pass our local paint rect to computeRectForRepaint() which will
// map to parent coords and recurse up the parent chain.
- FloatRect repaintRect = object->repaintRectInLocalCoordinates();
- object->computeFloatRectForRepaint(repaintContainer, repaintRect);
+ FloatRect repaintRect = object->paintInvalidationRectInLocalCoordinates();
+ object->computeFloatRectForPaintInvalidation(repaintContainer, repaintRect);
return enclosingLayoutRect(repaintRect);
}
@@ -60,9 +60,9 @@ void SVGRenderSupport::computeFloatRectForRepaint(const RenderObject* object, co
{
repaintRect.inflate(object->style()->outlineWidth());
- // Translate to coords in our parent renderer, and then call computeFloatRectForRepaint() on our parent.
+ // Translate to coords in our parent renderer, and then call computeFloatRectForPaintInvalidation() on our parent.
repaintRect = object->localToParentTransform().mapRect(repaintRect);
- object->parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+ object->parent()->computeFloatRectForPaintInvalidation(repaintContainer, repaintRect, fixed);
}
void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
@@ -100,18 +100,24 @@ const RenderObject* SVGRenderSupport::pushMappingToContainer(const RenderObject*
return parent;
}
-bool SVGRenderSupport::checkForSVGRepaintDuringLayout(RenderObject* object)
+bool SVGRenderSupport::parentTransformDidChange(RenderObject* object)
{
- if (!object->checkForRepaintDuringLayout())
- return false;
// When a parent container is transformed in SVG, all children will be painted automatically
// so we are able to skip redundant repaint checks.
RenderObject* parent = object->parent();
return !(parent && parent->isSVGContainer() && toRenderSVGContainer(parent)->didTransformToRootUpdate());
}
+bool SVGRenderSupport::checkForSVGRepaintDuringLayout(RenderObject* object)
+{
+ if (!object->checkForPaintInvalidationDuringLayout())
+ return false;
+
+ return parentTransformDidChange(object);
+}
+
// Update a bounding box taking into account the validity of the other bounding box.
-static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
+inline void SVGRenderSupport::updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
{
bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
if (!otherValid)
@@ -135,18 +141,14 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* contain
// When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes
// the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound
// the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also.
- for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) {
+ for (RenderObject* current = container->slowFirstChild(); current; current = current->nextSibling()) {
if (current->isSVGHiddenContainer())
continue;
const AffineTransform& transform = current->localToParentTransform();
- if (transform.isIdentity()) {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
- strokeBoundingBox.unite(current->repaintRectInLocalCoordinates());
- } else {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
- strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
- }
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current,
+ transform.mapRect(current->objectBoundingBox()));
+ strokeBoundingBox.unite(transform.mapRect(current->paintInvalidationRectInLocalCoordinates()));
}
repaintBoundingBox = strokeBoundingBox;
@@ -154,9 +156,6 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* contain
bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo)
{
- if (localTransform.isIdentity())
- return localRepaintRect.intersects(paintInfo.rect);
-
return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect);
}
@@ -170,17 +169,17 @@ const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* st
return toRenderSVGRoot(start);
}
-static inline void invalidateResourcesOfChildren(RenderObject* start)
+inline void SVGRenderSupport::invalidateResourcesOfChildren(RenderObject* start)
{
ASSERT(!start->needsLayout());
if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start))
resources->removeClientFromCache(start, false);
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling())
+ for (RenderObject* child = start->slowFirstChild(); child; child = child->nextSibling())
invalidateResourcesOfChildren(child);
}
-static inline bool layoutSizeOfNearestViewportChanged(const RenderObject* start)
+inline bool SVGRenderSupport::layoutSizeOfNearestViewportChanged(const RenderObject* start)
{
while (start && !start->isSVGRoot() && !start->isSVGViewportContainer())
start = start->parent();
@@ -212,7 +211,7 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
bool transformChanged = transformToRootChanged(start);
HashSet<RenderObject*> notlayoutedObjects;
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = start->slowFirstChild(); child; child = child->nextSibling()) {
bool needsLayout = selfNeedsLayout;
bool childEverHadLayout = child->everHadLayout();
@@ -228,9 +227,9 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
if (element->hasRelativeLengths()) {
// When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
- if (child->isSVGShape())
+ if (child->isSVGShape()) {
toRenderSVGShape(child)->setNeedsShapeUpdate();
- else if (child->isSVGText()) {
+ } else if (child->isSVGText()) {
toRenderSVGText(child)->setNeedsTextMetricsUpdate();
toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
}
@@ -240,7 +239,7 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
}
}
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
// Resource containers are nasty: they can invalidate clients outside the current SubtreeLayoutScope.
// Since they only care about viewport size changes (to resolve their relative lengths), we trigger
// their invalidation directly from SVGSVGElement::svgAttributeChange() or at a higher
@@ -257,9 +256,10 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
// We could handle this in the individual objects, but for now it's easier to have
// parent containers call repaint(). (RenderBlock::layout* has similar logic.)
if (!childEverHadLayout && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
- child->repaint();
- } else if (layoutSizeChanged)
+ child->paintInvalidationForWholeRenderer();
+ } else if (layoutSizeChanged) {
notlayoutedObjects.add(child);
+ }
}
if (!layoutSizeChanged) {
@@ -284,23 +284,16 @@ void SVGRenderSupport::layoutResourcesIfNeeded(const RenderObject* object)
bool SVGRenderSupport::isOverflowHidden(const RenderObject* object)
{
- // SVG doesn't support independent x/y overflow
- ASSERT(object->style()->overflowX() == object->style()->overflowY());
-
- // OSCROLL is never set for SVG - see StyleResolver::adjustRenderStyle
- ASSERT(object->style()->overflowX() != OSCROLL);
-
// RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size.
- ASSERT(!object->isRoot());
+ ASSERT(!object->isDocumentElement());
- return object->style()->overflowX() == OHIDDEN;
+ return object->style()->overflowX() == OHIDDEN || object->style()->overflowX() == OSCROLL;
}
-void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* object, FloatRect& repaintRect)
+void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* renderer, FloatRect& repaintRect)
{
- ASSERT(object);
+ ASSERT(renderer);
- RenderObject* renderer = const_cast<RenderObject*>(object);
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
if (!resources)
return;
@@ -357,21 +350,22 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const
ASSERT(svgStyle);
SVGLengthContext lengthContext(toSVGElement(object->node()));
- context->setStrokeThickness(svgStyle->strokeWidth().value(lengthContext));
+ context->setStrokeThickness(svgStyle->strokeWidth()->value(lengthContext));
context->setLineCap(svgStyle->capStyle());
context->setLineJoin(svgStyle->joinStyle());
context->setMiterLimit(svgStyle->strokeMiterLimit());
- const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
- if (dashes.isEmpty())
+ RefPtr<SVGLengthList> dashes = svgStyle->strokeDashArray();
+ if (dashes->isEmpty())
return;
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ SVGLengthList::ConstIterator it = dashes->begin();
+ SVGLengthList::ConstIterator itEnd = dashes->end();
+ for (; it != itEnd; ++it)
+ dashArray.append(it->value(lengthContext));
- context->setLineDash(dashArray, svgStyle->strokeDashOffset().value(lengthContext));
+ context->setLineDash(dashArray, svgStyle->strokeDashOffset()->value(lengthContext));
}
void SVGRenderSupport::applyStrokeStyleToStrokeData(StrokeData* strokeData, const RenderStyle* style, const RenderObject* object)
@@ -386,29 +380,28 @@ void SVGRenderSupport::applyStrokeStyleToStrokeData(StrokeData* strokeData, cons
ASSERT(svgStyle);
SVGLengthContext lengthContext(toSVGElement(object->node()));
- strokeData->setThickness(svgStyle->strokeWidth().value(lengthContext));
+ strokeData->setThickness(svgStyle->strokeWidth()->value(lengthContext));
strokeData->setLineCap(svgStyle->capStyle());
strokeData->setLineJoin(svgStyle->joinStyle());
strokeData->setMiterLimit(svgStyle->strokeMiterLimit());
- const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
- if (dashes.isEmpty())
+ RefPtr<SVGLengthList> dashes = svgStyle->strokeDashArray();
+ if (dashes->isEmpty())
return;
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ size_t length = dashes->length();
+ for (size_t i = 0; i < length; ++i)
+ dashArray.append(dashes->at(i)->value(lengthContext));
- strokeData->setLineDash(dashArray, svgStyle->strokeDashOffset().value(lengthContext));
+ strokeData->setLineDash(dashArray, svgStyle->strokeDashOffset()->value(lengthContext));
}
-bool SVGRenderSupport::isEmptySVGInlineText(const RenderObject* object)
+bool SVGRenderSupport::isRenderableTextNode(const RenderObject* object)
{
- // RenderSVGInlineText performs whitespace filtering in order to support xml:space
- // (http://www.w3.org/TR/SVG/struct.html#LangSpaceAttrs), and can end up with an empty string
- // even when its original constructor argument is non-empty.
- return object->isSVGInlineText() && toRenderSVGInlineText(object)->hasEmptyText();
+ ASSERT(object->isText());
+ // <br> is marked as text, but is not handled by the SVG rendering code-path.
+ return object->isSVGInlineText() && !toRenderSVGInlineText(object)->hasEmptyText();
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h
index 4265f64c780..087dcfbbd44 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h
@@ -24,23 +24,22 @@
#ifndef SVGRenderSupport_h
#define SVGRenderSupport_h
-#include "core/rendering/PaintInfo.h"
-
namespace WebCore {
+class AffineTransform;
class FloatPoint;
class FloatRect;
-class ImageBuffer;
+class GraphicsContext;
class LayoutRect;
-class RenderBoxModelObject;
+struct PaintInfo;
class RenderGeometryMap;
class RenderLayerModelObject;
class RenderObject;
class RenderStyle;
class RenderSVGRoot;
+class StrokeData;
class TransformState;
-// SVGRendererSupport is a helper class sharing code between all SVG renderers.
class SVGRenderSupport {
public:
// Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Container
@@ -62,8 +61,11 @@ public:
static bool pointInClippingArea(RenderObject*, const FloatPoint&);
static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox);
+
static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo&);
+ static bool parentTransformDidChange(RenderObject*);
+
// Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations
static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer);
static void computeFloatRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed);
@@ -81,13 +83,14 @@ public:
// FIXME: These methods do not belong here.
static const RenderSVGRoot* findTreeRootObject(const RenderObject*);
- // Helper method for determining whether an RenderSVGInlineText object has zero length text.
- static bool isEmptySVGInlineText(const RenderObject*);
+ // Helper method for determining if a RenderObject marked as text (isText()== true)
+ // can/will be rendered as part of a <text>.
+ static bool isRenderableTextNode(const RenderObject*);
private:
- // This class is not constructable.
- SVGRenderSupport();
- ~SVGRenderSupport();
+ static void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox);
+ static void invalidateResourcesOfChildren(RenderObject* start);
+ static bool layoutSizeOfNearestViewportChanged(const RenderObject* start);
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
index b92e9b99833..15726cb9c37 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
@@ -30,7 +30,6 @@
#include "core/rendering/svg/SVGRenderTreeAsText.h"
-#include "SVGNames.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderTreeAsText.h"
#include "core/rendering/svg/RenderSVGGradientStop.h"
@@ -64,6 +63,7 @@
#include "core/svg/SVGRadialGradientElement.h"
#include "core/svg/SVGRectElement.h"
#include "core/svg/SVGStopElement.h"
+#include "platform/graphics/DashArray.h"
#include "platform/graphics/GraphicsTypes.h"
#include <math.h>
@@ -154,15 +154,35 @@ static TextStream& operator<<(TextStream& ts, const WindRule rule)
return ts;
}
+namespace {
+
+template<typename Enum>
+String SVGEnumerationToString(Enum value)
+{
+ const SVGEnumerationStringEntries& entries = getStaticStringEntries<Enum>();
+
+ SVGEnumerationStringEntries::const_iterator it = entries.begin();
+ SVGEnumerationStringEntries::const_iterator itEnd = entries.end();
+ for (; it != itEnd; ++it) {
+ if (value == it->first)
+ return it->second;
+ }
+
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+}
+
static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType)
{
- ts << SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::toString(unitType);
+ ts << SVGEnumerationToString<SVGUnitTypes::SVGUnitType>(unitType);
return ts;
}
static TextStream& operator<<(TextStream& ts, const SVGMarkerUnitsType& markerUnit)
{
- ts << SVGPropertyTraits<SVGMarkerUnitsType>::toString(markerUnit);
+ ts << SVGEnumerationToString<SVGMarkerUnitsType>(markerUnit);
return ts;
}
@@ -221,7 +241,7 @@ static TextStream& operator<<(TextStream& ts, LineJoin style)
static TextStream& operator<<(TextStream& ts, const SVGSpreadMethodType& type)
{
- ts << SVGPropertyTraits<SVGSpreadMethodType>::toString(type).upper();
+ ts << SVGEnumerationToString<SVGSpreadMethodType>(type).upper();
return ts;
}
@@ -260,21 +280,22 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object);
ASSERT(shape.element());
- Color fallbackColor;
- if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
+ bool hasFallback;
+ if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), hasFallback)) {
TextStreamSeparator s(" ");
ts << " [stroke={" << s;
writeSVGPaintingResource(ts, strokePaintingResource);
SVGLengthContext lengthContext(shape.element());
- double dashOffset = svgStyle->strokeDashOffset().value(lengthContext);
- double strokeWidth = svgStyle->strokeWidth().value(lengthContext);
- const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
+ double dashOffset = svgStyle->strokeDashOffset()->value(lengthContext);
+ double strokeWidth = svgStyle->strokeWidth()->value(lengthContext);
+ RefPtr<SVGLengthList> dashes = svgStyle->strokeDashArray();
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ SVGLengthList::ConstIterator it = dashes->begin();
+ SVGLengthList::ConstIterator itEnd = dashes->end();
+ for (; it != itEnd; ++it)
+ dashArray.append(it->value(lengthContext));
writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f);
writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0);
@@ -288,7 +309,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
ts << "}]";
}
- if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
+ if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), hasFallback)) {
TextStreamSeparator s(" ");
ts << " [fill={" << s;
writeSVGPaintingResource(ts, fillPaintingResource);
@@ -317,37 +338,38 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
writePositionAndStyle(ts, shape);
SVGElement* svgElement = shape.element();
+ ASSERT(svgElement);
SVGLengthContext lengthContext(svgElement);
- if (svgElement->hasTagName(SVGNames::rectTag)) {
- SVGRectElement* element = toSVGRectElement(svgElement);
- writeNameValuePair(ts, "x", element->xCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "y", element->yCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "width", element->widthCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "height", element->heightCurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::lineTag)) {
- SVGLineElement* element = toSVGLineElement(svgElement);
- writeNameValuePair(ts, "x1", element->x1CurrentValue().value(lengthContext));
- writeNameValuePair(ts, "y1", element->y1CurrentValue().value(lengthContext));
- writeNameValuePair(ts, "x2", element->x2CurrentValue().value(lengthContext));
- writeNameValuePair(ts, "y2", element->y2CurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::ellipseTag)) {
- SVGEllipseElement* element = toSVGEllipseElement(svgElement);
- writeNameValuePair(ts, "cx", element->cxCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "cy", element->cyCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "rx", element->rxCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "ry", element->ryCurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::circleTag)) {
- SVGCircleElement* element = toSVGCircleElement(svgElement);
- writeNameValuePair(ts, "cx", element->cxCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "cy", element->cyCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "r", element->rCurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::polygonTag) || svgElement->hasTagName(SVGNames::polylineTag)) {
- writeNameAndQuotedValue(ts, "points", toSVGPolyElement(svgElement)->pointsCurrentValue().valueAsString());
- } else if (svgElement->hasTagName(SVGNames::pathTag)) {
+ if (isSVGRectElement(*svgElement)) {
+ SVGRectElement& element = toSVGRectElement(*svgElement);
+ writeNameValuePair(ts, "x", element.x()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "y", element.y()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "width", element.width()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "height", element.height()->currentValue()->value(lengthContext));
+ } else if (isSVGLineElement(*svgElement)) {
+ SVGLineElement& element = toSVGLineElement(*svgElement);
+ writeNameValuePair(ts, "x1", element.x1()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "y1", element.y1()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "x2", element.x2()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "y2", element.y2()->currentValue()->value(lengthContext));
+ } else if (isSVGEllipseElement(*svgElement)) {
+ SVGEllipseElement& element = toSVGEllipseElement(*svgElement);
+ writeNameValuePair(ts, "cx", element.cx()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "cy", element.cy()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "rx", element.rx()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "ry", element.ry()->currentValue()->value(lengthContext));
+ } else if (isSVGCircleElement(*svgElement)) {
+ SVGCircleElement& element = toSVGCircleElement(*svgElement);
+ writeNameValuePair(ts, "cx", element.cx()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "cy", element.cy()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "r", element.r()->currentValue()->value(lengthContext));
+ } else if (isSVGPolyElement(*svgElement)) {
+ writeNameAndQuotedValue(ts, "points", toSVGPolyElement(*svgElement).points()->currentValue()->valueAsString());
+ } else if (isSVGPathElement(*svgElement)) {
String pathString;
// FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests.
- buildStringFromByteStream(toSVGPathElement(svgElement)->pathByteStream(), pathString, NormalizedParsing);
+ buildStringFromByteStream(toSVGPathElement(*svgElement).pathByteStream(), pathString, NormalizedParsing);
writeNameAndQuotedValue(ts, "data", pathString);
} else
ASSERT_NOT_REACHED();
@@ -380,11 +402,10 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
if (fragments.isEmpty())
return;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- const SVGRenderStyle* svgStyle = textRenderer->style()->svgStyle();
- String text = textBox->textRenderer()->text();
+ const SVGRenderStyle* svgStyle = textRenderer.style()->svgStyle();
+ String text = textBox->textRenderer().text();
unsigned fragmentsSize = fragments.size();
for (unsigned i = 0; i < fragmentsSize; ++i) {
@@ -452,7 +473,7 @@ static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int
static void writeChildren(TextStream& ts, const RenderObject& object, int indent)
{
- for (RenderObject* child = object.firstChild(); child; child = child->nextSibling())
+ for (RenderObject* child = object.slowFirstChild(); child; child = child->nextSibling())
write(ts, *child, indent + 1);
}
@@ -490,7 +511,8 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
ts << "\n";
// Creating a placeholder filter which is passed to the builder.
FloatRect dummyRect;
- RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true);
+ IntRect dummyIntRect;
+ RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyIntRect, dummyRect, dummyRect, true);
if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) {
if (FilterEffect* lastEffect = builder->lastEffect())
lastEffect->externalRepresentation(ts, indent + 1);
@@ -614,7 +636,7 @@ void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int
if (!style)
return;
- ts << " [offset=" << stopElement->offsetCurrentValue() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n";
+ ts << " [offset=" << stopElement->offset()->currentValue()->value() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n";
}
void writeResources(TextStream& ts, const RenderObject& object, int indent)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h
index 055c587df57..63f26442a6d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h
@@ -31,10 +31,6 @@
namespace WebCore {
class Color;
-class FloatRect;
-class FloatSize;
-class Node;
-class RenderImage;
class RenderObject;
class RenderSVGGradientStop;
class RenderSVGImage;
@@ -43,7 +39,6 @@ class RenderSVGShape;
class RenderSVGRoot;
class RenderSVGText;
class AffineTransform;
-class SVGUnitTypes;
// functions used by the main RenderTreeAsText code
void write(TextStream&, const RenderSVGShape&, int indent);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp
index 55545097c0f..23766e3a505 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp
@@ -26,9 +26,10 @@
#include "core/rendering/svg/SVGRenderingContext.h"
-#include "core/frame/Frame.h"
+#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
-#include "core/page/Page.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/Settings.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/svg/RenderSVGImage.h"
#include "core/rendering/svg/RenderSVGResource.h"
@@ -113,23 +114,28 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
// Setup transparency layers before setting up SVG resources!
bool isRenderingMask = isRenderingMaskImage(m_object);
- float opacity = isRenderingMask ? 1 : style->opacity();
- blink::WebBlendMode blendMode = isRenderingMask ? blink::WebBlendModeNormal : style->blendMode();
- if (opacity < 1 || blendMode != blink::WebBlendModeNormal) {
- FloatRect repaintRect = m_object->repaintRectInLocalCoordinates();
-
- if (opacity < 1 || blendMode != blink::WebBlendModeNormal) {
- m_paintInfo->context->clip(repaintRect);
- if (blendMode != blink::WebBlendModeNormal) {
- if (!(m_renderingFlags & RestoreGraphicsContext)) {
- m_paintInfo->context->save();
- m_renderingFlags |= RestoreGraphicsContext;
- }
- m_paintInfo->context->setCompositeOperation(CompositeSourceOver, blendMode);
+ // RenderLayer takes care of root opacity.
+ float opacity = (object->isSVGRoot() || isRenderingMask) ? 1 : style->opacity();
+ bool hasBlendMode = style->hasBlendMode() && !isRenderingMask;
+
+ if (opacity < 1 || hasBlendMode || style->hasIsolation()) {
+ FloatRect repaintRect = m_object->paintInvalidationRectInLocalCoordinates();
+ m_paintInfo->context->clip(repaintRect);
+
+ if (hasBlendMode) {
+ if (!(m_renderingFlags & RestoreGraphicsContext)) {
+ m_paintInfo->context->save();
+ m_renderingFlags |= RestoreGraphicsContext;
}
- m_paintInfo->context->beginTransparencyLayer(opacity);
- m_renderingFlags |= EndOpacityLayer;
+ m_paintInfo->context->setCompositeOperation(CompositeSourceOver, style->blendMode());
}
+
+ m_paintInfo->context->beginTransparencyLayer(opacity);
+
+ if (hasBlendMode)
+ m_paintInfo->context->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
+
+ m_renderingFlags |= EndOpacityLayer;
}
ClipPathOperation* clipPathOperation = style->clipPath();
@@ -197,20 +203,23 @@ float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObje
ASSERT(renderer);
AffineTransform ctm;
- calculateTransformationToOutermostCoordinateSystem(renderer, ctm);
+ // FIXME: calculateDeviceSpaceTransformation() queries layer compositing state - which is not
+ // supported during layout. Hence, the result may not include all CSS transforms.
+ calculateDeviceSpaceTransformation(renderer, ctm);
return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
}
-void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
+void SVGRenderingContext::calculateDeviceSpaceTransformation(const RenderObject* renderer, AffineTransform& absoluteTransform)
{
- ASSERT(renderer);
- absoluteTransform = currentContentTransformation();
+ // FIXME: trying to compute a device space transform at record time is wrong. All clients
+ // should be updated to avoid relying on this information, and the method should be removed.
- float deviceScaleFactor = 1;
- if (Page* page = renderer->document().page())
- deviceScaleFactor = page->deviceScaleFactor();
+ ASSERT(renderer);
+ // We're about to possibly clear renderer, so save the deviceScaleFactor now.
+ float deviceScaleFactor = renderer->document().frameHost()->deviceScaleFactor();
// Walk up the render tree, accumulating SVG transforms.
+ absoluteTransform = currentContentTransformation();
while (renderer) {
absoluteTransform = renderer->localToParentTransform() * absoluteTransform;
if (renderer->isSVGRoot())
@@ -220,23 +229,22 @@ void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(con
// Continue walking up the layer tree, accumulating CSS transforms.
RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
- while (layer) {
- if (TransformationMatrix* layerTransform = layer->transform())
- absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;
-
+ while (layer && layer->isAllowedToQueryCompositingState()) {
// We can stop at compositing layers, to match the backing resolution.
// FIXME: should we be computing the transform to the nearest composited layer,
// or the nearest composited layer that does not paint into its ancestor?
// I think this is the nearest composited ancestor since we will inherit its
// transforms in the composited layer tree.
- if (layer->hasCompositedLayerMapping())
+ if (layer->compositingState() != NotComposited)
break;
+ if (TransformationMatrix* layerTransform = layer->transform())
+ absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;
+
layer = layer->parent();
}
- if (deviceScaleFactor != 1)
- absoluteTransform.scale(deviceScaleFactor);
+ absoluteTransform.scale(deviceScaleFactor);
}
void SVGRenderingContext::renderSubtree(GraphicsContext* context, RenderObject* item, const AffineTransform& subtreeContentTransformation)
@@ -278,7 +286,7 @@ bool SVGRenderingContext::bufferForeground(OwnPtr<ImageBuffer>& imageBuffer)
// Invalidate an existing buffer if the scale is not correct.
if (imageBuffer) {
- AffineTransform transform = m_paintInfo->context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
+ AffineTransform transform = m_paintInfo->context->getCTM();
IntSize expandedBoundingBox = expandedIntSize(boundingBox.size());
IntSize bufferSize(static_cast<int>(ceil(expandedBoundingBox.width() * transform.xScale())), static_cast<int>(ceil(expandedBoundingBox.height() * transform.yScale())));
if (bufferSize != imageBuffer->size())
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h
index 742e0a09997..3fcda0ae099 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h
@@ -79,7 +79,7 @@ public:
static void renderSubtree(GraphicsContext*, RenderObject*, const AffineTransform&);
static float calculateScreenFontSizeScalingFactor(const RenderObject*);
- static void calculateTransformationToOutermostCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
+ static void calculateDeviceSpaceTransformation(const RenderObject*, AffineTransform& absoluteTransform);
static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
static void clear2DRotation(AffineTransform&);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp
index 5c42dbcef69..dcb5113bff7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/svg/SVGResources.h"
-#include "SVGNames.h"
+#include "core/SVGNames.h"
#include "core/rendering/style/SVGRenderStyle.h"
#include "core/rendering/svg/RenderSVGResourceClipper.h"
#include "core/rendering/svg/RenderSVGResourceFilter.h"
@@ -38,6 +38,8 @@
namespace WebCore {
+using namespace SVGNames;
+
SVGResources::SVGResources()
: m_linkedResource(0)
{
@@ -49,39 +51,45 @@ static HashSet<AtomicString>& clipperFilterMaskerTags()
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());
- s_tagList.add(SVGNames::circleTag.localName());
- s_tagList.add(SVGNames::ellipseTag.localName());
- s_tagList.add(SVGNames::glyphTag.localName());
- s_tagList.add(SVGNames::gTag.localName());
- s_tagList.add(SVGNames::imageTag.localName());
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::markerTag.localName());
- s_tagList.add(SVGNames::maskTag.localName());
- s_tagList.add(SVGNames::missing_glyphTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
- s_tagList.add(SVGNames::rectTag.localName());
- s_tagList.add(SVGNames::svgTag.localName());
- s_tagList.add(SVGNames::textTag.localName());
- s_tagList.add(SVGNames::useTag.localName());
+ s_tagList.add(aTag.localName());
+ s_tagList.add(circleTag.localName());
+ s_tagList.add(ellipseTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(glyphTag.localName());
+#endif
+ s_tagList.add(gTag.localName());
+ s_tagList.add(imageTag.localName());
+ s_tagList.add(lineTag.localName());
+ s_tagList.add(markerTag.localName());
+ s_tagList.add(maskTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(missing_glyphTag.localName());
+#endif
+ s_tagList.add(pathTag.localName());
+ s_tagList.add(polygonTag.localName());
+ s_tagList.add(polylineTag.localName());
+ s_tagList.add(rectTag.localName());
+ s_tagList.add(svgTag.localName());
+ s_tagList.add(textTag.localName());
+ s_tagList.add(useTag.localName());
// 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());
+ s_tagList.add(clipPathTag.localName());
// 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());
- s_tagList.add(SVGNames::textPathTag.localName());
- s_tagList.add(SVGNames::tspanTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(altGlyphTag.localName());
+#endif
+ s_tagList.add(textPathTag.localName());
+ s_tagList.add(tspanTag.localName());
// Not listed in the definitions is the foreignObject element, but clip-path
// is a supported attribute.
- s_tagList.add(SVGNames::foreignObjectTag.localName());
+ s_tagList.add(foreignObjectTag.localName());
// Elements that we ignore, as it doesn't make any sense.
// defs, pattern, switch (FIXME: Mail SVG WG about these)
@@ -91,34 +99,36 @@ static HashSet<AtomicString>& clipperFilterMaskerTags()
return s_tagList;
}
-static HashSet<AtomicString>& markerTags()
+bool SVGResources::supportsMarkers(const SVGElement& element)
{
DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
+ s_tagList.add(lineTag.localName());
+ s_tagList.add(pathTag.localName());
+ s_tagList.add(polygonTag.localName());
+ s_tagList.add(polylineTag.localName());
}
- return s_tagList;
+ return s_tagList.contains(element.localName());
}
static HashSet<AtomicString>& fillAndStrokeTags()
{
DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::altGlyphTag.localName());
- s_tagList.add(SVGNames::circleTag.localName());
- s_tagList.add(SVGNames::ellipseTag.localName());
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
- s_tagList.add(SVGNames::rectTag.localName());
- s_tagList.add(SVGNames::textTag.localName());
- s_tagList.add(SVGNames::textPathTag.localName());
- s_tagList.add(SVGNames::tspanTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(altGlyphTag.localName());
+#endif
+ s_tagList.add(circleTag.localName());
+ s_tagList.add(ellipseTag.localName());
+ s_tagList.add(lineTag.localName());
+ s_tagList.add(pathTag.localName());
+ s_tagList.add(polygonTag.localName());
+ s_tagList.add(polylineTag.localName());
+ s_tagList.add(rectTag.localName());
+ s_tagList.add(textTag.localName());
+ s_tagList.add(textPathTag.localName());
+ s_tagList.add(tspanTag.localName());
}
return s_tagList;
@@ -128,37 +138,52 @@ static HashSet<AtomicString>& chainableResourceTags()
{
DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::linearGradientTag.localName());
- s_tagList.add(SVGNames::filterTag.localName());
- s_tagList.add(SVGNames::patternTag.localName());
- s_tagList.add(SVGNames::radialGradientTag.localName());
+ s_tagList.add(linearGradientTag.localName());
+ s_tagList.add(filterTag.localName());
+ s_tagList.add(patternTag.localName());
+ s_tagList.add(radialGradientTag.localName());
}
return s_tagList;
}
-static inline String targetReferenceFromResource(SVGElement* element)
+static inline AtomicString targetReferenceFromResource(SVGElement& element)
{
String target;
- if (element->hasTagName(SVGNames::patternTag))
- target = toSVGPatternElement(element)->hrefCurrentValue();
- else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
- target = toSVGGradientElement(element)->hrefCurrentValue();
- else if (element->hasTagName(SVGNames::filterTag))
- target = toSVGFilterElement(element)->hrefCurrentValue();
+ if (isSVGPatternElement(element))
+ target = toSVGPatternElement(element).href()->currentValue()->value();
+ else if (isSVGGradientElement(element))
+ target = toSVGGradientElement(element).href()->currentValue()->value();
+ else if (isSVGFilterElement(element))
+ target = toSVGFilterElement(element).href()->currentValue()->value();
else
ASSERT_NOT_REACHED();
- return SVGURIReference::fragmentIdentifierFromIRIString(target, element->document());
+ return SVGURIReference::fragmentIdentifierFromIRIString(target, element.treeScope());
+}
+
+static inline bool svgPaintTypeHasURL(SVGPaint::SVGPaintType paintType)
+{
+ switch (paintType) {
+ case SVGPaint::SVG_PAINTTYPE_URI_NONE:
+ case SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR:
+ case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR:
+ case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR:
+ case SVGPaint::SVG_PAINTTYPE_URI:
+ return true;
+ default:
+ break;
+ }
+ return false;
}
-static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
+static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(TreeScope& treeScope, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
{
- if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)
+ if (!svgPaintTypeHasURL(paintType))
return 0;
- id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document);
- RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id);
+ id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, treeScope);
+ RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(treeScope, id);
if (!container) {
hasPendingResource = true;
return 0;
@@ -171,10 +196,10 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document&
return container;
}
-static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element)
+static inline void registerPendingResource(SVGDocumentExtensions& extensions, const AtomicString& id, SVGElement* element)
{
ASSERT(element);
- extensions->addPendingResource(id, element);
+ extensions.addPendingResource(id, element);
}
bool SVGResources::hasResourceData() const
@@ -206,10 +231,9 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
if (!element)
return nullptr;
- Document& document = object->document();
+ TreeScope& treeScope = element->treeScope();
- SVGDocumentExtensions* extensions = document.accessSVGExtensions();
- ASSERT(extensions);
+ SVGDocumentExtensions& extensions = object->document().accessSVGExtensions();
const AtomicString& tagName = element->localName();
if (tagName.isNull())
@@ -218,35 +242,35 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
OwnPtr<SVGResources> resources;
if (clipperFilterMaskerTags().contains(tagName)) {
if (style->hasClipper()) {
- AtomicString id(style->clipperResource());
- if (!ensureResources(resources)->setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
+ AtomicString id = style->clipperResource();
+ if (!ensureResources(resources)->setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(treeScope, id)))
registerPendingResource(extensions, id, element);
}
if (style->hasFilter()) {
- AtomicString id(style->filterResource());
- if (!ensureResources(resources)->setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
+ AtomicString id = style->filterResource();
+ if (!ensureResources(resources)->setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(treeScope, id)))
registerPendingResource(extensions, id, element);
}
if (style->hasMasker()) {
- AtomicString id(style->maskerResource());
- if (!ensureResources(resources)->setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id)))
+ AtomicString id = style->maskerResource();
+ if (!ensureResources(resources)->setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(treeScope, id)))
registerPendingResource(extensions, id, element);
}
}
- if (markerTags().contains(tagName) && style->hasMarkers()) {
- AtomicString markerStartId(style->markerStartResource());
- if (!ensureResources(resources)->setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId)))
+ if (style->hasMarkers() && supportsMarkers(*element)) {
+ const AtomicString& markerStartId = style->markerStartResource();
+ if (!ensureResources(resources)->setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(treeScope, markerStartId)))
registerPendingResource(extensions, markerStartId, element);
- AtomicString markerMidId(style->markerMidResource());
- if (!ensureResources(resources)->setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId)))
+ const AtomicString& markerMidId = style->markerMidResource();
+ if (!ensureResources(resources)->setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(treeScope, markerMidId)))
registerPendingResource(extensions, markerMidId, element);
- AtomicString markerEndId(style->markerEndResource());
- if (!ensureResources(resources)->setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId)))
+ const AtomicString& markerEndId = style->markerEndResource();
+ if (!ensureResources(resources)->setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(treeScope, style->markerEndResource())))
registerPendingResource(extensions, markerEndId, element);
}
@@ -254,7 +278,7 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
if (style->hasFill()) {
bool hasPendingResource = false;
AtomicString id;
- RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(document, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource);
+ RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(treeScope, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource);
if (!ensureResources(resources)->setFill(resource) && hasPendingResource) {
registerPendingResource(extensions, id, element);
}
@@ -263,7 +287,7 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
if (style->hasStroke()) {
bool hasPendingResource = false;
AtomicString id;
- RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(document, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource);
+ RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(treeScope, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource);
if (!ensureResources(resources)->setStroke(resource) && hasPendingResource) {
registerPendingResource(extensions, id, element);
}
@@ -271,8 +295,8 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
}
if (chainableResourceTags().contains(tagName)) {
- AtomicString id(targetReferenceFromResource(element));
- if (!ensureResources(resources)->setLinkedResource(getRenderSVGResourceContainerById(document, id)))
+ AtomicString id = targetReferenceFromResource(*element);
+ if (!ensureResources(resources)->setLinkedResource(getRenderSVGResourceContainerById(treeScope, id)))
registerPendingResource(extensions, id, element);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h
index 8eb10adcb4e..41cdf2569d8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h
@@ -20,6 +20,7 @@
#ifndef SVGResources_h
#define SVGResources_h
+#include "wtf/FastAllocBase.h"
#include "wtf/HashSet.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
@@ -27,13 +28,13 @@
namespace WebCore {
-class Document;
class RenderObject;
class RenderSVGResourceClipper;
class RenderSVGResourceContainer;
class RenderSVGResourceFilter;
class RenderSVGResourceMarker;
class RenderSVGResourceMasker;
+class SVGElement;
class SVGRenderStyle;
// Holds a set of resources associated with a RenderObject
@@ -45,6 +46,8 @@ public:
static PassOwnPtr<SVGResources> buildResources(const RenderObject*, const SVGRenderStyle*);
void layoutIfNeeded();
+ static bool supportsMarkers(const SVGElement&);
+
// Ordinary resources
RenderSVGResourceClipper* clipper() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->clipper : 0; }
RenderSVGResourceMarker* markerStart() const { return m_markerData ? m_markerData->markerStart : 0; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp
index 7a8ed18b4d8..b8ba7101ded 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/svg/SVGResourcesCache.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCycleSolver.h"
@@ -51,7 +51,7 @@ void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const
return;
// Put object in cache.
- SVGResources* resources = m_cache.set(object, newResources.release()).iterator->value.get();
+ SVGResources* resources = m_cache.set(object, newResources.release()).storedValue->value.get();
// Run cycle-detection _afterwards_, so self-references can be caught as well.
SVGResourcesCycleSolver solver(object, resources);
@@ -85,10 +85,8 @@ static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObje
{
Document& document = renderer->document();
- SVGDocumentExtensions* extensions = document.accessSVGExtensions();
- ASSERT(extensions);
-
- SVGResourcesCache* cache = extensions->resourcesCache();
+ SVGDocumentExtensions& extensions = document.accessSVGExtensions();
+ SVGResourcesCache* cache = extensions.resourcesCache();
ASSERT(cache);
return cache;
@@ -124,11 +122,11 @@ void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifferen
ASSERT(renderer->node());
ASSERT(renderer->node()->isSVGElement());
- if (diff == StyleDifferenceEqual || !renderer->parent())
+ if (diff.hasNoChange() || !renderer->parent())
return;
// In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint.
- if (renderer->isSVGResourceFilterPrimitive() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrColorChange))
+ if (renderer->isSVGResourceFilterPrimitive() && !diff.needsLayout())
return;
// Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a renderer.
@@ -194,9 +192,9 @@ void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
// Mark users of destroyed resources as pending resolution based on the id of the old resource.
Element* resourceElement = resource->element();
Element* clientElement = toElement(it->key->node());
- SVGDocumentExtensions* extensions = clientElement->document().accessSVGExtensions();
+ SVGDocumentExtensions& extensions = clientElement->document().accessSVGExtensions();
- extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
+ extensions.addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h
index ff5e9f903af..7bf878e7237 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h
@@ -20,7 +20,8 @@
#ifndef SVGResourcesCache_h
#define SVGResourcesCache_h
-#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/style/StyleDifference.h"
+#include "wtf/FastAllocBase.h"
#include "wtf/HashMap.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
index efa1b933394..ae7e954fb04 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
@@ -47,117 +47,83 @@ SVGResourcesCycleSolver::~SVGResourcesCycleSolver()
{
}
-bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) const
-{
- ASSERT(renderer);
-
- // First operate on the resources of the given renderer.
- // <marker id="a"> <path marker-start="url(#b)"/> ...
- // <marker id="b" marker-start="url(#a)"/>
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) {
- HashSet<RenderSVGResourceContainer*> resourceSet;
- resources->buildSetOfResources(resourceSet);
-
- // Walk all resources and check wheter they reference any resource contained in the resources set.
- HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) {
- if (m_allResources.contains(*it))
- return true;
- }
- }
+struct ActiveFrame {
+ typedef SVGResourcesCycleSolver::ResourceSet ResourceSet;
- // Then operate on the child resources of the given renderer.
- // <marker id="a"> <path marker-start="url(#b)"/> ...
- // <marker id="b"> <path marker-start="url(#a)"/> ...
- for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
- SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child);
- if (!childResources)
- continue;
+ ActiveFrame(ResourceSet& activeSet, RenderSVGResourceContainer* resource)
+ : m_activeSet(activeSet)
+ , m_resource(resource)
+ {
+ m_activeSet.add(m_resource);
+ }
+ ~ActiveFrame()
+ {
+ m_activeSet.remove(m_resource);
+ }
- // A child of the given 'resource' contains resources.
- HashSet<RenderSVGResourceContainer*> childSet;
- childResources->buildSetOfResources(childSet);
+ ResourceSet& m_activeSet;
+ RenderSVGResourceContainer* m_resource;
+};
- // Walk all child resources and check wheter they reference any resource contained in the resources set.
- HashSet<RenderSVGResourceContainer*>::iterator end = childSet.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = childSet.begin(); it != end; ++it) {
- if (m_allResources.contains(*it))
- return true;
+bool SVGResourcesCycleSolver::resourceContainsCycles(RenderSVGResourceContainer* resource)
+{
+ // If we've traversed this sub-graph before and no cycles were observed, then
+ // reuse that result.
+ if (m_dagCache.contains(resource))
+ return false;
+
+ ActiveFrame frame(m_activeResources, resource);
+
+ RenderObject* node = resource;
+ while (node) {
+ // Skip subtrees which are themselves resources. (They will be
+ // processed - if needed - when they are actually referenced.)
+ if (node != resource && node->isSVGResourceContainer()) {
+ node = node->nextInPreOrderAfterChildren(resource);
+ continue;
}
-
- // Walk children recursively, stop immediately if we found a cycle
- if (resourceContainsCycles(child))
- return true;
+ if (SVGResources* nodeResources = SVGResourcesCache::cachedResourcesForRenderObject(node)) {
+ // Fetch all the resources referenced by |node|.
+ ResourceSet nodeSet;
+ nodeResources->buildSetOfResources(nodeSet);
+
+ // Iterate resources referenced by |node|.
+ ResourceSet::iterator end = nodeSet.end();
+ for (ResourceSet::iterator it = nodeSet.begin(); it != end; ++it) {
+ if (m_activeResources.contains(*it) || resourceContainsCycles(*it))
+ return true;
+ }
+ }
+ node = node->nextInPreOrder(resource);
}
+ // No cycles found in (or from) this resource. Add it to the "DAG cache".
+ m_dagCache.add(resource);
return false;
}
void SVGResourcesCycleSolver::resolveCycles()
{
- ASSERT(m_allResources.isEmpty());
-
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nBefore cycle detection:\n");
- m_resources->dump(m_renderer);
-#endif
-
- // Stash all resources into a HashSet for the ease of traversing.
- HashSet<RenderSVGResourceContainer*> localResources;
- m_resources->buildSetOfResources(localResources);
- ASSERT(!localResources.isEmpty());
-
- // Add all parent resource containers to the HashSet.
- HashSet<RenderSVGResourceContainer*> parentResources;
- RenderObject* parent = m_renderer->parent();
- while (parent) {
- if (parent->isSVGResourceContainer())
- parentResources.add(toRenderSVGResourceContainer(parent));
- parent = parent->parent();
- }
+ ASSERT(m_activeResources.isEmpty());
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n");
- {
- fprintf(stderr, "Local resources:\n");
- HashSet<RenderSVGResourceContainer*>::iterator end = localResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
-
- fprintf(stderr, "Parent resources:\n");
- end = parentResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
- }
-#endif
-
- // Build combined set of local and parent resources.
- m_allResources = localResources;
- HashSet<RenderSVGResourceContainer*>::iterator end = parentResources.end();
- 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 the starting RenderObject is a resource container itself, then add it
+ // to the active set (to break direct self-references.)
if (m_renderer->isSVGResourceContainer())
- m_allResources.add(toRenderSVGResourceContainer(m_renderer));
+ m_activeResources.add(toRenderSVGResourceContainer(m_renderer));
- ASSERT(!m_allResources.isEmpty());
+ ResourceSet localResources;
+ m_resources->buildSetOfResources(localResources);
- // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
- // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it.
- end = localResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) {
- RenderSVGResourceContainer* resource = *it;
- if (parentResources.contains(resource) || resourceContainsCycles(resource))
- breakCycle(resource);
+ // This performs a depth-first search for a back-edge in all the
+ // (potentially disjoint) graphs formed by the resources referenced by
+ // |m_renderer|.
+ ResourceSet::iterator end = localResources.end();
+ for (ResourceSet::iterator it = localResources.begin(); it != end; ++it) {
+ if (m_activeResources.contains(*it) || resourceContainsCycles(*it))
+ breakCycle(*it);
}
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nAfter cycle detection:\n");
- m_resources->dump(m_renderer);
-#endif
-
- m_allResources.clear();
+ m_activeResources.clear();
}
void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer* resourceLeadingToCycle)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h
index cadaa5a311e..aadd9f6fa54 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h
@@ -37,13 +37,17 @@ public:
void resolveCycles();
+ typedef HashSet<RenderSVGResourceContainer*> ResourceSet;
+
private:
- bool resourceContainsCycles(RenderObject*) const;
+ bool resourceContainsCycles(RenderSVGResourceContainer*);
void breakCycle(RenderSVGResourceContainer*);
RenderObject* m_renderer;
SVGResources* m_resources;
- HashSet<RenderSVGResourceContainer*> m_allResources;
+
+ ResourceSet m_activeResources;
+ ResourceSet m_dagCache;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp
index ec9a953d1b3..4cd80101e37 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp
@@ -24,7 +24,6 @@
#include "config.h"
#include "core/rendering/svg/SVGRootInlineBox.h"
-#include "SVGNames.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGText.h"
#include "core/rendering/svg/SVGInlineFlowBox.h"
@@ -33,15 +32,12 @@
namespace WebCore {
-void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
- RenderObject* boxRenderer = renderer();
- ASSERT(boxRenderer);
-
- bool isPrinting = renderer()->document().printing();
+ bool isPrinting = renderer().document().printing();
bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
PaintInfo childPaintInfo(paintInfo);
@@ -54,35 +50,29 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
}
}
- SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext);
+ SVGRenderingContext renderingContext(&renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer()));
-
- child->paint(paintInfo, LayoutPoint(), 0, 0);
- }
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->paint(paintInfo, paintOffset, 0, 0);
}
}
-void SVGRootInlineBox::markDirty(bool dirty)
+void SVGRootInlineBox::markDirty()
{
- if (dirty)
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
- child->markDirty(true);
- RootInlineBox::markDirty(dirty);
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->markDirty();
+ RootInlineBox::markDirty();
}
void SVGRootInlineBox::computePerCharacterLayoutInformation()
{
- RenderSVGText* textRoot = toRenderSVGText(block());
- ASSERT(textRoot);
+ RenderSVGText& textRoot = toRenderSVGText(block());
- Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes();
+ Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot.layoutAttributes();
if (layoutAttributes.isEmpty())
return;
- if (textRoot->needsReordering())
+ if (textRoot.needsReordering())
reorderValueLists(layoutAttributes);
// Perform SVG text layout phase two (see SVGTextLayoutEngine for details).
@@ -103,24 +93,23 @@ void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGText
{
for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
if (child->isSVGInlineTextBox()) {
- ASSERT(child->renderer());
- ASSERT(child->renderer()->isSVGInlineText());
+ ASSERT(child->renderer().isSVGInlineText());
characterLayout.layoutInlineTextBox(toSVGInlineTextBox(child));
} else {
// Skip generated content.
- Node* node = child->renderer()->node();
+ Node* node = child->renderer().node();
if (!node)
continue;
SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
- bool isTextPath = node->hasTagName(SVGNames::textPathTag);
+ bool isTextPath = isSVGTextPathElement(*node);
if (isTextPath) {
// Build text chunks for all <textPath> children, using the line layout algorithm.
// This is needeed as text-anchor is just an additional startOffset for text paths.
SVGTextLayoutEngine lineLayout(characterLayout.layoutAttributes());
layoutCharactersInTextBoxes(flowBox, lineLayout);
- characterLayout.beginTextPathLayout(child->renderer(), lineLayout);
+ characterLayout.beginTextPathLayout(&child->renderer(), lineLayout);
}
layoutCharactersInTextBoxes(flowBox, characterLayout);
@@ -136,8 +125,7 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
FloatRect boxRect;
if (child->isSVGInlineTextBox()) {
- ASSERT(child->renderer());
- ASSERT(child->renderer()->isSVGInlineText());
+ ASSERT(child->renderer().isSVGInlineText());
SVGInlineTextBox* textBox = toSVGInlineTextBox(child);
boxRect = textBox->calculateBoundaries();
@@ -147,7 +135,7 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
textBox->setLogicalHeight(boxRect.height());
} else {
// Skip generated content.
- if (!child->renderer()->node())
+ if (!child->renderer().node())
continue;
SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
@@ -166,18 +154,17 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect)
{
- RenderBlockFlow* parentBlock = block();
- ASSERT(parentBlock);
+ RenderBlockFlow& parentBlock = block();
// Finally, assign the root block position, now that all content is laid out.
LayoutRect boundingRect = enclosingLayoutRect(childRect);
- parentBlock->setLocation(boundingRect.location());
- parentBlock->setSize(boundingRect.size());
+ parentBlock.setLocation(boundingRect.location());
+ parentBlock.setSize(boundingRect.size());
// Position all children relative to the parent block.
for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
// Skip generated content.
- if (!child->renderer()->node())
+ if (!child->renderer().node())
continue;
child->adjustPosition(-childRect.x(), -childRect.y());
}
@@ -221,21 +208,11 @@ static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAtt
SVGCharacterDataMap::iterator itLast = lastAttributes->characterDataMap().find(lastPosition + 1);
bool firstPresent = itFirst != firstAttributes->characterDataMap().end();
bool lastPresent = itLast != lastAttributes->characterDataMap().end();
- if (!firstPresent && !lastPresent)
+ // We only want to perform the swap if both inline boxes are absolutely
+ // positioned.
+ if (!firstPresent || !lastPresent)
return;
-
- if (firstPresent && lastPresent) {
- std::swap(itFirst->value, itLast->value);
- return;
- }
-
- if (firstPresent && !lastPresent) {
- lastAttributes->characterDataMap().set(lastPosition + 1, itFirst->value);
- return;
- }
-
- // !firstPresent && lastPresent
- firstAttributes->characterDataMap().set(firstPosition + 1, itLast->value);
+ std::swap(itFirst->value, itLast->value);
}
static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext,
@@ -282,12 +259,12 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve
// Reordering is only necessary for BiDi text that is _absolutely_ positioned.
if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
- RenderSVGInlineText* firstContext = toRenderSVGInlineText(firstTextBox->textRenderer());
- RenderSVGInlineText* lastContext = toRenderSVGInlineText(lastTextBox->textRenderer());
+ RenderSVGInlineText& firstContext = toRenderSVGInlineText(firstTextBox->textRenderer());
+ RenderSVGInlineText& lastContext = toRenderSVGInlineText(lastTextBox->textRenderer());
SVGTextLayoutAttributes* firstAttributes = 0;
SVGTextLayoutAttributes* lastAttributes = 0;
- findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes);
+ findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes);
swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h
index efbe2f6b79b..862c9b24a4e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h
@@ -29,24 +29,22 @@
namespace WebCore {
-class SVGInlineTextBox;
-
class SVGRootInlineBox FINAL : public RootInlineBox {
public:
- SVGRootInlineBox(RenderBlockFlow* block)
+ SVGRootInlineBox(RenderBlockFlow& block)
: RootInlineBox(block)
, m_logicalHeight(0)
{
}
- virtual bool isSVGRootInlineBox() const OVERRIDE FINAL { return true; }
+ virtual bool isSVGRootInlineBox() const OVERRIDE { return true; }
- virtual float virtualLogicalHeight() const OVERRIDE FINAL { return m_logicalHeight; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return m_logicalHeight; }
void setLogicalHeight(float height) { m_logicalHeight = height; }
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE FINAL;
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
- virtual void markDirty(bool dirty = true) OVERRIDE FINAL;
+ virtual void markDirty() OVERRIDE;
void computePerCharacterLayoutInformation();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
index d26d868fff1..488fbd4bddd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
@@ -91,10 +91,9 @@ void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxe
SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
ASSERT(textBox);
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- const RenderStyle* style = textRenderer->style();
+ const RenderStyle* style = toRenderSVGInlineText(textBox->textRenderer()).style();
ASSERT(style);
const SVGRenderStyle* svgStyle = style->svgStyle();
@@ -125,11 +124,14 @@ void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxe
// Handle 'lengthAdjust' property.
float desiredTextLength = 0;
- if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textRenderer->parent())) {
+ if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textRenderer.parent())) {
SVGLengthContext lengthContext(textContentElement);
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+ if (textContentElement->textLengthIsSpecifiedByUser())
+ desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
+ else
+ desiredTextLength = 0;
- switch (textContentElement->lengthAdjustCurrentValue()) {
+ switch (textContentElement->lengthAdjust()->currentValue()->enumValue()) {
case SVGLengthAdjustUnknown:
break;
case SVGLengthAdjustSpacing:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
index 7c65a7e55e6..cbf018dc87a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -23,6 +23,7 @@
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGTextMetricsBuilder.h"
#include "core/svg/SVGTextPositioningElement.h"
namespace WebCore {
@@ -53,7 +54,7 @@ void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render
buildCharacterDataMap(textRoot);
}
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
+ SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
}
bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText* textRoot)
@@ -72,14 +73,14 @@ bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSV
return false;
buildCharacterDataMap(textRoot);
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
+ SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
return true;
}
void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text)
{
ASSERT(text);
- m_metricsBuilder.measureTextRenderer(text);
+ SVGTextMetricsBuilder::measureTextRenderer(text);
}
static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, UChar& lastCharacter)
@@ -104,7 +105,7 @@ void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject
{
ASSERT(!start->isSVGText() || m_textPositions.isEmpty());
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = start->slowFirstChild(); child; child = child->nextSibling()) {
if (child->isSVGInlineText()) {
processRenderSVGInlineText(toRenderSVGInlineText(child), m_textLength, lastCharacter);
continue;
@@ -163,43 +164,43 @@ void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRo
static inline void updateCharacterData(unsigned i, float& lastRotation, SVGCharacterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xList, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList* dyList, const SVGNumberList* rotateList)
{
if (xList)
- data.x = xList->at(i).value(lengthContext);
+ data.x = xList->at(i)->value(lengthContext);
if (yList)
- data.y = yList->at(i).value(lengthContext);
+ data.y = yList->at(i)->value(lengthContext);
if (dxList)
- data.dx = dxList->at(i).value(lengthContext);
+ data.dx = dxList->at(i)->value(lengthContext);
if (dyList)
- data.dy = dyList->at(i).value(lengthContext);
+ data.dy = dyList->at(i)->value(lengthContext);
if (rotateList) {
- data.rotate = rotateList->at(i).value();
+ data.rotate = rotateList->at(i)->value();
lastRotation = data.rotate;
}
}
void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& position)
{
- const SVGLengthList& xList = position.element->xCurrentValue();
- const SVGLengthList& yList = position.element->yCurrentValue();
- const SVGLengthList& dxList = position.element->dxCurrentValue();
- const SVGLengthList& dyList = position.element->dyCurrentValue();
- const SVGNumberList& rotateList = position.element->rotateCurrentValue();
-
- unsigned xListSize = xList.size();
- unsigned yListSize = yList.size();
- unsigned dxListSize = dxList.size();
- unsigned dyListSize = dyList.size();
- unsigned rotateListSize = rotateList.size();
+ RefPtr<SVGLengthList> xList = position.element->x()->currentValue();
+ RefPtr<SVGLengthList> yList = position.element->y()->currentValue();
+ RefPtr<SVGLengthList> dxList = position.element->dx()->currentValue();
+ RefPtr<SVGLengthList> dyList = position.element->dy()->currentValue();
+ RefPtr<SVGNumberList> rotateList = position.element->rotate()->currentValue();
+
+ unsigned xListSize = xList->length();
+ unsigned yListSize = yList->length();
+ unsigned dxListSize = dxList->length();
+ unsigned dyListSize = dyList->length();
+ unsigned rotateListSize = rotateList->length();
if (!xListSize && !yListSize && !dxListSize && !dyListSize && !rotateListSize)
return;
float lastRotation = SVGTextLayoutAttributes::emptyValue();
SVGLengthContext lengthContext(position.element);
for (unsigned i = 0; i < position.length; ++i) {
- const SVGLengthList* xListPtr = i < xListSize ? &xList : 0;
- const SVGLengthList* yListPtr = i < yListSize ? &yList : 0;
- const SVGLengthList* dxListPtr = i < dxListSize ? &dxList : 0;
- const SVGLengthList* dyListPtr = i < dyListSize ? &dyList : 0;
- const SVGNumberList* rotateListPtr = i < rotateListSize ? &rotateList : 0;
+ const SVGLengthList* xListPtr = i < xListSize ? xList.get() : 0;
+ const SVGLengthList* yListPtr = i < yListSize ? yList.get() : 0;
+ const SVGLengthList* dxListPtr = i < dxListSize ? dxList.get() : 0;
+ const SVGLengthList* dyListPtr = i < dyListSize ? dyList.get() : 0;
+ const SVGNumberList* rotateListPtr = i < rotateListSize ? rotateList.get() : 0;
if (!xListPtr && !yListPtr && !dxListPtr && !dyListPtr && !rotateListPtr)
break;
@@ -218,7 +219,7 @@ void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& po
if (lastRotation == SVGTextLayoutAttributes::emptyValue())
return;
- for (unsigned i = rotateList.size(); i < position.length; ++i) {
+ for (unsigned i = rotateList->length(); i < position.length; ++i) {
SVGCharacterDataMap::iterator it = m_characterDataMap.find(position.start + i + 1);
if (it == m_characterDataMap.end()) {
SVGCharacterData data;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
index d92c125f47f..82d2d064660 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
@@ -20,7 +20,7 @@
#ifndef SVGTextLayoutAttributesBuilder_h
#define SVGTextLayoutAttributesBuilder_h
-#include "core/rendering/svg/SVGTextMetricsBuilder.h"
+#include "core/rendering/svg/SVGTextLayoutAttributes.h"
#include "wtf/Vector.h"
namespace WebCore {
@@ -73,7 +73,6 @@ private:
unsigned m_textLength;
Vector<TextPosition> m_textPositions;
SVGCharacterDataMap m_characterDataMap;
- SVGTextMetricsBuilder m_metricsBuilder;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
index 0ade353f4a7..fc5dc792329 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
@@ -47,6 +47,7 @@ SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou
, m_dy(0)
, m_isVerticalText(false)
, m_inPathLayout(false)
+ , m_textPathCalculator(0)
, m_textPathLength(0)
, m_textPathCurrentOffset(0)
, m_textPathSpacing(0)
@@ -148,7 +149,7 @@ bool SVGTextLayoutEngine::parentDefinesTextLength(RenderObject* parent) const
while (currentParent) {
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(currentParent)) {
SVGLengthContext lengthContext(textContentElement);
- if (textContentElement->lengthAdjustCurrentValue() == SVGLengthAdjustSpacing && textContentElement->specifiedTextLength().value(lengthContext) > 0)
+ if (textContentElement->lengthAdjust()->currentValue()->enumValue() == SVGLengthAdjustSpacing && textContentElement->textLengthIsSpecifiedByUser())
return true;
}
@@ -169,11 +170,12 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
m_inPathLayout = true;
RenderSVGTextPath* textPath = toRenderSVGTextPath(object);
- m_textPath = textPath->layoutPath();
- if (m_textPath.isEmpty())
+ Path path = textPath->layoutPath();
+ if (path.isEmpty())
return;
+ m_textPathCalculator = new Path::PositionCalculator(path);
m_textPathStartOffset = textPath->startOffset();
- m_textPathLength = m_textPath.length();
+ m_textPathLength = path.length();
if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1)
m_textPathStartOffset *= m_textPathLength;
@@ -206,8 +208,11 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) {
SVGLengthContext lengthContext(textContentElement);
- lengthAdjust = textContentElement->lengthAdjustCurrentValue();
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+ lengthAdjust = textContentElement->lengthAdjust()->currentValue()->enumValue();
+ if (textContentElement->textLengthIsSpecifiedByUser())
+ desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
+ else
+ desiredTextLength = 0;
}
if (!desiredTextLength)
@@ -222,7 +227,8 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
void SVGTextLayoutEngine::endTextPathLayout()
{
m_inPathLayout = false;
- m_textPath = Path();
+ delete m_textPathCalculator;
+ m_textPathCalculator = 0;
m_textPathLength = 0;
m_textPathStartOffset = 0;
m_textPathCurrentOffset = 0;
@@ -234,18 +240,17 @@ void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox)
{
ASSERT(textBox);
- RenderSVGInlineText* text = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(text);
- ASSERT(text->parent());
- ASSERT(text->parent()->node());
- ASSERT(text->parent()->node()->isSVGElement());
+ RenderSVGInlineText& text = toRenderSVGInlineText(textBox->textRenderer());
+ ASSERT(text.parent());
+ ASSERT(text.parent()->node());
+ ASSERT(text.parent()->node()->isSVGElement());
- const RenderStyle* style = text->style();
+ const RenderStyle* style = text.style();
ASSERT(style);
textBox->clearTextFragments();
m_isVerticalText = style->svgStyle()->isVerticalWritingMode();
- layoutTextOnLineOrPath(textBox, text, style);
+ layoutTextOnLineOrPath(textBox, &text, style);
if (m_inPathLayout) {
m_pathLayoutBoxes.append(textBox);
@@ -421,7 +426,7 @@ void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& vis
void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, RenderSVGInlineText* text, const RenderStyle* style)
{
- if (m_inPathLayout && m_textPath.isEmpty())
+ if (m_inPathLayout && !m_textPathCalculator)
return;
SVGElement* lengthContext = toSVGElement(text->parent()->node());
@@ -440,7 +445,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
const Font& font = style->font();
- SVGTextLayoutEngineSpacing spacingLayout(font);
+ SVGTextLayoutEngineSpacing spacingLayout(font, style->effectiveZoom());
SVGTextLayoutEngineBaseline baselineLayout(font);
bool didStartTextFragment = false;
@@ -505,8 +510,8 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
// Calculate SVG Fonts kerning, if needed.
float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, visualMetrics.glyph());
- // Calculate CSS 'kerning', 'letter-spacing' and 'word-spacing' for next character, if needed.
- float spacing = spacingLayout.calculateCSSKerningAndSpacing(svgStyle, lengthContext, currentCharacter);
+ // Calculate CSS 'letter-spacing' and 'word-spacing' for next character, if needed.
+ float spacing = spacingLayout.calculateCSSSpacing(currentCharacter);
float textPathOffset = 0;
if (m_inPathLayout) {
@@ -552,14 +557,11 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
if (textPathOffset > m_textPathLength)
break;
- bool ok = false;
- FloatPoint point = m_textPath.pointAtLength(textPathOffset, ok);
- ASSERT(ok);
-
+ FloatPoint point;
+ bool ok = m_textPathCalculator->pointAndNormalAtLength(textPathOffset, point, angle);
+ ASSERT_UNUSED(ok, ok);
x = point.x();
y = point.y();
- angle = m_textPath.normalAngleAtLength(textPathOffset, ok);
- ASSERT(ok);
// For vertical text on path, the actual angle has to be rotated 90 degrees anti-clockwise, not the orientation angle!
if (m_isVerticalText)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h
index 3ae5fa09087..b3c91a445b2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h
@@ -32,9 +32,7 @@ namespace WebCore {
class RenderObject;
class RenderStyle;
class RenderSVGInlineText;
-class SVGElement;
class SVGInlineTextBox;
-class SVGRenderStyle;
// SVGTextLayoutEngine performs the second layout phase for SVG text.
//
@@ -96,7 +94,7 @@ private:
bool m_inPathLayout;
// Text on path layout
- Path m_textPath;
+ Path::PositionCalculator* m_textPathCalculator;
float m_textPathLength;
float m_textPathStartOffset;
float m_textPathCurrentOffset;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
index 3825b4b1220..95c3beb137c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
@@ -38,12 +38,12 @@ SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font)
float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const
{
if (style->baselineShift() == BS_LENGTH) {
- SVGLength baselineShiftValueLength = style->baselineShiftValue();
- if (baselineShiftValueLength.unitType() == LengthTypePercentage)
- return baselineShiftValueLength.valueAsPercentage() * m_font.pixelSize();
+ RefPtr<SVGLength> baselineShiftValueLength = style->baselineShiftValue();
+ if (baselineShiftValueLength->unitType() == LengthTypePercentage)
+ return baselineShiftValueLength->valueAsPercentage() * m_font.fontDescription().computedPixelSize();
SVGLengthContext lengthContext(contextElement);
- return baselineShiftValueLength.value(lengthContext);
+ return baselineShiftValueLength->value(lengthContext);
}
switch (style->baselineShift()) {
@@ -160,7 +160,7 @@ float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVertica
case GO_AUTO: {
// Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
// Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
- unsigned int unicodeRange = findCharUnicodeRange(character);
+ unsigned unicodeRange = findCharUnicodeRange(character);
if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)
return 90;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
index 6f68e475f1e..e93bb48b41a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
@@ -21,8 +21,8 @@
#include "core/rendering/svg/SVGTextLayoutEngineSpacing.h"
-#include "core/rendering/style/SVGRenderStyle.h"
#include "core/svg/SVGLengthContext.h"
+#include "platform/fonts/Character.h"
#include "platform/fonts/Font.h"
#if ENABLE(SVG_FONTS)
@@ -33,18 +33,23 @@
namespace WebCore {
-SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font)
+SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font, float effectiveZoom)
: m_font(font)
, m_lastCharacter(0)
+ , m_effectiveZoom(effectiveZoom)
+#if ENABLE(SVG_FONTS)
+ , m_lastGlyph(0)
+#endif
{
+ ASSERT(m_effectiveZoom);
}
-float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph)
+float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, Glyph currentGlyph)
{
#if ENABLE(SVG_FONTS)
const SimpleFontData* fontData = m_font.primaryFont();
if (!fontData->isSVGFont()) {
- m_lastGlyph.isValid = false;
+ m_lastGlyph = 0;
return 0;
}
@@ -58,50 +63,44 @@ float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const
SVGFontElement* svgFont = svgFontFace->associatedFontElement();
if (!svgFont) {
- m_lastGlyph.isValid = false;
+ m_lastGlyph = 0;
return 0;
}
float kerning = 0;
- if (m_lastGlyph.isValid) {
+ if (m_lastGlyph) {
if (isVerticalText)
- kerning = svgFont->verticalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
+ kerning = svgFont->verticalKerningForPairOfGlyphs(m_lastGlyph, currentGlyph);
else
- kerning = svgFont->horizontalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
+ kerning = svgFont->horizontalKerningForPairOfGlyphs(m_lastGlyph, currentGlyph);
+
+ kerning *= m_font.fontDescription().computedSize() / m_font.fontMetrics().unitsPerEm();
}
m_lastGlyph = currentGlyph;
- m_lastGlyph.isValid = true;
- kerning *= m_font.size() / m_font.fontMetrics().unitsPerEm();
return kerning;
#else
- return false;
+ return 0;
#endif
}
-float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderStyle* style, SVGElement* contextElement, UChar currentCharacter)
+float SVGTextLayoutEngineSpacing::calculateCSSSpacing(UChar currentCharacter)
{
- float kerning = 0;
- SVGLength kerningLength = style->kerning();
- if (kerningLength.unitType() == LengthTypePercentage)
- kerning = kerningLength.valueAsPercentage() * m_font.pixelSize();
- else {
- SVGLengthContext lengthContext(contextElement);
- kerning = kerningLength.value(lengthContext);
- }
-
UChar lastCharacter = m_lastCharacter;
m_lastCharacter = currentCharacter;
- if (!kerning && !m_font.letterSpacing() && !m_font.wordSpacing())
+ if (!m_font.fontDescription().letterSpacing() && !m_font.fontDescription().wordSpacing())
return 0;
- float spacing = m_font.letterSpacing() + kerning;
- if (currentCharacter && lastCharacter && m_font.wordSpacing()) {
- if (Font::treatAsSpace(currentCharacter) && !Font::treatAsSpace(lastCharacter))
- spacing += m_font.wordSpacing();
+ float spacing = m_font.fontDescription().letterSpacing();
+ if (currentCharacter && lastCharacter && m_font.fontDescription().wordSpacing()) {
+ if (Character::treatAsSpace(currentCharacter) && !Character::treatAsSpace(lastCharacter))
+ spacing += m_font.fontDescription().wordSpacing();
}
+ if (m_effectiveZoom != 1)
+ spacing = spacing / m_effectiveZoom;
+
return spacing;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
index 5cc8bec5533..8618e246dd4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
@@ -25,24 +25,23 @@
namespace WebCore {
class Font;
-class SVGRenderStyle;
-class SVGElement;
-// Helper class used by SVGTextLayoutEngine to handle 'kerning' / 'letter-spacing' and 'word-spacing'.
+// Helper class used by SVGTextLayoutEngine to handle 'letter-spacing' and 'word-spacing'.
class SVGTextLayoutEngineSpacing {
WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineSpacing);
public:
- SVGTextLayoutEngineSpacing(const Font&);
+ SVGTextLayoutEngineSpacing(const Font&, float effectiveZoom);
- float calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph);
- float calculateCSSKerningAndSpacing(const SVGRenderStyle*, SVGElement* lengthContext, UChar currentCharacter);
+ float calculateSVGKerning(bool isVerticalText, Glyph currentGlyph);
+ float calculateCSSSpacing(UChar currentCharacter);
private:
const Font& m_font;
UChar m_lastCharacter;
+ float m_effectiveZoom;
#if ENABLE(SVG_FONTS)
- SVGTextMetrics::Glyph m_lastGlyph;
+ Glyph m_lastGlyph;
#endif
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp
index 26c82dbec27..3ab52797f77 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp
@@ -30,6 +30,7 @@ SVGTextMetrics::SVGTextMetrics()
: m_width(0)
, m_height(0)
, m_length(0)
+ , m_glyph(0)
{
}
@@ -37,6 +38,7 @@ SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType)
: m_width(0)
, m_height(0)
, m_length(1)
+ , m_glyph(0)
{
}
@@ -51,18 +53,21 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun&
int length = 0;
// Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
- m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor;
+ m_width = scaledFont.width(run, length, m_glyph) / scalingFactor;
m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;
- m_glyph.unicodeString = run.is8Bit() ? String(run.characters8(), length) : String(run.characters16(), length);
- m_glyph.isValid = true;
-
ASSERT(length >= 0);
m_length = static_cast<unsigned>(length);
}
TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned position, unsigned length)
{
+ ASSERT(text->style());
+ return constructTextRun(text, position, length, text->style()->direction());
+}
+
+TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned position, unsigned length, TextDirection textDirection)
+{
RenderStyle* style = text->style();
ASSERT(style);
@@ -71,7 +76,7 @@ TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned pos
, 0 // xPos, only relevant with allowTabs=true
, 0 // padding, only relevant for justified text, not relevant for SVG
, TextRun::AllowTrailingExpansion
- , style->direction()
+ , textDirection
, isOverride(style->unicodeBidi()) /* directionalOverride */);
if (length) {
@@ -95,13 +100,19 @@ TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned pos
return run;
}
+SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length, TextDirection textDirection)
+{
+ ASSERT(text);
+ return SVGTextMetrics(text, constructTextRun(text, position, length, textDirection));
+}
+
SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length)
{
ASSERT(text);
return SVGTextMetrics(text, constructTextRun(text, position, length));
}
-SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, const String& glyphName)
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, Glyph glyphNameGlyphId)
{
ASSERT(text);
@@ -111,11 +122,7 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, uns
m_width = width / scalingFactor;
m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor;
- if (needsContext) {
- m_glyph.isValid = true;
- m_glyph.unicodeString = text->substring(position, length);
- m_glyph.name = glyphName;
- }
+ m_glyph = needsContext ? glyphNameGlyphId : 0;
m_length = length;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h
index 362933997ed..3c04901e2cf 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h
@@ -20,12 +20,13 @@
#ifndef SVGTextMetrics_h
#define SVGTextMetrics_h
+#include "platform/fonts/Glyph.h"
+#include "platform/text/TextDirection.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
class RenderSVGInlineText;
-class SVGTextLayoutAttributes;
class TextRun;
class SVGTextMetrics {
@@ -36,12 +37,16 @@ public:
SVGTextMetrics();
SVGTextMetrics(MetricsType);
- SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, const String& glyphName);
+ SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, Glyph glyphNameGlyphId);
+ // FIXME: Migrate away from these to the two below.
static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length);
static TextRun constructTextRun(RenderSVGInlineText*, unsigned position, unsigned length);
- bool isEmpty() const { return !m_width && !m_height && !m_glyph.isValid && m_length == 1; }
+ static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length, TextDirection);
+ static TextRun constructTextRun(RenderSVGInlineText*, unsigned position, unsigned length, TextDirection);
+
+ bool isEmpty() const { return !m_width && !m_height && m_length <= 1; }
float width() const { return m_width; }
void setWidth(float width) { m_width = width; }
@@ -49,19 +54,8 @@ public:
float height() const { return m_height; }
unsigned length() const { return m_length; }
- struct Glyph {
- Glyph()
- : isValid(false)
- {
- }
-
- bool isValid;
- String name;
- String unicodeString;
- };
-
// Only useful when measuring individual characters, to lookup ligatures.
- const Glyph& glyph() const { return m_glyph; }
+ Glyph glyph() const { return m_glyph; }
private:
SVGTextMetrics(RenderSVGInlineText*, const TextRun&);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
index 46a27979e9d..eaaa9361d19 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
@@ -21,186 +21,238 @@
#include "core/rendering/svg/SVGTextMetricsBuilder.h"
+#include "core/rendering/svg/RenderSVGInline.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGTextMetrics.h"
+#include "platform/fonts/GlyphBuffer.h"
+#include "platform/fonts/WidthIterator.h"
+#include "platform/text/BidiCharacterRun.h"
+#include "platform/text/BidiResolver.h"
+#include "platform/text/TextDirection.h"
+#include "platform/text/TextPath.h"
+#include "platform/text/TextRun.h"
+#include "platform/text/TextRunIterator.h"
+#include "wtf/Vector.h"
namespace WebCore {
-SVGTextMetricsBuilder::SVGTextMetricsBuilder()
- : m_text(0)
- , m_run(static_cast<const UChar*>(0), 0)
- , m_textPosition(0)
+class SVGTextMetricsCalculator {
+public:
+ SVGTextMetricsCalculator(RenderSVGInlineText*);
+ ~SVGTextMetricsCalculator();
+
+ SVGTextMetrics computeMetricsForCharacter(unsigned textPosition);
+ unsigned textLength() const { return static_cast<unsigned>(m_run.charactersLength()); }
+
+ bool characterStartsSurrogatePair(unsigned textPosition) const
+ {
+ return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength() && U16_IS_TRAIL(m_run[textPosition + 1]);
+ }
+ bool characterIsWhiteSpace(unsigned textPosition) const
+ {
+ return m_run[textPosition] == ' ';
+ }
+
+private:
+ void setupBidiRuns();
+ SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition);
+ SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition);
+
+ RenderSVGInlineText* m_text;
+ BidiCharacterRun* m_bidiRun;
+ TextRun m_run;
+ BidiResolver<TextRunIterator, BidiCharacterRun> m_bidiResolver;
+ bool m_isComplexText;
+ float m_totalWidth;
+ TextDirection m_textDirection;
+
+ // Simple text only.
+ OwnPtr<WidthIterator> m_simpleWidthIterator;
+};
+
+SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text)
+ : m_text(text)
+ , m_bidiRun(0)
+ , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength()))
, m_isComplexText(false)
, m_totalWidth(0)
{
+ const Font& scaledFont = text->scaledFont();
+ CodePath codePath = scaledFont.codePath(m_run);
+ m_isComplexText = codePath == ComplexPath;
+ m_run.setCharacterScanForCodePath(!m_isComplexText);
+
+ if (!m_isComplexText)
+ m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
+ else
+ setupBidiRuns();
}
-inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const
+SVGTextMetricsCalculator::~SVGTextMetricsCalculator()
{
- return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]);
+ if (m_bidiRun)
+ m_bidiResolver.runs().deleteRuns();
}
-bool SVGTextMetricsBuilder::advance()
+void SVGTextMetricsCalculator::setupBidiRuns()
{
- m_textPosition += m_currentMetrics.length();
- if (int(m_textPosition) >= m_run.charactersLength())
- return false;
-
- if (m_isComplexText)
- advanceComplexText();
- else
- advanceSimpleText();
+ RenderStyle* style = m_text->style();
+ m_textDirection = style->direction();
+ if (isOverride(style->unicodeBidi()))
+ return;
- return m_currentMetrics.length() > 0;
+ BidiStatus status(LTR, false);
+ status.last = status.lastStrong = WTF::Unicode::OtherNeutral;
+ m_bidiResolver.setStatus(status);
+ m_bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&m_run, 0));
+ const bool hardLineBreak = false;
+ const bool reorderRuns = false;
+ m_bidiResolver.createBidiRunsForLine(TextRunIterator(&m_run, m_run.length()), NoVisualOverride, hardLineBreak, reorderRuns);
+ BidiRunList<BidiCharacterRun>& bidiRuns = m_bidiResolver.runs();
+ m_bidiRun = bidiRuns.firstRun();
}
-void SVGTextMetricsBuilder::advanceSimpleText()
+SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsigned textPosition)
{
GlyphBuffer glyphBuffer;
- unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1, &glyphBuffer);
- if (!metricsLength) {
- m_currentMetrics = SVGTextMetrics();
- return;
- }
+ unsigned metricsLength = m_simpleWidthIterator->advance(textPosition + 1, &glyphBuffer);
+ if (!metricsLength)
+ return SVGTextMetrics();
float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth;
m_totalWidth = m_simpleWidthIterator->runWidthSoFar();
-#if ENABLE(SVG_FONTS)
- m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName());
-#else
- m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, emptyString());
-#endif
+ Glyph glyphId = glyphBuffer.glyphAt(0);
+ return SVGTextMetrics(m_text, textPosition, metricsLength, currentWidth, glyphId);
}
-void SVGTextMetricsBuilder::advanceComplexText()
+SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsigned textPosition)
{
- unsigned metricsLength = currentCharacterStartsSurrogatePair() ? 2 : 1;
- m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosition, metricsLength);
- m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, m_textPosition + metricsLength);
- ASSERT(m_currentMetrics.length() == metricsLength);
+ unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1;
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textPosition, metricsLength, m_textDirection);
+ ASSERT(metrics.length() == metricsLength);
+ unsigned startPosition = m_bidiRun ? m_bidiRun->start() : 0;
+ ASSERT(startPosition <= textPosition);
+ SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, startPosition, textPosition - startPosition + metricsLength, m_textDirection);
// Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken
// when rendering the glyph "in context" (with it's surrounding characters) it changes due to shaping.
// So whenever currentWidth != currentMetrics.width(), we are processing a text run whose length is
// not equal to the sum of the individual lengths of the glyphs, when measuring them isolated.
- float currentWidth = m_complexStartToCurrentMetrics.width() - m_totalWidth;
- if (currentWidth != m_currentMetrics.width())
- m_currentMetrics.setWidth(currentWidth);
+ float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth;
+ if (currentWidth != metrics.width())
+ metrics.setWidth(currentWidth);
- m_totalWidth = m_complexStartToCurrentMetrics.width();
+ m_totalWidth = complexStartToCurrentMetrics.width();
+ return metrics;
}
-void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlineText* text)
+SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned textPosition)
{
- m_text = text;
- m_textPosition = 0;
- m_currentMetrics = SVGTextMetrics();
- m_complexStartToCurrentMetrics = SVGTextMetrics();
- m_totalWidth = 0;
-
- const Font& scaledFont = text->scaledFont();
- m_run = SVGTextMetrics::constructTextRun(text, 0, text->textLength());
- m_isComplexText = scaledFont.codePath(m_run) == Font::Complex;
+ if (m_bidiRun) {
+ if (textPosition >= static_cast<unsigned>(m_bidiRun->stop())) {
+ m_bidiRun = m_bidiRun->next();
+ // New BiDi run means new reference position for measurements, so reset |m_totalWidth|.
+ m_totalWidth = 0;
+ }
+ ASSERT(m_bidiRun);
+ ASSERT(static_cast<int>(textPosition) < m_bidiRun->stop());
+ m_textDirection = m_bidiRun->direction();
+ }
if (m_isComplexText)
- m_simpleWidthIterator.clear();
- else
- m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
+ return computeMetricsForCharacterComplex(textPosition);
+
+ return computeMetricsForCharacterSimple(textPosition);
}
struct MeasureTextData {
MeasureTextData(SVGCharacterDataMap* characterDataMap)
: allCharactersMap(characterDataMap)
- , hasLastCharacter(false)
- , lastCharacter(0)
- , processRenderer(false)
+ , lastCharacterWasWhiteSpace(true)
, valueListPosition(0)
- , skippedCharacters(0)
{
}
SVGCharacterDataMap* allCharactersMap;
- bool hasLastCharacter;
- UChar lastCharacter;
- bool processRenderer;
+ bool lastCharacterWasWhiteSpace;
unsigned valueListPosition;
- unsigned skippedCharacters;
};
-void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data)
+static void measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data, bool processRenderer)
{
ASSERT(text);
SVGTextLayoutAttributes* attributes = text->layoutAttributes();
Vector<SVGTextMetrics>* textMetricsValues = &attributes->textMetricsValues();
- if (data->processRenderer) {
+ if (processRenderer) {
if (data->allCharactersMap)
attributes->clear();
else
textMetricsValues->clear();
}
- initializeMeasurementWithTextRenderer(text);
+ SVGTextMetricsCalculator calculator(text);
bool preserveWhiteSpace = text->style()->whiteSpace() == PRE;
- int surrogatePairCharacters = 0;
-
- while (advance()) {
- UChar currentCharacter = m_run[m_textPosition];
- if (currentCharacter == ' ' && !preserveWhiteSpace && (!data->hasLastCharacter || data->lastCharacter == ' ')) {
- if (data->processRenderer)
+ unsigned surrogatePairCharacters = 0;
+ unsigned skippedCharacters = 0;
+ unsigned textPosition = 0;
+ unsigned textLength = calculator.textLength();
+
+ SVGTextMetrics currentMetrics;
+ for (; textPosition < textLength; textPosition += currentMetrics.length()) {
+ currentMetrics = calculator.computeMetricsForCharacter(textPosition);
+ if (!currentMetrics.length())
+ break;
+
+ bool characterIsWhiteSpace = calculator.characterIsWhiteSpace(textPosition);
+ if (characterIsWhiteSpace && !preserveWhiteSpace && data->lastCharacterWasWhiteSpace) {
+ if (processRenderer)
textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));
if (data->allCharactersMap)
- data->skippedCharacters += m_currentMetrics.length();
+ skippedCharacters += currentMetrics.length();
continue;
}
- if (data->processRenderer) {
+ if (processRenderer) {
if (data->allCharactersMap) {
- const SVGCharacterDataMap::const_iterator it = data->allCharactersMap->find(data->valueListPosition + m_textPosition - data->skippedCharacters - surrogatePairCharacters + 1);
+ const SVGCharacterDataMap::const_iterator it = data->allCharactersMap->find(data->valueListPosition + textPosition - skippedCharacters - surrogatePairCharacters + 1);
if (it != data->allCharactersMap->end())
- attributes->characterDataMap().set(m_textPosition + 1, it->value);
+ attributes->characterDataMap().set(textPosition + 1, it->value);
}
- textMetricsValues->append(m_currentMetrics);
+ textMetricsValues->append(currentMetrics);
}
- if (data->allCharactersMap && currentCharacterStartsSurrogatePair())
+ if (data->allCharactersMap && calculator.characterStartsSurrogatePair(textPosition))
surrogatePairCharacters++;
- data->hasLastCharacter = true;
- data->lastCharacter = currentCharacter;
+ data->lastCharacterWasWhiteSpace = characterIsWhiteSpace;
}
if (!data->allCharactersMap)
return;
- data->valueListPosition += m_textPosition - data->skippedCharacters;
- data->skippedCharacters = 0;
+ data->valueListPosition += textPosition - skippedCharacters;
}
-void SVGTextMetricsBuilder::walkTree(RenderObject* start, RenderSVGInlineText* stopAtLeaf, MeasureTextData* data)
+static void walkTree(RenderSVGText* start, RenderSVGInlineText* stopAtLeaf, MeasureTextData* data)
{
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ RenderObject* child = start->firstChild();
+ while (child) {
if (child->isSVGInlineText()) {
RenderSVGInlineText* text = toRenderSVGInlineText(child);
- if (stopAtLeaf && stopAtLeaf != text) {
- data->processRenderer = false;
- measureTextRenderer(text, data);
+ measureTextRenderer(text, data, !stopAtLeaf || stopAtLeaf == text);
+ if (stopAtLeaf && stopAtLeaf == text)
+ return;
+ } else if (child->isSVGInline()) {
+ // Visit children of text content elements.
+ if (RenderObject* inlineChild = toRenderSVGInline(child)->firstChild()) {
+ child = inlineChild;
continue;
}
-
- data->processRenderer = true;
- measureTextRenderer(text, data);
- if (stopAtLeaf)
- return;
-
- continue;
}
-
- if (!child->isSVGInline())
- continue;
-
- walkTree(child, stopAtLeaf, data);
+ child = child->nextInPreOrderAfterChildren(start);
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h
index 076b052283a..bf0c5c77095 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h
@@ -21,48 +21,18 @@
#define SVGTextMetricsBuilder_h
#include "core/rendering/svg/SVGTextLayoutAttributes.h"
-#include "core/rendering/svg/SVGTextMetrics.h"
-#include "platform/fonts/WidthIterator.h"
-#include "platform/text/TextRun.h"
-#include "wtf/Vector.h"
namespace WebCore {
-class RenderObject;
class RenderSVGInlineText;
class RenderSVGText;
-struct MeasureTextData;
-class SVGTextMetricsBuilder {
- WTF_MAKE_NONCOPYABLE(SVGTextMetricsBuilder);
-public:
- SVGTextMetricsBuilder();
- void measureTextRenderer(RenderSVGInlineText*);
- void buildMetricsAndLayoutAttributes(RenderSVGText*, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
+namespace SVGTextMetricsBuilder {
-private:
- bool advance();
- void advanceSimpleText();
- void advanceComplexText();
- bool currentCharacterStartsSurrogatePair() const;
+void measureTextRenderer(RenderSVGInlineText*);
+void buildMetricsAndLayoutAttributes(RenderSVGText*, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
- void initializeMeasurementWithTextRenderer(RenderSVGInlineText*);
- void walkTree(RenderObject*, RenderSVGInlineText* stopAtLeaf, MeasureTextData*);
- void measureTextRenderer(RenderSVGInlineText*, MeasureTextData*);
-
- RenderSVGInlineText* m_text;
- TextRun m_run;
- unsigned m_textPosition;
- bool m_isComplexText;
- SVGTextMetrics m_currentMetrics;
- float m_totalWidth;
-
- // Simple text only.
- OwnPtr<WidthIterator> m_simpleWidthIterator;
-
- // Complex text only.
- SVGTextMetrics m_complexStartToCurrentMetrics;
-};
+} // namespace SVGTextMetricsBuilder
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp
index 4bf2a3c3da7..f5ead0d4366 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp
@@ -90,7 +90,7 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox)
for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnLine()) {
if (child->isInlineFlowBox()) {
// Skip generated content.
- if (!child->renderer()->node())
+ if (!child->renderer().node())
continue;
collectTextBoxesInFlowBox(toInlineFlowBox(child));
@@ -112,8 +112,7 @@ bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra
// Loop over all text boxes
for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBoxPosition) {
queryData->textBox = m_textBoxes.at(textBoxPosition);
- queryData->textRenderer = toRenderSVGInlineText(queryData->textBox->textRenderer());
- ASSERT(queryData->textRenderer);
+ queryData->textRenderer = &toRenderSVGInlineText(queryData->textBox->textRenderer());
ASSERT(queryData->textRenderer->style());
ASSERT(queryData->textRenderer->style()->svgStyle());
@@ -142,7 +141,9 @@ bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData,
startPosition -= queryData->processedCharacters;
endPosition -= queryData->processedCharacters;
- if (startPosition >= endPosition || startPosition < 0 || endPosition < 0)
+ startPosition = max(0, startPosition);
+
+ if (startPosition >= endPosition)
return false;
modifyStartEndPositionsRespectingLigatures(queryData, startPosition, endPosition);
@@ -215,15 +216,11 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i
return;
if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) {
- if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) {
+ if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset))
startPosition = lastPositionOffset;
- alterStartPosition = false;
- }
- if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) {
+ if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset))
endPosition = positionOffset;
- alterEndPosition = false;
- }
}
}
@@ -480,8 +477,6 @@ static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const
AffineTransform fragmentTransform;
fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
- if (fragmentTransform.isIdentity())
- return;
extent = fragmentTransform.mapRect(extent);
}
@@ -499,10 +494,10 @@ bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragm
return true;
}
-SVGRect SVGTextQuery::extentOfCharacter(unsigned position) const
+FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const
{
if (m_textBoxes.isEmpty())
- return SVGRect();
+ return FloatRect();
ExtentOfCharacterData data(position);
executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback);
@@ -540,7 +535,7 @@ bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT
return false;
}
-int SVGTextQuery::characterNumberAtPosition(const SVGPoint& position) const
+int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
{
if (m_textBoxes.isEmpty())
return -1;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h
index 652d751af70..a5601f74d30 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h
@@ -21,8 +21,8 @@
#define SVGTextQuery_h
#include "core/rendering/svg/SVGTextFragment.h"
-#include "core/svg/SVGPoint.h"
-#include "core/svg/SVGRect.h"
+#include "platform/geometry/FloatPoint.h"
+#include "platform/geometry/FloatRect.h"
#include "wtf/Vector.h"
namespace WebCore {
@@ -41,8 +41,8 @@ public:
FloatPoint startPositionOfCharacter(unsigned position) const;
FloatPoint endPositionOfCharacter(unsigned position) const;
float rotationOfCharacter(unsigned position) const;
- SVGRect extentOfCharacter(unsigned position) const;
- int characterNumberAtPosition(const SVGPoint&) const;
+ FloatRect extentOfCharacter(unsigned position) const;
+ int characterNumberAtPosition(const FloatPoint&) const;
// Public helper struct. Private classes in SVGTextQuery inherit from it.
struct Data;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
index c48c91e2486..7765117cd28 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
@@ -23,7 +23,6 @@
#if ENABLE(SVG_FONTS)
#include "core/rendering/svg/SVGTextRunRenderingContext.h"
-#include "SVGNames.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
@@ -46,6 +45,10 @@ static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const Simp
RefPtr<CustomFontData> customFontData = fontData->customFontData();
const SVGFontData* svgFontData = static_cast<const SVGFontData*>(customFontData.get());
+ // FIXME crbug.com/359380 : The current editing impl references the font after the svg font nodes are removed.
+ if (svgFontData->shouldSkipDrawing())
+ return 0;
+
fontFace = svgFontData->svgFontFaceElement();
ASSERT(fontFace);
@@ -73,12 +76,12 @@ static inline RenderSVGResource* activePaintingResourceFromRun(const TextRun& ru
return 0;
}
-float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, String& glyphName) const
+float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, Glyph& glyphId) const
{
WidthIterator it(&font, run);
GlyphBuffer glyphBuffer;
charsConsumed += it.advance(run.length(), &glyphBuffer);
- glyphName = it.lastGlyphName();
+ glyphId = !glyphBuffer.isEmpty() ? glyphBuffer.glyphAt(0) : 0;
return it.runWidthSoFar();
}
@@ -119,14 +122,17 @@ void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const T
glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
+ unsigned short resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
+ // From a resource perspective this ought to be treated as "text mode".
+ resourceMode |= ApplyToTextMode;
+
FloatPoint currentPoint = point;
- RenderSVGResourceMode resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
for (int i = 0; i < numGlyphs; ++i) {
Glyph glyph = glyphBuffer.glyphAt(from + i);
if (!glyph)
continue;
- float advance = glyphBuffer.advanceAt(from + i);
+ float advance = glyphBuffer.advanceAt(from + i).width();
SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
ASSERT(!svgGlyph.isPartOfLigature);
ASSERT(svgGlyph.tableEntry == glyph);
@@ -198,7 +204,7 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co
RenderObject* parentRenderObject = renderObject->isText() ? renderObject->parent() : renderObject;
ASSERT(parentRenderObject);
if (Element* parentRenderObjectElement = toElement(parentRenderObject->node())) {
- if (parentRenderObjectElement->hasTagName(SVGNames::altGlyphTag))
+ if (isSVGAltGlyphElement(*parentRenderObjectElement))
glyphData.fontData = primaryFont;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h
index e71eca2ca29..382c51feb50 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h
@@ -29,7 +29,7 @@ namespace WebCore {
class RenderObject;
class RenderSVGResource;
-class SVGTextRunRenderingContext : public TextRun::RenderingContext {
+class SVGTextRunRenderingContext FINAL : public TextRun::RenderingContext {
public:
static PassRefPtr<SVGTextRunRenderingContext> create(RenderObject* renderer)
{
@@ -42,9 +42,13 @@ public:
RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; }
void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; }
- virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength);
- virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
- virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, String& glyphName) const;
+ virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) OVERRIDE;
+ virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const OVERRIDE;
+ virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, Glyph& glyphId) const OVERRIDE;
+#else
+ virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) OVERRIDE { return 0; }
+ virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const OVERRIDE { }
+ virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, Glyph& glyphId) const OVERRIDE { return 0; }
#endif
private: