tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / rendering / svg / RenderSVGRoot.cpp
index 7d411da..5b71c7f 100755 (executable)
 #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"
@@ -37,6 +40,7 @@
 #include "SVGLength.h"
 #include "SVGRenderSupport.h"
 #include "SVGResources.h"
+#include "SVGResourcesCache.h"
 #include "SVGSVGElement.h"
 #include "SVGStyledElement.h"
 #include "SVGViewSpec.h"
@@ -114,34 +118,58 @@ void RenderSVGRoot::computePreferredLogicalWidths()
     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());
@@ -173,20 +201,24 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) cons
 
 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())
@@ -213,18 +245,17 @@ void RenderSVGRoot::layout()
     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,
@@ -241,12 +272,8 @@ void RenderSVGRoot::layout()
 
 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)
@@ -263,8 +290,8 @@ 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.
@@ -323,26 +350,6 @@ void RenderSVGRoot::updateFromElement()
     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
@@ -384,20 +391,22 @@ LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(RenderBoxModelObject* re
     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
@@ -427,8 +436,7 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
     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);