• 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 "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