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
19f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgbool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
20f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org                                      const Context& ctx,
21ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                      SkBitmap* dst, SkIPoint* offset) const {
221a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap source = src;
231a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkImageFilter* input = getInput(0);
246776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
254cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
261a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
271a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
281a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
29e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect dstRect;
304cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&dstRect, fDstRect);
316776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIRect dstIRect;
326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    dstRect.roundOut(&dstIRect);
336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int w = dstIRect.width();
346776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int h = dstIRect.height();
351a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
361a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
371a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
381a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
39e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect srcRect;
404cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&srcRect, fSrcRect);
41e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect srcIRect;
42e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
436776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    srcIRect.offset(-srcOffset);
441a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap subset;
45e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect bounds;
46e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    source.getBounds(&bounds);
476776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
48e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    if (!srcIRect.intersect(bounds)) {
496776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fX = offset->fY = 0;
50e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org        return true;
51e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    } else if (!source.extractSubset(&subset, srcIRect)) {
521a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
531a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
541a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
551a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
56cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    if (NULL == device.get()) {
57cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
58cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
591a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkCanvas canvas(device);
601a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkPaint paint;
611a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
621a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
636776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkMatrix shaderMatrix;
646776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
656776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                              SkIntToScalar(srcOffset.fY));
669c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
679c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
689c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                  &shaderMatrix));
691a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setShader(shader);
706776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    canvas.translate(-dstRect.fLeft, -dstRect.fTop);
711a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    canvas.drawRect(dstRect, paint);
721a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    *dst = device->accessBitmap(false);
736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = dstIRect.fLeft;
746776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = dstIRect.fTop;
751a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    return true;
761a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
771a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
780a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgbool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
790a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                                       SkIRect* dst) const {
800a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkRect srcRect;
810a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    ctm.mapRect(&srcRect, fSrcRect);
820a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkIRect srcIRect;
830a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
840a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    srcIRect.join(src);
850a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    *dst = srcIRect;
860a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    return true;
870a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
880a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
898b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkTileImageFilter::SkTileImageFilter(SkReadBuffer& buffer)
90ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org  : INHERITED(1, buffer) {
911a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.readRect(&fSrcRect);
921a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.readRect(&fDstRect);
93c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org    buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
941a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
951a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
968b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkTileImageFilter::flatten(SkWriteBuffer& buffer) const {
971a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    this->INHERITED::flatten(buffer);
981a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fSrcRect);
991a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fDstRect);
1001a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
101