/* * Copyright (C) 2006 Nikolas Zimmermann * 2007 Rob Buis * 2008 Dirk Schulze * 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 { inline void RenderSVGResource::adjustColorForPseudoRules(const RenderStyle* style, bool useFillPaint, Color& color) { if (style->insideLink() != InsideVisitedLink) return; RenderStyle* visitedStyle = style->getCachedPseudoStyle(VISITED_LINK); SVGPaint* visitedPaint = useFillPaint ? visitedStyle->svgStyle()->fillPaint() : visitedStyle->svgStyle()->strokePaint(); if (visitedPaint->paintType() == SVGPaint::SVG_PAINTTYPE_URI) return; Color visitedColor; if (visitedPaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) visitedColor = visitedStyle->color(); else visitedColor = visitedPaint->color(); if (visitedColor.isValid()) color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha()); } // FIXME: This method and strokePaintingResource() should be refactored, to share even more code RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style) { ASSERT(object); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); if (!svgStyle || !svgStyle->hasFill()) return 0; SVGPaint* fillPaint = svgStyle->fillPaint(); ASSERT(fillPaint); RenderSVGResource* fillPaintingResource = 0; SVGPaint::SVGPaintType paintType = fillPaint->paintType(); if (paintType == SVGPaint::SVG_PAINTTYPE_URI || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) { if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) fillPaintingResource = resources->fill(); } if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !fillPaintingResource) { RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); fillPaintingResource = solidResource; Color fillColor; if (fillPaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) fillColor = style->visitedDependentColor(CSSPropertyColor); else fillColor = fillPaint->color(); adjustColorForPseudoRules(style, true /* useFillPaint */, fillColor); // FIXME: Ideally invalid colors would never get set on the RenderStyle and this could turn into an ASSERT if (fillColor.isValid()) solidResource->setColor(fillColor); else fillPaintingResource = 0; } if (!fillPaintingResource) { // default value (black), see bug 11017 RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); solidResource->setColor(Color::black); fillPaintingResource = solidResource; } return fillPaintingResource; } RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style) { ASSERT(object); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); if (!svgStyle || !svgStyle->hasStroke()) return 0; SVGPaint* strokePaint = svgStyle->strokePaint(); ASSERT(strokePaint); RenderSVGResource* strokePaintingResource = 0; FloatRect objectBoundingBox = object->objectBoundingBox(); SVGPaint::SVGPaintType paintType = strokePaint->paintType(); if (!objectBoundingBox.isEmpty() && (paintType == SVGPaint::SVG_PAINTTYPE_URI || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)) { if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) strokePaintingResource = resources->stroke(); } if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !strokePaintingResource) { RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); strokePaintingResource = solidResource; Color strokeColor; if (strokePaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) strokeColor = style->visitedDependentColor(CSSPropertyColor); else strokeColor = strokePaint->color(); adjustColorForPseudoRules(style, false /* useFillPaint */, strokeColor); // FIXME: Ideally invalid colors would never get set on the RenderStyle and this could turn into an ASSERT if (strokeColor.isValid()) solidResource->setColor(strokeColor); else strokePaintingResource = 0; } if (!strokePaintingResource) { // default value (black), see bug 11017 RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); solidResource->setColor(Color::black); strokePaintingResource = solidResource; } return strokePaintingResource; } 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()->invalidateClients(); break; } current = current->parent(); } } } #endif