RenderSVGViewportContainer.cpp [plain text]
#include "config.h"
#if ENABLE(SVG)
#include "RenderSVGViewportContainer.h"
#include "GraphicsContext.h"
#include "RenderView.h"
#include "SVGElementInstance.h"
#include "SVGNames.h"
#include "SVGSVGElement.h"
#include "SVGUseElement.h"
namespace WebCore {
RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
: RenderSVGContainer(node)
, m_didTransformToRootUpdate(false)
, m_isLayoutSizeChanged(false)
, m_needsTransformUpdate(true)
{
}
void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
{
if (!node()->hasTagName(SVGNames::svgTag))
return;
m_isLayoutSizeChanged = toSVGSVGElement(node())->hasRelativeLengths() && selfNeedsLayout();
}
void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
{
if (SVGRenderSupport::isOverflowHidden(this))
paintInfo.context->clip(m_viewport);
}
void RenderSVGViewportContainer::calcViewport()
{
SVGElement* element = toSVGElement(node());
if (!element->hasTagName(SVGNames::svgTag))
return;
SVGSVGElement* svg = toSVGSVGElement(element);
FloatRect oldViewport = m_viewport;
SVGLengthContext lengthContext(element);
m_viewport = FloatRect(svg->x().value(lengthContext), svg->y().value(lengthContext), svg->width().value(lengthContext), svg->height().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);
SVGLengthContext lengthContext(element);
if (useElement->hasAttribute(SVGNames::widthAttr))
m_viewport.setWidth(useElement->width().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->height().value(lengthContext));
else if (isSymbolElement && svg->hasAttribute(SVGNames::heightAttr)) {
SVGLength containerHeight(LengthModeHeight, "100%");
m_viewport.setHeight(containerHeight.value(lengthContext));
}
}
if (oldViewport != m_viewport) {
setNeedsBoundariesUpdate();
setNeedsTransformUpdate();
}
}
bool RenderSVGViewportContainer::calculateLocalTransform()
{
m_didTransformToRootUpdate = m_needsTransformUpdate || SVGRenderSupport::transformToRootChanged(parent());
if (!m_needsTransformUpdate)
return false;
m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform();
m_needsTransformUpdate = false;
return true;
}
AffineTransform RenderSVGViewportContainer::viewportTransform() const
{
if (node()->hasTagName(SVGNames::svgTag)) {
SVGSVGElement* svg = toSVGSVGElement(node());
return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
}
return AffineTransform();
}
bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& pointInParent)
{
if (!SVGRenderSupport::isOverflowHidden(this))
return true;
return m_viewport.contains(pointInParent);
}
void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (node()->hasTagName(SVGNames::svgTag)) {
if (toSVGSVGElement(node())->hasEmptyViewBox())
return;
}
RenderSVGContainer::paint(paintInfo, paintOffset);
}
}
#endif // ENABLE(SVG)