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 | |
12 | // Both [I]Vectors and Sk[I]Sizes are transformed as non-positioned values, i.e. go through |
13 | // mapVectors() not mapPoints(). |
14 | static SkIVector map_as_vector(int32_t x, int32_t y, const SkMatrix& matrix) { |
15 | SkVector v = SkVector::Make(SkIntToScalar(x), SkIntToScalar(y)); |
16 | matrix.mapVectors(&v, 1); |
17 | return SkIVector::Make(SkScalarRoundToInt(v.fX), SkScalarRoundToInt(v.fY)); |
18 | } |
19 | |
20 | static SkVector map_as_vector(SkScalar x, SkScalar y, const SkMatrix& matrix) { |
21 | SkVector v = SkVector::Make(x, y); |
22 | matrix.mapVectors(&v, 1); |
23 | return v; |
24 | } |
25 | |
26 | namespace skif { |
27 | |
28 | Mapping Mapping::Make(const SkMatrix& ctm, const SkImageFilter* filter) { |
29 | SkMatrix remainder, layer; |
30 | SkSize scale; |
31 | if (ctm.isScaleTranslate() || as_IFB(filter)->canHandleComplexCTM()) { |
32 | // It doesn't matter what type of matrix ctm is, we can have layer space be equivalent to |
33 | // device space. |
34 | remainder = SkMatrix::I(); |
35 | layer = ctm; |
36 | } else if (ctm.decomposeScale(&scale, &remainder)) { |
37 | // TODO (michaelludwig) - Should maybe strip out any fractional part of the translation in |
38 | // 'ctm' so that can be incorporated during regular drawing, instead of by resampling the |
39 | // filtered image. |
40 | layer = SkMatrix::MakeScale(scale.fWidth, scale.fHeight); |
41 | } else { |
42 | // Perspective |
43 | // TODO (michaelludwig) - Should investigate choosing a scale factor for the layer matrix |
44 | // that minimizes the aliasing in the final draw. |
45 | remainder = ctm; |
46 | layer = SkMatrix::I(); |
47 | } |
48 | return Mapping(remainder, layer); |
49 | } |
50 | |
51 | // Instantiate map specializations for the 6 geometric types used during filtering |
52 | template<> |
53 | SkIRect Mapping::map<SkIRect>(const SkIRect& geom, const SkMatrix& matrix) { |
54 | return matrix.mapRect(SkRect::Make(geom)).roundOut(); |
55 | } |
56 | |
57 | template<> |
58 | SkRect Mapping::map<SkRect>(const SkRect& geom, const SkMatrix& matrix) { |
59 | return matrix.mapRect(geom); |
60 | } |
61 | |
62 | template<> |
63 | SkIPoint Mapping::map<SkIPoint>(const SkIPoint& geom, const SkMatrix& matrix) { |
64 | SkPoint p = SkPoint::Make(SkIntToScalar(geom.fX), SkIntToScalar(geom.fY)); |
65 | matrix.mapPoints(&p, 1); |
66 | return SkIPoint::Make(SkScalarRoundToInt(p.fX), SkScalarRoundToInt(p.fY)); |
67 | } |
68 | |
69 | template<> |
70 | SkPoint Mapping::map<SkPoint>(const SkPoint& geom, const SkMatrix& matrix) { |
71 | SkPoint p; |
72 | matrix.mapPoints(&p, &geom, 1); |
73 | return p; |
74 | } |
75 | |
76 | template<> |
77 | IVector Mapping::map<IVector>(const IVector& geom, const SkMatrix& matrix) { |
78 | return IVector(map_as_vector(geom.fX, geom.fY, matrix)); |
79 | } |
80 | |
81 | template<> |
82 | Vector Mapping::map<Vector>(const Vector& geom, const SkMatrix& matrix) { |
83 | return Vector(map_as_vector(geom.fX, geom.fY, matrix)); |
84 | } |
85 | |
86 | template<> |
87 | SkISize Mapping::map<SkISize>(const SkISize& geom, const SkMatrix& matrix) { |
88 | SkIVector v = map_as_vector(geom.fWidth, geom.fHeight, matrix); |
89 | return SkISize::Make(v.fX, v.fY); |
90 | } |
91 | |
92 | template<> |
93 | SkSize Mapping::map<SkSize>(const SkSize& geom, const SkMatrix& matrix) { |
94 | SkVector v = map_as_vector(geom.fWidth, geom.fHeight, matrix); |
95 | return SkSize::Make(v.fX, v.fY); |
96 | } |
97 | |
98 | } // end namespace skif |
99 | |