summaryrefslogtreecommitdiff
path: root/effects/SkTileImageFilter.cpp
blob: ccca4ff74caf3a75ccd7e43cb6d22246d91f9674 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTileImageFilter.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkFlattenableBuffers.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkShader.h"
#include "SkValidationUtils.h"

bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
                                      SkBitmap* dst, SkIPoint* offset) {
    SkBitmap source = src;
    SkImageFilter* input = getInput(0);
    SkIPoint localOffset = SkIPoint::Make(0, 0);
    if (input && !input->filterImage(proxy, src, ctm, &source, &localOffset)) {
        return false;
    }

    int w = SkScalarTruncToInt(fDstRect.width());
    int h = SkScalarTruncToInt(fDstRect.height());
    if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
        return false;
    }

    SkIRect srcRect;
    fSrcRect.roundOut(&srcRect);
    SkBitmap subset;
    if (!source.extractSubset(&subset, srcRect)) {
        return false;
    }

    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
    SkIRect bounds;
    source.getBounds(&bounds);
    SkCanvas canvas(device);
    SkPaint paint;
    paint.setXfermodeMode(SkXfermode::kSrc_Mode);

    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
    paint.setShader(shader);
    SkRect dstRect = fDstRect;
    dstRect.offset(SkIntToScalar(localOffset.fX), SkIntToScalar(localOffset.fY));
    canvas.drawRect(dstRect, paint);
    *dst = device->accessBitmap(false);
    return true;
}

SkTileImageFilter::SkTileImageFilter(SkFlattenableReadBuffer& buffer)
  : INHERITED(1, buffer) {
    buffer.readRect(&fSrcRect);
    buffer.readRect(&fDstRect);
    buffer.validate(SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
}

void SkTileImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.writeRect(fSrcRect);
    buffer.writeRect(fDstRect);
}