• 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 
532     bool isEnabled = true;
533     switch ((int32_t(delta2 > CURVE_COLLINEARITY_EPSILON) << 1) + int32_t(delta3 > CURVE_COLLINEARITY_EPSILON)) {
534         case COLLINEAR:
535             /** All are Collinear or p1 == p4 */
536             delta41 = delta41X * delta41X + delta41Y * delta41Y;
537             if (delta41 == 0) {
538                 delta2 = CalcSqDistance(x1, y1, x2, y2);
539                 delta3 = CalcSqDistance(x4, y4, x3, y3);
540             } else {
541                 delta41 = 1 / delta41;
542                 dxTemp = x2 - x1;
543                 dyTemp = y2 - y1;
544                 delta2 = delta41 * (dxTemp * delta41X + dyTemp * delta41Y);
545                 dxTemp = x3 - x1;
546                 dyTemp = y3 - y1;
547                 delta3 = delta41 * (dxTemp * delta41X + dyTemp * delta41Y);
548                 if (delta2 > 0 && delta2 < 1 && delta3 > 0 && delta3 < 1) {
549                     /** Simple Collinear Case,1--2--3--4 */
550                     /** We Can Leave Only Two Endpoints */
551                     return;
552                 }
553 
554                 if (delta2 <= 0) {
555                     delta2 = CalcSqDistance(x2, y2, x1, y1);
556                 } else if (delta2 >= 1) {
557                     delta2 = CalcSqDistance(x2, y2, x4, y4);
558                 } else {
559                     delta2 = CalcSqDistance(x2, y2, x1 + delta2 * delta41X, y1 + delta2 * delta41Y);
560                 }
561                 if (delta3 <= 0) {
562                     delta3 = CalcSqDistance(x3, y3, x1, y1);
563                 } else if (delta3 >= 1) {
564                     delta3 = CalcSqDistance(x3, y3, x4, y4);
565                 } else {
566                     delta3 = CalcSqDistance(x3, y3, x1 + delta3 * delta41X, y1 + delta3 * delta41Y);
567                 }
568             }
569 
570             if (delta2 > delta3) {
571                 if (delta2 < distanceToleranceSquare_) {
572                     points_.PushBack(PointF(x2, y2));
573                     isEnabled = false;
574                 }
575             } else {
576                 if (delta3 < distanceToleranceSquare_) {
577                     points_.PushBack(PointF(x3, y3));
578                     isEnabled = false;
579                 }
580             }
581             break;
582         case COLLINEAR1:
583             /** p1、p2、p4 is Collinear */
584             if (delta3 * delta3 <= distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
585                 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
586                     points_.PushBack(PointF(x23, y23));
587                     isEnabled = false;
588                 }
589                 if (isEnabled) {
590                     dxTemp = MATH_ABS(FastAtan2F(y4 - y3, x4 - x3) - FastAtan2F(y3 - y2, x3 - x2));
591                     if (dxTemp >= PI) {
592                         dxTemp = FLOATNUM * PI - dxTemp;
593                     }
594                     if (dxTemp < angleTolerance_) {
595                         points_.PushBack(PointF(x2, y2));
596                         points_.PushBack(PointF(x3, y3));
597                         isEnabled = false;
598                     }
599                     if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
600                         points_.PushBack(PointF(x3, y3));
601                         isEnabled = false;
602                     }
603                 }
604             }
605             break;
606         case COLLINEAR2:
607             /** p1、p3、p4 is Collinear. */
608             if (delta2 * delta2 <= distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
609                 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
610                     points_.PushBack(PointF(x23, y23));
611                     isEnabled = false;
612                 }
613                 if (isEnabled) {
614                     dxTemp = MATH_ABS(FastAtan2F(y3 - y2, x3 - x2) - FastAtan2F(y2 - y1, x2 - x1));
615                     if (dxTemp >= PI) {
616                         dxTemp = FLOATNUM * PI - dxTemp;
617                     }
618                     if (dxTemp < angleTolerance_) {
619                         points_.PushBack(PointF(x2, y2));
620                         points_.PushBack(PointF(x3, y3));
621                         isEnabled = false;
622                     }
623                     if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
624                         points_.PushBack(PointF(x2, y2));
625                         isEnabled = false;
626                     }
627                 }
628             }
629             break;
630         case COLLINEAR3:
631             if ((delta2 + delta3) * (delta2 + delta3) <=
632                     distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
633                 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
634                     points_.PushBack(PointF(x23, y23));
635                     isEnabled = false;
636                 }
637                 delta41 = FastAtan2F(y3 - y2, x3 - x2);
638                 dxTemp = MATH_ABS(delta41 - FastAtan2F(y2 - y1, x2 - x1));
639                 dyTemp = MATH_ABS(FastAtan2F(y4 - y3, x4 - x3) - delta41);
640                 if (dxTemp >= PI) {
641                     dxTemp = FLOATNUM * PI - dxTemp;
642                 }
643                 if (dyTemp >= PI) {
644                     dyTemp = FLOATNUM * PI - dyTemp;
645                 }
646                 if (isEnabled) {
647                     if (dxTemp + dyTemp < angleTolerance_) {
648                         points_.PushBack(PointF(x23, y23));
649                         isEnabled = false;
650                     }
651                     if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
652                         points_.PushBack(PointF(x2, y2));
653                         isEnabled = false;
654                     }
655                     if (isEnabled && cuspLimit_ != 0.0f && dyTemp > cuspLimit_) {
656                         points_.PushBack(PointF(x3, y3));
657                         isEnabled = false;
658                     }
659                 }
660             }
661             break;
662     }
663     if (!isEnabled) {
664         return;
665     }
666     Recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
667     Recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
668 }
669 
Bezier(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)670 void CubicBezierCurveDividOperate::Bezier(float x1, float y1,
671                                           float x2, float y2,
672                                           float x3, float y3,
673                                           float x4, float y4)
674 {
675     points_.PushBack(PointF(x1, y1));
676     Recursive(x1, y1, x2, y2, x3, y3, x4, y4, 0);
677     points_.PushBack(PointF(x4, y4));
678 }
679 } // namespace OHOS
680