1 /*
2  * Copyright (c) 2020-2021 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 "draw/draw_arc.h"
17 #include "common/image.h"
18 #include "gfx_utils/graphic_math.h"
19 
20 namespace OHOS {
21 #define IS_IN_DEGREERANE(d, s, e) ((s) <= (e)) ? (((d) >= (s)) && ((d) <= (e))) : (((d) >= (s)) || ((d) <= (e)))
GetInstance()22 DrawArc* DrawArc::GetInstance()
23 {
24     static DrawArc drawArc;
25     return &drawArc;
26 }
27 
DrawImg(BufferInfo & gfxDstBuffer,const Point & imgPos,Rect & area,const Rect & invalidatedArea,const Style & style,uint8_t opaScale,const Image * image)28 void DrawArc::DrawImg(BufferInfo& gfxDstBuffer,
29                       const Point& imgPos,
30                       Rect& area,
31                       const Rect& invalidatedArea,
32                       const Style& style,
33                       uint8_t opaScale,
34                       const Image* image)
35 {
36     if (image == nullptr) {
37         return;
38     }
39     ImageHeader header = {0};
40     image->GetHeader(header);
41 
42     Rect cordsTmp;
43     cordsTmp.SetPosition(imgPos.x, imgPos.y);
44     cordsTmp.SetHeight(header.height);
45     cordsTmp.SetWidth(header.width);
46     if (area.Intersect(area, invalidatedArea)) {
47         image->DrawImage(gfxDstBuffer, cordsTmp, area, style, opaScale);
48     }
49 }
50 
DrawVerLine(BufferInfo & gfxDstBuffer,const Point & begin,const Point & imgPos,const Rect & mask,int16_t len,const Style & style,uint8_t opaScale,const Image * image)51 void DrawArc::DrawVerLine(BufferInfo& gfxDstBuffer,
52                           const Point& begin,
53                           const Point& imgPos,
54                           const Rect& mask,
55                           int16_t len,
56                           const Style& style,
57                           uint8_t opaScale,
58                           const Image* image)
59 {
60     Rect rect(begin.x, begin.y, begin.x, begin.y + len);
61     if ((image != nullptr) && (image->GetSrcType() != IMG_SRC_UNKNOWN)) {
62         DrawImg(gfxDstBuffer, imgPos, rect, mask, style, opaScale, image);
63     } else {
64         DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, rect, mask, style.lineColor_, opaScale);
65     }
66 }
67 
DrawHorLine(BufferInfo & gfxDstBuffer,const Point & begin,const Point & imgPos,const Rect & mask,int16_t len,const Style & style,uint8_t opaScale,const Image * image)68 void DrawArc::DrawHorLine(BufferInfo& gfxDstBuffer,
69                           const Point& begin,
70                           const Point& imgPos,
71                           const Rect& mask,
72                           int16_t len,
73                           const Style& style,
74                           uint8_t opaScale,
75                           const Image* image)
76 {
77     if ((image != nullptr) && (image->GetSrcType() != IMG_SRC_UNKNOWN)) {
78         Rect rect(begin.x, begin.y, begin.x + len, begin.y);
79         DrawImg(gfxDstBuffer, imgPos, rect, mask, style, opaScale, image);
80     } else {
81         if (len == 0) {
82             DrawUtils::GetInstance()->DrawPixel(gfxDstBuffer, begin.x, begin.y, mask, style.lineColor_, opaScale);
83         } else {
84             Rect rect(begin.x, begin.y, begin.x + len, begin.y);
85             DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, rect, mask, style.lineColor_, opaScale);
86         }
87     }
88 }
89 
GetDrawAngle(int16_t angle)90 int16_t DrawArc::GetDrawAngle(int16_t angle)
91 {
92     if (angle < 0) {
93         angle = (angle % CIRCLE_IN_DEGREE) + CIRCLE_IN_DEGREE;
94     } else if (angle > CIRCLE_IN_DEGREE) {
95         angle = angle % CIRCLE_IN_DEGREE;
96     }
97     return angle;
98 }
99 
GetDrawRange(int16_t & start,int16_t & end)100 void DrawArc::GetDrawRange(int16_t& start, int16_t& end)
101 {
102     int16_t tempAngle = GetDrawAngle(start);
103     if (start == end) {
104         start = tempAngle;
105         end = tempAngle;
106     } else if (end - start >= CIRCLE_IN_DEGREE) {
107         // draw circle
108         start = 0;
109         end = CIRCLE_IN_DEGREE;
110     } else {
111         start = tempAngle;
112         end = GetDrawAngle(end);
113     }
114 }
115 
CalculateTanDegree(uint16_t x,uint16_t y)116 uint16_t DrawArc::CalculateTanDegree(uint16_t x, uint16_t y)
117 {
118     uint16_t degree = FastAtan2(x, y);
119     if ((degree == QUARTER_IN_DEGREE) && (y != 0)) {
120         degree--;
121     }
122     if ((degree == 0) && (x != 0)) {
123         degree++;
124     }
125     return degree;
126 }
127 
DrawCircleNoEndpoint(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,const Rect & mask,const Style & style,uint8_t opa,bool anti)128 void DrawArc::DrawCircleNoEndpoint(BufferInfo& gfxDstBuffer,
129                                    ArcInfo& arcInfo,
130                                    const Rect& mask,
131                                    const Style& style,
132                                    uint8_t opa,
133                                    bool anti)
134 {
135     DrawAxisLine(gfxDstBuffer, arcInfo, mask, style, opa);
136 
137     int16_t yStart = mask.GetTop() - arcInfo.center.y;
138     int16_t yEnd = mask.GetBottom() - arcInfo.center.y;
139     CalculatedYStartAndYEnd(yStart, yEnd);
140 
141     int16_t xLineStart = -outRadius_;
142     int16_t xLineStart2 = xLineStart - 1;
143     int16_t xLineStart3 = COORD_MIN;
144 
145     for (y_ = yEnd; y_ > yStart; y_--) {
146         ySqr_ = static_cast<int32_t>(y_) * y_;
147         bool isSetStartPot = false;
148         for (int16_t xi = xLineStart2; xi < 0; xi++) {
149             uint32_t currentSqr = static_cast<int32_t>(xi) * xi + ySqr_;
150             if (currentSqr > outRadiusSqr_) {
151                 continue;
152             }
153             if (!isSetStartPot) {
154                 xLineStart2 = xi;
155                 lineStart_ = xi;
156                 if (xLineStart3 != COORD_MIN) {
157                     xi = xLineStart3;
158                 }
159                 isSetStartPot = true;
160             }
161             if (y_ <= -inRadius_) {
162                 lineEnd_ = -1;
163                 break;
164             }
165             if (currentSqr < inRadiusSqr_) {
166                 xLineStart3 = xi - 1;
167                 lineEnd_ = xi - 1;
168                 break;
169             }
170         }
171         if (!isSetStartPot) {
172             continue;
173         }
174 #if defined(ENABLE_ANTIALIAS) && ENABLE_ANTIALIAS
175         if (anti) {
176             DrawLineAnti(gfxDstBuffer, arcInfo, mask, style, opa);
177         }
178 #endif
179         DrawLineWithDegree(gfxDstBuffer, arcInfo, -lineEnd_, -lineStart_, y_, mask, style, opa, ARC_QUADRANT_ONE);
180 
181         DrawLineWithDegree(gfxDstBuffer, arcInfo, -lineEnd_, -lineStart_, -y_, mask, style, opa, ARC_QUADRANT_TWO);
182 
183         DrawLineWithDegree(gfxDstBuffer, arcInfo, lineStart_, lineEnd_, -y_, mask, style, opa, ARC_QUADRANT_THREE);
184 
185         DrawLineWithDegree(gfxDstBuffer, arcInfo, lineStart_, lineEnd_, y_, mask, style, opa, ARC_QUADRANT_FOUR);
186     }
187 }
188 
CalculatedYStartAndYEnd(int16_t & yStart,int16_t & yEnd)189 void DrawArc::CalculatedYStartAndYEnd(int16_t& yStart, int16_t& yEnd)
190 {
191     if ((yStart >= 0) && (yEnd >= 0)) {
192         int16_t tmp = yStart;
193         yStart = -yEnd;
194         yEnd = -tmp;
195     } else if ((yStart < 0) && (yEnd > 0)) {
196         yStart = MATH_MIN(yStart, -yEnd);
197         yEnd = -1;
198     }
199     yStart = MATH_MAX(yStart, -outRadius_) - 1;
200     yEnd = MATH_MIN(yEnd, -1);
201 }
202 
DrawAxisLine(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,const Rect & mask,const Style & style,uint8_t opa)203 void DrawArc::DrawAxisLine(BufferInfo& gfxDstBuffer,
204                            ArcInfo& arcInfo,
205                            const Rect& mask,
206                            const Style& style,
207                            uint8_t opa)
208 {
209     int16_t lineWidth = 0;
210     int16_t outRadius = outRadius_ - 1;
211     int16_t inRadius = inRadius_;
212     if (inRadius <= 0) {
213         inRadius = 1;
214         DrawHorLine(gfxDstBuffer, arcInfo.center, arcInfo.imgPos, mask, 0, style, opa, arcInfo.imgSrc);
215     }
216     lineWidth = outRadius - inRadius;
217 
218     if (isCircle_ || (IS_IN_DEGREERANE(THREE_QUARTER_IN_DEGREE, arcInfo.startAngle, arcInfo.endAngle))) {
219         DrawHorLine(gfxDstBuffer, Point { static_cast<int16_t>(arcInfo.center.x - outRadius), arcInfo.center.y },
220                     arcInfo.imgPos, mask, lineWidth, style, opa, arcInfo.imgSrc);
221     }
222 
223     if (isCircle_ || (IS_IN_DEGREERANE(QUARTER_IN_DEGREE, arcInfo.startAngle, arcInfo.endAngle))) {
224         DrawHorLine(gfxDstBuffer, Point { static_cast<int16_t>(arcInfo.center.x + inRadius), arcInfo.center.y },
225                     arcInfo.imgPos, mask, lineWidth, style, opa, arcInfo.imgSrc);
226     }
227 
228     if (isCircle_ || (IS_IN_DEGREERANE(0, arcInfo.startAngle, arcInfo.endAngle))) {
229         DrawVerLine(gfxDstBuffer, Point { arcInfo.center.x, static_cast<int16_t>(arcInfo.center.y - outRadius) },
230                     arcInfo.imgPos, mask, lineWidth, style, opa, arcInfo.imgSrc);
231     }
232 
233     if (isCircle_ || (IS_IN_DEGREERANE(SEMICIRCLE_IN_DEGREE, arcInfo.startAngle, arcInfo.endAngle))) {
234         DrawVerLine(gfxDstBuffer, Point { arcInfo.center.x, static_cast<int16_t>(arcInfo.center.y + inRadius) },
235                     arcInfo.imgPos, mask, lineWidth, style, opa, arcInfo.imgSrc);
236     }
237 }
238 
DrawLineWithDegree(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,int16_t start,int16_t end,int16_t y,const Rect & mask,const Style & style,uint8_t opaScale,uint8_t quadrant)239 void DrawArc::DrawLineWithDegree(BufferInfo& gfxDstBuffer,
240                                  ArcInfo& arcInfo,
241                                  int16_t start,
242                                  int16_t end,
243                                  int16_t y,
244                                  const Rect& mask,
245                                  const Style& style,
246                                  uint8_t opaScale,
247                                  uint8_t quadrant)
248 {
249     if (isCircle_) {
250         DrawHorLine(gfxDstBuffer,
251                     Point {static_cast<int16_t>(arcInfo.center.x + start), static_cast<int16_t>(arcInfo.center.y + y)},
252                     arcInfo.imgPos, mask, end - start, style, opaScale, arcInfo.imgSrc);
253         return;
254     }
255     uint16_t degreeStart = GetDegreeInQuadrant(CalculateTanDegree(MATH_ABS(start), MATH_ABS(y)), quadrant);
256     uint16_t degreeEnd = GetDegreeInQuadrant(CalculateTanDegree(MATH_ABS(end), MATH_ABS(y)), quadrant);
257     if (degreeStart > degreeEnd) {
258         uint16_t tmp = degreeStart;
259         degreeStart = degreeEnd;
260         degreeEnd = tmp;
261     }
262 
263     int16_t lineDegreeRet = GetDegreeRangeIntersectState(degreeStart, degreeEnd, arcInfo.startAngle, arcInfo.endAngle);
264     int16_t drawEnd = 0;
265     switch (lineDegreeRet) {
266         case OUT_DEGREE_RANG:
267             return;
268         case IN_DEGREE_RANG:
269             DrawHorLine(gfxDstBuffer,
270                 Point { static_cast<int16_t>(arcInfo.center.x + start), static_cast<int16_t>(arcInfo.center.y + y) },
271                 arcInfo.imgPos, mask, end - start, style, opaScale, arcInfo.imgSrc);
272             return;
273         case INTERSECT:
274             DrawLineWithDegreeInner(gfxDstBuffer, arcInfo, start, end, y, mask, style, opaScale, quadrant);
275             return;
276         case DOUBLE_INTERSECT:
277             drawEnd = DrawLineWithDegreeInner(gfxDstBuffer, arcInfo, start, end, y, mask, style, opaScale, quadrant);
278             DrawLineWithDegreeInner(gfxDstBuffer, arcInfo, drawEnd + 1, end, y, mask, style, opaScale, quadrant);
279             return;
280         default:
281             return;
282     }
283 }
284 
DrawLineWithDegreeInner(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,int16_t start,int16_t end,int16_t y,const Rect & mask,const Style & style,uint8_t opaScale,uint8_t quadrant)285 int16_t DrawArc::DrawLineWithDegreeInner(BufferInfo& gfxDstBuffer,
286                                          ArcInfo& arcInfo,
287                                          int16_t start,
288                                          int16_t end,
289                                          int16_t y,
290                                          const Rect& mask,
291                                          const Style& style,
292                                          uint8_t opaScale,
293                                          uint8_t quadrant)
294 {
295     int16_t drawStart = COORD_MIN;
296     int16_t drawEnd = COORD_MIN;
297     for (int16_t xi = start; xi <= end; xi++) {
298         uint16_t degreeBase = CalculateTanDegree(MATH_ABS(xi), MATH_ABS(y));
299         uint16_t degree = GetDegreeInQuadrant(degreeBase, quadrant);
300         if (IS_IN_DEGREERANE(degree, arcInfo.startAngle, arcInfo.endAngle)) {
301             if (drawStart == COORD_MIN) {
302                 drawStart = xi;
303             }
304         } else {
305             if ((drawStart != COORD_MIN) && (drawEnd == COORD_MIN)) {
306                 drawEnd = xi - 1;
307                 break;
308             }
309         }
310     }
311     if (drawEnd == COORD_MIN) {
312         drawEnd = end;
313     }
314     if ((drawStart != COORD_MIN) && (drawEnd != COORD_MIN)) {
315         DrawHorLine(gfxDstBuffer,
316             Point { static_cast<int16_t>(arcInfo.center.x + drawStart), static_cast<int16_t>(arcInfo.center.y + y) },
317             arcInfo.imgPos, mask, drawEnd - drawStart, style, opaScale, arcInfo.imgSrc);
318     }
319     return drawEnd;
320 }
321 
322 #if ENABLE_ANTIALIAS
DrawLineAnti(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,const Rect & mask,const Style & style,uint8_t opa)323 void DrawArc::DrawLineAnti(BufferInfo& gfxDstBuffer, ArcInfo& arcInfo, const Rect& mask,
324                            const Style& style, uint8_t opa)
325 {
326     outAntiStart_ = lineStart_;
327     outAntiEnd_ = lineStart_;
328     inAntiStart_ = lineEnd_ + 1;
329     inAntiEnd_ = COORD_MIN;
330 
331     for (int16_t xAnti = lineStart_; xAnti <= lineEnd_; xAnti++) {
332         uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
333         if ((currentSqr <= antiOutRadiusSqr_) || (xAnti == lineEnd_)) {
334             lineStart_ = xAnti;
335             outAntiEnd_ = xAnti - 1;
336             break;
337         }
338     }
339 
340     for (int16_t xAnti = lineEnd_ + 1; xAnti <= -1; xAnti++) {
341         uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
342         if ((currentSqr <= antiInRadiusSqr_) || (xAnti == -1)) {
343             inAntiEnd_ = xAnti;
344             break;
345         }
346     }
347 
348     for (int16_t xAnti = outAntiStart_; xAnti <= outAntiEnd_; xAnti++) {
349         uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
350         uint8_t antiOpa =
351             (((static_cast<uint64_t>(outRadius_) << 1) - 1 - (currentSqr - antiOutRadiusSqr_)) * OPA_OPAQUE) /
352             ((outRadius_ << 1) - 1);
353         antiOpa = (opa == OPA_OPAQUE) ? antiOpa : (static_cast<uint16_t>(antiOpa) * opa) >> SHIFT_8;
354         DrawPointAnti(gfxDstBuffer, arcInfo, xAnti, mask, style, antiOpa);
355     }
356 
357     for (int16_t xAnti = inAntiStart_; xAnti <= inAntiEnd_; xAnti++) {
358         uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
359         if (currentSqr <= antiInRadiusSqr_) {
360             break;
361         }
362         uint8_t antiOpa = (static_cast<uint64_t>(currentSqr - antiInRadiusSqr_) * OPA_OPAQUE) / ((inRadius_ << 1) - 1);
363         antiOpa = (opa == OPA_OPAQUE) ? antiOpa : (static_cast<uint16_t>(antiOpa) * opa) >> SHIFT_8;
364         DrawPointAnti(gfxDstBuffer, arcInfo, xAnti, mask, style, antiOpa);
365     }
366 }
367 
DrawPointAnti(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,int16_t x,const Rect & mask,const Style & style,uint8_t antiOpa)368 void DrawArc::DrawPointAnti(BufferInfo& gfxDstBuffer, ArcInfo& arcInfo, int16_t x, const Rect& mask,
369                             const Style& style, uint8_t antiOpa)
370 {
371     int16_t startX;
372     int16_t starty;
373     uint16_t degreeBase = CalculateTanDegree(MATH_ABS(x), MATH_ABS(y_));
374     if (isCircle_ || (IS_IN_DEGREERANE(CIRCLE_IN_DEGREE - degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
375         startX = arcInfo.center.x + x;
376         starty = arcInfo.center.y + y_;
377         DrawHorLine(gfxDstBuffer, Point { startX, starty }, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
378     }
379     if (isCircle_ || (IS_IN_DEGREERANE(SEMICIRCLE_IN_DEGREE + degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
380         startX = arcInfo.center.x + x;
381         starty = arcInfo.center.y - y_;
382         DrawHorLine(gfxDstBuffer, Point { startX, starty }, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
383     }
384     if (isCircle_ || (IS_IN_DEGREERANE(degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
385         startX = arcInfo.center.x - x;
386         starty = arcInfo.center.y + y_;
387         DrawHorLine(gfxDstBuffer, Point { startX, starty }, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
388     }
389     if (isCircle_ || (IS_IN_DEGREERANE(SEMICIRCLE_IN_DEGREE - degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
390         startX = arcInfo.center.x - x;
391         starty = arcInfo.center.y - y_;
392         DrawHorLine(gfxDstBuffer, Point { startX, starty }, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
393     }
394 }
395 #endif
396 
GetDegreeInQuadrant(uint16_t degree,uint8_t quadrant)397 uint16_t DrawArc::GetDegreeInQuadrant(uint16_t degree, uint8_t quadrant)
398 {
399     switch (quadrant) {
400         case ARC_QUADRANT_ONE:
401             return degree;
402         case ARC_QUADRANT_TWO:
403             return SEMICIRCLE_IN_DEGREE - degree;
404         case ARC_QUADRANT_THREE:
405             return SEMICIRCLE_IN_DEGREE + degree;
406         case ARC_QUADRANT_FOUR:
407             return CIRCLE_IN_DEGREE - degree;
408         default:
409             return degree;
410     }
411 }
412 
Draw(BufferInfo & gfxDstBuffer,ArcInfo & arcInfo,const Rect & mask,const Style & style,uint8_t opaScale,uint8_t cap)413 void DrawArc::Draw(BufferInfo& gfxDstBuffer, ArcInfo& arcInfo, const Rect& mask,
414                    const Style& style, uint8_t opaScale, uint8_t cap)
415 {
416     OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.lineOpa_);
417     if ((opa == OPA_TRANSPARENT) || (style.lineWidth_ < 1)) {
418         return;
419     }
420 
421     SetArcInfo(arcInfo, style);
422     if (arcInfo.startAngle != arcInfo.endAngle) {
423         if ((arcInfo.imgSrc != nullptr) && (arcInfo.imgSrc->GetSrcType() != IMG_SRC_UNKNOWN)) {
424             DrawCircleNoEndpoint(gfxDstBuffer, arcInfo, mask, style, opa, false);
425         } else {
426             DrawCircleNoEndpoint(gfxDstBuffer, arcInfo, mask, style, opa, true);
427         }
428     }
429 
430     if (!isCircle_ && (cap != CapType::CAP_NONE)) {
431         int16_t lineWidth = style.lineWidth_;
432         if (lineWidth > arcInfo.radius) {
433             lineWidth = arcInfo.radius;
434         }
435 
436         ArcInfo endArcInfo = arcInfo;
437         endArcInfo.startAngle = 0;
438         endArcInfo.endAngle = CIRCLE_IN_DEGREE;
439 
440         int16_t outRadius = arcInfo.radius - 1;
441         lineWidth--;
442         /* the arc radius of the round cap should be half the line width */
443         endArcInfo.radius = (static_cast<uint16_t>(lineWidth + 1) >> 1) + 1;
444 
445         /* 0.5: round up */
446         float temp = (outRadius - endArcInfo.radius + 1) * Sin(arcInfo.startAngle);
447         int16_t startCapX = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
448 
449         temp = (outRadius - endArcInfo.radius + 1) * Sin(QUARTER_IN_DEGREE - arcInfo.startAngle);
450         int16_t startCapY = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
451 
452         endArcInfo.center.x += startCapX;
453         endArcInfo.center.y -= startCapY;
454         SetArcInfo(endArcInfo, style);
455 
456         temp = (outRadius - endArcInfo.radius + 1) * Sin(arcInfo.endAngle);
457         int16_t endCapX = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
458 
459         temp = (outRadius - endArcInfo.radius + 1) * Sin(QUARTER_IN_DEGREE - arcInfo.endAngle);
460         int16_t endCapY = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
461 
462         if ((endCapX == startCapX) && (endCapY == startCapY)) {
463             if (cap != CapType::CAP_ROUND_UNSHOW) {
464                 DrawCircleNoEndpoint(gfxDstBuffer, endArcInfo, mask, style, opa, true);
465             }
466         } else {
467             DrawCircleNoEndpoint(gfxDstBuffer, endArcInfo, mask, style, opa, true);
468         }
469 
470         endArcInfo.center = arcInfo.center;
471         endArcInfo.center.x += endCapX;
472         endArcInfo.center.y -= endCapY;
473         SetArcInfo(endArcInfo, style);
474         if (endCapX != 0) {
475             DrawCircleNoEndpoint(gfxDstBuffer, endArcInfo, mask, style, opa, true);
476         } else {
477             if (cap != CapType::CAP_ROUND_UNSHOW) {
478                 DrawCircleNoEndpoint(gfxDstBuffer, endArcInfo, mask, style, opa, true);
479             }
480         }
481     }
482 }
483 
GetDegreeRangeIntersectState(uint16_t degreeStart,uint16_t degreeEnd,uint16_t start,uint16_t end)484 int16_t DrawArc::GetDegreeRangeIntersectState(uint16_t degreeStart, uint16_t degreeEnd, uint16_t start, uint16_t end)
485 {
486     if (start <= end) {
487         if ((degreeStart >= start) && (degreeStart <= end) && (degreeEnd >= start) && (degreeEnd <= end)) {
488             return IN_DEGREE_RANG;
489         } else if ((degreeEnd < start) || (degreeStart > end)) {
490             return OUT_DEGREE_RANG;
491         } else {
492             return INTERSECT;
493         }
494     } else {
495         if (((degreeStart >= start) && (degreeEnd >= start)) || ((degreeStart <= end) && (degreeEnd <= end))) {
496             return IN_DEGREE_RANG;
497         } else if ((degreeStart > end) && (degreeEnd < start)) {
498             return OUT_DEGREE_RANG;
499         } else if ((degreeStart <= end) && (degreeEnd >= start)) {
500             return DOUBLE_INTERSECT;
501         } else {
502             return INTERSECT;
503         }
504     }
505 }
506 
SetArcInfo(ArcInfo & arcInfo,const Style & style)507 void DrawArc::SetArcInfo(ArcInfo& arcInfo, const Style& style)
508 {
509     outRadius_ = arcInfo.radius;
510     inRadius_ = outRadius_ - style.lineWidth_;
511     if (inRadius_ < 0) {
512         inRadius_ = 0;
513     }
514     outRadiusSqr_ = outRadius_ * outRadius_;
515     inRadiusSqr_ = inRadius_ * inRadius_;
516 
517     if ((arcInfo.startAngle == 0) && (arcInfo.endAngle == CIRCLE_IN_DEGREE)) {
518         isCircle_ = true;
519     } else {
520         isCircle_ = false;
521     }
522 
523 #if ENABLE_ANTIALIAS
524     antiOutRadiusSqr_ = (outRadius_ - 1) * (outRadius_ - 1);
525     if (inRadius_ == 0) {
526         antiInRadiusSqr_ = 0;
527     } else {
528         antiInRadiusSqr_ = (inRadius_ - 1) * (inRadius_ - 1);
529     }
530 #endif
531 }
532 } // namespace OHOS
533