1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "render/rs_fly_out_shader_filter.h"
16
17 #include "common/rs_common_def.h"
18 #include "common/rs_optional_trace.h"
19 #include "platform/common/rs_log.h"
20 #include "src/core/SkOpts.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 // 0.22 means the ratio of deformation distance of the first four points a, a1, b1, b to width when fly out
25 static const float FLYOUT_DEFORM_PERCENTAGE_ONE = 0.22f;
26 // 0.19 means the ratio of deformation distance of the points a2, b2 to width when fly out
27 static const float FLYOUT_DEFORM_PERCENTAGE_TWO = 0.19f;
28 // 0.07 means the ratio of deformation distance of the points c3, c2, d3, d2 to width when fly in
29 static const float FLYIN_DEFORM_PERCENTAGE_ONE = 0.07f;
30 // 0.04 means the ratio of deformation distance of the points c3, c2, d3, d2 to height when fly in
31 static const float FLYIN_DEFORM_PERCENTAGE_HEIGHT = 0.04f;
32 // 0.21 means the ratio of deformation distance of the points e, e2, f, f2 to width when fly in
33 static const float FLYIN_DEFORM_PERCENTAGE_TWO = 0.21f;
34 static const size_t POINT_NUM = 12; // 12 anchor points of a patch
35 static const uint32_t FLY_OUT_MODE = 0;
36 static const uint32_t FLY_IN_MODE = 1;
37
38
RSFlyOutShaderFilter(float degree,uint32_t flyMode)39 RSFlyOutShaderFilter::RSFlyOutShaderFilter(float degree, uint32_t flyMode)
40 : RSDrawingFilterOriginal(nullptr), degree_(degree), flyMode_(flyMode)
41 {
42 type_ = FilterType::FLY_OUT;
43
44 hash_ = SkOpts::hash(&type_, sizeof(type_), 0);
45 hash_ = SkOpts::hash(°ree_, sizeof(degree_), hash_);
46 hash_ = SkOpts::hash(&flyMode_, sizeof(flyMode_), hash_);
47 }
48
49
50 RSFlyOutShaderFilter::~RSFlyOutShaderFilter() = default;
51
GetDescription()52 std::string RSFlyOutShaderFilter::GetDescription()
53 {
54 return "RSFlyOutShaderFilter " + std::to_string(degree_);
55 }
56
GetDegree() const57 float RSFlyOutShaderFilter::GetDegree() const
58 {
59 return degree_;
60 }
61
GetFlyMode() const62 uint32_t RSFlyOutShaderFilter::GetFlyMode() const
63 {
64 return flyMode_;
65 }
66
GetBrush(const std::shared_ptr<Drawing::Image> & image) const67 Drawing::Brush RSFlyOutShaderFilter::GetBrush(const std::shared_ptr<Drawing::Image>& image) const
68 {
69 Drawing::Brush brush;
70 if (image == nullptr) {
71 return brush;
72 }
73 brush.SetBlendMode(Drawing::BlendMode::SRC_OVER);
74 Drawing::SamplingOptions samplingOptions;
75 Drawing::Matrix scaleMat;
76 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
77 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
78 return brush;
79 }
80
CalculateDeformation(std::array<Drawing::Point,POINT_NUM> & flyUp,std::array<Drawing::Point,POINT_NUM> & flyDown,const float deformWidth,const float deformHeight) const81 void RSFlyOutShaderFilter::CalculateDeformation(std::array<Drawing::Point, POINT_NUM>& flyUp,
82 std::array<Drawing::Point, POINT_NUM>& flyDown, const float deformWidth, const float deformHeight) const
83 {
84 float flyOutOffsetOne = FLYOUT_DEFORM_PERCENTAGE_ONE * deformWidth * degree_;
85 float flyOutOffsetTwo = FLYOUT_DEFORM_PERCENTAGE_TWO * deformWidth * degree_;
86 float flyInOffsetOne = FLYIN_DEFORM_PERCENTAGE_ONE * deformWidth * (1.0 - degree_);
87 float flyInOffsetTwo = FLYIN_DEFORM_PERCENTAGE_TWO * deformWidth * (1.0 - degree_);
88 float flyInOffsetHeight = FLYIN_DEFORM_PERCENTAGE_HEIGHT * deformHeight * (1.0 - degree_);
89
90 if (flyMode_ == FLY_OUT_MODE) {
91 // upper half part
92 flyUp[0].Offset(flyOutOffsetOne, 0); // Point 0 is a, which is the top left control point
93 flyUp[1].Offset(flyOutOffsetOne, 0); // Point 1 is a1 on the left one-third of the top edge
94 flyUp[2].Offset(-flyOutOffsetOne, 0); // Point 2 is b1 on the right one-third of the top edge
95 flyUp[3].Offset(-flyOutOffsetOne, 0); // Point 3 is b, which is thetop right control point
96 flyUp[4].Offset(-flyOutOffsetTwo, 0); // Point 4 is b2 on the upper one-third of the right edge
97 flyUp[11].Offset(flyOutOffsetTwo, 0); // Point 11 is a2 on the upper one-third of the left edge
98 } else if (flyMode_ == FLY_IN_MODE) {
99 // upper half part
100 flyUp[5].Offset(flyInOffsetOne, flyInOffsetHeight); // Point 5 is d2 on the upper two-thirds of the right edge
101 flyUp[10].Offset(-flyInOffsetOne, flyInOffsetHeight); // Point 10 is c2 on the upper two-thirds of left edge
102 // lower half part
103 flyDown[4].Offset(-flyInOffsetOne, -flyInOffsetHeight); // Point 4 is d3 on the lower two-thirds of right edge
104 flyDown[5].Offset(-flyInOffsetTwo, 0); // Point 5 is f2 on the lower one-third of the right edge
105 flyDown[6].Offset(-flyInOffsetTwo, 0); // Point 6 is f, which is the bottom right control point
106 flyDown[7].Offset(flyInOffsetTwo, 0); // Point 7 is f1 on the right one-third of the bottom edge
107 flyDown[8].Offset(-flyInOffsetTwo, 0); // Point 8 is e1 on the left one-third of the bottom edge
108 flyDown[9].Offset(flyInOffsetTwo, 0); // Point 9 is e, which is the bottom left control point
109 flyDown[10].Offset(flyInOffsetTwo, 0); // Point 10 is e2 on the lower one-third of the left edge
110 flyDown[11].Offset(flyInOffsetOne, -flyInOffsetHeight); // Point 11 is c3 on the lower two-thirds of left edge
111 }
112 }
113
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst) const114 void RSFlyOutShaderFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
115 const Drawing::Rect& src, const Drawing::Rect& dst) const
116 {
117 if (image == nullptr || image->GetWidth() <= 0 || image->GetHeight() <= 0) {
118 ROSEN_LOGE("RSFlyOutShaderFilter::shader error");
119 return;
120 }
121
122 auto brush = GetBrush(image);
123 canvas.AttachBrush(brush);
124
125 int imageWidth = image->GetWidth();
126 int imageHeight = image->GetHeight();
127 float width = imageWidth; // the width of two deformation part
128 float height = imageHeight / 2.0; // the height of two deformation part
129 // 4 coordinates of image texture
130 const std::array<Drawing::Point, 4> texCoordsUp = {
131 Drawing::Point{ 0.0f, 0.0f }, Drawing::Point{ imageWidth, 0.0f },
132 Drawing::Point{ imageWidth, height }, Drawing::Point{ 0.0f, height } };
133 // 4 coordinates of image texture
134 const std::array<Drawing::Point, 4> texCoordsDown = {
135 Drawing::Point{ 0.0f, height }, Drawing::Point{ imageWidth, height },
136 Drawing::Point{ imageWidth, imageHeight}, Drawing::Point{ 0.0f, imageHeight } };
137
138 // coordinates init of deformation part
139 float segmentWidthOne = width / 3.0; // Anchor point 1 is located at one-third of the width.
140 float segmentWidthTwo = width / 3.0 * 2.0; // Anchor point 2 is located at two-thirds of the width.
141 float segmentHeightOne = height / 3.0; // Anchor point 1 is located at one-third of the height.
142 float segmentHeightTwo = height / 3.0 * 2.0; // Anchor point 2 is located at two-thirds of the height.
143 std::array<Drawing::Point, POINT_NUM> flyUp = {
144 // top edge control points of upper part
145 Drawing::Point{0.0f, 0.0f}, Drawing::Point{segmentWidthOne, 0.0f},
146 Drawing::Point{segmentWidthTwo, 0.0f}, Drawing::Point{width, 0.0f},
147 // right edge control points of upper part
148 Drawing::Point{width, segmentHeightOne}, Drawing::Point{width, segmentHeightTwo},
149 // bottom edge control points of upper part
150 Drawing::Point{width, height}, Drawing::Point{segmentWidthTwo, height},
151 Drawing::Point{segmentWidthOne, height}, Drawing::Point{0.0f, height},
152 // left edge control points of upper part
153 Drawing::Point{0.0f, segmentHeightTwo}, Drawing::Point{0.0f, segmentHeightOne}
154 };
155 std::array<Drawing::Point, POINT_NUM> flyDown = {
156 // top edge control points of lower part
157 Drawing::Point{0.0f, height}, Drawing::Point{segmentWidthOne, height},
158 Drawing::Point{segmentWidthTwo, height}, Drawing::Point{width, height},
159 // right edge control points of lower part
160 Drawing::Point{width, height + segmentHeightOne}, Drawing::Point{width, height + segmentHeightTwo},
161 // bottom edge control points of lower part
162 Drawing::Point{width, imageHeight}, Drawing::Point{segmentWidthTwo, imageHeight},
163 Drawing::Point{segmentWidthOne, imageHeight}, Drawing::Point{0.0f, imageHeight},
164 // left edge control points of lower part
165 Drawing::Point{0.0f, height + segmentHeightTwo}, Drawing::Point{0.0f, height + segmentHeightOne}
166 };
167
168 // deformation coordinate
169 CalculateDeformation(flyUp, flyDown, width, imageHeight);
170
171 Drawing::Path path;
172 // The 0th point is the starting point of drawing.
173 path.MoveTo(flyUp[0].GetX(), flyUp[0].GetY());
174 // The 1st, 2nd, and 3rd control points are connected to represent the upper edge.
175 path.CubicTo(flyUp[1], flyUp[2], flyUp[3]);
176 // The 4th, 5th and 6th control points are connected to represent the right edge of upper part.
177 path.CubicTo(flyUp[4], flyUp[5], flyUp[6]);
178 // The 4th, 5th and 6th control points are connected to represent the right edge of lower part.
179 path.CubicTo(flyDown[4], flyDown[5], flyDown[6]);
180 // The 7th, 8th, and 9th control points are connected to represent the bottom edge.
181 path.CubicTo(flyDown[7], flyDown[8], flyDown[9]);
182 // The 0th, 10th, and 11th control points are connected to represent the left edge of lower part.
183 path.CubicTo(flyDown[10], flyDown[11], flyDown[0]);
184 // The 0th, 10th, and 11th control points are connected to represent the left edge upper part.
185 path.CubicTo(flyUp[10], flyUp[11], flyUp[0]);
186 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, true);
187 canvas.DrawPatch(flyUp.data(), nullptr, texCoordsUp.data(), Drawing::BlendMode::SRC_OVER);
188 canvas.DrawPatch(flyDown.data(), nullptr, texCoordsDown.data(), Drawing::BlendMode::SRC_OVER);
189 canvas.DetachBrush();
190 }
191 } // namespace Rosen
192 } // namespace OHOS