blob: d640ac7adbd969331c8a43e98b15dddc64027b39 [file] [log] [blame]
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkTileImageFilter.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkDevice.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
13#include "SkWriteBuffer.h"
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000014#include "SkMatrix.h"
15#include "SkPaint.h"
16#include "SkShader.h"
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +000017#include "SkValidationUtils.h"
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000018
reed9fa60da2014-08-21 07:59:51 -070019SkTileImageFilter* SkTileImageFilter::Create(const SkRect& srcRect, const SkRect& dstRect,
senorblanco5e5f9482014-08-26 12:27:12 -070020 SkImageFilter* input, uint32_t uniqueID) {
reed9fa60da2014-08-21 07:59:51 -070021 if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) {
22 return NULL;
23 }
senorblanco5e5f9482014-08-26 12:27:12 -070024 return SkNEW_ARGS(SkTileImageFilter, (srcRect, dstRect, input, uniqueID));
reed9fa60da2014-08-21 07:59:51 -070025}
26
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +000027bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
28 const Context& ctx,
commit-bot@chromium.orgae761f72014-02-05 22:32:02 +000029 SkBitmap* dst, SkIPoint* offset) const {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000030 SkBitmap source = src;
31 SkImageFilter* input = getInput(0);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000032 SkIPoint srcOffset = SkIPoint::Make(0, 0);
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000033 if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000034 return false;
35 }
36
senorblanco@chromium.orge93e1db2013-12-09 18:31:42 +000037 SkRect dstRect;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000038 ctx.ctm().mapRect(&dstRect, fDstRect);
reedb07a94f2014-11-19 05:03:18 -080039 const SkIRect dstIRect = dstRect.roundOut();
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000040 int w = dstIRect.width();
41 int h = dstIRect.height();
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000042 if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
43 return false;
44 }
45
senorblanco@chromium.orge93e1db2013-12-09 18:31:42 +000046 SkRect srcRect;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000047 ctx.ctm().mapRect(&srcRect, fSrcRect);
senorblanco@chromium.orge93e1db2013-12-09 18:31:42 +000048 SkIRect srcIRect;
49 srcRect.roundOut(&srcIRect);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000050 srcIRect.offset(-srcOffset);
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000051 SkBitmap subset;
senorblanco@chromium.orge93e1db2013-12-09 18:31:42 +000052 SkIRect bounds;
53 source.getBounds(&bounds);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000054
senorblanco@chromium.orge93e1db2013-12-09 18:31:42 +000055 if (!srcIRect.intersect(bounds)) {
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000056 offset->fX = offset->fY = 0;
senorblanco@chromium.orge93e1db2013-12-09 18:31:42 +000057 return true;
58 } else if (!source.extractSubset(&subset, srcIRect)) {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000059 return false;
60 }
61
62 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000063 if (NULL == device.get()) {
64 return false;
65 }
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000066 SkCanvas canvas(device);
67 SkPaint paint;
68 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
69
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000070 SkMatrix shaderMatrix;
71 shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
72 SkIntToScalar(srcOffset.fY));
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +000073 SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
74 SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
75 &shaderMatrix));
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000076 paint.setShader(shader);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000077 canvas.translate(-dstRect.fLeft, -dstRect.fTop);
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000078 canvas.drawRect(dstRect, paint);
79 *dst = device->accessBitmap(false);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000080 offset->fX = dstIRect.fLeft;
81 offset->fY = dstIRect.fTop;
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000082 return true;
83}
84
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +000085bool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
86 SkIRect* dst) const {
87 SkRect srcRect;
88 ctm.mapRect(&srcRect, fSrcRect);
89 SkIRect srcIRect;
90 srcRect.roundOut(&srcIRect);
91 srcIRect.join(src);
92 *dst = srcIRect;
93 return true;
94}
95
reed9fa60da2014-08-21 07:59:51 -070096SkFlattenable* SkTileImageFilter::CreateProc(SkReadBuffer& buffer) {
97 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
98 SkRect src, dst;
99 buffer.readRect(&src);
100 buffer.readRect(&dst);
senorblanco5e5f9482014-08-26 12:27:12 -0700101 return Create(src, dst, common.getInput(0), common.uniqueID());
reed9fa60da2014-08-21 07:59:51 -0700102}
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +0000103
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000104void SkTileImageFilter::flatten(SkWriteBuffer& buffer) const {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +0000105 this->INHERITED::flatten(buffer);
106 buffer.writeRect(fSrcRect);
107 buffer.writeRect(fDstRect);
108}