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" 1205dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco#include "SkOffsetImageFilter.h" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 151a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkMatrix.h" 161a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkPaint.h" 171a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org#include "SkShader.h" 18c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 191a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 205ea95df02de9cd774d0b84d1341599bbd9c0d8dbreedSkImageFilter* SkTileImageFilter::Create(const SkRect& srcRect, const SkRect& dstRect, 215ea95df02de9cd774d0b84d1341599bbd9c0d8dbreed SkImageFilter* input) { 229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) { 2396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 2505dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco if (srcRect.width() == dstRect.width() && srcRect.height() == dstRect.height()) { 2605dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco SkRect ir = dstRect; 2705dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco if (!ir.intersect(srcRect)) { 2805dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco return SkSafeRef(input); 2905dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco } 3005dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco CropRect cropRect(ir); 3105dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco return SkOffsetImageFilter::Create(dstRect.x() - srcRect.x(), 3205dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco dstRect.y() - srcRect.y(), 3305dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco input, &cropRect); 3405dcb4c7a9fe350af495e4cc53f8ad0cc9b79052senorblanco } 35385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new SkTileImageFilter(srcRect, dstRect, input); 369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3848e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillipsbool SkTileImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src, 3948e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips const Context& ctx, 4048e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips SkBitmap* dst, SkIPoint* offset) const { 41d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips SkBitmap source = src; 42d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips SkIPoint srcOffset = SkIPoint::Make(0, 0); 4348e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips if (!this->filterInputDeprecated(0, proxy, src, ctx, &source, &srcOffset)) { 44d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips return false; 45d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips } 461a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 47e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkRect dstRect; 484cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&dstRect, fDstRect); 49b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco if (!dstRect.intersect(SkRect::Make(ctx.clipBounds()))) { 50b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco offset->fX = offset->fY = 0; 51b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco return true; 52b50b97d70a62d90f5266113c9a5ba6cd1b912eddsenorblanco } 53b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkIRect dstIRect = dstRect.roundOut(); 54d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips int w = dstIRect.width(); 55d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips int h = dstIRect.height(); 56d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) { 571a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org return false; 581a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org } 591a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 60e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkRect srcRect; 614cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&srcRect, fSrcRect); 62e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org SkIRect srcIRect; 63e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org srcRect.roundOut(&srcIRect); 646776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org srcIRect.offset(-srcOffset); 651a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org SkBitmap subset; 66a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkIRect srcBounds; 67a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco source.getBounds(&srcBounds); 686776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org 69a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco if (!SkIRect::Intersects(srcIRect, srcBounds)) { 706776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = offset->fY = 0; 71e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org return true; 721a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org } 73a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco if (srcBounds.contains(srcIRect)) { 74a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco if (!source.extractSubset(&subset, srcIRect)) { 75a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco return false; 76a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco } 77a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco } else { 78a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(srcIRect.width(), 79a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco srcIRect.height(), 80a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco kPossible_TileUsage)); 81a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco if (!device) { 82a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco return false; 83a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco } 84a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkCanvas canvas(device); 85a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco canvas.drawBitmap(src, SkIntToScalar(srcOffset.x()), 86a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkIntToScalar(srcOffset.y())); 87a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco subset = device->accessBitmap(false); 88a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco } 89a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkASSERT(subset.width() == srcIRect.width()); 90a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkASSERT(subset.height() == srcIRect.height()); 911a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 92d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h)); 9396fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == device.get()) { 94cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org return false; 95cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 961a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org SkCanvas canvas(device); 971a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org SkPaint paint; 981a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org paint.setXfermodeMode(SkXfermode::kSrc_Mode); 991a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 1009c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset, 101a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)); 1021a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org paint.setShader(shader); 1036776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org canvas.translate(-dstRect.fLeft, -dstRect.fTop); 1041a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org canvas.drawRect(dstRect, paint); 1051a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org *dst = device->accessBitmap(false); 1066776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = dstIRect.fLeft; 1076776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = dstIRect.fTop; 1081a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org return true; 1091a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org} 1101a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 111db64af3b178a19ecb47d2b9a373113687d8921fdsenorblancovoid SkTileImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, 112db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco SkIRect* dst, MapDirection direction) const { 113db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco SkRect rect = kReverse_MapDirection == direction ? fSrcRect : fDstRect; 114db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco ctm.mapRect(&rect); 115db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco rect.roundOut(dst); 116db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco} 117db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco 1180a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgbool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 119d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco SkIRect* dst, MapDirection direction) const { 120d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco // Don't recurse into inputs. 121d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco *dst = src; 1220a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org return true; 1230a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org} 1240a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org 125c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillipsvoid SkTileImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 126db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco *dst = fDstRect; 127c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips} 128c3176aa5e578cc64a2534a9ddac2fec5ab6d8d77robertphillips 1299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkTileImageFilter::CreateProc(SkReadBuffer& buffer) { 1309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 1319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect src, dst; 1329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&src); 1339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&dst); 13424e06d5244ae96e440410e1d76e039983b2efac9senorblanco return Create(src, dst, common.getInput(0)); 1359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 1361a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 1378b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkTileImageFilter::flatten(SkWriteBuffer& buffer) const { 1381a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org this->INHERITED::flatten(buffer); 1391a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org buffer.writeRect(fSrcRect); 1401a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org buffer.writeRect(fDstRect); 1411a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org} 142f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 143f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 144f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkTileImageFilter::toString(SkString* str) const { 145f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkTileImageFilter: ("); 14663195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips str->appendf("src: %.2f %.2f %.2f %.2f", 14763195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom); 14863195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips str->appendf(" dst: %.2f %.2f %.2f %.2f", 14963195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips fDstRect.fLeft, fDstRect.fTop, fDstRect.fRight, fDstRect.fBottom); 15063195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips if (this->getInput(0)) { 151d312dcade1e54a687b18755b5b8efbc0d01ec69erobertphillips str->appendf("input: ("); 15263195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips this->getInput(0)->toString(str); 15363195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips str->appendf(")"); 15463195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips } 155f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 156f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 157f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 158