SkTileImageFilter.cpp revision 63195181d12751bed2fae6e167c7bed7f4a2de2a
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,
2024e06d5244ae96e440410e1d76e039983b2efac9senorblanco                                             SkImageFilter* input) {
219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) {
229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
2424e06d5244ae96e440410e1d76e039983b2efac9senorblanco    return SkNEW_ARGS(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 {
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);
39b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    const SkIRect dstIRect = dstRect.roundOut();
406776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int w = dstIRect.width();
416776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int h = dstIRect.height();
421a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
431a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
441a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
451a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
46e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect srcRect;
474cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&srcRect, fSrcRect);
48e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect srcIRect;
49e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
506776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    srcIRect.offset(-srcOffset);
511a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap subset;
52e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect bounds;
53e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    source.getBounds(&bounds);
546776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
55e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    if (!srcIRect.intersect(bounds)) {
566776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fX = offset->fY = 0;
57e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org        return true;
58e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    } else if (!source.extractSubset(&subset, srcIRect)) {
591a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
601a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
611a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
621a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
63cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    if (NULL == device.get()) {
64cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
65cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
661a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkCanvas canvas(device);
671a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkPaint paint;
681a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
691a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
706776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkMatrix shaderMatrix;
716776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                              SkIntToScalar(srcOffset.fY));
739c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
749c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
759c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                  &shaderMatrix));
761a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setShader(shader);
776776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    canvas.translate(-dstRect.fLeft, -dstRect.fTop);
781a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    canvas.drawRect(dstRect, paint);
791a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    *dst = device->accessBitmap(false);
806776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = dstIRect.fLeft;
816776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = dstIRect.fTop;
821a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    return true;
831a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
841a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
850a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgbool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
860a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                                       SkIRect* dst) const {
870a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkRect srcRect;
880a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    ctm.mapRect(&srcRect, fSrcRect);
890a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkIRect srcIRect;
900a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
910a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    srcIRect.join(src);
920a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    *dst = srcIRect;
930a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    return true;
940a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
950a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkTileImageFilter::CreateProc(SkReadBuffer& buffer) {
979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
989fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkRect src, dst;
999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readRect(&src);
1009fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readRect(&dst);
10124e06d5244ae96e440410e1d76e039983b2efac9senorblanco    return Create(src, dst, common.getInput(0));
1029fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1031a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
1048b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkTileImageFilter::flatten(SkWriteBuffer& buffer) const {
1051a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    this->INHERITED::flatten(buffer);
1061a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fSrcRect);
1071a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fDstRect);
1081a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
109f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
110f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING
111f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkTileImageFilter::toString(SkString* str) const {
112f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("SkTileImageFilter: (");
11363195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips    str->appendf("src: %.2f %.2f %.2f %.2f",
11463195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips                 fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom);
11563195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips    str->appendf(" dst: %.2f %.2f %.2f %.2f",
11663195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips                 fDstRect.fLeft, fDstRect.fTop, fDstRect.fRight, fDstRect.fBottom);
11763195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips    if (this->getInput(0)) {
11863195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips        str->appendf("input: (");
11963195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips        this->getInput(0)->toString(str);
12063195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips        str->appendf(")");
12163195181d12751bed2fae6e167c7bed7f4a2de2arobertphillips    }
122f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->append(")");
123f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips}
124f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif
125