1f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org/* 2f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org * Copyright 2013 Google Inc. 3f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org * 4f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org * Use of this source code is governed by a BSD-style license that can be 5f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org * found in the LICENSE file. 6f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org */ 7f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 8f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org#include "SkDropShadowImageFilter.h" 9f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 10f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org#include "SkBitmap.h" 11f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org#include "SkBlurImageFilter.h" 12f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org#include "SkCanvas.h" 13f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org#include "SkColorMatrixFilter.h" 14f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org#include "SkDevice.h" 158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 17f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 18f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgSkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, 19f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org SkColor color, SkImageFilter* input) 20d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com : INHERITED(input) 21f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org , fDx(dx) 22f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org , fDy(dy) 23d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fSigmaX(sigma) 24d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fSigmaY(sigma) 25d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fColor(color) 26d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com{ 27d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com} 28d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 29f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgSkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, 30f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org SkScalar sigmaX, SkScalar sigmaY, SkColor color, 31f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org SkImageFilter* input, const CropRect* cropRect) 32d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com : INHERITED(input, cropRect) 33d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fDx(dx) 34d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fDy(dy) 35d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fSigmaX(sigmaX) 36d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com , fSigmaY(sigmaY) 37f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org , fColor(color) 38f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org{ 39f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org} 40f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 418b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkDropShadowImageFilter::SkDropShadowImageFilter(SkReadBuffer& buffer) 42ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org : INHERITED(1, buffer) { 43f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org fDx = buffer.readScalar(); 44f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org fDy = buffer.readScalar(); 45d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com fSigmaX = buffer.readScalar(); 46d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com fSigmaY = buffer.readScalar(); 47f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org fColor = buffer.readColor(); 48c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org buffer.validate(SkScalarIsFinite(fDx) && 49c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org SkScalarIsFinite(fDy) && 50d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com SkScalarIsFinite(fSigmaX) && 51d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com SkScalarIsFinite(fSigmaY)); 52f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org} 53f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 548b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const 55f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org{ 56f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org this->INHERITED::flatten(buffer); 57f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org buffer.writeScalar(fDx); 58f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org buffer.writeScalar(fDy); 59d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com buffer.writeScalar(fSigmaX); 60d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com buffer.writeScalar(fSigmaY); 61f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org buffer.writeColor(fColor); 62f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org} 63f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 64f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgbool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, 65f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org const Context& ctx, 66f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org SkBitmap* result, SkIPoint* offset) const 67f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org{ 68f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org SkBitmap src = source; 696776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org SkIPoint srcOffset = SkIPoint::Make(0, 0); 704cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) 71f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org return false; 72f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 73d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com SkIRect bounds; 74118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) { 75d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com return false; 76d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 77d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 78d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 79cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org if (NULL == device.get()) { 80cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org return false; 81cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 82f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org SkCanvas canvas(device.get()); 83f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org 84ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org SkVector sigma = SkVector::Make(fSigmaX, fSigmaY); 85ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org ctx.ctm().mapVectors(&sigma, 1); 8674bdde0d50f45c5848381ec207c1464b70a48ee3senorblanco@chromium.org sigma.fX = SkMaxScalar(0, sigma.fX); 8774bdde0d50f45c5848381ec207c1464b70a48ee3senorblanco@chromium.org sigma.fY = SkMaxScalar(0, sigma.fY); 88cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(sigma.fX, sigma.fY)); 89f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org SkAutoTUnref<SkColorFilter> colorFilter( 90f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode)); 91f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org SkPaint paint; 92f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org paint.setImageFilter(blurFilter.get()); 93f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org paint.setColorFilter(colorFilter.get()); 94f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 95ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org SkVector offsetVec = SkVector::Make(fDx, fDy); 96ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org ctx.ctm().mapVectors(&offsetVec, 1); 97118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft), 98118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org SkIntToScalar(srcOffset.fY - bounds.fTop)); 992bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint); 100f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org canvas.drawBitmap(src, 0, 0); 101f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org *result = device->accessBitmap(false); 1026776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = bounds.fLeft; 1036776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = bounds.fTop; 104f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org return true; 105f44fcdca01722959c3be335f44e88b59dbb33a10junov@chromium.org} 106336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 107336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkDropShadowImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 108336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org if (getInput(0)) { 109336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org getInput(0)->computeFastBounds(src, dst); 110336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org } else { 111336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org *dst = src; 112336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org } 113336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 114336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org SkRect shadowBounds = *dst; 115336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org shadowBounds.offset(fDx, fDy); 116336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org shadowBounds.outset(SkScalarMul(fSigmaX, SkIntToScalar(3)), 117336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org SkScalarMul(fSigmaY, SkIntToScalar(3))); 118336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org dst->join(shadowBounds); 119336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org} 120c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org 121c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.orgbool SkDropShadowImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 122c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkIRect* dst) const { 123c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkIRect bounds = src; 124c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org if (getInput(0) && !getInput(0)->filterBounds(src, ctm, &bounds)) { 125c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org return false; 126c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org } 127ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org SkVector offsetVec = SkVector::Make(fDx, fDy); 128ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org ctm.mapVectors(&offsetVec, 1); 129c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org bounds.offset(-SkScalarCeilToInt(offsetVec.x()), 130c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org -SkScalarCeilToInt(offsetVec.y())); 131ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org SkVector sigma = SkVector::Make(fSigmaX, fSigmaY); 132ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org ctm.mapVectors(&sigma, 1); 133c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))), 134c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3)))); 135c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org bounds.join(src); 136c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org *dst = bounds; 137c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org return true; 138c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org} 139