• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC
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/SkMatrix.h"
9 #include "src/core/SkImageFilterTypes.h"
10 #include "src/core/SkImageFilter_Base.h"
11 #include "src/core/SkMatrixPriv.h"
12 
13 // Both [I]Vectors and Sk[I]Sizes are transformed as non-positioned values, i.e. go through
14 // mapVectors() not mapPoints().
map_as_vector(int32_t x,int32_t y,const SkMatrix & matrix)15 static SkIVector map_as_vector(int32_t x, int32_t y, const SkMatrix& matrix) {
16     SkVector v = SkVector::Make(SkIntToScalar(x), SkIntToScalar(y));
17     matrix.mapVectors(&v, 1);
18     return SkIVector::Make(SkScalarRoundToInt(v.fX), SkScalarRoundToInt(v.fY));
19 }
20 
map_as_vector(SkScalar x,SkScalar y,const SkMatrix & matrix)21 static SkVector map_as_vector(SkScalar x, SkScalar y, const SkMatrix& matrix) {
22     SkVector v = SkVector::Make(x, y);
23     matrix.mapVectors(&v, 1);
24     return v;
25 }
26 
27 namespace skif {
28 
DecomposeCTM(const SkMatrix & ctm,const SkImageFilter * filter,const skif::ParameterSpace<SkPoint> & representativePoint)29 Mapping Mapping::DecomposeCTM(const SkMatrix& ctm, const SkImageFilter* filter,
30                               const skif::ParameterSpace<SkPoint>& representativePoint) {
31     SkMatrix remainder, layer;
32     SkSize scale;
33     if (ctm.isScaleTranslate() || as_IFB(filter)->canHandleComplexCTM()) {
34         // It doesn't matter what type of matrix ctm is, we can have layer space be equivalent to
35         // device space.
36         remainder = SkMatrix::I();
37         layer = ctm;
38     } else if (ctm.decomposeScale(&scale, &remainder)) {
39         // This case implies some amount of sampling post-filtering, either due to skew or rotation
40         // in the original matrix. As such, keep the layer matrix as simple as possible.
41         layer = SkMatrix::Scale(scale.fWidth, scale.fHeight);
42     } else {
43         // Perspective, which has a non-uniform scaling effect on the filter. Pick a single scale
44         // factor that best matches where the filter will be evaluated.
45         SkScalar scale = SkMatrixPriv::DifferentialAreaScale(ctm, SkPoint(representativePoint));
46         if (SkScalarIsFinite(scale)) {
47             // Now take the sqrt to go from an area scale factor to a scaling per X and Y
48             // FIXME: It would be nice to be able to choose a non-uniform scale.
49             scale = SkScalarSqrt(scale);
50         } else {
51             // The representative point was behind the W = 0 plane, so don't factor out any scale.
52             scale = 1.f;
53         }
54 
55         remainder = ctm;
56         remainder.preScale(SkScalarInvert(scale), SkScalarInvert(scale));
57         layer = SkMatrix::Scale(scale, scale);
58     }
59     return Mapping(remainder, layer);
60 }
61 
62 // Instantiate map specializations for the 6 geometric types used during filtering
63 template<>
map(const SkIRect & geom,const SkMatrix & matrix)64 SkIRect Mapping::map<SkIRect>(const SkIRect& geom, const SkMatrix& matrix) {
65     return matrix.mapRect(SkRect::Make(geom)).roundOut();
66 }
67 
68 template<>
map(const SkRect & geom,const SkMatrix & matrix)69 SkRect Mapping::map<SkRect>(const SkRect& geom, const SkMatrix& matrix) {
70     return matrix.mapRect(geom);
71 }
72 
73 template<>
map(const SkIPoint & geom,const SkMatrix & matrix)74 SkIPoint Mapping::map<SkIPoint>(const SkIPoint& geom, const SkMatrix& matrix) {
75     SkPoint p = SkPoint::Make(SkIntToScalar(geom.fX), SkIntToScalar(geom.fY));
76     matrix.mapPoints(&p, 1);
77     return SkIPoint::Make(SkScalarRoundToInt(p.fX), SkScalarRoundToInt(p.fY));
78 }
79 
80 template<>
map(const SkPoint & geom,const SkMatrix & matrix)81 SkPoint Mapping::map<SkPoint>(const SkPoint& geom, const SkMatrix& matrix) {
82     SkPoint p;
83     matrix.mapPoints(&p, &geom, 1);
84     return p;
85 }
86 
87 template<>
map(const IVector & geom,const SkMatrix & matrix)88 IVector Mapping::map<IVector>(const IVector& geom, const SkMatrix& matrix) {
89     return IVector(map_as_vector(geom.fX, geom.fY, matrix));
90 }
91 
92 template<>
map(const Vector & geom,const SkMatrix & matrix)93 Vector Mapping::map<Vector>(const Vector& geom, const SkMatrix& matrix) {
94     return Vector(map_as_vector(geom.fX, geom.fY, matrix));
95 }
96 
97 template<>
map(const SkISize & geom,const SkMatrix & matrix)98 SkISize Mapping::map<SkISize>(const SkISize& geom, const SkMatrix& matrix) {
99     SkIVector v = map_as_vector(geom.fWidth, geom.fHeight, matrix);
100     return SkISize::Make(v.fX, v.fY);
101 }
102 
103 template<>
map(const SkSize & geom,const SkMatrix & matrix)104 SkSize Mapping::map<SkSize>(const SkSize& geom, const SkMatrix& matrix) {
105     SkVector v = map_as_vector(geom.fWidth, geom.fHeight, matrix);
106     return SkSize::Make(v.fX, v.fY);
107 }
108 
109 } // end namespace skif
110