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
199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkTileImageFilter* SkTileImageFilter::Create(const SkRect& srcRect, const SkRect& dstRect,
205e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                             SkImageFilter* input, uint32_t uniqueID) {
219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) {
229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
245e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return SkNEW_ARGS(SkTileImageFilter, (srcRect, dstRect, input, uniqueID));
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 {
301a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap source = src;
311a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkImageFilter* input = getInput(0);
326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
334cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
341a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
351a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
361a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
37e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect dstRect;
384cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&dstRect, fDstRect);
396776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIRect dstIRect;
406776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    dstRect.roundOut(&dstIRect);
416776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int w = dstIRect.width();
426776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int h = dstIRect.height();
431a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
441a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
451a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
461a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
47e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect srcRect;
484cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&srcRect, fSrcRect);
49e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect srcIRect;
50e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
516776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    srcIRect.offset(-srcOffset);
521a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap subset;
53e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect bounds;
54e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    source.getBounds(&bounds);
556776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
56e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    if (!srcIRect.intersect(bounds)) {
576776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fX = offset->fY = 0;
58e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org        return true;
59e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    } else if (!source.extractSubset(&subset, srcIRect)) {
601a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
611a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
621a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
631a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
64cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    if (NULL == device.get()) {
65cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
66cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
671a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkCanvas canvas(device);
681a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkPaint paint;
691a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
701a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
716776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkMatrix shaderMatrix;
726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                              SkIntToScalar(srcOffset.fY));
749c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
759c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
769c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                  &shaderMatrix));
771a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setShader(shader);
786776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    canvas.translate(-dstRect.fLeft, -dstRect.fTop);
791a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    canvas.drawRect(dstRect, paint);
801a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    *dst = device->accessBitmap(false);
816776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = dstIRect.fLeft;
826776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = dstIRect.fTop;
831a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    return true;
841a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
851a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
860a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgbool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
870a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                                       SkIRect* dst) const {
880a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkRect srcRect;
890a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    ctm.mapRect(&srcRect, fSrcRect);
900a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkIRect srcIRect;
910a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
920a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    srcIRect.join(src);
930a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    *dst = srcIRect;
940a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    return true;
950a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
960a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
988b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkTileImageFilter::SkTileImageFilter(SkReadBuffer& buffer)
99ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org  : INHERITED(1, buffer) {
1001a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.readRect(&fSrcRect);
1011a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.readRect(&fDstRect);
102c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org    buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
1031a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
1049fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1059fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1069fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkTileImageFilter::CreateProc(SkReadBuffer& buffer) {
1079fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1089fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkRect src, dst;
1099fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readRect(&src);
1109fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readRect(&dst);
1115e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return Create(src, dst, common.getInput(0), common.uniqueID());
1129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1131a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
1148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkTileImageFilter::flatten(SkWriteBuffer& buffer) const {
1151a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    this->INHERITED::flatten(buffer);
1161a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fSrcRect);
1171a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fDstRect);
1181a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
119