Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2007 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) 2008 Dirk Schulze <krit (at) webkit.org>
      5  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  */
     22 
     23 #include "config.h"
     24 
     25 #if ENABLE(SVG)
     26 #include "RenderSVGResource.h"
     27 
     28 #include "RenderSVGResourceContainer.h"
     29 #include "RenderSVGResourceSolidColor.h"
     30 #include "SVGResources.h"
     31 #include "SVGURIReference.h"
     32 
     33 namespace WebCore {
     34 
     35 static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, Color& fallbackColor)
     36 {
     37     ASSERT(object);
     38     ASSERT(style);
     39 
     40     // If we have no style at all, ignore it.
     41     const SVGRenderStyle* svgStyle = style->svgStyle();
     42     if (!svgStyle)
     43         return 0;
     44 
     45     // If we have no fill/stroke, return 0.
     46     if (mode == ApplyToFillMode) {
     47         if (!svgStyle->hasFill())
     48             return 0;
     49     } else {
     50         if (!svgStyle->hasStroke())
     51             return 0;
     52     }
     53 
     54     SVGPaint* paint = mode == ApplyToFillMode ? svgStyle->fillPaint() : svgStyle->strokePaint();
     55     ASSERT(paint);
     56 
     57     SVGPaint::SVGPaintType paintType = paint->paintType();
     58     if (paintType == SVGPaint::SVG_PAINTTYPE_NONE)
     59         return 0;
     60 
     61     Color color;
     62     if (paintType == SVGPaint::SVG_PAINTTYPE_RGBCOLOR
     63         || paintType == SVGPaint::SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR
     64         || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR
     65         || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR)
     66         color = paint->color();
     67     else if (paintType == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR || paintType == SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR)
     68         color = style->visitedDependentColor(CSSPropertyColor);
     69 
     70     if (style->insideLink() == InsideVisitedLink) {
     71         RenderStyle* visitedStyle = style->getCachedPseudoStyle(VISITED_LINK);
     72         ASSERT(visitedStyle);
     73 
     74         if (SVGPaint* visitedPaint = mode == ApplyToFillMode ? visitedStyle->svgStyle()->fillPaint() : visitedStyle->svgStyle()->strokePaint()) {
     75             // For SVG_PAINTTYPE_CURRENTCOLOR, 'color' already contains the 'visitedColor'.
     76             if (visitedPaint->paintType() < SVGPaint::SVG_PAINTTYPE_URI_NONE && visitedPaint->paintType() != SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) {
     77                 const Color& visitedColor = visitedPaint->color();
     78                 if (visitedColor.isValid())
     79                     color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
     80             }
     81         }
     82     }
     83 
     84     // If the primary resource is just a color, return immediately.
     85     RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource();
     86     if (paintType < SVGPaint::SVG_PAINTTYPE_URI_NONE) {
     87         // If an invalid fill color is specified, fallback to fill/stroke="none".
     88         if (!color.isValid())
     89             return 0;
     90 
     91         colorResource->setColor(color);
     92         return colorResource;
     93     }
     94 
     95     // If no resources are associated with the given renderer, return the color resource.
     96     SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
     97     if (!resources) {
     98         // If a paint server is specified, and no or an invalid fallback color is given, default to fill/stroke="black".
     99         if (!color.isValid())
    100             color = Color::black;
    101 
    102         colorResource->setColor(color);
    103         return colorResource;
    104     }
    105 
    106     // If the requested resource is not available, return the color resource.
    107     RenderSVGResource* uriResource = mode == ApplyToFillMode ? resources->fill() : resources->stroke();
    108     if (!uriResource) {
    109         // If a paint server is specified, and no or an invalid fallback color is given, default to fill/stroke="black".
    110         if (!color.isValid())
    111             color = Color::black;
    112 
    113         colorResource->setColor(color);
    114         return colorResource;
    115     }
    116 
    117     // The paint server resource exists, though it may be invalid (pattern with width/height=0). Pass the fallback color to our caller
    118     // so it can use the solid color painting resource, if applyResource() on the URI resource failed.
    119     fallbackColor = color;
    120     return uriResource;
    121 }
    122 
    123 RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
    124 {
    125     return requestPaintingResource(ApplyToFillMode, object, style, fallbackColor);
    126 }
    127 
    128 RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
    129 {
    130     return requestPaintingResource(ApplyToStrokeMode, object, style, fallbackColor);
    131 }
    132 
    133 RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
    134 {
    135     static RenderSVGResourceSolidColor* s_sharedSolidPaintingResource = 0;
    136     if (!s_sharedSolidPaintingResource)
    137         s_sharedSolidPaintingResource = new RenderSVGResourceSolidColor;
    138     return s_sharedSolidPaintingResource;
    139 }
    140 
    141 void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout)
    142 {
    143     ASSERT(object);
    144     if (needsLayout)
    145         object->setNeedsLayout(true);
    146 
    147     // Invalidate resources in ancestor chain, if needed.
    148     RenderObject* current = object->parent();
    149     while (current) {
    150         if (current->isSVGResourceContainer()) {
    151             current->toRenderSVGResourceContainer()->removeAllClientsFromCache();
    152             break;
    153         }
    154 
    155         current = current->parent();
    156     }
    157 }
    158 
    159 }
    160 
    161 #endif
    162