Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) 2009 Google, Inc.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  */
     21 
     22 #include "config.h"
     23 
     24 #include "core/rendering/svg/RenderSVGTransformableContainer.h"
     25 
     26 #include "core/rendering/svg/SVGRenderSupport.h"
     27 #include "core/svg/SVGGElement.h"
     28 #include "core/svg/SVGGraphicsElement.h"
     29 #include "core/svg/SVGUseElement.h"
     30 
     31 namespace blink {
     32 
     33 RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElement* node)
     34     : RenderSVGContainer(node)
     35     , m_needsTransformUpdate(true)
     36     , m_didTransformToRootUpdate(false)
     37 {
     38 }
     39 
     40 static bool hasValidPredecessor(const Node* node)
     41 {
     42     ASSERT(node);
     43     for (node = node->previousSibling(); node; node = node->previousSibling()) {
     44         if (node->isSVGElement() && toSVGElement(node)->isValid())
     45             return true;
     46     }
     47     return false;
     48 }
     49 
     50 bool RenderSVGTransformableContainer::isChildAllowed(RenderObject* child, RenderStyle* style) const
     51 {
     52     ASSERT(element());
     53     if (isSVGSwitchElement(*element())) {
     54         Node* node = child->node();
     55         // Reject non-SVG/non-valid elements.
     56         if (!node->isSVGElement() || !toSVGElement(node)->isValid())
     57             return false;
     58         // Reject this child if it isn't the first valid node.
     59         if (hasValidPredecessor(node))
     60             return false;
     61     } else if (isSVGAElement(*element())) {
     62         // http://www.w3.org/2003/01/REC-SVG11-20030114-errata#linking-text-environment
     63         // The 'a' element may contain any element that its parent may contain, except itself.
     64         if (isSVGAElement(*child->node()))
     65             return false;
     66         if (parent() && parent()->isSVG())
     67             return parent()->isChildAllowed(child, style);
     68     }
     69     return RenderSVGContainer::isChildAllowed(child, style);
     70 }
     71 
     72 bool RenderSVGTransformableContainer::calculateLocalTransform()
     73 {
     74     SVGGraphicsElement* element = toSVGGraphicsElement(this->element());
     75     ASSERT(element);
     76 
     77     // If we're either the renderer for a <use> element, or for any <g> element inside the shadow
     78     // tree, that was created during the use/symbol/svg expansion in SVGUseElement. These containers
     79     // need to respect the translations induced by their corresponding use elements x/y attributes.
     80     SVGUseElement* useElement = 0;
     81     if (isSVGUseElement(*element)) {
     82         useElement = toSVGUseElement(element);
     83     } else if (isSVGGElement(*element) && toSVGGElement(element)->inUseShadowTree()) {
     84         SVGElement* correspondingElement = element->correspondingElement();
     85         if (isSVGUseElement(correspondingElement))
     86             useElement = toSVGUseElement(correspondingElement);
     87     }
     88 
     89     if (useElement) {
     90         SVGLengthContext lengthContext(useElement);
     91         FloatSize translation(
     92             useElement->x()->currentValue()->value(lengthContext),
     93             useElement->y()->currentValue()->value(lengthContext));
     94         if (translation != m_lastTranslation)
     95             m_needsTransformUpdate = true;
     96         m_lastTranslation = translation;
     97     }
     98 
     99     m_didTransformToRootUpdate = m_needsTransformUpdate || SVGRenderSupport::transformToRootChanged(parent());
    100     if (!m_needsTransformUpdate)
    101         return false;
    102 
    103     m_localTransform = element->animatedLocalTransform();
    104     m_localTransform.translate(m_lastTranslation.width(), m_lastTranslation.height());
    105     m_needsTransformUpdate = false;
    106     return true;
    107 }
    108 
    109 }
    110