#if ENABLE(SVG)
#include "RenderSVGRoot.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "LayoutRepainter.h"
+#include "Page.h"
#include "RenderPart.h"
#include "RenderSVGContainer.h"
#include "RenderSVGResource.h"
#include "SVGLength.h"
#include "SVGRenderSupport.h"
#include "SVGResources.h"
+#include "SVGResourcesCache.h"
#include "SVGSVGElement.h"
#include "SVGStyledElement.h"
#include "SVGViewSpec.h"
setPreferredLogicalWidthsDirty(false);
}
-LayoutUnit RenderSVGRoot::computeIntrinsicWidth(LayoutUnit replacedWidth) const
+bool RenderSVGRoot::isEmbeddedThroughSVGImage() const
{
- if (!style()->width().isPercent())
- return replacedWidth;
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- return static_cast<int>(ceilf(replacedWidth * style()->effectiveZoom()));
+ if (!node())
+ return false;
+
+ Frame* frame = node()->document()->frame();
+ if (!frame)
+ return false;
+
+ // Test whether we're embedded through an img.
+ if (!frame->page() || !frame->page()->chrome())
+ return false;
+
+ ChromeClient* chromeClient = frame->page()->chrome()->client();
+ if (!chromeClient || !chromeClient->isSVGImageChromeClient())
+ return false;
+
+ return true;
}
-LayoutUnit RenderSVGRoot::computeIntrinsicHeight(LayoutUnit replacedHeight) const
+bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const
{
- if (!style()->height().isPercent())
- return replacedHeight;
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- return static_cast<int>(ceilf(replacedHeight * style()->effectiveZoom()));
+ if (!node())
+ return false;
+
+ Frame* 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())
+ return false;
+ return frame->document()->isSVGDocument();
}
LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) const
{
- LayoutUnit replacedWidth = RenderBox::computeReplacedLogicalWidth(includeMaxWidth);
+ // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size.
+ LayoutUnit replacedWidth = m_containerSize.width();
+ if (replacedWidth > 0)
+ return replacedWidth;
+
+ replacedWidth = RenderBox::computeReplacedLogicalWidth(includeMaxWidth);
Frame* frame = node() && node()->document() ? node()->document()->frame() : 0;
if (!frame)
- return computeIntrinsicWidth(replacedWidth);
+ return replacedWidth;
- // If our frame has an owner renderer, we're embedded through eg. object/embed.
- RenderPart* ownerRenderer = frame->ownerRenderer();
- if (!ownerRenderer)
- return computeIntrinsicWidth(replacedWidth);
+ if (!isEmbeddedThroughFrameContainingSVGDocument())
+ return replacedWidth;
+ RenderPart* ownerRenderer = frame->ownerRenderer();
RenderStyle* ownerRendererStyle = ownerRenderer->style();
ASSERT(ownerRendererStyle);
ASSERT(frame->contentRenderer());
LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
{
- LayoutUnit replacedHeight = RenderBox::computeReplacedLogicalHeight();
+ // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size.
+ LayoutUnit replacedHeight = m_containerSize.height();
+ if (replacedHeight > 0)
+ return replacedHeight;
+ replacedHeight = RenderBox::computeReplacedLogicalHeight();
Frame* frame = node() && node()->document() ? node()->document()->frame() : 0;
if (!frame)
- return computeIntrinsicHeight(replacedHeight);
+ return replacedHeight;
+
+ if (!isEmbeddedThroughFrameContainingSVGDocument())
+ return replacedHeight;
- // If our frame has an owner renderer, we're embedded through eg. object/embed.
RenderPart* ownerRenderer = frame->ownerRenderer();
- if (!ownerRenderer)
- return computeIntrinsicHeight(replacedHeight);
+ ASSERT(ownerRenderer);
RenderStyle* ownerRendererStyle = ownerRenderer->style();
ASSERT(ownerRendererStyle);
- ASSERT(frame->contentRenderer());
Length ownerHeight = ownerRendererStyle->height();
if (ownerHeight.isAuto())
LayoutSize oldSize(width(), height());
computeLogicalWidth();
computeLogicalHeight();
- calcViewport();
SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
- m_isLayoutSizeChanged = svg->hasRelativeLengths() && oldSize != size();
-
+ m_isLayoutSizeChanged = needsLayout || (svg->hasRelativeLengths() && oldSize != size());
+
if (view() && view()->frameView() && view()->frameView()->embeddedContentBox()) {
if (!m_needsSizeNegotiationWithHostDocument)
m_needsSizeNegotiationWithHostDocument = !m_everHadLayout || oldSize != size();
} else
ASSERT(!m_needsSizeNegotiationWithHostDocument);
- SVGRenderSupport::layoutChildren(this, needsLayout);
+ SVGRenderSupport::layoutChildren(this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(this));
m_isLayoutSizeChanged = false;
// At this point LayoutRepainter already grabbed the old bounds,
bool RenderSVGRoot::selfWillPaint()
{
-#if ENABLE(FILTERS)
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
return resources && resources->filter();
-#else
- return false;
-#endif
}
void RenderSVGRoot::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if (paintInfo.phase == PaintPhaseBlockBackground)
return;
- // An empty viewport disables rendering. FIXME: Should we still render filters?
- if (m_viewportSize.isEmpty())
+ // An empty viewport disables rendering.
+ if (borderBoxRect().isEmpty())
return;
// Don't paint if we don't have kids, except if we have filters we should paint those.
SVGResourcesCache::clientUpdatedFromElement(this, style());
}
-void RenderSVGRoot::calcViewport()
-{
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
-
- if (!svg->hasSetContainerSize()) {
- // In the normal case of <svg> being stand-alone or in a CSSBoxModel object we use
- // RenderBox::width()/height() (which pulls data from RenderStyle)
- m_viewportSize = FloatSize(width(), height());
- return;
- }
-
- // In the SVGImage case grab the SVGLength values off of SVGSVGElement and use
- // the special relativeWidthValue accessors which respect the specified containerSize
- // FIXME: Check how SVGImage + zooming is supposed to be handled?
- SVGLength width = svg->width();
- SVGLength height = svg->height();
- m_viewportSize = FloatSize(width.unitType() == LengthTypePercentage ? svg->relativeWidthValue() : width.value(svg),
- height.unitType() == LengthTypePercentage ? svg->relativeHeightValue() : height.value(svg));
-}
-
// RenderBox methods will expect coordinates w/o any transforms in coordinates
// relative to our borderBox origin. This method gives us exactly that.
AffineTransform RenderSVGRoot::localToBorderBoxTransform() const
return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
}
-void RenderSVGRoot::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& repaintRect, bool fixed) const
+void RenderSVGRoot::computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect& repaintRect, 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 = localToBorderBoxTransform().mapRect(repaintRect);
// Apply initial viewport clip - not affected by overflow settings
- repaintRect.intersect(enclosingLayoutRect(FloatRect(FloatPoint(), m_viewportSize)));
+ repaintRect.intersect(borderBoxRect());
const SVGRenderStyle* svgStyle = style()->svgStyle();
if (const ShadowData* shadow = svgStyle->shadow())
shadow->adjustRectForShadow(repaintRect);
- RenderBox::computeRectForRepaint(repaintContainer, repaintRect, fixed);
+ LayoutRect rect = enclosingIntRect(repaintRect);
+ RenderBox::computeRectForRepaint(repaintContainer, rect, fixed);
+ repaintRect = rect;
}
void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
LayoutPoint pointInBorderBox = pointInParent - parentOriginToBorderBox();
// Note: For now, we're ignoring hits to border and padding for <svg>
- LayoutPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox();
- if (!contentBoxRect().contains(pointInContentBox))
+ if (!contentBoxRect().contains(pointInBorderBox))
return false;
LayoutPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);