This source file includes following definitions.
- m_translation
- create
- contentScriptType
- setContentScriptType
- contentStyleType
- setContentStyleType
- viewport
- pixelUnitToMillimeterX
- pixelUnitToMillimeterY
- screenPixelToMillimeterX
- screenPixelToMillimeterY
- currentView
- currentScale
- setCurrentScale
- create
- commitChange
- currentTranslateFromJavascript
- setCurrentTranslate
- updateCurrentTranslate
- parseAttribute
- svgAttributeChanged
- intersectsAllowingEmpty
- isIntersectionOrEnclosureTarget
- checkIntersectionOrEnclosure
- collectIntersectionOrEnclosureList
- getIntersectionList
- getEnclosureList
- checkIntersection
- checkEnclosure
- deselectAll
- createSVGNumber
- createSVGLength
- createSVGAngle
- createSVGPoint
- createSVGMatrix
- createSVGRect
- createSVGTransform
- createSVGTransformFromMatrix
- localCoordinateSpaceTransform
- rendererIsNeeded
- createRenderer
- insertedInto
- removedFrom
- pauseAnimations
- unpauseAnimations
- animationsPaused
- getCurrentTime
- setCurrentTime
- selfHasRelativeLengths
- currentViewBoxRect
- currentViewportSize
- widthAttributeEstablishesViewport
- heightAttributeEstablishesViewport
- intrinsicWidth
- intrinsicHeight
- viewBoxToViewTransform
- setupInitialView
- inheritViewAttributes
- getElementById
#include "config.h"
#include "core/svg/SVGSVGElement.h"
#include "HTMLNames.h"
#include "SVGNames.h"
#include "bindings/v8/ScriptEventListener.h"
#include "core/css/CSSHelper.h"
#include "core/dom/Document.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/StaticNodeList.h"
#include "core/editing/FrameSelection.h"
#include "core/events/EventListener.h"
#include "core/frame/LocalFrame.h"
#include "core/page/FrameTree.h"
#include "core/frame/FrameView.h"
#include "core/frame/UseCounter.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/RenderPart.h"
#include "core/rendering/svg/RenderSVGModelObject.h"
#include "core/rendering/svg/RenderSVGResource.h"
#include "core/rendering/svg/RenderSVGRoot.h"
#include "core/rendering/svg/RenderSVGViewportContainer.h"
#include "core/svg/SVGAngleTearOff.h"
#include "core/svg/SVGElementInstance.h"
#include "core/svg/SVGNumberTearOff.h"
#include "core/svg/SVGPreserveAspectRatio.h"
#include "core/svg/SVGRectTearOff.h"
#include "core/svg/SVGTransform.h"
#include "core/svg/SVGTransformList.h"
#include "core/svg/SVGTransformTearOff.h"
#include "core/svg/SVGViewElement.h"
#include "core/svg/SVGViewSpec.h"
#include "core/svg/animation/SMILTimeContainer.h"
#include "platform/FloatConversion.h"
#include "platform/LengthFunctions.h"
#include "platform/geometry/FloatRect.h"
#include "platform/transforms/AffineTransform.h"
#include "wtf/StdLibExtras.h"
namespace WebCore {
inline SVGSVGElement::SVGSVGElement(Document& doc)
    : SVGGraphicsElement(SVGNames::svgTag, doc)
    , SVGFitToViewBox(this)
    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
    , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
    , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
    , m_useCurrentView(false)
    , m_timeContainer(SMILTimeContainer::create(*this))
    , m_translation(SVGPoint::create())
{
    ScriptWrappable::init(this);
    m_width->setDefaultValueAsString("100%");
    m_height->setDefaultValueAsString("100%");
    addToPropertyMap(m_x);
    addToPropertyMap(m_y);
    addToPropertyMap(m_width);
    addToPropertyMap(m_height);
    UseCounter::count(doc, UseCounter::SVGSVGElement);
}
PassRefPtr<SVGSVGElement> SVGSVGElement::create(Document& document)
{
    return adoptRef(new SVGSVGElement(document));
}
SVGSVGElement::~SVGSVGElement()
{
    if (m_viewSpec)
        m_viewSpec->detachContextElement();
    
    
    document().accessSVGExtensions().removeTimeContainer(this);
    ASSERT(inDocument() || !accessDocumentSVGExtensions().isSVGRootWithRelativeLengthDescendents(this));
}
const AtomicString& SVGSVGElement::contentScriptType() const
{
    DEFINE_STATIC_LOCAL(const AtomicString, defaultValue, ("text/ecmascript", AtomicString::ConstructFromLiteral));
    const AtomicString& n = fastGetAttribute(SVGNames::contentScriptTypeAttr);
    return n.isNull() ? defaultValue : n;
}
void SVGSVGElement::setContentScriptType(const AtomicString& type)
{
    setAttribute(SVGNames::contentScriptTypeAttr, type);
}
const AtomicString& SVGSVGElement::contentStyleType() const
{
    DEFINE_STATIC_LOCAL(const AtomicString, defaultValue, ("text/css", AtomicString::ConstructFromLiteral));
    const AtomicString& n = fastGetAttribute(SVGNames::contentStyleTypeAttr);
    return n.isNull() ? defaultValue : n;
}
void SVGSVGElement::setContentStyleType(const AtomicString& type)
{
    setAttribute(SVGNames::contentStyleTypeAttr, type);
}
PassRefPtr<SVGRectTearOff> SVGSVGElement::viewport() const
{
    
    
    return SVGRectTearOff::create(SVGRect::create(), 0, PropertyIsNotAnimVal);
}
float SVGSVGElement::pixelUnitToMillimeterX() const
{
    return 1 / cssPixelsPerMillimeter;
}
float SVGSVGElement::pixelUnitToMillimeterY() const
{
    return 1 / cssPixelsPerMillimeter;
}
float SVGSVGElement::screenPixelToMillimeterX() const
{
    return pixelUnitToMillimeterX();
}
float SVGSVGElement::screenPixelToMillimeterY() const
{
    return pixelUnitToMillimeterY();
}
SVGViewSpec* SVGSVGElement::currentView()
{
    if (!m_viewSpec)
        m_viewSpec = SVGViewSpec::create(this);
    return m_viewSpec.get();
}
float SVGSVGElement::currentScale() const
{
    if (!inDocument() || !isOutermostSVGSVGElement())
        return 1;
    LocalFrame* frame = document().frame();
    if (!frame)
        return 1;
    const FrameTree& frameTree = frame->tree();
    
    
    
    return frameTree.parent() ? 1 : frame->pageZoomFactor();
}
void SVGSVGElement::setCurrentScale(float scale)
{
    if (!inDocument() || !isOutermostSVGSVGElement())
        return;
    LocalFrame* frame = document().frame();
    if (!frame)
        return;
    const FrameTree& frameTree = frame->tree();
    
    
    
    if (frameTree.parent())
        return;
    frame->setPageZoomFactor(scale);
}
class SVGCurrentTranslateTearOff : public SVGPointTearOff {
public:
    static PassRefPtr<SVGCurrentTranslateTearOff> create(SVGSVGElement* contextElement)
    {
        return adoptRef(new SVGCurrentTranslateTearOff(contextElement));
    }
    virtual void commitChange() OVERRIDE
    {
        ASSERT(contextElement());
        toSVGSVGElement(contextElement())->updateCurrentTranslate();
    }
private:
    SVGCurrentTranslateTearOff(SVGSVGElement* contextElement)
        : SVGPointTearOff(contextElement->m_translation, contextElement, PropertyIsNotAnimVal)
    {
    }
};
PassRefPtr<SVGPointTearOff> SVGSVGElement::currentTranslateFromJavascript()
{
    return SVGCurrentTranslateTearOff::create(this);
}
void SVGSVGElement::setCurrentTranslate(const FloatPoint& point)
{
    m_translation->setValue(point);
    updateCurrentTranslate();
}
void SVGSVGElement::updateCurrentTranslate()
{
    if (RenderObject* object = renderer())
        object->setNeedsLayout();
    if (parentNode() == document() && document().renderer())
        document().renderer()->repaint();
}
void SVGSVGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    SVGParsingError parseError = NoError;
    if (!nearestViewportElement()) {
        bool setListener = true;
        
        if (name == HTMLNames::onunloadAttr)
            document().setWindowAttributeEventListener(EventTypeNames::unload, createAttributeEventListener(document().frame(), name, value));
        else if (name == HTMLNames::onresizeAttr)
            document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value));
        else if (name == HTMLNames::onscrollAttr)
            document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value));
        else if (name == SVGNames::onzoomAttr)
            document().setWindowAttributeEventListener(EventTypeNames::zoom, createAttributeEventListener(document().frame(), name, value));
        else
            setListener = false;
        if (setListener)
            return;
    }
    if (name == HTMLNames::onabortAttr) {
        document().setWindowAttributeEventListener(EventTypeNames::abort, createAttributeEventListener(document().frame(), name, value));
    } else if (name == HTMLNames::onerrorAttr) {
        document().setWindowAttributeEventListener(EventTypeNames::error, createAttributeEventListener(document().frame(), name, value));
    } else if (name == SVGNames::xAttr) {
        m_x->setBaseValueAsString(value, parseError);
    } else if (name == SVGNames::yAttr) {
        m_y->setBaseValueAsString(value, parseError);
    } else if (name == SVGNames::widthAttr) {
        m_width->setBaseValueAsString(value, parseError);
    } else if (name == SVGNames::heightAttr) {
        m_height->setBaseValueAsString(value, parseError);
    } else if (SVGFitToViewBox::parseAttribute(name, value, document(), parseError)) {
    } else if (SVGZoomAndPan::parseAttribute(name, value)) {
    } else {
        SVGGraphicsElement::parseAttribute(name, value);
    }
    reportAttributeParsingError(parseError, name, value);
}
void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
{
    bool updateRelativeLengthsOrViewBox = false;
    bool widthChanged = attrName == SVGNames::widthAttr;
    if (widthChanged
        || attrName == SVGNames::heightAttr
        || attrName == SVGNames::xAttr
        || attrName == SVGNames::yAttr) {
        updateRelativeLengthsOrViewBox = true;
        updateRelativeLengthsInformation();
        invalidateRelativeLengthClients();
        
        
        if (widthChanged) {
            RenderObject* renderObject = renderer();
            if (renderObject && renderObject->isSVGRoot())
                toRenderSVGRoot(renderObject)->setNeedsLayoutAndPrefWidthsRecalc();
        }
    }
    if (SVGFitToViewBox::isKnownAttribute(attrName)) {
        updateRelativeLengthsOrViewBox = true;
        if (RenderObject* object = renderer())
            object->setNeedsTransformUpdate();
    }
    SVGElementInstance::InvalidationGuard invalidationGuard(this);
    if (updateRelativeLengthsOrViewBox
        || SVGZoomAndPan::isKnownAttribute(attrName)) {
        if (renderer())
            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer());
        return;
    }
    SVGGraphicsElement::svgAttributeChanged(attrName);
}
static bool intersectsAllowingEmpty(const FloatRect& r1, const FloatRect& r2)
{
    if (r1.width() < 0 || r1.height() < 0 || r2.width() < 0 || r2.height() < 0)
        return false;
    return r1.x() < r2.maxX() && r2.x() < r1.maxX()
        && r1.y() < r2.maxY() && r2.y() < r1.maxY();
}
static bool isIntersectionOrEnclosureTarget(RenderObject* renderer)
{
    return renderer->isSVGShape()
        || renderer->isSVGText()
        || renderer->isSVGImage()
        || isSVGUseElement(*renderer->node());
}
bool SVGSVGElement::checkIntersectionOrEnclosure(const SVGElement& element, const FloatRect& rect,
    CheckIntersectionOrEnclosure mode) const
{
    RenderObject* renderer = element.renderer();
    ASSERT(!renderer || renderer->style());
    if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
        return false;
    if (!isIntersectionOrEnclosureTarget(renderer))
        return false;
    AffineTransform ctm = toSVGGraphicsElement(element).computeCTM(AncestorScope, DisallowStyleUpdate, this);
    FloatRect mappedRepaintRect = ctm.mapRect(renderer->repaintRectInLocalCoordinates());
    bool result = false;
    switch (mode) {
    case CheckIntersection:
        result = intersectsAllowingEmpty(rect, mappedRepaintRect);
        break;
    case CheckEnclosure:
        result = rect.contains(mappedRepaintRect);
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
    return result;
}
PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const FloatRect& rect,
    SVGElement* referenceElement, CheckIntersectionOrEnclosure mode) const
{
    Vector<RefPtr<Node> > nodes;
    const SVGElement* root = this;
    if (referenceElement) {
        
        if (contains(referenceElement)) {
            root = referenceElement;
        } else if (!isDescendantOf(referenceElement)) {
            
            return StaticNodeList::adopt(nodes);
        }
    }
    for (SVGGraphicsElement* element = Traversal<SVGGraphicsElement>::firstWithin(*root); element;
        element = Traversal<SVGGraphicsElement>::next(*element, root)) {
        if (checkIntersectionOrEnclosure(*element, rect, mode))
            nodes.append(element);
    }
    return StaticNodeList::adopt(nodes);
}
PassRefPtr<NodeList> SVGSVGElement::getIntersectionList(PassRefPtr<SVGRectTearOff> rect, SVGElement* referenceElement) const
{
    document().updateLayoutIgnorePendingStylesheets();
    return collectIntersectionOrEnclosureList(rect->target()->value(), referenceElement, CheckIntersection);
}
PassRefPtr<NodeList> SVGSVGElement::getEnclosureList(PassRefPtr<SVGRectTearOff> rect, SVGElement* referenceElement) const
{
    document().updateLayoutIgnorePendingStylesheets();
    return collectIntersectionOrEnclosureList(rect->target()->value(), referenceElement, CheckEnclosure);
}
bool SVGSVGElement::checkIntersection(SVGElement* element, PassRefPtr<SVGRectTearOff> rect) const
{
    ASSERT(element);
    document().updateLayoutIgnorePendingStylesheets();
    return checkIntersectionOrEnclosure(*element, rect->target()->value(), CheckIntersection);
}
bool SVGSVGElement::checkEnclosure(SVGElement* element, PassRefPtr<SVGRectTearOff> rect) const
{
    ASSERT(element);
    document().updateLayoutIgnorePendingStylesheets();
    return checkIntersectionOrEnclosure(*element, rect->target()->value(), CheckEnclosure);
}
void SVGSVGElement::deselectAll()
{
    if (LocalFrame* frame = document().frame())
        frame->selection().clear();
}
PassRefPtr<SVGNumberTearOff> SVGSVGElement::createSVGNumber()
{
    return SVGNumberTearOff::create(SVGNumber::create(0.0f), 0, PropertyIsNotAnimVal);
}
PassRefPtr<SVGLengthTearOff> SVGSVGElement::createSVGLength()
{
    return SVGLengthTearOff::create(SVGLength::create(), 0, PropertyIsNotAnimVal);
}
PassRefPtr<SVGAngleTearOff> SVGSVGElement::createSVGAngle()
{
    return SVGAngleTearOff::create(SVGAngle::create(), 0, PropertyIsNotAnimVal);
}
PassRefPtr<SVGPointTearOff> SVGSVGElement::createSVGPoint()
{
    return SVGPointTearOff::create(SVGPoint::create(), 0, PropertyIsNotAnimVal);
}
PassRefPtr<SVGMatrixTearOff> SVGSVGElement::createSVGMatrix()
{
    return SVGMatrixTearOff::create(AffineTransform());
}
PassRefPtr<SVGRectTearOff> SVGSVGElement::createSVGRect()
{
    return SVGRectTearOff::create(SVGRect::create(), 0, PropertyIsNotAnimVal);
}
PassRefPtr<SVGTransformTearOff> SVGSVGElement::createSVGTransform()
{
    return SVGTransformTearOff::create(SVGTransform::create(SVG_TRANSFORM_MATRIX), 0, PropertyIsNotAnimVal);
}
PassRefPtr<SVGTransformTearOff> SVGSVGElement::createSVGTransformFromMatrix(PassRefPtr<SVGMatrixTearOff> matrix)
{
    return SVGTransformTearOff::create(SVGTransform::create(matrix->value()), 0, PropertyIsNotAnimVal);
}
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGElement::CTMScope mode) const
{
    AffineTransform viewBoxTransform;
    if (!hasEmptyViewBox()) {
        FloatSize size = currentViewportSize();
        viewBoxTransform = viewBoxToViewTransform(size.width(), size.height());
    }
    AffineTransform transform;
    if (!isOutermostSVGSVGElement()) {
        SVGLengthContext lengthContext(this);
        transform.translate(m_x->currentValue()->value(lengthContext), m_y->currentValue()->value(lengthContext));
    } else if (mode == SVGElement::ScreenScope) {
        if (RenderObject* renderer = this->renderer()) {
            FloatPoint location;
            float zoomFactor = 1;
            
            
            
            
            if (renderer->isSVGRoot()) {
                location = toRenderSVGRoot(renderer)->localToBorderBoxTransform().mapPoint(location);
                zoomFactor = 1 / renderer->style()->effectiveZoom();
            }
            
            
            location = renderer->localToAbsolute(location, UseTransforms);
            location.scale(zoomFactor, zoomFactor);
            
            
            transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f());
            
            if (FrameView* view = document().view()) {
                LayoutSize scrollOffset = view->scrollOffset();
                scrollOffset.scale(zoomFactor);
                transform.translate(-scrollOffset.width(), -scrollOffset.height());
            }
        }
    }
    return transform.multiply(viewBoxTransform);
}
bool SVGSVGElement::rendererIsNeeded(const RenderStyle& style)
{
    
    
    
    
    if (document().documentElement() == this)
        return true;
    return Element::rendererIsNeeded(style);
}
RenderObject* SVGSVGElement::createRenderer(RenderStyle*)
{
    if (isOutermostSVGSVGElement())
        return new RenderSVGRoot(this);
    return new RenderSVGViewportContainer(this);
}
Node::InsertionNotificationRequest SVGSVGElement::insertedInto(ContainerNode* rootParent)
{
    if (rootParent->inDocument()) {
        UseCounter::count(document(), UseCounter::SVGSVGElementInDocument);
        document().accessSVGExtensions().addTimeContainer(this);
        
        
        
        if (!document().parsing() && !document().processingLoadEvent() && document().loadEventFinished() && !timeContainer()->isStarted())
            timeContainer()->begin();
    }
    return SVGGraphicsElement::insertedInto(rootParent);
}
void SVGSVGElement::removedFrom(ContainerNode* rootParent)
{
    if (rootParent->inDocument()) {
        SVGDocumentExtensions& svgExtensions = document().accessSVGExtensions();
        svgExtensions.removeTimeContainer(this);
        svgExtensions.removeSVGRootWithRelativeLengthDescendents(this);
    }
    SVGGraphicsElement::removedFrom(rootParent);
}
void SVGSVGElement::pauseAnimations()
{
    if (!m_timeContainer->isPaused())
        m_timeContainer->pause();
}
void SVGSVGElement::unpauseAnimations()
{
    if (m_timeContainer->isPaused())
        m_timeContainer->resume();
}
bool SVGSVGElement::animationsPaused() const
{
    return m_timeContainer->isPaused();
}
float SVGSVGElement::getCurrentTime() const
{
    return narrowPrecisionToFloat(m_timeContainer->elapsed().value());
}
void SVGSVGElement::setCurrentTime(float seconds)
{
    if (std::isnan(seconds))
        return;
    seconds = max(seconds, 0.0f);
    m_timeContainer->setElapsed(seconds);
}
bool SVGSVGElement::selfHasRelativeLengths() const
{
    return m_x->currentValue()->isRelative()
        || m_y->currentValue()->isRelative()
        || m_width->currentValue()->isRelative()
        || m_height->currentValue()->isRelative()
        || hasAttribute(SVGNames::viewBoxAttr);
}
FloatRect SVGSVGElement::currentViewBoxRect() const
{
    if (m_useCurrentView)
        return m_viewSpec ? m_viewSpec->viewBox()->currentValue()->value() : FloatRect();
    FloatRect useViewBox = viewBox()->currentValue()->value();
    if (!useViewBox.isEmpty())
        return useViewBox;
    if (!renderer() || !renderer()->isSVGRoot())
        return FloatRect();
    if (!toRenderSVGRoot(renderer())->isEmbeddedThroughSVGImage())
        return FloatRect();
    Length intrinsicWidth = this->intrinsicWidth();
    Length intrinsicHeight = this->intrinsicHeight();
    if (!intrinsicWidth.isFixed() || !intrinsicHeight.isFixed())
        return FloatRect();
    
    
    return FloatRect(FloatPoint(), FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0)));
}
FloatSize SVGSVGElement::currentViewportSize() const
{
    Length intrinsicWidth = this->intrinsicWidth();
    Length intrinsicHeight = this->intrinsicHeight();
    if (intrinsicWidth.isFixed() && intrinsicHeight.isFixed())
        return FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0));
    if (!renderer())
        return FloatSize();
    if (renderer()->isSVGRoot()) {
        LayoutRect contentBoxRect = toRenderSVGRoot(renderer())->contentBoxRect();
        return FloatSize(contentBoxRect.width() / renderer()->style()->effectiveZoom(), contentBoxRect.height() / renderer()->style()->effectiveZoom());
    }
    FloatRect viewportRect = toRenderSVGViewportContainer(renderer())->viewport();
    return FloatSize(viewportRect.width(), viewportRect.height());
}
bool SVGSVGElement::widthAttributeEstablishesViewport() const
{
    if (!renderer() || renderer()->isSVGViewportContainer())
        return true;
    
    
    
    
    
    
    
    
    RenderSVGRoot* root = toRenderSVGRoot(renderer());
    
    if (root->isEmbeddedThroughFrameContainingSVGDocument())
        return !root->hasReplacedLogicalWidth() && !document().frame()->ownerRenderer()->hasReplacedLogicalWidth();
    
    if (root->isEmbeddedThroughSVGImage() || document().documentElement() != this)
        return !root->hasReplacedLogicalWidth();
    return true;
}
bool SVGSVGElement::heightAttributeEstablishesViewport() const
{
    if (!renderer() || renderer()->isSVGViewportContainer())
        return true;
    
    
    
    
    RenderSVGRoot* root = toRenderSVGRoot(renderer());
    
    if (root->isEmbeddedThroughFrameContainingSVGDocument())
        return !root->hasReplacedLogicalHeight() && !document().frame()->ownerRenderer()->hasReplacedLogicalHeight();
    
    if (root->isEmbeddedThroughSVGImage() || document().documentElement() != this)
        return !root->hasReplacedLogicalHeight();
    return true;
}
Length SVGSVGElement::intrinsicWidth(ConsiderCSSMode mode) const
{
    if (widthAttributeEstablishesViewport() || mode == IgnoreCSSProperties) {
        if (m_width->currentValue()->unitType() == LengthTypePercentage)
            return Length(m_width->currentValue()->valueAsPercentage() * 100, Percent);
        SVGLengthContext lengthContext(this);
        return Length(m_width->currentValue()->value(lengthContext), Fixed);
    }
    ASSERT(renderer());
    return renderer()->style()->width();
}
Length SVGSVGElement::intrinsicHeight(ConsiderCSSMode mode) const
{
    if (heightAttributeEstablishesViewport() || mode == IgnoreCSSProperties) {
        if (m_height->currentValue()->unitType() == LengthTypePercentage)
            return Length(m_height->currentValue()->valueAsPercentage() * 100, Percent);
        SVGLengthContext lengthContext(this);
        return Length(m_height->currentValue()->value(lengthContext), Fixed);
    }
    ASSERT(renderer());
    return renderer()->style()->height();
}
AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const
{
    if (!m_useCurrentView || !m_viewSpec)
        return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), preserveAspectRatio()->currentValue(), viewWidth, viewHeight);
    AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), m_viewSpec->preserveAspectRatio()->currentValue(), viewWidth, viewHeight);
    RefPtr<SVGTransformList> transformList = m_viewSpec->transform();
    if (transformList->isEmpty())
        return ctm;
    AffineTransform transform;
    if (transformList->concatenate(transform))
        ctm *= transform;
    return ctm;
}
void SVGSVGElement::setupInitialView(const String& fragmentIdentifier, Element* anchorNode)
{
    RenderObject* renderer = this->renderer();
    SVGViewSpec* view = m_viewSpec.get();
    if (view)
        view->reset();
    bool hadUseCurrentView = m_useCurrentView;
    m_useCurrentView = false;
    if (fragmentIdentifier.startsWith("xpointer(")) {
        
        if (renderer && hadUseCurrentView)
            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
        return;
    }
    if (fragmentIdentifier.startsWith("svgView(")) {
        if (!view)
            view = currentView(); 
        if (view->parseViewSpec(fragmentIdentifier))
            m_useCurrentView = true;
        else
            view->reset();
        if (renderer && (hadUseCurrentView || m_useCurrentView))
            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
        return;
    }
    
    
    
    
    if (isSVGViewElement(anchorNode)) {
        SVGViewElement& viewElement = toSVGViewElement(*anchorNode);
        if (SVGSVGElement* svg = viewElement.ownerSVGElement()) {
            svg->inheritViewAttributes(&viewElement);
            if (RenderObject* renderer = svg->renderer())
                RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
        }
    }
    
    
}
void SVGSVGElement::inheritViewAttributes(SVGViewElement* viewElement)
{
    SVGViewSpec* view = currentView();
    m_useCurrentView = true;
    if (viewElement->hasAttribute(SVGNames::viewBoxAttr))
        view->viewBox()->baseValue()->setValue(viewElement->viewBox()->currentValue()->value());
    else
        view->viewBox()->baseValue()->setValue(viewBox()->currentValue()->value());
    if (viewElement->hasAttribute(SVGNames::preserveAspectRatioAttr)) {
        view->preserveAspectRatio()->baseValue()->setAlign(viewElement->preserveAspectRatio()->currentValue()->align());
        view->preserveAspectRatio()->baseValue()->setMeetOrSlice(viewElement->preserveAspectRatio()->currentValue()->meetOrSlice());
    } else {
        view->preserveAspectRatio()->baseValue()->setAlign(preserveAspectRatio()->currentValue()->align());
        view->preserveAspectRatio()->baseValue()->setMeetOrSlice(preserveAspectRatio()->currentValue()->meetOrSlice());
    }
    if (viewElement->hasAttribute(SVGNames::zoomAndPanAttr))
        view->setZoomAndPan(viewElement->zoomAndPan());
    else
        view->setZoomAndPan(zoomAndPan());
}
Element* SVGSVGElement::getElementById(const AtomicString& id) const
{
    Element* element = treeScope().getElementById(id);
    if (element && element->isDescendantOf(this))
        return element;
    
    
    for (Element* element = ElementTraversal::firstWithin(*this); element; element = ElementTraversal::next(*element, this)) {
        if (element->getIdAttribute() == id)
            return element;
    }
    return 0;
}
}