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
16 #include "common/rs_common_def.h"
17 #include "common/rs_optional_trace.h"
18 #include "platform/common/rs_log.h"
19 #include "render/rs_attraction_effect_filter.h"
20 #include "src/core/SkOpts.h"
21 #include "utils/point.h"
22
23 namespace OHOS {
24 namespace Rosen {
RSAttractionEffectFilter(float attractionFraction)25 RSAttractionEffectFilter::RSAttractionEffectFilter(float attractionFraction)
26 : RSDrawingFilterOriginal(nullptr), attractionFraction_(attractionFraction)
27 {
28 type_ = FilterType::ATTRACTION_EFFECT;
29
30 hash_ = SkOpts::hash(&type_, sizeof(type_), 0);
31 hash_ = SkOpts::hash(&attractionFraction_, sizeof(attractionFraction_), hash_);
32 }
33
34 RSAttractionEffectFilter::~RSAttractionEffectFilter() = default;
35
GetDescription()36 std::string RSAttractionEffectFilter::GetDescription()
37 {
38 return "RSAttractionEffectFilter " + std::to_string(attractionFraction_);
39 }
40
IsValid() const41 bool RSAttractionEffectFilter::IsValid() const
42 {
43 constexpr float epsilon = 0.001f;
44 return attractionFraction_ > epsilon;
45 }
46
GetAttractionFraction() const47 float RSAttractionEffectFilter::GetAttractionFraction() const
48 {
49 return attractionFraction_;
50 }
51
GetAttractionDirtyRegion() const52 RectI RSAttractionEffectFilter::GetAttractionDirtyRegion() const
53 {
54 return attractionDirtyRegion_;
55 }
56
IsWithinThreshold(const float left,const float right,const float threshold)57 bool RSAttractionEffectFilter::IsWithinThreshold(const float left, const float right, const float threshold)
58 {
59 return (std::abs(left - right) <= threshold);
60 }
61
LerpPoint(const Drawing::Point & firstPoint,const Drawing::Point & secondPoint,float firstFactor,float secondFactor)62 Drawing::Point RSAttractionEffectFilter::LerpPoint(const Drawing::Point &firstPoint, const Drawing::Point &secondPoint,
63 float firstFactor, float secondFactor)
64 {
65 Drawing::Point p = { 0.0f, 0.0f };
66 p = firstFactor * firstPoint + secondFactor * secondPoint;
67 return p;
68 }
69
CubicBezier(const Drawing::Point & p0,const Drawing::Point & p1,const Drawing::Point & p2,const Drawing::Point & p3,float t)70 Drawing::Point RSAttractionEffectFilter::CubicBezier(const Drawing::Point &p0, const Drawing::Point &p1,
71 const Drawing::Point &p2, const Drawing::Point &p3, float t)
72 {
73 // p(t) = (1 - t)^3 * p0 + 3 * t * (1 - t)^2 * p1 + 3 * t^2 * (1-t) * p2 + t^3 * p3
74 float tSquared = t * t;
75 float tCubed = t * t * t;
76 float u = 1 - t;
77 float uSquared = u * u;
78 float uCubed = u * u * u;
79
80 Drawing::Point p = { 0.0f, 0.0f };
81 float besselCoefficient = 3.0f;
82 p = p0 * uCubed + p1 * besselCoefficient * uSquared * t + p2 * besselCoefficient * u * tSquared + p3 * tCubed;
83 return p;
84 }
85
CalculateCubic(float p1,float p2,float t)86 float RSAttractionEffectFilter::CalculateCubic(float p1, float p2, float t)
87 {
88 // p(t) = 3 * t * (1 - t)^2 * p1 + 3 * t^2 * (1-t) * p2 + t^3
89 return 3.0f * p1 * (1.0f - t) * (1.0f - t) * t + 3.0f * p2 * (1.0f - t) * t * t + t * t * t;
90 }
91
BinarySearch(float targetX,const Drawing::Point & p1,const Drawing::Point & p2)92 float RSAttractionEffectFilter::BinarySearch(float targetX, const Drawing::Point &p1, const Drawing::Point &p2)
93 {
94 float start = 0.0f;
95 float end = 1.0f;
96 float midPoint = 0.0f;
97 int maxIterCount = 100;
98 int currentIter = 0;
99 while (currentIter < maxIterCount) {
100 midPoint = (start + end) / 2.0f;
101 float estimate = CalculateCubic(p1.GetX(), p2.GetX(), midPoint);
102 if (IsWithinThreshold(targetX, estimate, 0.001f)) {
103 return CalculateCubic(p1.GetY(), p2.GetY(), midPoint);
104 }
105 if (estimate < targetX) {
106 start = midPoint;
107 } else {
108 end = midPoint;
109 }
110 currentIter++;
111 }
112 return CalculateCubic(p1.GetY(), p2.GetY(), midPoint);
113 }
114
CalculateCubicsCtrlPointOffset(const std::vector<Drawing::Point> controlPointOfVertex)115 std::vector<Drawing::Point> RSAttractionEffectFilter::CalculateCubicsCtrlPointOffset(
116 const std::vector<Drawing::Point> controlPointOfVertex)
117 {
118 std::vector<Drawing::Point> pathList;
119 Drawing::Point topLeft = controlPointOfVertex[0];
120 Drawing::Point topRight = controlPointOfVertex[1];
121 Drawing::Point bottomLeft = controlPointOfVertex[2];
122 Drawing::Point bottomRight = controlPointOfVertex[3];
123
124 // The two numbers represent the weights of the two points
125 const float firstPointWeight = 0.33f;
126 const float secondPointWeight = 0.67f;
127 pathList.push_back(topLeft); // 0:top left
128 pathList.push_back(LerpPoint(topLeft, topRight, secondPointWeight, firstPointWeight)); // 1:top one third
129 pathList.push_back(LerpPoint(topLeft, topRight, firstPointWeight, secondPointWeight)); // 2:top two thirds
130 pathList.push_back(topRight); // 3:top right
131 pathList.push_back(LerpPoint(topRight, bottomRight, secondPointWeight, firstPointWeight)); // 4:right one third
132 pathList.push_back(LerpPoint(topRight, bottomRight, firstPointWeight, secondPointWeight)); // 5:right two thirds
133 pathList.push_back(bottomRight); // 6:bottom right
134 pathList.push_back(LerpPoint(bottomLeft, bottomRight, firstPointWeight, secondPointWeight)); // 7:bottom two thirds
135 pathList.push_back(LerpPoint(bottomLeft, bottomRight, secondPointWeight, firstPointWeight)); // 8:bottom one third
136 pathList.push_back(bottomLeft); // 9:bottom left
137 pathList.push_back(LerpPoint(topLeft, bottomLeft, firstPointWeight, secondPointWeight)); // 10:left two thirds
138 pathList.push_back(LerpPoint(topLeft, bottomLeft, secondPointWeight, firstPointWeight)); // 11:left one third
139 return pathList;
140 }
141
CreateIndexSequence(int direction)142 std::vector<int> RSAttractionEffectFilter::CreateIndexSequence(int direction)
143 {
144 // Select the parameter index of the window control point according to the window position.
145 // 0 to 11 indicate the index of the window control point, which is rotated clockwise.
146 if (!isBelowTarget_) {
147 return direction == 1 ?
148 std::vector<int>{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } :
149 std::vector<int>{ 3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4 };
150 } else {
151 return direction == 1 ?
152 std::vector<int>{ 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8 } :
153 std::vector<int>{ 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
154 }
155 }
156
CalculateCubicsCtrlPoint(std::vector<Drawing::Point> controlPointOfVertex,const Drawing::Point points[],int direction,bool isFirstCtrl)157 std::vector<Drawing::Point> RSAttractionEffectFilter::CalculateCubicsCtrlPoint(
158 std::vector<Drawing::Point> controlPointOfVertex,
159 const Drawing::Point points[], // Array instead of vector
160 int direction, // Determine whether the flag on the left or right is used.
161 bool isFirstCtrl)
162 {
163 std::vector<Drawing::Point> pathList = CalculateCubicsCtrlPointOffset(controlPointOfVertex);
164
165 std::vector<int> indice = CreateIndexSequence(direction);
166 std::vector<Drawing::Point> pathCtrlPointList(POINT_NUM, Drawing::Point(0.0f, 0.0f));
167
168 for (int i = 0; i < POINT_NUM; i++) {
169 int index = indice[i];
170 if (!isBelowTarget_) {
171 pathCtrlPointList[i] = pathList[index] + (isFirstCtrl ? points[i] : points[0]);
172 continue;
173 }
174
175 float px = isFirstCtrl ? points[i].GetX() : points[0].GetX();
176 float py = isFirstCtrl ? points[i].GetY() : points[0].GetY();
177
178 if (direction == 1) {
179 px = -px;
180 pathCtrlPointList[i] = { -(pathList[index].GetY() + px), pathList[index].GetX() + py };
181 } else {
182 py = -py;
183 pathCtrlPointList[i] = { pathList[index].GetY() + px, -(pathList[index].GetX() + py) };
184 }
185 }
186 return pathCtrlPointList;
187 }
188
CalculateBezierVelList(const std::vector<Drawing::Point> & velocityList,std::vector<Drawing::Point> & velocityCtrl,int direction)189 void RSAttractionEffectFilter::CalculateBezierVelList(const std::vector<Drawing::Point> &velocityList,
190 std::vector<Drawing::Point> &velocityCtrl, int direction)
191 {
192 std::vector<Drawing::Point> curveVelList;
193 Drawing::Point topVelocity = velocityList[0];
194 Drawing::Point bottomVelocity = velocityList[1];
195
196 // The two numbers represent the weights of the two points
197 // Weights are obtained through regression of a large amount of data.
198 const float lerpPointWeight1 = 0.17f;
199 const float lerpPointWeight2 = 0.33f;
200 const float lerpPointWeight3 = 0.5f;
201 const float lerpPointWeight4 = 0.67f;
202 const float lerpPointWeight5 = 0.83f;
203 const float lerpPointWeight6 = 0.57f;
204
205 curveVelList.push_back(LerpPoint(topVelocity, bottomVelocity, lerpPointWeight3, lerpPointWeight3));
206 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight2, lerpPointWeight4));
207 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight1, lerpPointWeight5));
208 curveVelList.push_back(topVelocity);
209 // The window is located below the dock bar and uses additional parameters.
210 if (isBelowTarget_) {
211 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight1, lerpPointWeight4));
212 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight2, lerpPointWeight6));
213 } else {
214 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight1, lerpPointWeight5));
215 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight2, lerpPointWeight4));
216 }
217 curveVelList.push_back(LerpPoint(topVelocity, bottomVelocity, lerpPointWeight3, lerpPointWeight3));
218 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight4, lerpPointWeight2));
219 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight5, lerpPointWeight1));
220 curveVelList.push_back(bottomVelocity);
221 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight5, lerpPointWeight1));
222 curveVelList.push_back(LerpPoint(bottomVelocity, topVelocity, lerpPointWeight4, lerpPointWeight2));
223 std::vector<int> indice = CreateIndexSequence(direction);
224
225 for (int i = 0; i < POINT_NUM; i++) {
226 int index = indice[i];
227 velocityCtrl[i] = curveVelList[index];
228 }
229 }
230
InitWindowInitCtrlPoints()231 void RSAttractionEffectFilter::InitWindowInitCtrlPoints()
232 {
233 // Find the third division point
234 float third = 1.0f / 3.0f;
235 float twoThirds = 2.0f / 3.0f;
236 float widthOneThird = canvasWidth_ * third;
237 float widthTwoThirds = canvasWidth_ * twoThirds;
238 float heightOneThird = canvasHeight_ * third;
239 float heightTwoThirds = canvasHeight_ * twoThirds;
240
241 windowCtrlPoints_[TOP_LEFT_INDEX] = { 0.0f, 0.0f };
242 windowCtrlPoints_[TOP_ONE_THIRD] = { widthOneThird, 0.0f };
243 windowCtrlPoints_[TOP_TWO_THIRDS] = { widthTwoThirds, 0.0f };
244 windowCtrlPoints_[TOP_RIGHT_INDEX] = { canvasWidth_, 0.0f };
245 windowCtrlPoints_[RIGHT_ONE_THIRD] = { canvasWidth_, heightOneThird };
246 windowCtrlPoints_[RIGHT_TWO_THIRDS] = { canvasWidth_, heightTwoThirds };
247 windowCtrlPoints_[BOTTOM_RIGHT_INDEX] = { canvasWidth_, canvasHeight_ };
248 windowCtrlPoints_[BOTTOM_TWO_THIRDS] = { widthTwoThirds, canvasHeight_ };
249 windowCtrlPoints_[BOTTOM_ONE_THIRD] = { widthOneThird, canvasHeight_ };
250 windowCtrlPoints_[BOTTOM_LEFT_INDEX] = { 0.0f, canvasHeight_ };
251 windowCtrlPoints_[LEFT_TWO_THIRDS] = { 0.0f, heightTwoThirds };
252 windowCtrlPoints_[LEFT_ONE_THIRD] = { 0.0f, heightOneThird };
253 }
254
CalculateDeltaXAndDeltaY(const Drawing::Point & pointDst,float & deltaX,float & deltaY,int direction)255 void RSAttractionEffectFilter::CalculateDeltaXAndDeltaY(const Drawing::Point &pointDst, float &deltaX, float &deltaY,
256 int direction)
257 {
258 Drawing::Point windowCenter = { 0.5 * canvasWidth_, canvasHeight_ };
259 if (windowCenter.GetY() > pointDst.GetY()) {
260 if (direction == 1) {
261 deltaX = std::abs((windowCtrlPoints_[TOP_LEFT_INDEX].GetY() + windowCtrlPoints_[BOTTOM_LEFT_INDEX].GetY()) /
262 2.0f - pointDst.GetY());
263 deltaY = std::abs(windowCtrlPoints_[TOP_LEFT_INDEX].GetX() - pointDst.GetX());
264 } else {
265 deltaX = std::abs(
266 (windowCtrlPoints_[TOP_RIGHT_INDEX].GetY() + windowCtrlPoints_[BOTTOM_RIGHT_INDEX].GetY()) / 2.0f -
267 pointDst.GetY());
268 deltaY = std::abs(windowCtrlPoints_[TOP_RIGHT_INDEX].GetX() - pointDst.GetX());
269 }
270 } else {
271 deltaX = std::abs(windowCenter.GetX() - pointDst.GetX());
272 deltaY = std::abs(windowCenter.GetY() - pointDst.GetY());
273 }
274 }
275
CalculateUpperCtrlPointOfVertex(float deltaX,float deltaY,float width,float height,int direction)276 std::vector<Drawing::Point> RSAttractionEffectFilter::CalculateUpperCtrlPointOfVertex(float deltaX, float deltaY,
277 float width, float height, int direction)
278 {
279 // Different regression parameters are used for different scenarios
280 // The window is located below the dock bar. Parameters with greater distortion are used.
281 // Coordinates of the upper control point of the curve:(k1 * width + k2 * deltaX, k3 * height + k4 * deltaY)
282 Drawing::Point topLeft = isBelowTarget_ ?
283 Drawing::Point((0.016f * width - 0.08f * deltaX) * direction, 0.464f * height + 0.40f * deltaY) :
284 Drawing::Point((-0.100f * width - 0.008f * deltaX) * direction, 0.008f * height + 0.085f * deltaY);
285 Drawing::Point bottomLeft = isBelowTarget_ ?
286 Drawing::Point((-0.15f * width - 0.075f * deltaX) * direction, 0.0f * height + 0.2f * deltaY) :
287 Drawing::Point((-0.008f * width - 0.008f * deltaX) * direction, 0.0f * height - 0.008f * deltaY);
288 Drawing::Point topRight = { (-1.147f * width - 0.016f * deltaX) * direction, -0.187f * height + 0.30f * deltaY };
289 Drawing::Point bottomRight = { (-0.84f * width - 0.2f * deltaX) * direction, -0.859f * height - 0.2f * deltaY };
290 std::vector<Drawing::Point> upperControlPoint = { topLeft, topRight, bottomLeft, bottomRight };
291 return upperControlPoint;
292 }
293
CalculateLowerCtrlPointOfVertex(float deltaX,float deltaY,float width,float height,int direction)294 std::vector<Drawing::Point> RSAttractionEffectFilter::CalculateLowerCtrlPointOfVertex(float deltaX, float deltaY,
295 float width, float height, int direction)
296 {
297 float inverseWidth = (width >= 1.0f) ? (1.0f / width) : 1.0f;
298 // Different regression parameters are used for different scenarios
299 // The window is located below the dock bar. Parameters with greater distortion are used.
300 // Coordinates of the lower control point of the curve:(m1*(deltaX * height/width - width)), m2 * deltaY)
301 Drawing::Point topLeft = isBelowTarget_ ?
302 Drawing::Point((0.300f * (deltaX * height * inverseWidth - width)) * direction, -0.20f * deltaY) :
303 Drawing::Point((0.131f * (deltaX * height * inverseWidth - width)) * direction, -0.20f * deltaY);
304 Drawing::Point topRight = isBelowTarget_ ?
305 Drawing::Point((0.450f * (deltaX * height * inverseWidth - width)) * direction, -0.30f * deltaY) :
306 Drawing::Point((0.147f * (deltaX * height * inverseWidth - width)) * direction, -0.30f * deltaY);
307 Drawing::Point bottomLeft = isBelowTarget_ ?
308 Drawing::Point((0.150f * (deltaX * height * inverseWidth - width)) * direction, -0.20f * deltaY) :
309 Drawing::Point((0.085f * (deltaX * height * inverseWidth - width)) * direction, 0.008f * deltaY);
310 Drawing::Point bottomRight = isBelowTarget_ ?
311 Drawing::Point((0.300f * (deltaX * height * inverseWidth - width)) * direction, -0.112f * deltaY) :
312 Drawing::Point((0.147f * (deltaX * height * inverseWidth - width)) * direction, -0.069f * deltaY);
313 std::vector<Drawing::Point> lowerControlPoint = { topLeft, topRight, bottomLeft, bottomRight };
314 return lowerControlPoint;
315 }
316
CalculateVelocityCtrlPointUpper(std::vector<Drawing::Point> & velocityCtrlPointUpper)317 void RSAttractionEffectFilter::CalculateVelocityCtrlPointUpper(std::vector<Drawing::Point>& velocityCtrlPointUpper)
318 {
319 // Cubic Bezier curve with two control points
320 Drawing::Point topVelFirst = { 0.50f, 0.0f };
321 // Use faster speed when the lower edge of the window is above the dock bar
322 Drawing::Point bottomVelFirst = isBelowTarget_ ? Drawing::Point(0.2f, 0.0f) : Drawing::Point(0.0f, 0.0f);
323 velocityCtrlPointUpper.push_back(topVelFirst);
324 velocityCtrlPointUpper.push_back(bottomVelFirst);
325 }
326
CalculateVelocityCtrlPointLower(std::vector<Drawing::Point> & velocityCtrlPointLower)327 void RSAttractionEffectFilter::CalculateVelocityCtrlPointLower(std::vector<Drawing::Point>& velocityCtrlPointLower)
328 {
329 // Cubic Bezier curve with two control points
330 Drawing::Point topVelSecond = { 0.50f, 1.0f };
331 // Use faster speed when the lower edge of the window is above the dock bar
332 Drawing::Point bottomVelSecond = isBelowTarget_ ? Drawing::Point(0.2f, 1.0f) : Drawing::Point(0.0f, 1.0f);
333 velocityCtrlPointLower.push_back(topVelSecond);
334 velocityCtrlPointLower.push_back(bottomVelSecond);
335 }
336
UpdateDirtyRegion(float leftPoint,float topPonit)337 void RSAttractionEffectFilter::UpdateDirtyRegion(float leftPoint, float topPonit)
338 {
339 float dirtyRegionMinX = windowStatusPoints_[0].GetX();
340 float dirtyRegionMaxX = windowStatusPoints_[0].GetX();
341 float dirtyRegionMinY = windowStatusPoints_[0].GetY();
342 float dirtyRegionMaxY = windowStatusPoints_[0].GetY();
343
344 ROSEN_LOGI("RSAttractionEffectFilter::UpdateDirtyRegion:%f", dirtyRegionMinX);
345 for (int i = 1; i < POINT_NUM; ++i) {
346 float x = windowStatusPoints_[i].GetX();
347 float y = windowStatusPoints_[i].GetY();
348 dirtyRegionMinX = std::min(dirtyRegionMinX, x);
349 dirtyRegionMaxX = std::max(dirtyRegionMaxX, x);
350 dirtyRegionMinY = std::min(dirtyRegionMinY, y);
351 dirtyRegionMaxY = std::max(dirtyRegionMaxY, y);
352 }
353
354 int dirtyRegionLeftCurrent = static_cast<int>(dirtyRegionMinX + leftPoint);
355 int dirtyRegionTopCurrent = static_cast<int>(dirtyRegionMinY + topPonit);
356 int dirtyRegionRightCurrent = static_cast<int>(dirtyRegionMaxX + leftPoint);
357 int dirtyRegionBottomCurrent = static_cast<int>(dirtyRegionMaxY + topPonit);
358
359 attractionDirtyRegion_.left_ = dirtyRegionLeftCurrent;
360 attractionDirtyRegion_.top_ = dirtyRegionTopCurrent;
361 attractionDirtyRegion_.width_ = dirtyRegionRightCurrent - dirtyRegionLeftCurrent;
362 attractionDirtyRegion_.height_ = dirtyRegionBottomCurrent - dirtyRegionTopCurrent;
363 }
364
CalculateWindowStatus(float canvasWidth,float canvasHeight,Vector2f & destinationPoint)365 void RSAttractionEffectFilter::CalculateWindowStatus(float canvasWidth, float canvasHeight, Vector2f& destinationPoint)
366 {
367 canvasWidth_ = canvasWidth;
368 canvasHeight_ = canvasHeight;
369 InitWindowInitCtrlPoints();
370
371 Drawing::Point pointDst[1] = { { destinationPoint.x_, destinationPoint.y_ } };
372 Drawing::Point windowBottomCenter = { 0.5 * canvasWidth_, 0.5 * canvasHeight_ };
373
374 // 1 indicates that the window is to the right of the target point,
375 // and - 1 indicates that the window is to the left.
376 int direction = (windowBottomCenter.GetX() > pointDst[0].GetX()) ? 1 : -1;
377 // true indicates that the lower edge of the window is below the dock bar,
378 // and false indicates that the lower edge of the window is above the dock bar.
379 isBelowTarget_ = (windowBottomCenter.GetY() > pointDst[0].GetY()) ? true : false;
380
381 float width = isBelowTarget_ ? canvasHeight_ : canvasWidth_;
382 float height = isBelowTarget_ ? canvasWidth_ : canvasHeight_;
383 float deltaX = 0.0f;
384 float deltaY = 0.0f;
385 CalculateDeltaXAndDeltaY(pointDst[0], deltaX, deltaY, direction);
386
387 std::vector<Drawing::Point> upperControlPointOfVertex =
388 CalculateUpperCtrlPointOfVertex(deltaX, deltaY, width, height, direction);
389 std::vector<Drawing::Point> lowerControlPointOfVertex =
390 CalculateLowerCtrlPointOfVertex(deltaX, deltaY, width, height, direction);
391 std::vector<Drawing::Point> velocityCtrlPointUpper;
392 CalculateVelocityCtrlPointUpper(velocityCtrlPointUpper);
393 std::vector<Drawing::Point> velocityCtrlPointLower;
394 CalculateVelocityCtrlPointLower(velocityCtrlPointLower);
395
396 std::vector<Drawing::Point> controlPointListFirst =
397 CalculateCubicsCtrlPoint(upperControlPointOfVertex, windowCtrlPoints_, direction, true);
398 std::vector<Drawing::Point> controlPointListSecond =
399 CalculateCubicsCtrlPoint(lowerControlPointOfVertex, pointDst, direction, false);
400
401 std::vector<Drawing::Point> speedListsFirst(POINT_NUM, Drawing::Point(0.0f, 0.0f));
402 std::vector<Drawing::Point> speedListsSecond(POINT_NUM, Drawing::Point(0.0f, 0.0f));
403 CalculateBezierVelList(velocityCtrlPointUpper, speedListsFirst, direction);
404 CalculateBezierVelList(velocityCtrlPointLower, speedListsSecond, direction);
405
406 for (int i = 0; i < POINT_NUM; ++i) {
407 float speed = BinarySearch(attractionFraction_, speedListsFirst[i], speedListsSecond[i]);
408 windowStatusPoints_[i] = CubicBezier(windowCtrlPoints_[i], controlPointListFirst[i], controlPointListSecond[i],
409 pointDst[0], speed);
410 }
411 }
412
GetBrush(const std::shared_ptr<Drawing::Image> & image) const413 Drawing::Brush RSAttractionEffectFilter::GetBrush(const std::shared_ptr<Drawing::Image>& image) const
414 {
415 Drawing::Brush brush;
416 brush.SetBlendMode(Drawing::BlendMode::SRC_OVER);
417 Drawing::SamplingOptions samplingOptions;
418 Drawing::Matrix scaleMat;
419 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
420 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
421 return brush;
422 }
423
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst) const424 void RSAttractionEffectFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
425 const Drawing::Rect& src, const Drawing::Rect& dst) const
426 {
427 if (!IsValid() || !image || image->GetWidth() == 0 || image->GetHeight() == 0) {
428 ROSEN_LOGE("RSAttractionEffectFilter::shader error");
429 return;
430 }
431 RS_OPTIONAL_TRACE_NAME_FMT("DrawAttraction:%f", attractionFraction_);
432 int width = image->GetWidth();
433 int height = image->GetHeight();
434
435 auto brush = GetBrush(image);
436 canvas.AttachBrush(brush);
437
438 // 4 coordinates of image texture
439 const Drawing::Point texCoords[4] = { { 0.0f, 0.0f }, { width, 0.0f }, { width, height }, { 0.0f, height } };
440
441 canvas.DrawPatch(windowStatusPoints_, nullptr, texCoords, Drawing::BlendMode::SRC_OVER);
442 canvas.DetachBrush();
443 }
444 } // namespace Rosen
445 } // namespace OHOS