1 /*
2 * Copyright 2015 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 "include/core/SkString.h"
9 #include "src/core/SkLocalMatrixImageFilter.h"
10 #include "src/core/SkReadBuffer.h"
11 #include "src/core/SkSpecialImage.h"
12
Make(const SkMatrix & localM,sk_sp<SkImageFilter> input)13 sk_sp<SkImageFilter> SkLocalMatrixImageFilter::Make(const SkMatrix& localM,
14 sk_sp<SkImageFilter> input) {
15 if (!input) {
16 return nullptr;
17 }
18 if (localM.isIdentity()) {
19 return input;
20 }
21 MatrixCapability inputCapability = as_IFB(input)->getCTMCapability();
22 if ((inputCapability == MatrixCapability::kTranslate && !localM.isTranslate()) ||
23 (inputCapability == MatrixCapability::kScaleTranslate && !localM.isScaleTranslate())) {
24 // Nothing we can do at this point
25 return nullptr;
26 }
27 return sk_sp<SkImageFilter>(new SkLocalMatrixImageFilter(localM, input));
28 }
29
SkLocalMatrixImageFilter(const SkMatrix & localM,sk_sp<SkImageFilter> input)30 SkLocalMatrixImageFilter::SkLocalMatrixImageFilter(const SkMatrix& localM,
31 sk_sp<SkImageFilter> input)
32 : INHERITED(&input, 1, nullptr)
33 , fLocalM(localM) {
34 }
35
CreateProc(SkReadBuffer & buffer)36 sk_sp<SkFlattenable> SkLocalMatrixImageFilter::CreateProc(SkReadBuffer& buffer) {
37 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
38 SkMatrix lm;
39 buffer.readMatrix(&lm);
40 return SkLocalMatrixImageFilter::Make(lm, common.getInput(0));
41 }
42
flatten(SkWriteBuffer & buffer) const43 void SkLocalMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
44 this->INHERITED::flatten(buffer);
45 buffer.writeMatrix(fLocalM);
46 }
47
onFilterImage(const Context & ctx,SkIPoint * offset) const48 sk_sp<SkSpecialImage> SkLocalMatrixImageFilter::onFilterImage(const Context& ctx,
49 SkIPoint* offset) const {
50 skif::Mapping newMapping = ctx.mapping();
51 newMapping.concatLocal(fLocalM);
52 Context localCtx = ctx.withNewMapping(newMapping);
53 return this->filterInput(0, localCtx, offset);
54 }
55
onFilterBounds(const SkIRect & src,const SkMatrix & ctm,MapDirection dir,const SkIRect * inputRect) const56 SkIRect SkLocalMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
57 MapDirection dir, const SkIRect* inputRect) const {
58 return this->getInput(0)->filterBounds(src, SkMatrix::Concat(ctm, fLocalM), dir, inputRect);
59 }
60
computeFastBounds(const SkRect & bounds) const61 SkRect SkLocalMatrixImageFilter::computeFastBounds(const SkRect& bounds) const {
62 // In order to match the behavior of onFilterBounds, we map 'bounds' by the inverse of our
63 // local matrix, pass that to our child, and then map the result by our local matrix.
64 SkMatrix localInv;
65 if (!fLocalM.invert(&localInv)) {
66 return this->getInput(0)->computeFastBounds(bounds);
67 }
68
69 SkRect localBounds = localInv.mapRect(bounds);
70 return fLocalM.mapRect(this->getInput(0)->computeFastBounds(localBounds));
71 }
72