SkTileImageFilter.cpp revision b50b97d70a62d90f5266113c9a5ba6cd1b912edd
11a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org/* 21a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * Copyright 2013 Google Inc. 31a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * 41a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be 51a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * found in the LICENSE file. 61a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org */ 71a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 81a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkTileImageFilter.h" 91a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkBitmap.h" 101a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkCanvas.h" 111a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkDevice.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 141a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkMatrix.h" 151a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkPaint.h" 161a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkShader.h" 17c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 181a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 195ea95df02de9cd774d0b84d1341599bbd9c0d8dbreedSkImageFilter* SkTileImageFilter::Create(const SkRect& srcRect, const SkRect& dstRect, 205ea95df02de9cd774d0b84d1341599bbd9c0d8dbreed SkImageFilter* input) { 219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) { 2296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 24385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new SkTileImageFilter(srcRect, dstRect, input); 259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 27f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgbool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, 28f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org const Context& ctx, 29ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org SkBitmap* dst, SkIPoint* offset) const { 30d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips SkBitmap source = src; 31d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips SkIPoint srcOffset = SkIPoint::Make(0, 0); 32b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco if (!this->filterInput(0, proxy, src, ctx, &source, &srcOffset)) { 33d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips return false; 34d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips } 351a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 36e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkRect dstRect; 374cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&dstRect, fDstRect); 38b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco#ifndef SK_DISABLE_TILE_IMAGE_FILTER_DEST_OPTIMIZATION 39b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco if (!dstRect.intersect(SkRect::Make(ctx.clipBounds()))) { 40b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco offset->fX = offset->fY = 0; 41b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco return true; 42b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco } 43b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco#endif 44b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkIRect dstIRect = dstRect.roundOut(); 45d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips int w = dstIRect.width(); 46d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips int h = dstIRect.height(); 47d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) { 481a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org return false; 491a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org } 501a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 51e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkRect srcRect; 524cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&srcRect, fSrcRect); 53e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkIRect srcIRect; 54e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org srcRect.roundOut(&srcIRect); 556776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org srcIRect.offset(-srcOffset); 561a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org SkBitmap subset; 57e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkIRect bounds; 58e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org source.getBounds(&bounds); 596776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org 60e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org if (!srcIRect.intersect(bounds)) { 616776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = offset->fY = 0; 62e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org return true; 63e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org } else if (!source.extractSubset(&subset, srcIRect)) { 641a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org return false; 651a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org } 661a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 67d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h)); 6896fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == device.get()) { 69cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org return false; 70cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 711a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org SkCanvas canvas(device); 721a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org SkPaint paint; 731a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org paint.setXfermodeMode(SkXfermode::kSrc_Mode); 741a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 756776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org SkMatrix shaderMatrix; 766776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX), 776776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org SkIntToScalar(srcOffset.fY)); 789c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset, 799c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, 809c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org &shaderMatrix)); 811a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org paint.setShader(shader); 826776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org canvas.translate(-dstRect.fLeft, -dstRect.fTop); 831a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org canvas.drawRect(dstRect, paint); 841a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org *dst = device->accessBitmap(false); 856776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = dstIRect.fLeft; 866776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = dstIRect.fTop; 871a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org return true; 881a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org} 891a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 90db64af3b178a19ecb47d2b9a373113687d8921fdsenorblancovoid SkTileImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, 91db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco SkIRect* dst, MapDirection direction) const { 92db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco SkRect rect = kReverse_MapDirection == direction ? fSrcRect : fDstRect; 93db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco ctm.mapRect(&rect); 94db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco rect.roundOut(dst); 95db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco#ifdef SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS 96db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco dst->join(src); 97db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco#endif 98db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco} 99db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco 1000a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgbool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 1010a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org SkIRect* dst) const { 102db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco this->onFilterNodeBounds(src, ctm, dst, kReverse_MapDirection); 1030a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org return true; 1040a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org} 1050a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org 106c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillipsvoid SkTileImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 107db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco#ifdef SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS 108c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips // This is a workaround for skia:3194. 109c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips *dst = src; 110c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips dst->join(fDstRect); 111db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco#else 112db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco *dst = fDstRect; 113db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco#endif 114c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips} 115c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips 1169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkTileImageFilter::CreateProc(SkReadBuffer& buffer) { 1179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 1189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect src, dst; 1199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&src); 1209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&dst); 12124e06d5244ae96e440410e1d76e039983b2efac9senorblanco return Create(src, dst, common.getInput(0)); 1229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 1231a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 1248b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkTileImageFilter::flatten(SkWriteBuffer& buffer) const { 1251a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org this->INHERITED::flatten(buffer); 1261a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org buffer.writeRect(fSrcRect); 1271a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org buffer.writeRect(fDstRect); 1281a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org} 129f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 130f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 131f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkTileImageFilter::toString(SkString* str) const { 132f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkTileImageFilter: ("); 13363195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips str->appendf("src: %.2f %.2f %.2f %.2f", 13463195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom); 13563195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips str->appendf(" dst: %.2f %.2f %.2f %.2f", 13663195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips fDstRect.fLeft, fDstRect.fTop, fDstRect.fRight, fDstRect.fBottom); 13763195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips if (this->getInput(0)) { 138d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips str->appendf("input: ("); 13963195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips this->getInput(0)->toString(str); 14063195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips str->appendf(")"); 14163195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips } 142f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 143f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 144f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 145