1 /* 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2010 Dirk Schulze <krit (at) webkit.org> 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 #if ENABLE(SVG) && ENABLE(FILTERS) 25 #include "SVGFEImageElement.h" 26 27 #include "Attr.h" 28 #include "CachedImage.h" 29 #include "CachedResourceLoader.h" 30 #include "ColorSpace.h" 31 #include "Document.h" 32 #include "Image.h" 33 #include "RenderObject.h" 34 #include "RenderSVGResource.h" 35 #include "SVGImageBufferTools.h" 36 #include "SVGNames.h" 37 #include "SVGPreserveAspectRatio.h" 38 39 namespace WebCore { 40 41 // Animated property definitions 42 DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGFEImageElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio) 43 DEFINE_ANIMATED_STRING(SVGFEImageElement, XLinkNames::hrefAttr, Href, href) 44 DEFINE_ANIMATED_BOOLEAN(SVGFEImageElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 45 46 inline SVGFEImageElement::SVGFEImageElement(const QualifiedName& tagName, Document* document) 47 : SVGFilterPrimitiveStandardAttributes(tagName, document) 48 { 49 } 50 51 PassRefPtr<SVGFEImageElement> SVGFEImageElement::create(const QualifiedName& tagName, Document* document) 52 { 53 return adoptRef(new SVGFEImageElement(tagName, document)); 54 } 55 56 SVGFEImageElement::~SVGFEImageElement() 57 { 58 if (m_cachedImage) 59 m_cachedImage->removeClient(this); 60 } 61 62 void SVGFEImageElement::requestImageResource() 63 { 64 if (m_cachedImage) { 65 m_cachedImage->removeClient(this); 66 m_cachedImage = 0; 67 } 68 69 Element* hrefElement = document()->getElementById(SVGURIReference::getTarget(href())); 70 if (hrefElement && hrefElement->isSVGElement() && hrefElement->renderer()) 71 return; 72 73 m_cachedImage = ownerDocument()->cachedResourceLoader()->requestImage(href()); 74 75 if (m_cachedImage) 76 m_cachedImage->addClient(this); 77 } 78 79 void SVGFEImageElement::parseMappedAttribute(Attribute* attr) 80 { 81 const String& value = attr->value(); 82 if (attr->name() == SVGNames::preserveAspectRatioAttr) 83 SVGPreserveAspectRatio::parsePreserveAspectRatio(this, value); 84 else { 85 if (SVGURIReference::parseMappedAttribute(attr)) { 86 requestImageResource(); 87 return; 88 } 89 if (SVGLangSpace::parseMappedAttribute(attr)) 90 return; 91 if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) 92 return; 93 94 SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr); 95 } 96 } 97 98 void SVGFEImageElement::svgAttributeChanged(const QualifiedName& attrName) 99 { 100 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 101 102 if (attrName == SVGNames::preserveAspectRatioAttr) 103 invalidate(); 104 } 105 106 void SVGFEImageElement::synchronizeProperty(const QualifiedName& attrName) 107 { 108 SVGFilterPrimitiveStandardAttributes::synchronizeProperty(attrName); 109 110 if (attrName == anyQName()) { 111 synchronizePreserveAspectRatio(); 112 synchronizeHref(); 113 synchronizeExternalResourcesRequired(); 114 return; 115 } 116 117 if (attrName == SVGNames::preserveAspectRatioAttr) 118 synchronizePreserveAspectRatio(); 119 else if (SVGURIReference::isKnownAttribute(attrName)) 120 synchronizeHref(); 121 else if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) 122 synchronizeExternalResourcesRequired(); 123 } 124 125 AttributeToPropertyTypeMap& SVGFEImageElement::attributeToPropertyTypeMap() 126 { 127 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ()); 128 return s_attributeToPropertyTypeMap; 129 } 130 131 void SVGFEImageElement::fillAttributeToPropertyTypeMap() 132 { 133 AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap(); 134 135 SVGFilterPrimitiveStandardAttributes::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap); 136 attributeToPropertyTypeMap.set(SVGNames::preserveAspectRatioAttr, AnimatedPreserveAspectRatio); 137 attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedString); 138 } 139 140 void SVGFEImageElement::notifyFinished(CachedResource*) 141 { 142 if (!inDocument()) 143 return; 144 145 Element* parent = parentElement(); 146 ASSERT(parent); 147 148 if (!parent->hasTagName(SVGNames::filterTag) || !parent->renderer()) 149 return; 150 151 RenderSVGResource::markForLayoutAndParentResourceInvalidation(parent->renderer()); 152 } 153 154 PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter* filter) 155 { 156 if (!m_cachedImage && !m_targetImage) { 157 Element* hrefElement = document()->getElementById(SVGURIReference::getTarget(href())); 158 if (!hrefElement || !hrefElement->isSVGElement()) 159 return 0; 160 161 RenderObject* renderer = hrefElement->renderer(); 162 if (!renderer) 163 return 0; 164 165 IntRect targetRect = enclosingIntRect(renderer->objectBoundingBox()); 166 m_targetImage = ImageBuffer::create(targetRect.size(), ColorSpaceLinearRGB); 167 168 AffineTransform contentTransformation; 169 SVGImageBufferTools::renderSubtreeToImageBuffer(m_targetImage.get(), renderer, contentTransformation); 170 } 171 172 return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage() : m_cachedImage->image(), preserveAspectRatio()); 173 } 174 175 void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 176 { 177 SVGFilterPrimitiveStandardAttributes::addSubresourceAttributeURLs(urls); 178 179 addSubresourceURL(urls, document()->completeURL(href())); 180 } 181 182 } 183 184 #endif // ENABLE(SVG) 185