1/* 2 * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> 3 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 4 * Copyright (C) 2013 Google Inc. All rights reserved. 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#include "platform/graphics/filters/FETile.h" 24 25#include "SkTileImageFilter.h" 26 27#include "platform/graphics/GraphicsContext.h" 28#include "platform/graphics/Pattern.h" 29#include "platform/graphics/UnacceleratedImageBufferSurface.h" 30#include "platform/graphics/filters/SkiaImageFilterBuilder.h" 31#include "platform/text/TextStream.h" 32#include "platform/transforms/AffineTransform.h" 33#include "third_party/skia/include/core/SkDevice.h" 34 35namespace blink { 36 37FETile::FETile(Filter* filter) 38 : FilterEffect(filter) 39{ 40} 41 42PassRefPtr<FETile> FETile::create(Filter* filter) 43{ 44 return adoptRef(new FETile(filter)); 45} 46 47FloatRect FETile::mapPaintRect(const FloatRect& rect, bool forward) 48{ 49 return forward ? maxEffectRect() : inputEffect(0)->maxEffectRect(); 50} 51 52void FETile::applySoftware() 53{ 54 FilterEffect* in = inputEffect(0); 55 56 ImageBuffer* resultImage = createImageBufferResult(); 57 if (!resultImage) 58 return; 59 60 setIsAlphaImage(in->isAlphaImage()); 61 62 // Source input needs more attention. It has the size of the filterRegion but gives the 63 // size of the cutted sourceImage back. This is part of the specification and optimization. 64 FloatRect tileRect = in->maxEffectRect(); 65 FloatPoint inMaxEffectLocation = tileRect.location(); 66 FloatPoint maxEffectLocation = maxEffectRect().location(); 67 if (in->filterEffectType() == FilterEffectTypeSourceInput) { 68 Filter* filter = this->filter(); 69 tileRect = filter->absoluteFilterRegion(); 70 } 71 72 OwnPtr<ImageBufferSurface> surface; 73 IntSize intTileSize = roundedIntSize(tileRect.size()); 74 surface = adoptPtr(new UnacceleratedImageBufferSurface(intTileSize)); 75 OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(surface.release()); 76 if (!tileImage) 77 return; 78 79 GraphicsContext* tileImageContext = tileImage->context(); 80 tileImageContext->scale(intTileSize.width() / tileRect.width(), intTileSize.height() / tileRect.height()); 81 tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y()); 82 83 if (ImageBuffer* tileImageBuffer = in->asImageBuffer()) 84 tileImageContext->drawImageBuffer(tileImageBuffer, IntRect(in->absolutePaintRect().location(), tileImageBuffer->size())); 85 86 RefPtr<Pattern> pattern = Pattern::createBitmapPattern(tileImage->copyImage(CopyBackingStore)); 87 88 AffineTransform patternTransform; 89 patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y()); 90 pattern->setPatternSpaceTransform(patternTransform); 91 GraphicsContext* filterContext = resultImage->context(); 92 filterContext->setFillPattern(pattern); 93 filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size())); 94} 95 96static FloatRect getRect(FilterEffect* effect) 97{ 98 FloatRect result = effect->filter()->filterRegion(); 99 FloatRect boundaries = effect->effectBoundaries(); 100 if (effect->hasX()) 101 result.setX(boundaries.x()); 102 if (effect->hasY()) 103 result.setY(boundaries.y()); 104 if (effect->hasWidth()) 105 result.setWidth(boundaries.width()); 106 if (effect->hasHeight()) 107 result.setHeight(boundaries.height()); 108 return result; 109} 110 111PassRefPtr<SkImageFilter> FETile::createImageFilter(SkiaImageFilterBuilder* builder) 112{ 113 RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace())); 114 FloatRect srcRect = inputEffect(0) ? getRect(inputEffect(0)) : filter()->filterRegion(); 115 FloatRect dstRect = getRect(this); 116 return adoptRef(SkTileImageFilter::Create(srcRect, dstRect, input.get())); 117} 118 119TextStream& FETile::externalRepresentation(TextStream& ts, int indent) const 120{ 121 writeIndent(ts, indent); 122 ts << "[feTile"; 123 FilterEffect::externalRepresentation(ts); 124 ts << "]\n"; 125 inputEffect(0)->externalRepresentation(ts, indent + 1); 126 127 return ts; 128} 129 130} // namespace blink 131