Flutter Engine
 
Loading...
Searching...
No Matches
dl_image_filter.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
9
10namespace flutter {
11
12std::shared_ptr<DlImageFilter> DlImageFilter::MakeBlur(DlScalar sigma_x,
13 DlScalar sigma_y,
14 DlTileMode tile_mode) {
15 return DlBlurImageFilter::Make(sigma_x, sigma_y, tile_mode);
16}
17
18std::shared_ptr<DlImageFilter> DlImageFilter::MakeDilate(DlScalar radius_x,
19 DlScalar radius_y) {
20 return DlDilateImageFilter::Make(radius_x, radius_y);
21}
22
23std::shared_ptr<DlImageFilter> DlImageFilter::MakeErode(DlScalar radius_x,
24 DlScalar radius_y) {
25 return DlErodeImageFilter::Make(radius_x, radius_y);
26}
27
28std::shared_ptr<DlImageFilter> DlImageFilter::MakeMatrix(
29 const DlMatrix& matrix,
30 DlImageSampling sampling) {
31 return DlMatrixImageFilter::Make(matrix, sampling);
32}
33
34std::shared_ptr<DlImageFilter> DlImageFilter::MakeRuntimeEffect(
35 sk_sp<DlRuntimeEffect> runtime_effect,
36 std::vector<std::shared_ptr<DlColorSource>> samplers,
37 std::shared_ptr<std::vector<uint8_t>> uniform_data) {
39 std::move(runtime_effect), std::move(samplers), std::move(uniform_data));
40}
41
42std::shared_ptr<DlImageFilter> DlImageFilter::MakeColorFilter(
43 const std::shared_ptr<const DlColorFilter>& filter) {
44 return DlColorFilterImageFilter::Make(filter);
45}
46
47std::shared_ptr<DlImageFilter> DlImageFilter::MakeCompose(
48 const std::shared_ptr<DlImageFilter>& outer,
49 const std::shared_ptr<DlImageFilter>& inner) {
50 return DlComposeImageFilter::Make(outer, inner);
51}
52
54 DlScalar x,
55 DlScalar y) {
56 FML_DCHECK(std::isfinite(x) && x >= 0);
57 FML_DCHECK(std::isfinite(y) && y >= 0);
58 FML_DCHECK(ctm.IsFinite() && !ctm.HasPerspective2D());
59
60 // The x and y scalars would have been used to expand a local space
61 // rectangle which is then transformed by ctm. In order to do the
62 // expansion correctly, we should look at the relevant math. The
63 // 4 corners will be moved outward by the following vectors:
64 // (UL,UR,LR,LL) = ((-x, -y), (+x, -y), (+x, +y), (-x, +y))
65 // After applying the transform, each of these vectors could be
66 // pointing in any direction so we need to examine each transformed
67 // delta vector and how it affected the bounds.
68 // Looking at just the affine 2x3 entries of the CTM we can delta
69 // transform these corner offsets and get the following:
70 // UL = dCTM(-x, -y) = (- x*m00 - y*m01, - x*m10 - y*m11)
71 // UR = dCTM(+x, -y) = ( x*m00 - y*m01, x*m10 - y*m11)
72 // LR = dCTM(+x, +y) = ( x*m00 + y*m01, x*m10 + y*m11)
73 // LL = dCTM(-x, +y) = (- x*m00 + y*m01, - x*m10 + y*m11)
74 // The X vectors are all some variation of adding or subtracting
75 // the sum of x*m00 and y*m01 or their difference. Similarly the Y
76 // vectors are +/- the associated sum/difference of x*m10 and y*m11.
77 // The largest displacements, both left/right or up/down, will
78 // happen when the signs of the m00/m01/m10/m11 matrix entries
79 // coincide with the signs of the scalars, i.e. are all positive.
80 return {x * abs(ctm.m[0]) + y * abs(ctm.m[4]),
81 x * abs(ctm.m[1]) + y * abs(ctm.m[5])};
82}
83
85 DlScalar radius_x,
86 DlScalar radius_y,
87 const DlMatrix& ctm,
88 DlIRect& output_bounds) {
89 if (ctm.IsFinite() && ctm.IsInvertible()) {
90 if (ctm.HasPerspective2D()) {
91 // Ideally this code would use Impeller classes to do the math, see:
92 // https://github.com/flutter/flutter/issues/159175
93 SkMatrix sk_ctm = ToSkMatrix(ctm);
94 FML_DCHECK(sk_ctm.hasPerspective());
95 SkIRect sk_input_bounds =
96 SkIRect::MakeLTRB(input_bounds.GetLeft(), input_bounds.GetTop(),
97 input_bounds.GetRight(), input_bounds.GetBottom());
98
99 SkMatrix inverse;
100 if (sk_ctm.invert(&inverse)) {
101 SkRect local_bounds = inverse.mapRect(SkRect::Make(sk_input_bounds));
102 local_bounds.inset(radius_x, radius_y);
103 output_bounds = ToDlIRect(sk_ctm.mapRect(local_bounds).roundOut());
104 return &output_bounds;
105 }
106 } else {
107 DlVector2 device_radius = map_vectors_affine(ctm, radius_x, radius_y);
108 output_bounds =
109 input_bounds.Expand(-floor(device_radius.x), -floor(device_radius.y));
110 return &output_bounds;
111 }
112 }
113 output_bounds = input_bounds;
114 return nullptr;
115}
116
118 DlScalar radius_x,
119 DlScalar radius_y,
120 const DlMatrix& ctm,
121 DlIRect& output_bounds) {
122 if (ctm.IsFinite() && ctm.IsInvertible()) {
123 if (ctm.HasPerspective2D()) {
124 // Ideally this code would use Impeller classes to do the math, see:
125 // https://github.com/flutter/flutter/issues/159175
126 SkMatrix sk_ctm = ToSkMatrix(ctm);
127 FML_DCHECK(sk_ctm.hasPerspective());
128 SkIRect sk_input_bounds =
129 SkIRect::MakeLTRB(input_bounds.GetLeft(), input_bounds.GetTop(),
130 input_bounds.GetRight(), input_bounds.GetBottom());
131
132 SkMatrix inverse;
133 if (sk_ctm.invert(&inverse)) {
134 SkRect local_bounds = inverse.mapRect(SkRect::Make(sk_input_bounds));
135 local_bounds.outset(radius_x, radius_y);
136 output_bounds = ToDlIRect(sk_ctm.mapRect(local_bounds).roundOut());
137 return &output_bounds;
138 }
139 } else {
140 DlVector2 device_radius = map_vectors_affine(ctm, radius_x, radius_y);
141 output_bounds =
142 input_bounds.Expand(ceil(device_radius.x), ceil(device_radius.y));
143 return &output_bounds;
144 }
145 }
146 output_bounds = input_bounds;
147 return nullptr;
148}
149
150std::shared_ptr<DlImageFilter> DlImageFilter::makeWithLocalMatrix(
151 const DlMatrix& matrix) const {
152 if (matrix.IsIdentity()) {
153 return shared();
154 }
155 // Matrix
156 switch (this->matrix_capability()) {
158 if (!matrix.IsTranslationOnly()) {
159 // Nothing we can do at this point
160 return nullptr;
161 }
162 break;
163 }
165 if (!matrix.IsTranslationScaleOnly()) {
166 // Nothing we can do at this point
167 return nullptr;
168 }
169 break;
170 }
171 default:
172 break;
173 }
174 return DlLocalMatrixImageFilter::Make(matrix, shared());
175}
176
177} // namespace flutter
virtual std::shared_ptr< DlImageFilter > shared() const=0
static std::shared_ptr< DlImageFilter > Make(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static std::shared_ptr< DlImageFilter > Make(const std::shared_ptr< const DlColorFilter > &filter)
static std::shared_ptr< DlImageFilter > Make(const std::shared_ptr< DlImageFilter > &outer, const std::shared_ptr< DlImageFilter > &inner)
static std::shared_ptr< DlImageFilter > Make(DlScalar radius_x, DlScalar radius_y)
static std::shared_ptr< DlImageFilter > Make(DlScalar radius_x, DlScalar radius_y)
static std::shared_ptr< DlImageFilter > MakeDilate(DlScalar radius_x, DlScalar radius_y)
virtual std::shared_ptr< DlImageFilter > makeWithLocalMatrix(const DlMatrix &matrix) const
static std::shared_ptr< DlImageFilter > MakeBlur(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static DlIRect * outset_device_bounds(const DlIRect &input_bounds, DlScalar radius_x, DlScalar radius_y, const DlMatrix &ctm, DlIRect &output_bounds)
static std::shared_ptr< DlImageFilter > MakeRuntimeEffect(sk_sp< DlRuntimeEffect > runtime_effect, std::vector< std::shared_ptr< DlColorSource > > samplers, std::shared_ptr< std::vector< uint8_t > > uniform_data)
static std::shared_ptr< DlImageFilter > MakeColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
static DlVector2 map_vectors_affine(const DlMatrix &ctm, DlScalar x, DlScalar y)
static DlIRect * inset_device_bounds(const DlIRect &input_bounds, DlScalar radius_x, DlScalar radius_y, const DlMatrix &ctm, DlIRect &output_bounds)
static std::shared_ptr< DlImageFilter > MakeMatrix(const DlMatrix &matrix, DlImageSampling sampling)
static std::shared_ptr< DlImageFilter > MakeCompose(const std::shared_ptr< DlImageFilter > &outer, const std::shared_ptr< DlImageFilter > &inner)
virtual MatrixCapability matrix_capability() const
static std::shared_ptr< DlImageFilter > MakeErode(DlScalar radius_x, DlScalar radius_y)
static std::shared_ptr< DlImageFilter > Make(const DlMatrix &matrix, const std::shared_ptr< DlImageFilter > &filter)
static std::shared_ptr< DlImageFilter > Make(const DlMatrix &matrix, DlImageSampling sampling)
static std::shared_ptr< DlImageFilter > Make(sk_sp< DlRuntimeEffect > runtime_effect, std::vector< std::shared_ptr< DlColorSource > > samplers, std::shared_ptr< std::vector< uint8_t > > uniform_data)
int32_t x
#define FML_DCHECK(condition)
Definition logging.h:122
double y
impeller::Scalar DlScalar
SkMatrix ToSkMatrix(const DlMatrix &matrix)
const DlIRect & ToDlIRect(const SkIRect &rect)
A 4x4 matrix using column-major storage.
Definition matrix.h:37
constexpr bool IsTranslationOnly() const
Returns true if the matrix has no entries other than translation components. Note that an identity ma...
Definition matrix.h:480
constexpr bool IsIdentity() const
Definition matrix.h:467
constexpr bool IsTranslationScaleOnly() const
Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix...
Definition matrix.h:493
Scalar m[16]
Definition matrix.h:39
bool IsInvertible() const
Definition matrix.h:321
constexpr bool HasPerspective2D() const
Definition matrix.h:414
bool IsFinite() const
Definition matrix.h:404
constexpr auto GetBottom() const
Definition rect.h:357
constexpr auto GetTop() const
Definition rect.h:353
constexpr auto GetLeft() const
Definition rect.h:351
constexpr auto GetRight() const
Definition rect.h:355
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition rect.h:618