1 /* 2 * Copyright (C) 2008 Alex Mathews <possessedpenguinbob (at) gmail.com> 3 * Copyright (C) 2009 Dirk Schulze <krit (at) 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 35 namespace blink { 36 37 FETile::FETile(Filter* filter) 38 : FilterEffect(filter) 39 { 40 } 41 42 PassRefPtr<FETile> FETile::create(Filter* filter) 43 { 44 return adoptRef(new FETile(filter)); 45 } 46 47 FloatRect FETile::mapPaintRect(const FloatRect& rect, bool forward) 48 { 49 return forward ? maxEffectRect() : inputEffect(0)->maxEffectRect(); 50 } 51 52 void 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 96 static 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 111 PassRefPtr<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 119 TextStream& 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