1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org> 5 * Copyright (C) 2010 Dirk Schulze <krit (at) webkit.org> 6 * Copyright (C) 2013 Google Inc. All rights reserved. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24 #include "config.h" 25 26 #include "core/svg/graphics/filters/SVGFEImage.h" 27 28 #include "SkBitmapSource.h" 29 #include "core/rendering/RenderObject.h" 30 #include "core/rendering/svg/SVGRenderingContext.h" 31 #include "core/svg/SVGElement.h" 32 #include "core/svg/SVGURIReference.h" 33 #include "platform/graphics/GraphicsContext.h" 34 #include "platform/graphics/filters/Filter.h" 35 #include "platform/text/TextStream.h" 36 #include "platform/transforms/AffineTransform.h" 37 38 namespace WebCore { 39 40 FEImage::FEImage(Filter* filter, PassRefPtr<Image> image, const SVGPreserveAspectRatio& preserveAspectRatio) 41 : FilterEffect(filter) 42 , m_image(image) 43 , m_document(0) 44 , m_preserveAspectRatio(preserveAspectRatio) 45 { 46 } 47 48 FEImage::FEImage(Filter* filter, Document& document, const String& href, const SVGPreserveAspectRatio& preserveAspectRatio) 49 : FilterEffect(filter) 50 , m_document(&document) 51 , m_href(href) 52 , m_preserveAspectRatio(preserveAspectRatio) 53 { 54 } 55 56 PassRefPtr<FEImage> FEImage::createWithImage(Filter* filter, PassRefPtr<Image> image, const SVGPreserveAspectRatio& preserveAspectRatio) 57 { 58 return adoptRef(new FEImage(filter, image, preserveAspectRatio)); 59 } 60 61 PassRefPtr<FEImage> FEImage::createWithIRIReference(Filter* filter, Document& document, const String& href, const SVGPreserveAspectRatio& preserveAspectRatio) 62 { 63 return adoptRef(new FEImage(filter, document, href, preserveAspectRatio)); 64 } 65 66 void FEImage::determineAbsolutePaintRect() 67 { 68 FloatRect paintRect = filter()->absoluteTransform().mapRect(filterPrimitiveSubregion()); 69 FloatRect srcRect; 70 if (m_image) { 71 srcRect.setSize(m_image->size()); 72 m_preserveAspectRatio.transformRect(paintRect, srcRect); 73 } else if (RenderObject* renderer = referencedRenderer()) 74 srcRect = filter()->absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); 75 76 if (clipsToBounds()) 77 paintRect.intersect(maxEffectRect()); 78 else 79 paintRect.unite(maxEffectRect()); 80 setAbsolutePaintRect(enclosingIntRect(paintRect)); 81 } 82 83 RenderObject* FEImage::referencedRenderer() const 84 { 85 if (!m_document) 86 return 0; 87 Element* hrefElement = SVGURIReference::targetElementFromIRIString(m_href, *m_document); 88 if (!hrefElement || !hrefElement->isSVGElement()) 89 return 0; 90 return hrefElement->renderer(); 91 } 92 93 void FEImage::applySoftware() 94 { 95 RenderObject* renderer = referencedRenderer(); 96 if (!m_image && !renderer) 97 return; 98 99 ImageBuffer* resultImage = createImageBufferResult(); 100 if (!resultImage) 101 return; 102 103 FloatRect destRect = filter()->absoluteTransform().mapRect(filterPrimitiveSubregion()); 104 105 FloatRect srcRect; 106 if (renderer) 107 srcRect = filter()->absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); 108 else { 109 srcRect = FloatRect(FloatPoint(), m_image->size()); 110 m_preserveAspectRatio.transformRect(destRect, srcRect); 111 } 112 113 IntPoint paintLocation = absolutePaintRect().location(); 114 destRect.move(-paintLocation.x(), -paintLocation.y()); 115 116 // FEImage results are always in ColorSpaceDeviceRGB 117 setResultColorSpace(ColorSpaceDeviceRGB); 118 119 if (renderer) { 120 SVGElement* contextNode = toSVGElement(renderer->node()); 121 if (contextNode->hasRelativeLengths()) { 122 SVGLengthContext lengthContext(contextNode); 123 FloatSize viewportSize; 124 125 // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport. 126 // Build up a transformation that maps from the viewport space to the filter primitive subregion. 127 if (lengthContext.determineViewport(viewportSize)) 128 resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect)); 129 } else { 130 const AffineTransform& absoluteTransform = filter()->absoluteTransform(); 131 resultImage->context()->concatCTM(absoluteTransform); 132 } 133 134 AffineTransform contentTransformation; 135 SVGRenderingContext::renderSubtree(resultImage->context(), renderer, contentTransformation); 136 return; 137 } 138 139 resultImage->context()->drawImage(m_image.get(), destRect, srcRect); 140 } 141 142 TextStream& FEImage::externalRepresentation(TextStream& ts, int indent) const 143 { 144 IntSize imageSize; 145 if (m_image) 146 imageSize = m_image->size(); 147 else if (RenderObject* renderer = referencedRenderer()) 148 imageSize = enclosingIntRect(renderer->repaintRectInLocalCoordinates()).size(); 149 writeIndent(ts, indent); 150 ts << "[feImage"; 151 FilterEffect::externalRepresentation(ts); 152 ts << " image-size=\"" << imageSize.width() << "x" << imageSize.height() << "\"]\n"; 153 // FIXME: should this dump also object returned by SVGFEImage::image() ? 154 return ts; 155 } 156 157 PassRefPtr<SkImageFilter> FEImage::createImageFilter(SkiaImageFilterBuilder* builder) 158 { 159 if (!m_image) 160 return 0; 161 162 if (!m_image->nativeImageForCurrentFrame()) 163 return 0; 164 165 return adoptRef(new SkBitmapSource(m_image->nativeImageForCurrentFrame()->bitmap())); 166 } 167 168 } // namespace WebCore 169