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_triangle.h" 17#include "draw/draw_utils.h" 18 19namespace OHOS { 20void DrawTriangle::Draw(BufferInfo& gfxDstBuffer, 21 const Point* points, 22 uint8_t count, 23 const Rect& mask, 24 const ColorType& color, 25 OpacityType opa) 26{ 27 if ((points == nullptr) || (count != VERTEX_NUM)) { 28 return; 29 } 30 // sort vertex according to y axis 31 Point p1 = points[0]; // 0: point index 32 Point p2 = points[1]; // 1: point index 33 Point p3 = points[2]; // 2: point index 34 // return if vertexs are invalid. 35 if ((p1.x == p2.x) && ((p1.y == p2.y) || (p1.x == p3.x))) { 36 return; 37 } 38 if ((p2.x == p3.x) && (p2.y == p3.y)) { 39 return; 40 } 41 if (((p1.x == p3.x) || (p1.y == p2.y)) && (p1.y == p3.y)) { 42 return; 43 } 44 SortVertexs(p1, p2, p3); 45 Edge edge1 = InitEdge(p1, p2); 46 Edge edge2 = InitEdge(p1, p3); 47 Rect area; 48 int16_t lastY = p1.y; 49 50 while (edge1.curPoint.y <= p3.y) { 51 // change edge1 from p1-p2 to p2-p3 52 if (edge1.curPoint.y == p2.y) { 53 edge1 = InitEdge(p2, p3); 54 if (edge1.dPoint.y == 0) { 55 return; 56 } 57 } 58 59 area.SetLeft(MATH_MIN(edge1.curPoint.x, edge2.curPoint.x)); 60 area.SetRight(MATH_MAX(edge1.curPoint.x, edge2.curPoint.x)); 61 area.SetTop(MATH_MIN(edge1.curPoint.y, edge2.curPoint.y)); 62 area.SetBottom(MATH_MAX(edge1.curPoint.y, edge2.curPoint.y)); 63 DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, area, mask, color, opa); 64 65 while (edge1.curPoint.y == lastY) { 66 // use Bresenham algorithm to get next point on edge1 67 StepToNextPointOnEdge(edge1); 68 } 69 while (edge2.curPoint.y == lastY) { 70 // use Bresenham algorithm to get next point on edge2 71 StepToNextPointOnEdge(edge2); 72 } 73 lastY = edge1.curPoint.y; 74 } 75} 76 77void DrawTriangle::SortVertexs(Point& p1, Point& p2, Point& p3) 78{ 79 SortPoint(p1, p2); 80 SortPoint(p2, p3); 81 SortPoint(p1, p2); 82} 83 84void DrawTriangle::SortPoint(Point& p1, Point& p2) 85{ 86 Point temp; 87 if (p1.y > p2.y) { 88 temp = p1; 89 p1 = p2; 90 p2 = temp; 91 } 92} 93 94void DrawTriangle::StepToNextPointOnEdge(Edge& edge) 95{ 96 if (edge.dPoint.x > edge.dPoint.y) { 97 edge.curPoint.x += edge.uPoint.x; 98 edge.eps += edge.dPoint.y; 99 if ((edge.eps << 1) >= edge.dPoint.x) { 100 edge.curPoint.y += edge.uPoint.y; 101 edge.eps -= edge.dPoint.x; 102 } 103 } else { 104 edge.curPoint.y += edge.uPoint.y; 105 edge.eps += edge.dPoint.x; 106 if ((edge.eps << 1) >= edge.dPoint.y) { 107 edge.curPoint.x += edge.uPoint.x; 108 edge.eps -= edge.dPoint.y; 109 } 110 } 111} 112 113DrawTriangle::Edge DrawTriangle::InitEdge(const Point& startP, const Point& endP) 114{ 115 Edge edge = { {0, 0}, {0, 0}, {0, 0}, 0 }; 116 edge.curPoint = startP; 117 edge.dPoint.x = startP.x - endP.x; 118 edge.dPoint.y = startP.y - endP.y; 119 edge.uPoint.x = (edge.dPoint.x < 0) ? 1 : -1; 120 edge.uPoint.y = (edge.dPoint.y < 0) ? 1 : -1; 121 edge.eps = 0; 122 edge.dPoint.x = MATH_ABS(edge.dPoint.x); 123 edge.dPoint.y = MATH_ABS(edge.dPoint.y); 124 return edge; 125} 126} // namespace OHOS 127