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