1a3e0fd82Sopenharmony_ci/* 2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License. 5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at 6a3e0fd82Sopenharmony_ci * 7a3e0fd82Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8a3e0fd82Sopenharmony_ci * 9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and 13a3e0fd82Sopenharmony_ci * limitations under the License. 14a3e0fd82Sopenharmony_ci */ 15a3e0fd82Sopenharmony_ci 16a3e0fd82Sopenharmony_ci#include "draw/draw_triangle.h" 17a3e0fd82Sopenharmony_ci#include "draw/draw_utils.h" 18a3e0fd82Sopenharmony_ci 19a3e0fd82Sopenharmony_cinamespace OHOS { 20a3e0fd82Sopenharmony_civoid DrawTriangle::Draw(BufferInfo& gfxDstBuffer, 21a3e0fd82Sopenharmony_ci const Point* points, 22a3e0fd82Sopenharmony_ci uint8_t count, 23a3e0fd82Sopenharmony_ci const Rect& mask, 24a3e0fd82Sopenharmony_ci const ColorType& color, 25a3e0fd82Sopenharmony_ci OpacityType opa) 26a3e0fd82Sopenharmony_ci{ 27a3e0fd82Sopenharmony_ci if ((points == nullptr) || (count != VERTEX_NUM)) { 28a3e0fd82Sopenharmony_ci return; 29a3e0fd82Sopenharmony_ci } 30a3e0fd82Sopenharmony_ci // sort vertex according to y axis 31a3e0fd82Sopenharmony_ci Point p1 = points[0]; // 0: point index 32a3e0fd82Sopenharmony_ci Point p2 = points[1]; // 1: point index 33a3e0fd82Sopenharmony_ci Point p3 = points[2]; // 2: point index 34a3e0fd82Sopenharmony_ci // return if vertexs are invalid. 35a3e0fd82Sopenharmony_ci if ((p1.x == p2.x) && ((p1.y == p2.y) || (p1.x == p3.x))) { 36a3e0fd82Sopenharmony_ci return; 37a3e0fd82Sopenharmony_ci } 38a3e0fd82Sopenharmony_ci if ((p2.x == p3.x) && (p2.y == p3.y)) { 39a3e0fd82Sopenharmony_ci return; 40a3e0fd82Sopenharmony_ci } 41a3e0fd82Sopenharmony_ci if (((p1.x == p3.x) || (p1.y == p2.y)) && (p1.y == p3.y)) { 42a3e0fd82Sopenharmony_ci return; 43a3e0fd82Sopenharmony_ci } 44a3e0fd82Sopenharmony_ci SortVertexs(p1, p2, p3); 45a3e0fd82Sopenharmony_ci Edge edge1 = InitEdge(p1, p2); 46a3e0fd82Sopenharmony_ci Edge edge2 = InitEdge(p1, p3); 47a3e0fd82Sopenharmony_ci Rect area; 48a3e0fd82Sopenharmony_ci int16_t lastY = p1.y; 49a3e0fd82Sopenharmony_ci 50a3e0fd82Sopenharmony_ci while (edge1.curPoint.y <= p3.y) { 51a3e0fd82Sopenharmony_ci // change edge1 from p1-p2 to p2-p3 52a3e0fd82Sopenharmony_ci if (edge1.curPoint.y == p2.y) { 53a3e0fd82Sopenharmony_ci edge1 = InitEdge(p2, p3); 54a3e0fd82Sopenharmony_ci if (edge1.dPoint.y == 0) { 55a3e0fd82Sopenharmony_ci return; 56a3e0fd82Sopenharmony_ci } 57a3e0fd82Sopenharmony_ci } 58a3e0fd82Sopenharmony_ci 59a3e0fd82Sopenharmony_ci area.SetLeft(MATH_MIN(edge1.curPoint.x, edge2.curPoint.x)); 60a3e0fd82Sopenharmony_ci area.SetRight(MATH_MAX(edge1.curPoint.x, edge2.curPoint.x)); 61a3e0fd82Sopenharmony_ci area.SetTop(MATH_MIN(edge1.curPoint.y, edge2.curPoint.y)); 62a3e0fd82Sopenharmony_ci area.SetBottom(MATH_MAX(edge1.curPoint.y, edge2.curPoint.y)); 63a3e0fd82Sopenharmony_ci DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, area, mask, color, opa); 64a3e0fd82Sopenharmony_ci 65a3e0fd82Sopenharmony_ci while (edge1.curPoint.y == lastY) { 66a3e0fd82Sopenharmony_ci // use Bresenham algorithm to get next point on edge1 67a3e0fd82Sopenharmony_ci StepToNextPointOnEdge(edge1); 68a3e0fd82Sopenharmony_ci } 69a3e0fd82Sopenharmony_ci while (edge2.curPoint.y == lastY) { 70a3e0fd82Sopenharmony_ci // use Bresenham algorithm to get next point on edge2 71a3e0fd82Sopenharmony_ci StepToNextPointOnEdge(edge2); 72a3e0fd82Sopenharmony_ci } 73a3e0fd82Sopenharmony_ci lastY = edge1.curPoint.y; 74a3e0fd82Sopenharmony_ci } 75a3e0fd82Sopenharmony_ci} 76a3e0fd82Sopenharmony_ci 77a3e0fd82Sopenharmony_civoid DrawTriangle::SortVertexs(Point& p1, Point& p2, Point& p3) 78a3e0fd82Sopenharmony_ci{ 79a3e0fd82Sopenharmony_ci SortPoint(p1, p2); 80a3e0fd82Sopenharmony_ci SortPoint(p2, p3); 81a3e0fd82Sopenharmony_ci SortPoint(p1, p2); 82a3e0fd82Sopenharmony_ci} 83a3e0fd82Sopenharmony_ci 84a3e0fd82Sopenharmony_civoid DrawTriangle::SortPoint(Point& p1, Point& p2) 85a3e0fd82Sopenharmony_ci{ 86a3e0fd82Sopenharmony_ci Point temp; 87a3e0fd82Sopenharmony_ci if (p1.y > p2.y) { 88a3e0fd82Sopenharmony_ci temp = p1; 89a3e0fd82Sopenharmony_ci p1 = p2; 90a3e0fd82Sopenharmony_ci p2 = temp; 91a3e0fd82Sopenharmony_ci } 92a3e0fd82Sopenharmony_ci} 93a3e0fd82Sopenharmony_ci 94a3e0fd82Sopenharmony_civoid DrawTriangle::StepToNextPointOnEdge(Edge& edge) 95a3e0fd82Sopenharmony_ci{ 96a3e0fd82Sopenharmony_ci if (edge.dPoint.x > edge.dPoint.y) { 97a3e0fd82Sopenharmony_ci edge.curPoint.x += edge.uPoint.x; 98a3e0fd82Sopenharmony_ci edge.eps += edge.dPoint.y; 99a3e0fd82Sopenharmony_ci if ((edge.eps << 1) >= edge.dPoint.x) { 100a3e0fd82Sopenharmony_ci edge.curPoint.y += edge.uPoint.y; 101a3e0fd82Sopenharmony_ci edge.eps -= edge.dPoint.x; 102a3e0fd82Sopenharmony_ci } 103a3e0fd82Sopenharmony_ci } else { 104a3e0fd82Sopenharmony_ci edge.curPoint.y += edge.uPoint.y; 105a3e0fd82Sopenharmony_ci edge.eps += edge.dPoint.x; 106a3e0fd82Sopenharmony_ci if ((edge.eps << 1) >= edge.dPoint.y) { 107a3e0fd82Sopenharmony_ci edge.curPoint.x += edge.uPoint.x; 108a3e0fd82Sopenharmony_ci edge.eps -= edge.dPoint.y; 109a3e0fd82Sopenharmony_ci } 110a3e0fd82Sopenharmony_ci } 111a3e0fd82Sopenharmony_ci} 112a3e0fd82Sopenharmony_ci 113a3e0fd82Sopenharmony_ciDrawTriangle::Edge DrawTriangle::InitEdge(const Point& startP, const Point& endP) 114a3e0fd82Sopenharmony_ci{ 115a3e0fd82Sopenharmony_ci Edge edge = { {0, 0}, {0, 0}, {0, 0}, 0 }; 116a3e0fd82Sopenharmony_ci edge.curPoint = startP; 117a3e0fd82Sopenharmony_ci edge.dPoint.x = startP.x - endP.x; 118a3e0fd82Sopenharmony_ci edge.dPoint.y = startP.y - endP.y; 119a3e0fd82Sopenharmony_ci edge.uPoint.x = (edge.dPoint.x < 0) ? 1 : -1; 120a3e0fd82Sopenharmony_ci edge.uPoint.y = (edge.dPoint.y < 0) ? 1 : -1; 121a3e0fd82Sopenharmony_ci edge.eps = 0; 122a3e0fd82Sopenharmony_ci edge.dPoint.x = MATH_ABS(edge.dPoint.x); 123a3e0fd82Sopenharmony_ci edge.dPoint.y = MATH_ABS(edge.dPoint.y); 124a3e0fd82Sopenharmony_ci return edge; 125a3e0fd82Sopenharmony_ci} 126a3e0fd82Sopenharmony_ci} // namespace OHOS 127