WebCore/rendering/RenderSVGResourceContainer.h
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public License
       
    15  * along with this library; see the file COPYING.LIB.  If not, write to
       
    16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    17  * Boston, MA 02110-1301, USA.
       
    18  *
       
    19  */
       
    20 
       
    21 #ifndef RenderSVGResourceContainer_h
       
    22 #define RenderSVGResourceContainer_h
       
    23 
       
    24 #if ENABLE(SVG)
       
    25 #include "RenderSVGHiddenContainer.h"
       
    26 
       
    27 #include "SVGStyledTransformableElement.h"
       
    28 #include "RenderSVGResource.h"
       
    29 #include "RenderSVGShadowTreeRootContainer.h"
       
    30 
       
    31 namespace WebCore {
       
    32 
       
    33 class RenderSVGResourceContainer : public RenderSVGHiddenContainer,
       
    34                                    public RenderSVGResource {
       
    35 public:
       
    36     RenderSVGResourceContainer(SVGStyledElement* node)
       
    37         : RenderSVGHiddenContainer(node)
       
    38         , RenderSVGResource()
       
    39         , m_id(node->hasID() ? node->getIdAttribute() : nullAtom)
       
    40     {
       
    41         ASSERT(node->document());
       
    42         node->document()->accessSVGExtensions()->addResource(m_id, this);
       
    43     }
       
    44 
       
    45     virtual ~RenderSVGResourceContainer()
       
    46     {
       
    47         ASSERT(node());
       
    48         ASSERT(node()->document());
       
    49         node()->document()->accessSVGExtensions()->removeResource(m_id);
       
    50     }
       
    51 
       
    52     void idChanged()
       
    53     {
       
    54         ASSERT(node());
       
    55         ASSERT(node()->document());
       
    56         SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions();
       
    57 
       
    58         // Remove old id, that is guaranteed to be present in cache
       
    59         extensions->removeResource(m_id);
       
    60         m_id = static_cast<Element*>(node())->getIdAttribute();
       
    61 
       
    62         // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now
       
    63         if (extensions->isPendingResource(m_id)) {
       
    64             OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id));
       
    65             if (clients->isEmpty())
       
    66                 return;
       
    67 
       
    68             HashSet<SVGStyledElement*>::const_iterator it = clients->begin();
       
    69             const HashSet<SVGStyledElement*>::const_iterator end = clients->end();
       
    70 
       
    71             for (; it != end; ++it) {
       
    72                 if (RenderObject* renderer = (*it)->renderer())
       
    73                     renderer->setNeedsLayout(true);
       
    74             }
       
    75         }
       
    76 
       
    77         // Recache us with the new id
       
    78         extensions->addResource(m_id, this);
       
    79     }
       
    80 
       
    81     virtual bool isSVGResourceContainer() const { return true; }
       
    82     virtual bool drawsContents() { return false; }
       
    83 
       
    84     virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; }
       
    85     virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const { return false; }
       
    86 
       
    87     static AffineTransform transformOnNonScalingStroke(RenderObject* object, const AffineTransform resourceTransform)
       
    88     {
       
    89         if (!object->isRenderPath())
       
    90             return resourceTransform;
       
    91 
       
    92         SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node());
       
    93         AffineTransform transform = resourceTransform;
       
    94         transform.multiply(element->getScreenCTM());
       
    95         return transform;
       
    96     }
       
    97 
       
    98     bool containsCyclicReference(const Node* startNode) const
       
    99     {
       
   100         ASSERT(startNode->document());
       
   101     
       
   102         for (Node* node = startNode->firstChild(); node; node = node->nextSibling()) {
       
   103             if (!node->isSVGElement())
       
   104                 continue;
       
   105     
       
   106             RenderObject* renderer = node->renderer();
       
   107             if (!renderer)
       
   108                 continue;
       
   109     
       
   110             RenderStyle* style = renderer->style();
       
   111             if (!style)
       
   112                 continue;
       
   113     
       
   114             const SVGRenderStyle* svgStyle = style->svgStyle();
       
   115             ASSERT(svgStyle);
       
   116     
       
   117             // Let the class inheriting from us decide whether the child element references ourselves.
       
   118             if (childElementReferencesResource(svgStyle, m_id))
       
   119                 return true;
       
   120 
       
   121             // Dive into shadow tree to check for cycles there.
       
   122             if (node->hasTagName(SVGNames::useTag)) {
       
   123                 ASSERT(renderer->isSVGShadowTreeRootContainer());
       
   124                 if (Node* shadowRoot = static_cast<RenderSVGShadowTreeRootContainer*>(renderer)->rootElement()) {
       
   125                     if (containsCyclicReference(shadowRoot))
       
   126                         return true;
       
   127                 }
       
   128 
       
   129             }
       
   130 
       
   131             if (node->hasChildNodes()) {
       
   132                 if (containsCyclicReference(node))
       
   133                     return true;
       
   134             }
       
   135         }
       
   136     
       
   137         return false;
       
   138     }
       
   139 
       
   140 private:
       
   141     AtomicString m_id;
       
   142 };
       
   143 
       
   144 inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document* document, const AtomicString& id)
       
   145 {
       
   146     if (id.isEmpty())
       
   147         return 0;
       
   148 
       
   149     if (RenderSVGResourceContainer* renderResource = document->accessSVGExtensions()->resourceById(id))
       
   150         return renderResource;
       
   151 
       
   152     return 0;
       
   153 }
       
   154 
       
   155 template<typename Renderer>
       
   156 Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id)
       
   157 {
       
   158     if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id))
       
   159         return container->cast<Renderer>();
       
   160 
       
   161     return 0;
       
   162 }
       
   163 
       
   164 }
       
   165 
       
   166 #endif
       
   167 #endif