SkTileImageFilter.cpp revision e93e1dbf0eced1e1b9aeed7c0c170961e2d61e32
1/*
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"
12#include "SkFlattenableBuffers.h"
13#include "SkMatrix.h"
14#include "SkPaint.h"
15#include "SkShader.h"
16#include "SkValidationUtils.h"
17
18bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
19                                      SkBitmap* dst, SkIPoint* offset) {
20    SkBitmap source = src;
21    SkImageFilter* input = getInput(0);
22    SkIPoint localOffset = SkIPoint::Make(0, 0);
23    if (input && !input->filterImage(proxy, src, ctm, &source, &localOffset)) {
24        return false;
25    }
26
27    SkRect dstRect;
28    ctm.mapRect(&dstRect, fDstRect);
29    int w = SkScalarCeilToInt(dstRect.width());
30    int h = SkScalarCeilToInt(dstRect.height());
31    if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
32        return false;
33    }
34
35    SkRect srcRect;
36    ctm.mapRect(&srcRect, fSrcRect);
37    SkIRect srcIRect;
38    srcRect.roundOut(&srcIRect);
39    SkBitmap subset;
40    SkIRect bounds;
41    source.getBounds(&bounds);
42    if (!srcIRect.intersect(bounds)) {
43        return true;
44    } else if (!source.extractSubset(&subset, srcIRect)) {
45        return false;
46    }
47
48    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
49    if (NULL == device.get()) {
50        return false;
51    }
52    SkCanvas canvas(device);
53    SkPaint paint;
54    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
55
56    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
57                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
58    paint.setShader(shader);
59    dstRect.offset(SkIntToScalar(localOffset.fX), SkIntToScalar(localOffset.fY));
60    canvas.drawRect(dstRect, paint);
61    *dst = device->accessBitmap(false);
62    return true;
63}
64
65SkTileImageFilter::SkTileImageFilter(SkFlattenableReadBuffer& buffer)
66  : INHERITED(1, buffer) {
67    buffer.readRect(&fSrcRect);
68    buffer.readRect(&fDstRect);
69    buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
70}
71
72void SkTileImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
73    this->INHERITED::flatten(buffer);
74    buffer.writeRect(fSrcRect);
75    buffer.writeRect(fDstRect);
76}
77