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