SkTileImageFilter.cpp revision 4cb543d6057b692e1099e9f115155f0bf323a0c8
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
194cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkImageFilter::Context& ctx,
20ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                      SkBitmap* dst, SkIPoint* offset) const {
211a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap source = src;
221a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkImageFilter* input = getInput(0);
236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
244cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
251a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
261a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
271a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
28e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect dstRect;
294cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&dstRect, fDstRect);
306776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIRect dstIRect;
316776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    dstRect.roundOut(&dstIRect);
326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int w = dstIRect.width();
336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    int h = dstIRect.height();
341a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
351a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
361a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
371a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
38e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkRect srcRect;
394cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapRect(&srcRect, fSrcRect);
40e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect srcIRect;
41e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    srcRect.roundOut(&srcIRect);
426776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    srcIRect.offset(-srcOffset);
431a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkBitmap subset;
44e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    SkIRect bounds;
45e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    source.getBounds(&bounds);
466776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
47e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    if (!srcIRect.intersect(bounds)) {
486776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fX = offset->fY = 0;
49e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org        return true;
50e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32senorblanco@chromium.org    } else if (!source.extractSubset(&subset, srcIRect)) {
511a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org        return false;
521a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    }
531a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
541a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
55cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    if (NULL == device.get()) {
56cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
57cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
581a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkCanvas canvas(device);
591a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    SkPaint paint;
601a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
611a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
6265caeaf32d09f5886f3c740cfef2f1c26ef9cb50skia.committer@gmail.com    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
631a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
646776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkMatrix shaderMatrix;
656776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
666776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                              SkIntToScalar(srcOffset.fY));
676776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    shader->setLocalMatrix(shaderMatrix);
681a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    paint.setShader(shader);
696776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    canvas.translate(-dstRect.fLeft, -dstRect.fTop);
701a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    canvas.drawRect(dstRect, paint);
711a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    *dst = device->accessBitmap(false);
726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = dstIRect.fLeft;
736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = dstIRect.fTop;
741a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    return true;
751a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
761a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
778b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkTileImageFilter::SkTileImageFilter(SkReadBuffer& buffer)
78ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org  : INHERITED(1, buffer) {
791a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.readRect(&fSrcRect);
801a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.readRect(&fDstRect);
81c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org    buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
821a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
831a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org
848b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkTileImageFilter::flatten(SkWriteBuffer& buffer) const {
851a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    this->INHERITED::flatten(buffer);
861a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fSrcRect);
871a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org    buffer.writeRect(fDstRect);
881a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org}
89