diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderSVGResource.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderSVGResource.cpp | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/RenderSVGResource.cpp b/Source/WebCore/rendering/RenderSVGResource.cpp new file mode 100644 index 0000000..f4c65d5 --- /dev/null +++ b/Source/WebCore/rendering/RenderSVGResource.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2007 Rob Buis <buis@kde.org> + * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(SVG) +#include "RenderSVGResource.h" + +#include "RenderSVGResourceContainer.h" +#include "RenderSVGResourceSolidColor.h" +#include "SVGResources.h" +#include "SVGURIReference.h" + +namespace WebCore { + +static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, Color& fallbackColor) +{ + ASSERT(object); + ASSERT(style); + + // If we have no style at all, ignore it. + const SVGRenderStyle* svgStyle = style->svgStyle(); + if (!svgStyle) + return 0; + + // If we have no fill/stroke, return 0. + if (mode == ApplyToFillMode) { + if (!svgStyle->hasFill()) + return 0; + } else { + if (!svgStyle->hasStroke()) + return 0; + } + + SVGPaint* paint = mode == ApplyToFillMode ? svgStyle->fillPaint() : svgStyle->strokePaint(); + ASSERT(paint); + + SVGPaint::SVGPaintType paintType = paint->paintType(); + if (paintType == SVGPaint::SVG_PAINTTYPE_NONE) + return 0; + + Color color; + if (paintType == SVGPaint::SVG_PAINTTYPE_RGBCOLOR + || paintType == SVGPaint::SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR + || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR + || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR) + color = paint->color(); + else if (paintType == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR || paintType == SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR) + color = style->visitedDependentColor(CSSPropertyColor); + + if (style->insideLink() == InsideVisitedLink) { + RenderStyle* visitedStyle = style->getCachedPseudoStyle(VISITED_LINK); + ASSERT(visitedStyle); + + if (SVGPaint* visitedPaint = mode == ApplyToFillMode ? visitedStyle->svgStyle()->fillPaint() : visitedStyle->svgStyle()->strokePaint()) { + // For SVG_PAINTTYPE_CURRENTCOLOR, 'color' already contains the 'visitedColor'. + if (visitedPaint->paintType() < SVGPaint::SVG_PAINTTYPE_URI_NONE && visitedPaint->paintType() != SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) { + const Color& visitedColor = visitedPaint->color(); + if (visitedColor.isValid()) + color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha()); + } + } + } + + // If the primary resource is just a color, return immediately. + RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource(); + if (paintType < SVGPaint::SVG_PAINTTYPE_URI_NONE) { + // If an invalid fill color is specified, fallback to fill/stroke="none". + if (!color.isValid()) + return 0; + + colorResource->setColor(color); + return colorResource; + } + + // If no resources are associated with the given renderer, return the color resource. + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); + if (!resources) { + // If a paint server is specified, and no or an invalid fallback color is given, default to fill/stroke="black". + if (!color.isValid()) + color = Color::black; + + colorResource->setColor(color); + return colorResource; + } + + // If the requested resource is not available, return the color resource. + RenderSVGResource* uriResource = mode == ApplyToFillMode ? resources->fill() : resources->stroke(); + if (!uriResource) { + // If a paint server is specified, and no or an invalid fallback color is given, default to fill/stroke="black". + if (!color.isValid()) + color = Color::black; + + colorResource->setColor(color); + return colorResource; + } + + // The paint server resource exists, though it may be invalid (pattern with width/height=0). Pass the fallback color to our caller + // so it can use the solid color painting resource, if applyResource() on the URI resource failed. + fallbackColor = color; + return uriResource; +} + +RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor) +{ + return requestPaintingResource(ApplyToFillMode, object, style, fallbackColor); +} + +RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor) +{ + return requestPaintingResource(ApplyToStrokeMode, object, style, fallbackColor); +} + +RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource() +{ + static RenderSVGResourceSolidColor* s_sharedSolidPaintingResource = 0; + if (!s_sharedSolidPaintingResource) + s_sharedSolidPaintingResource = new RenderSVGResourceSolidColor; + return s_sharedSolidPaintingResource; +} + +void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout) +{ + ASSERT(object); + if (needsLayout) + object->setNeedsLayout(true); + + // Invalidate resources in ancestor chain, if needed. + RenderObject* current = object->parent(); + while (current) { + if (current->isSVGResourceContainer()) { + current->toRenderSVGResourceContainer()->removeAllClientsFromCache(); + break; + } + + current = current->parent(); + } +} + +} + +#endif |