1/* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2010 Dirk Schulze <krit@webkit.org> 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(FILTERS) 26#include "SVGFEImage.h" 27 28#include "AffineTransform.h" 29#include "Filter.h" 30#include "GraphicsContext.h" 31#include "RenderElement.h" 32#include "RenderTreeAsText.h" 33#include "SVGElement.h" 34#include "SVGPreserveAspectRatio.h" 35#include "SVGRenderingContext.h" 36#include "SVGURIReference.h" 37#include "TextStream.h" 38 39namespace WebCore { 40 41FEImage::FEImage(Filter* filter, PassRefPtr<Image> image, const SVGPreserveAspectRatio& preserveAspectRatio) 42 : FilterEffect(filter) 43 , m_image(image) 44 , m_document(0) 45 , m_preserveAspectRatio(preserveAspectRatio) 46{ 47} 48 49FEImage::FEImage(Filter* filter, Document& document, const String& href, const SVGPreserveAspectRatio& preserveAspectRatio) 50 : FilterEffect(filter) 51 , m_document(&document) 52 , m_href(href) 53 , m_preserveAspectRatio(preserveAspectRatio) 54{ 55} 56 57PassRefPtr<FEImage> FEImage::createWithImage(Filter* filter, PassRefPtr<Image> image, const SVGPreserveAspectRatio& preserveAspectRatio) 58{ 59 return adoptRef(new FEImage(filter, image, preserveAspectRatio)); 60} 61 62PassRefPtr<FEImage> FEImage::createWithIRIReference(Filter* filter, Document& document, const String& href, const SVGPreserveAspectRatio& preserveAspectRatio) 63{ 64 return adoptRef(new FEImage(filter, document, href, preserveAspectRatio)); 65} 66 67void FEImage::determineAbsolutePaintRect() 68{ 69 FloatRect paintRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion()); 70 FloatRect srcRect; 71 if (m_image) { 72 srcRect.setSize(m_image->size()); 73 m_preserveAspectRatio.transformRect(paintRect, srcRect); 74 } else if (RenderElement* renderer = referencedRenderer()) 75 srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); 76 77 if (clipsToBounds()) 78 paintRect.intersect(maxEffectRect()); 79 else 80 paintRect.unite(maxEffectRect()); 81 setAbsolutePaintRect(enclosingIntRect(paintRect)); 82} 83 84RenderElement* FEImage::referencedRenderer() const 85{ 86 if (!m_document) 87 return 0; 88 Element* hrefElement = SVGURIReference::targetElementFromIRIString(m_href, *m_document); 89 if (!hrefElement || !hrefElement->isSVGElement()) 90 return 0; 91 return hrefElement->renderer(); 92} 93 94void FEImage::platformApplySoftware() 95{ 96 RenderElement* renderer = referencedRenderer(); 97 if (!m_image && !renderer) 98 return; 99 100 ImageBuffer* resultImage = createImageBufferResult(); 101 if (!resultImage) 102 return; 103 104 FloatRect destRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion()); 105 106 FloatRect srcRect; 107 if (renderer) 108 srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); 109 else { 110 srcRect = FloatRect(FloatPoint(), m_image->size()); 111 m_preserveAspectRatio.transformRect(destRect, srcRect); 112 } 113 114 IntPoint paintLocation = absolutePaintRect().location(); 115 destRect.move(-paintLocation.x(), -paintLocation.y()); 116 117 // FEImage results are always in ColorSpaceDeviceRGB 118 setResultColorSpace(ColorSpaceDeviceRGB); 119 120 if (renderer) { 121 const AffineTransform& absoluteTransform = filter().absoluteTransform(); 122 resultImage->context()->concatCTM(absoluteTransform); 123 124 SVGElement* contextNode = toSVGElement(renderer->element()); 125 if (contextNode->hasRelativeLengths()) { 126 SVGLengthContext lengthContext(contextNode); 127 FloatSize viewportSize; 128 129 // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport. 130 // Build up a transformation that maps from the viewport space to the filter primitive subregion. 131 if (lengthContext.determineViewport(viewportSize)) 132 resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect)); 133 } 134 135 AffineTransform contentTransformation; 136 SVGRenderingContext::renderSubtreeToImageBuffer(resultImage, *renderer, contentTransformation); 137 return; 138 } 139 140 resultImage->context()->drawImage(m_image.get(), ColorSpaceDeviceRGB, destRect, srcRect); 141} 142 143void FEImage::dump() 144{ 145} 146 147TextStream& FEImage::externalRepresentation(TextStream& ts, int indent) const 148{ 149 FloatSize imageSize; 150 if (m_image) 151 imageSize = m_image->size(); 152 else if (RenderObject* renderer = referencedRenderer()) 153 imageSize = enclosingIntRect(renderer->repaintRectInLocalCoordinates()).size(); 154 writeIndent(ts, indent); 155 ts << "[feImage"; 156 FilterEffect::externalRepresentation(ts); 157 ts << " image-size=\"" << imageSize.width() << "x" << imageSize.height() << "\"]\n"; 158 // FIXME: should this dump also object returned by SVGFEImage::image() ? 159 return ts; 160} 161 162} // namespace WebCore 163 164#endif // ENABLE(FILTERS) 165