• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "gfx_utils/diagram/vertexprimitive/geometry_curves.h"
17 #include "gfx_utils/graphic_math.h"
18 #include "gfx_utils/diagram/common/common_math.h"
19 namespace OHOS {
20 const float CURVE_COLLINEARITY_EPSILON = 1e-30;
21 const float CURVE_ANGLE_TO_LERANCE_EPSILON = 0.01f;
22 const int32_t CURVE_RECURSION_LIMIT = 32;
23 const float CURVES_NUM_STEP_LEN = 0.25f;
ApproximationScale() const24 float QuadBezierCurveIncr::ApproximationScale() const
25 {
26     return approximationScale_;
27 }
28 
ApproximationScale(float scale)29 void QuadBezierCurveIncr::ApproximationScale(float scale)
30 {
31     approximationScale_ = scale;
32 }
33 
Init(float x1,float y1,float x2,float y2,float x3,float y3)34 void QuadBezierCurveIncr::Init(float x1, float y1,
35                                float x2, float y2,
36                                float x3, float y3)
37 {
38     startCoordinate_.x = x1;
39     startCoordinate_.y = y1;
40     endCoordinate_.x = x3;
41     endCoordinate_.y = y3;
42 
43     float deltaX1 = x2 - x1;
44     float deltaY1 = y2 - y1;
45     float deltaX2 = x3 - x2;
46     float deltaY2 = y3 - y2;
47 
48     float len = Sqrt(deltaX1 * deltaX1 + deltaY1 * deltaY1) +
49                 Sqrt(deltaX2 * deltaX2 + deltaY2 * deltaY2);
50 
51     numberSteps_ = MATH_UROUND(len * CURVES_NUM_STEP_LEN * approximationScale_);
52     const int32_t numStepsMax = 4;
53     if (numberSteps_ < numStepsMax) {
54         numberSteps_ = numStepsMax;
55     }
56     if (numberSteps_ == 0) {
57         return;
58     }
59     float subdivideStep = 1.0f / numberSteps_;
60     float subdivideStep2 = subdivideStep * subdivideStep;
61 
62     float tmpX = (x1 - x2 * FLOATNUM + x3) * subdivideStep2;
63     float tmpY = (y1 - y2 * FLOATNUM + y3) * subdivideStep2;
64 
65     savedFinalCoordinate_.x = x1;
66     finalCoordinate_.x = x1;
67     savedFinalCoordinate_.y = y1;
68     finalCoordinate_.y = y1;
69 
70     savedDeltaFinalCoordinate_.x = tmpX + (x2 - x1) * (FLOATNUM * subdivideStep);
71     deltaFinalCoordinate_.x = tmpX + (x2 - x1) * (FLOATNUM * subdivideStep);
72     savedDeltaFinalCoordinate_.y = tmpY + (y2 - y1) * (FLOATNUM * subdivideStep);
73     deltaFinalCoordinate_.y = tmpY + (y2 - y1) * (FLOATNUM * subdivideStep);
74 
75     copyDeltaFinalCoordinate_.x = tmpX * FLOATNUM;
76     copyDeltaFinalCoordinate_.y = tmpY * FLOATNUM;
77 
78     currentStep_ = numberSteps_;
79 }
80 
Reset()81 void QuadBezierCurveIncr::Reset()
82 {
83     numberSteps_ = 0;
84     currentStep_ = -1;
85 }
86 
ApproximationMethod() const87 CurveApproximationMethod QuadBezierCurveIncr::ApproximationMethod() const
88 {
89     return CURVEINCREMENT;
90 }
91 
AngleTolerance() const92 float QuadBezierCurveIncr::AngleTolerance() const
93 {
94     return 0.0f;
95 }
96 
CuspLimit() const97 float QuadBezierCurveIncr::CuspLimit() const
98 {
99     return 0.0f;
100 }
101 
Rewind(uint32_t)102 void QuadBezierCurveIncr::Rewind(uint32_t)
103 {
104     if (numberSteps_ == 0) {
105         currentStep_ = -1;
106         return;
107     }
108 
109     currentStep_ = numberSteps_;
110     finalCoordinate_.x = savedFinalCoordinate_.x;
111     finalCoordinate_.y = savedFinalCoordinate_.y;
112     deltaFinalCoordinate_.x = savedDeltaFinalCoordinate_.x;
113     deltaFinalCoordinate_.y = savedDeltaFinalCoordinate_.y;
114 }
115 
GenerateVertex(float * x,float * y)116 uint32_t QuadBezierCurveIncr::GenerateVertex(float* x, float* y)
117 {
118     if (currentStep_ < 0) {
119         return PATH_CMD_STOP;
120     }
121     if (currentStep_ == numberSteps_) {
122         *x = startCoordinate_.x;
123         *y = startCoordinate_.y;
124         --currentStep_;
125         return PATH_CMD_MOVE_TO;
126     }
127     if (currentStep_ == 0) {
128         *x = endCoordinate_.x;
129         *y = endCoordinate_.y;
130         --currentStep_;
131         return PATH_CMD_LINE_TO;
132     }
133 
134     finalCoordinate_.x += deltaFinalCoordinate_.x;
135     finalCoordinate_.y += deltaFinalCoordinate_.y;
136     deltaFinalCoordinate_.x += copyDeltaFinalCoordinate_.x;
137     deltaFinalCoordinate_.y += copyDeltaFinalCoordinate_.y;
138     *x = finalCoordinate_.x;
139     *y = finalCoordinate_.y;
140     --currentStep_;
141     return PATH_CMD_LINE_TO;
142 }
143 
Init(float x1,float y1,float x2,float y2,float x3,float y3)144 void QuadrBezierCurveDividOp::Init(float x1, float y1,
145                                    float x2, float y2,
146                                    float x3, float y3)
147 {
148     points_.Clear();
149     distanceToleranceSquare_ = HALFNUM / approximationScale_;
150     distanceToleranceSquare_ *= distanceToleranceSquare_;
151     Bezier(x1, y1, x2, y2, x3, y3);
152     count_ = 0;
153 }
154 
Reset()155 void QuadrBezierCurveDividOp::Reset()
156 {
157     points_.Clear();
158     count_ = 0;
159 }
160 
ApproximationMethod() const161 CurveApproximationMethod QuadrBezierCurveDividOp::ApproximationMethod() const
162 {
163     return CURVEDIVIDOPERATE;
164 }
165 
ApproximationScale(float scale)166 void QuadrBezierCurveDividOp::ApproximationScale(float scale)
167 {
168     approximationScale_ = scale;
169 }
170 
ApproximationScale() const171 float QuadrBezierCurveDividOp::ApproximationScale() const
172 {
173     return approximationScale_;
174 }
175 
AngleTolerance(float angle)176 void QuadrBezierCurveDividOp::AngleTolerance(float angle)
177 {
178     angleTolerance_ = angle;
179 }
180 
AngleTolerance() const181 float QuadrBezierCurveDividOp::AngleTolerance() const
182 {
183     return angleTolerance_;
184 }
185 
CuspLimit() const186 float QuadrBezierCurveDividOp::CuspLimit() const
187 {
188     return 0.0f;
189 }
190 
Rewind(uint32_t)191 void QuadrBezierCurveDividOp::Rewind(uint32_t)
192 {
193     count_ = 0;
194 }
195 
GenerateVertex(float * x,float * y)196 uint32_t QuadrBezierCurveDividOp::GenerateVertex(float* x, float* y)
197 {
198     if (count_ >= points_.Size()) {
199         return PATH_CMD_STOP;
200     }
201     const PointF& point = points_[count_++];
202     *x = point.x;
203     *y = point.y;
204     return (count_ == 1) ? PATH_CMD_MOVE_TO : PATH_CMD_LINE_TO;
205 }
206 
Recursive(float x1,float y1,float x2,float y2,float x3,float y3,uint32_t level)207 void QuadrBezierCurveDividOp::Recursive(float x1, float y1,
208                                         float x2, float y2,
209                                         float x3, float y3,
210                                         uint32_t level)
211 {
212     if (level > CURVE_RECURSION_LIMIT) {
213         return;
214     }
215 
216     // Calculates All Midpoints Of a Segment
217     float x12 = (x1 + x2) / FLOATNUM;
218     float y12 = (y1 + y2) / FLOATNUM;
219     float x23 = (x2 + x3) / FLOATNUM;
220     float y23 = (y2 + y3) / FLOATNUM;
221     float x123 = (x12 + x23) / FLOATNUM;
222     float y123 = (y12 + y23) / FLOATNUM;
223     float deltaX = x3 - x1;
224     float deltaY = y3 - y1;
225     float distance = MATH_ABS(((x2 - x3) * deltaY - (y2 - y3) * deltaX));
226     float da;
227     if (distance > CURVE_COLLINEARITY_EPSILON) {
228         if (distance * distance <= distanceToleranceSquare_ * (deltaX * deltaX + deltaY * deltaY)) {
229             // If The Curvature Does Not Exceed The Distance Tolerance Value
230             if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
231                 points_.PushBack(PointF(x123, y123));
232                 return;
233             }
234 
235             da = MATH_ABS(FastAtan2F(y3 - y2, x3 - x2) - FastAtan2F(y2 - y1, x2 - x1));
236             if (da >= PI) {
237                 da = TWO_TIMES * PI - da;
238             }
239 
240             if (da < angleTolerance_) {
241                 points_.PushBack(PointF(x123, y123));
242                 return;
243             }
244         }
245     } else {
246         da = deltaX * deltaX + deltaY * deltaY;
247         if (da == 0) {
248             distance = CalcSqDistance(x1, y1, x2, y2);
249         } else {
250             distance = ((x2 - x1) * deltaX + (y2 - y1) * deltaY) / da;
251             if (distance > 0 && distance < 1) {
252                 // Simple Collinear Case,1---2---3
253                 // We Can Leave Only Two Endpoints
254                 return;
255             }
256             if (distance <= 0) {
257                 distance = CalcSqDistance(x2, y2, x1, y1);
258             } else if (distance >= 1) {
259                 distance = CalcSqDistance(x2, y2, x3, y3);
260             } else {
261                 distance = CalcSqDistance(x2, y2, x1 + distance * deltaX, y1 + distance * deltaY);
262             }
263         }
264         if (distance < distanceToleranceSquare_) {
265             points_.PushBack(PointF(x2, y2));
266             return;
267         }
268     }
269 
270     // Continue Subdivision
271     Recursive(x1, y1, x12, y12, x123, y123, level + 1);
272     Recursive(x123, y123, x23, y23, x3, y3, level + 1);
273 }
274 
Bezier(float x1,float y1,float x2,float y2,float x3,float y3)275 void QuadrBezierCurveDividOp::Bezier(float x1, float y1,
276                                      float x2, float y2,
277                                      float x3, float y3)
278 {
279     points_.PushBack(PointF(x1, y1));
280     Recursive(x1, y1, x2, y2, x3, y3, 0);
281     points_.PushBack(PointF(x3, y3));
282 }
283 
ApproximationScale(float scale)284 void CubicBezierCurveIncrement::ApproximationScale(float scale)
285 {
286     approximationScale_ = scale;
287 }
288 
ApproximationScale() const289 float CubicBezierCurveIncrement::ApproximationScale() const
290 {
291     return approximationScale_;
292 }
293 
Init(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)294 void CubicBezierCurveIncrement::Init(float x1, float y1,
295                                      float x2, float y2,
296                                      float x3, float y3,
297                                      float x4, float y4)
298 {
299     startCoordinate_.x = x1;
300     startCoordinate_.y = y1;
301     endCoordinate_.x = x4;
302     endCoordinate_.y = y4;
303 
304     float deltaX1 = x2 - x1;
305     float deltaY1 = y2 - y1;
306     float deltaX2 = x3 - x2;
307     float deltaY2 = y3 - y2;
308     float deltaX3 = x4 - x3;
309     float deltaY3 = y4 - y3;
310 
311     float len = (Sqrt(deltaX1 * deltaX1 + deltaY1 * deltaY1) +
312                  Sqrt(deltaX2 * deltaX2 + deltaY2 * deltaY2) +
313                  Sqrt(deltaX3 * deltaX3 + deltaY3 * deltaY3)) *
314                  CURVES_NUM_STEP_LEN * approximationScale_;
315 
316     numberSteps_ = MATH_UROUND(len);
317     const int32_t cuvereNumStep = 4;
318     if (numberSteps_ < cuvereNumStep) {
319         numberSteps_ = cuvereNumStep;
320     }
321     if (numberSteps_ == 0) {
322         return;
323     }
324     float subdivideStep = 1.0f / numberSteps_;
325     float subdivideStep2 = subdivideStep * subdivideStep;
326     float subdivideStep3 = subdivideStep * subdivideStep * subdivideStep;
327     const float prelMin = 3.0f;
328     const float prelMax = 6.0f;
329 
330     float pre1 = prelMin * subdivideStep;
331     float pre2 = prelMin * subdivideStep2;
332     float pre4 = prelMax * subdivideStep2;
333     float pre5 = prelMax * subdivideStep3;
334 
335     float tmp1X = x1 - x2 * FLOATNUM + x3;
336     float tmp1Y = y1 - y2 * FLOATNUM + y3;
337 
338     float tmp2X = (x2 - x3) * prelMin - x1 + x4;
339     float tmp2Y = (y2 - y3) * prelMin - y1 + y4;
340 
341     savedFinalCoordinate_.x = x1;
342     finalCoordinate_.x = x1;
343     savedFinalCoordinate_.y = y1;
344     finalCoordinate_.y = y1;
345 
346     savedDeltaFinalCoordinate_.x = (x2 - x1) * pre1 + tmp1X * pre2 + tmp2X * subdivideStep3;
347     deltaFinalCoordinate_.x = (x2 - x1) * pre1 + tmp1X * pre2 + tmp2X * subdivideStep3;
348     savedDeltaFinalCoordinate_.y = (y2 - y1) * pre1 + tmp1Y * pre2 + tmp2Y * subdivideStep3;
349     deltaFinalCoordinate_.y = (y2 - y1) * pre1 + tmp1Y * pre2 + tmp2Y * subdivideStep3;
350 
351     savedCopyDeltaFinalCoordinate_.x = tmp1X * pre4 + tmp2X * pre5;
352     copyDeltaFinalCoordinate_.x = tmp1X * pre4 + tmp2X * pre5;
353     savedCopyDeltaFinalCoordinate_.y = tmp1Y * pre4 + tmp2Y * pre5;
354     copyDeltaFinalCoordinate_.y = tmp1Y * pre4 + tmp2Y * pre5;
355 
356     repeatCopyDeltaFinalCoordinate_.x = tmp2X * pre5;
357     repeatCopyDeltaFinalCoordinate_.y = tmp2Y * pre5;
358 
359     currentStep_ = numberSteps_;
360 }
361 
Reset()362 void CubicBezierCurveIncrement::Reset()
363 {
364     numberSteps_ = 0;
365     currentStep_ = -1;
366 }
367 
ApproximationMethod() const368 CurveApproximationMethod CubicBezierCurveIncrement::ApproximationMethod() const
369 {
370     return CURVEINCREMENT;
371 }
372 
AngleTolerance() const373 float CubicBezierCurveIncrement::AngleTolerance() const
374 {
375     return 0.0f;
376 }
377 
CuspLimit() const378 float CubicBezierCurveIncrement::CuspLimit() const
379 {
380     return 0.0f;
381 }
382 
Rewind(uint32_t)383 void CubicBezierCurveIncrement::Rewind(uint32_t)
384 {
385     if (numberSteps_ == 0) {
386         currentStep_ = -1;
387         return;
388     }
389 
390     currentStep_ = numberSteps_;
391     finalCoordinate_.x = savedFinalCoordinate_.x;
392     finalCoordinate_.y = savedFinalCoordinate_.y;
393     deltaFinalCoordinate_.x = savedDeltaFinalCoordinate_.x;
394     deltaFinalCoordinate_.y = savedDeltaFinalCoordinate_.y;
395     copyDeltaFinalCoordinate_.x = savedCopyDeltaFinalCoordinate_.x;
396     copyDeltaFinalCoordinate_.y = savedCopyDeltaFinalCoordinate_.y;
397 }
398 
GenerateVertex(float * x,float * y)399 uint32_t CubicBezierCurveIncrement::GenerateVertex(float* x, float* y)
400 {
401     if (currentStep_ < 0) {
402         return PATH_CMD_STOP;
403     }
404     if (currentStep_ == numberSteps_) {
405         *x = startCoordinate_.x;
406         *y = startCoordinate_.y;
407         --currentStep_;
408         return PATH_CMD_MOVE_TO;
409     }
410 
411     if (currentStep_ == 0) {
412         *x = endCoordinate_.x;
413         *y = endCoordinate_.y;
414         --currentStep_;
415         return PATH_CMD_LINE_TO;
416     }
417 
418     finalCoordinate_.x += deltaFinalCoordinate_.x;
419     finalCoordinate_.y += deltaFinalCoordinate_.y;
420     deltaFinalCoordinate_.x += copyDeltaFinalCoordinate_.x;
421     deltaFinalCoordinate_.y += copyDeltaFinalCoordinate_.y;
422     copyDeltaFinalCoordinate_.x += repeatCopyDeltaFinalCoordinate_.x;
423     copyDeltaFinalCoordinate_.y += repeatCopyDeltaFinalCoordinate_.y;
424 
425     *x = finalCoordinate_.x;
426     *y = finalCoordinate_.y;
427     --currentStep_;
428     return PATH_CMD_LINE_TO;
429 }
430 
Init(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)431 void CubicBezierCurveDividOperate::Init(float x1, float y1,
432                                         float x2, float y2,
433                                         float x3, float y3,
434                                         float x4, float y4)
435 {
436     points_.Clear();
437     distanceToleranceSquare_ = HALFNUM / approximationScale_;
438     distanceToleranceSquare_ *= distanceToleranceSquare_;
439     Bezier(x1, y1, x2, y2, x3, y3, x4, y4);
440     count_ = 0;
441 }
442 
Reset()443 void CubicBezierCurveDividOperate::Reset()
444 {
445     points_.Clear();
446     count_ = 0;
447 }
448 
ApproximationMethod() const449 CurveApproximationMethod CubicBezierCurveDividOperate::ApproximationMethod() const
450 {
451     return CURVEDIVIDOPERATE;
452 }
453 
ApproximationScale(float scale)454 void CubicBezierCurveDividOperate::ApproximationScale(float scale)
455 {
456     approximationScale_ = scale;
457 }
458 
ApproximationScale() const459 float CubicBezierCurveDividOperate::ApproximationScale() const
460 {
461     return approximationScale_;
462 }
463 
AngleTolerance(float angleValue)464 void CubicBezierCurveDividOperate::AngleTolerance(float angleValue)
465 {
466     angleTolerance_ = angleValue;
467 }
468 
AngleTolerance() const469 float CubicBezierCurveDividOperate::AngleTolerance() const
470 {
471     return angleTolerance_;
472 }
473 
CuspLimit(float angleValue)474 void CubicBezierCurveDividOperate::CuspLimit(float angleValue)
475 {
476     cuspLimit_ = (angleValue == 0.0f) ? 0.0f : PI - angleValue;
477 }
478 
CuspLimit() const479 float CubicBezierCurveDividOperate::CuspLimit() const
480 {
481     return (cuspLimit_ == 0.0f) ? 0.0f : PI - cuspLimit_;
482 }
483 
Rewind(uint32_t)484 void CubicBezierCurveDividOperate::Rewind(uint32_t)
485 {
486     count_ = 0;
487 }
488 
GenerateVertex(float * x,float * y)489 uint32_t CubicBezierCurveDividOperate::GenerateVertex(float* x, float* y)
490 {
491     if (count_ >= points_.Size()) {
492         return PATH_CMD_STOP;
493     }
494     const PointF& p = points_[count_++];
495     *x = p.x;
496     *y = p.y;
497     return (count_ == 1) ? PATH_CMD_MOVE_TO : PATH_CMD_LINE_TO;
498 }
499 
Recursive(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,uint32_t level)500 void CubicBezierCurveDividOperate::Recursive(float x1, float y1,
501                                              float x2, float y2,
502                                              float x3, float y3,
503                                              float x4, float y4,
504                                              uint32_t level)
505 {
506     if (level > CURVE_RECURSION_LIMIT) {
507         return;
508     }
509 
510     /** Calculates All Midpoints Of a Segment */
511     float x12 = (x1 + x2) / FLOATNUM;
512     float y12 = (y1 + y2) / FLOATNUM;
513     float x23 = (x2 + x3) / FLOATNUM;
514     float y23 = (y2 + y3) / FLOATNUM;
515     float x34 = (x3 + x4) / FLOATNUM;
516     float y34 = (y3 + y4) / FLOATNUM;
517     float x123 = (x12 + x23) / FLOATNUM;
518     float y123 = (y12 + y23) / FLOATNUM;
519     float x234 = (x23 + x34) / FLOATNUM;
520     float y234 = (y23 + y34) / FLOATNUM;
521     float x1234 = (x123 + x234) / FLOATNUM;
522     float y1234 = (y123 + y234) / FLOATNUM;
523     /** Try to Approximate the Entire Cubic Curve With a Straight Line */
524     float delta41X = x4 - x1;
525     float delta41Y = y4 - y1;
526     float delta2 = MATH_ABS(((x2 - x4) * delta41Y - (y2 - y4) * delta41X));
527     float delta3 = MATH_ABS(((x3 - x4) * delta41Y - (y3 - y4) * delta41X));
528     float dxTemp;
529     float dyTemp;
530     float delta41;
531     const float epsilon = 1e-6f;
532 
533     bool isEnabled = true;
534     switch ((int32_t(delta2 > CURVE_COLLINEARITY_EPSILON) << 1) + int32_t(delta3 > CURVE_COLLINEARITY_EPSILON)) {
535         case COLLINEAR:
536             /** All are Collinear or p1 == p4 */
537             delta41 = delta41X * delta41X + delta41Y * delta41Y;
538             if (std::fabs(delta41) < epsilon) {
539                 delta2 = CalcSqDistance(x1, y1, x2, y2);
540                 delta3 = CalcSqDistance(x4, y4, x3, y3);
541             } else {
542                 delta41 = 1 / delta41;
543                 dxTemp = x2 - x1;
544                 dyTemp = y2 - y1;
545                 delta2 = delta41 * (dxTemp * delta41X + dyTemp * delta41Y);
546                 dxTemp = x3 - x1;
547                 dyTemp = y3 - y1;
548                 delta3 = delta41 * (dxTemp * delta41X + dyTemp * delta41Y);
549                 if (delta2 > 0 && delta2 < 1 && delta3 > 0 && delta3 < 1) {
550                     /** Simple Collinear Case,1--2--3--4 */
551                     /** We Can Leave Only Two Endpoints */
552                     return;
553                 }
554 
555                 if (delta2 <= 0) {
556                     delta2 = CalcSqDistance(x2, y2, x1, y1);
557                 } else if (delta2 >= 1) {
558                     delta2 = CalcSqDistance(x2, y2, x4, y4);
559                 } else {
560                     delta2 = CalcSqDistance(x2, y2, x1 + delta2 * delta41X, y1 + delta2 * delta41Y);
561                 }
562                 if (delta3 <= 0) {
563                     delta3 = CalcSqDistance(x3, y3, x1, y1);
564                 } else if (delta3 >= 1) {
565                     delta3 = CalcSqDistance(x3, y3, x4, y4);
566                 } else {
567                     delta3 = CalcSqDistance(x3, y3, x1 + delta3 * delta41X, y1 + delta3 * delta41Y);
568                 }
569             }
570 
571             if (delta2 > delta3) {
572                 if (delta2 < distanceToleranceSquare_) {
573                     points_.PushBack(PointF(x2, y2));
574                     isEnabled = false;
575                 }
576             } else {
577                 if (delta3 < distanceToleranceSquare_) {
578                     points_.PushBack(PointF(x3, y3));
579                     isEnabled = false;
580                 }
581             }
582             break;
583         case COLLINEAR1:
584             /** p1、p2、p4 is Collinear */
585             if (delta3 * delta3 <= distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
586                 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
587                     points_.PushBack(PointF(x23, y23));
588                     isEnabled = false;
589                 }
590                 if (isEnabled) {
591                     dxTemp = MATH_ABS(FastAtan2F(y4 - y3, x4 - x3) - FastAtan2F(y3 - y2, x3 - x2));
592                     if (dxTemp >= PI) {
593                         dxTemp = FLOATNUM * PI - dxTemp;
594                     }
595                     if (dxTemp < angleTolerance_) {
596                         points_.PushBack(PointF(x2, y2));
597                         points_.PushBack(PointF(x3, y3));
598                         isEnabled = false;
599                     }
600                     if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
601                         points_.PushBack(PointF(x3, y3));
602                         isEnabled = false;
603                     }
604                 }
605             }
606             break;
607         case COLLINEAR2:
608             /** p1、p3、p4 is Collinear. */
609             if (delta2 * delta2 <= distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
610                 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
611                     points_.PushBack(PointF(x23, y23));
612                     isEnabled = false;
613                 }
614                 if (isEnabled) {
615                     dxTemp = MATH_ABS(FastAtan2F(y3 - y2, x3 - x2) - FastAtan2F(y2 - y1, x2 - x1));
616                     if (dxTemp >= PI) {
617                         dxTemp = FLOATNUM * PI - dxTemp;
618                     }
619                     if (dxTemp < angleTolerance_) {
620                         points_.PushBack(PointF(x2, y2));
621                         points_.PushBack(PointF(x3, y3));
622                         isEnabled = false;
623                     }
624                     if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
625                         points_.PushBack(PointF(x2, y2));
626                         isEnabled = false;
627                     }
628                 }
629             }
630             break;
631         case COLLINEAR3:
632             if ((delta2 + delta3) * (delta2 + delta3) <=
633                     distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
634                 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
635                     points_.PushBack(PointF(x23, y23));
636                     isEnabled = false;
637                 }
638                 delta41 = FastAtan2F(y3 - y2, x3 - x2);
639                 dxTemp = MATH_ABS(delta41 - FastAtan2F(y2 - y1, x2 - x1));
640                 dyTemp = MATH_ABS(FastAtan2F(y4 - y3, x4 - x3) - delta41);
641                 if (dxTemp >= PI) {
642                     dxTemp = FLOATNUM * PI - dxTemp;
643                 }
644                 if (dyTemp >= PI) {
645                     dyTemp = FLOATNUM * PI - dyTemp;
646                 }
647                 if (isEnabled) {
648                     if (dxTemp + dyTemp < angleTolerance_) {
649                         points_.PushBack(PointF(x23, y23));
650                         isEnabled = false;
651                     }
652                     if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
653                         points_.PushBack(PointF(x2, y2));
654                         isEnabled = false;
655                     }
656                     if (isEnabled && cuspLimit_ != 0.0f && dyTemp > cuspLimit_) {
657                         points_.PushBack(PointF(x3, y3));
658                         isEnabled = false;
659                     }
660                 }
661             }
662             break;
663     }
664     if (!isEnabled) {
665         return;
666     }
667     Recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
668     Recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
669 }
670 
Bezier(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)671 void CubicBezierCurveDividOperate::Bezier(float x1, float y1,
672                                           float x2, float y2,
673                                           float x3, float y3,
674                                           float x4, float y4)
675 {
676     points_.PushBack(PointF(x1, y1));
677     Recursive(x1, y1, x2, y2, x3, y3, x4, y4, 0);
678     points_.PushBack(PointF(x4, y4));
679 }
680 } // namespace OHOS
681