hekate/bdk/libs/lvgl/lv_draw/lv_draw_triangle.c
CTCaer 185526d134 Introducing Bootloader Development Kit (BDK)
BDK will allow developers to use the full collection of drivers,
with limited editing, if any, for making payloads for Nintendo Switch.

Using a single source for everything will also help decoupling
Switch specific code and easily port it to other Tegra X1/X1+ platforms.
And maybe even to lower targets.

Everything is now centrilized into bdk folder.
Every module or project can utilize it by simply including it.

This is just the start and it will continue to improve.
2020-06-14 15:25:21 +03:00

169 lines
4.5 KiB
C

/**
* @file lv_draw_triangle.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_triangle.h"
#include "../lv_misc/lv_math.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static void point_swap(lv_point_t * p1, lv_point_t * p2);
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
#if USE_LV_TRIANGLE != 0
/**
*
* @param points pointer to an array with 3 points
* @param mask the triangle will be drawn only in this mask
* @param color color of the triangle
*/
void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, lv_color_t color)
{
lv_point_t tri[3];
memcpy(tri, points, sizeof(tri));
/*Sort the vertices according to their y coordinate (0: y max, 1: y mid, 2:y min)*/
if(tri[1].y < tri[0].y) point_swap(&tri[1], &tri[0]);
if(tri[2].y < tri[1].y) point_swap(&tri[2], &tri[1]);
if(tri[1].y < tri[0].y) point_swap(&tri[1], &tri[0]);
/*Return is the triangle is degenerated*/
if(tri[0].x == tri[1].x && tri[0].y == tri[1].y) return;
if(tri[1].x == tri[2].x && tri[1].y == tri[2].y) return;
if(tri[0].x == tri[2].x && tri[0].y == tri[2].y) return;
if(tri[0].x == tri[1].x && tri[1].x == tri[2].x) return;
if(tri[0].y == tri[1].y && tri[1].y == tri[2].y) return;
/*Draw the triangle*/
lv_point_t edge1;
lv_coord_t dx1 = LV_MATH_ABS(tri[0].x - tri[1].x);
lv_coord_t sx1 = tri[0].x < tri[1].x ? 1 : -1;
lv_coord_t dy1 = LV_MATH_ABS(tri[0].y - tri[1].y);
lv_coord_t sy1 = tri[0].y < tri[1].y ? 1 : -1;
lv_coord_t err1 = (dx1 > dy1 ? dx1 : -dy1) / 2;
lv_coord_t err_tmp1;
lv_point_t edge2;
lv_coord_t dx2 = LV_MATH_ABS(tri[0].x - tri[2].x);
lv_coord_t sx2 = tri[0].x < tri[2].x ? 1 : -1;
lv_coord_t dy2 = LV_MATH_ABS(tri[0].y - tri[2].y);
lv_coord_t sy2 = tri[0].y < tri[2].y ? 1 : -1;
lv_coord_t err2 = (dx1 > dy2 ? dx2 : -dy2) / 2;
lv_coord_t err_tmp2;
lv_coord_t y1_tmp;
lv_coord_t y2_tmp;
edge1.x = tri[0].x;
edge1.y = tri[0].y;
edge2.x = tri[0].x;
edge2.y = tri[0].y;
lv_area_t act_area;
lv_area_t draw_area;
while(1) {
act_area.x1 = edge1.x;
act_area.x2 = edge2.x ;
act_area.y1 = edge1.y;
act_area.y2 = edge2.y ;
draw_area.x1 = LV_MATH_MIN(act_area.x1, act_area.x2);
draw_area.x2 = LV_MATH_MAX(act_area.x1, act_area.x2);
draw_area.y1 = LV_MATH_MIN(act_area.y1, act_area.y2);
draw_area.y2 = LV_MATH_MAX(act_area.y1, act_area.y2);
draw_area.x2--; /*Do not draw most right pixel because it will be drawn by the adjacent triangle*/
fill_fp(&draw_area, mask, color, LV_OPA_50);
/*Calc. the next point of edge1*/
y1_tmp = edge1.y;
do {
if(edge1.x == tri[1].x && edge1.y == tri[1].y) {
dx1 = LV_MATH_ABS(tri[1].x - tri[2].x);
sx1 = tri[1].x < tri[2].x ? 1 : -1;
dy1 = LV_MATH_ABS(tri[1].y - tri[2].y);
sy1 = tri[1].y < tri[2].y ? 1 : -1;
err1 = (dx1 > dy1 ? dx1 : -dy1) / 2;
} else if(edge1.x == tri[2].x && edge1.y == tri[2].y) return;
err_tmp1 = err1;
if(err_tmp1 > -dx1) {
err1 -= dy1;
edge1.x += sx1;
}
if(err_tmp1 < dy1) {
err1 += dx1;
edge1.y += sy1;
}
} while(edge1.y == y1_tmp);
/*Calc. the next point of edge2*/
y2_tmp = edge2.y;
do {
if(edge2.x == tri[2].x && edge2.y == tri[2].y) return;
err_tmp2 = err2;
if(err_tmp2 > -dx2) {
err2 -= dy2;
edge2.x += sx2;
}
if(err_tmp2 < dy2) {
err2 += dx2;
edge2.y += sy2;
}
} while(edge2.y == y2_tmp);
}
}
#endif
/**********************
* STATIC FUNCTIONS
**********************/
#if USE_LV_TRIANGLE != 0
/**
* Swap two points
* p1 pointer to the first point
* p2 pointer to the second point
*/
static void point_swap(lv_point_t * p1, lv_point_t * p2)
{
lv_point_t tmp;
tmp.x = p1->x;
tmp.y = p1->y;
p1->x = p2->x;
p1->y = p2->y;
p2->x = tmp.x;
p2->y = tmp.y;
}
#endif