Skip to content

Commit

Permalink
Port of the fast colorwheel change to v8 (lvgl#2092)
Browse files Browse the repository at this point in the history
  • Loading branch information
X-Ryl669 authored Feb 24, 2021
1 parent d2d8f97 commit 45d6fd2
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 29 deletions.
99 changes: 80 additions & 19 deletions src/extra/widgets/colorwheel/lv_colorwheel.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static lv_area_t get_knob_area(lv_obj_t * obj);
static void next_color_mode(lv_obj_t * obj);
static lv_res_t double_click_reset(lv_obj_t * obj);
static void refr_knob_pos(lv_obj_t * obj);
static lv_color_t angle_to_mode_color(lv_obj_t * obj, uint16_t angle);
static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle);
static uint16_t get_angle(lv_obj_t * obj);

/**********************
Expand Down Expand Up @@ -257,9 +257,10 @@ static void draw_disc_grad(lv_obj_t * obj, const lv_area_t * mask)
lv_draw_line_dsc_init(&line_dsc);
lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc);

line_dsc.width = (r * 628 / (360 / LV_CPICKER_DEF_QF)) / 100;
line_dsc.width = (r * 628 / (256 / LV_CPICKER_DEF_QF)) / 100;
line_dsc.width += 2;
uint16_t i;
uint32_t a = 0;
lv_coord_t cir_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN);

#if LV_DRAW_COMPLEX
Expand All @@ -285,15 +286,15 @@ static void draw_disc_grad(lv_obj_t * obj, const lv_area_t * mask)
lv_coord_t cir_w_extra = 0;
#endif


for(i = 0; i <= 360; i += LV_CPICKER_DEF_QF) {
line_dsc.color = angle_to_mode_color(obj, i);

for(i = 0; i <= 256; i += LV_CPICKER_DEF_QF, a += 360 * LV_CPICKER_DEF_QF) {
line_dsc.color = angle_to_mode_color_fast(obj, i);
uint16_t angle_trigo = (uint16_t)(a >> 8); /* i * 360 / 256 is the scale to apply, but we can skip multiplication here */
lv_point_t p[2];
p[0].x = cx + ((r + cir_w_extra) * lv_trigo_sin(i) >> LV_TRIGO_SHIFT);
p[0].y = cy + ((r + cir_w_extra) * lv_trigo_cos(i) >> LV_TRIGO_SHIFT);
p[1].x = cx + ((r - cir_w - cir_w_extra) * lv_trigo_sin(i) >> LV_TRIGO_SHIFT);
p[1].y = cy + ((r - cir_w - cir_w_extra) * lv_trigo_cos(i) >> LV_TRIGO_SHIFT);
p[0].x = cx + ((r + cir_w_extra) * lv_trigo_sin(angle_trigo) >> LV_TRIGO_SHIFT);
p[0].y = cy + ((r + cir_w_extra) * lv_trigo_cos(angle_trigo) >> LV_TRIGO_SHIFT);
p[1].x = cx + ((r - cir_w - cir_w_extra) * lv_trigo_sin(angle_trigo) >> LV_TRIGO_SHIFT);
p[1].y = cy + ((r - cir_w - cir_w_extra) * lv_trigo_cos(angle_trigo) >> LV_TRIGO_SHIFT);

lv_draw_line(&p[0], &p[1], mask, &line_dsc);
}
Expand Down Expand Up @@ -592,25 +593,85 @@ static lv_res_t double_click_reset(lv_obj_t * obj)
return LV_RES_OK;
}

static lv_color_t angle_to_mode_color(lv_obj_t * obj, uint16_t angle)
#define SWAPPTR(A, B) do { uint8_t * t = A; A = B; B = t; } while(0)
#define HSV_PTR_SWAP(sextant,r,g,b) if((sextant) & 2) { SWAPPTR((r), (b)); } if((sextant) & 4) { SWAPPTR((g), (b)); } if(!((sextant) & 6)) { \
if(!((sextant) & 1)) { SWAPPTR((r), (g)); } } else { if((sextant) & 1) { SWAPPTR((r), (g)); } }

/* Based on the idea from https://www.vagrearg.org/content/hsvrgb
Here we want to compute an approximate RGB value from a HSV input color space. We don't want to be accurate
(for that, there's lv_color_hsv_to_rgb), but we want to be fast.
Few tricks are used here: Hue is in range [0; 6 * 256] (so that the sextant is in the high byte and the fractional part is in the low byte)
both s and v are in [0; 255] range (very convenient to avoid divisions).
We fold all symmetry by swapping the R, G, B pointers so that the code is the same for all sextants.
We replace division by 255 by a division by 256, a.k.a a shift right by 8 bits.
This is wrong, but since this is only used to compute the pixels on the screen and not the final color, it's ok.
*/
static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b);
static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b)
{
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *) obj;
lv_color_t color;
angle = angle % 360;
if (!s) { *r = *g = *b = v; return; }

switch(colorwheel->mode) {
uint8_t sextant = h >> 8;
HSV_PTR_SWAP(sextant, r, g, b); /* Swap pointers so the conversion code is the same */

*g = v;

uint8_t bb = ~s;
uint16_t ww = v * bb; /* Don't try to be precise, but instead, be fast */
*b = ww >> 8;

uint8_t h_frac = h & 0xff;

if(!(sextant & 1)) {
/* Up slope */
ww = !h_frac ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_frac)); /* Skip multiply if not required */
} else {
/* Down slope */
ww = s * h_frac;
}
bb = ww >> 8;
bb = ~bb;
ww = v * bb;
*r = ww >> 8;
}

static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle)
{
lv_colorwheel_t * ext = (lv_colorwheel_t*)obj;
uint8_t r = 0, g = 0, b = 0;
static uint16_t h = 0;
static uint8_t s = 0, v = 0, m = 255;

switch(ext->mode) {
default:
case LV_COLORWHEEL_MODE_HUE:
color = lv_color_hsv_to_rgb(angle, colorwheel->hsv.s, colorwheel->hsv.v);
/* Don't recompute costly scaling if it does not change */
if (m != ext->mode) {
s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20);
m = ext->mode;
}
fast_hsv2rgb(angle * 6, s, v, &r, &g, &b); /* A smart compiler will replace x * 6 by (x << 2) + (x << 1) if it's more efficient */
break;
case LV_COLORWHEEL_MODE_SATURATION:
color = lv_color_hsv_to_rgb(colorwheel->hsv.h, (angle * 100) / 360, colorwheel->hsv.v);
/* Don't recompute costly scaling if it does not change */
if (m != ext->mode) {
h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20);
m = ext->mode;
}
fast_hsv2rgb(h, angle, v, &r, &g, &b);
break;
case LV_COLORWHEEL_MODE_VALUE:
color = lv_color_hsv_to_rgb(colorwheel->hsv.h, colorwheel->hsv.s, (angle * 100) / 360);
/* Don't recompute costly scaling if it does not change */
if (m != ext->mode) {
h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20);
m = ext->mode;
}
fast_hsv2rgb(h, s, angle, &r, &g, &b);
break;
}
return color;
return LV_COLOR_MAKE(r, g, b);
}

static uint16_t get_angle(lv_obj_t * obj)
Expand Down
8 changes: 0 additions & 8 deletions src/lv_font/lv_font_fmt_txt.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,10 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic
break;
}

<<<<<<< HEAD
if(_lv_mem_get_size(LV_GC_ROOT(_lv_font_decompr_buf)) < buf_size) {
uint8_t * tmp = lv_mem_realloc(LV_GC_ROOT(_lv_font_decompr_buf), buf_size);
LV_ASSERT_MEM(tmp);
if(tmp == NULL) return NULL;
LV_GC_ROOT(_lv_font_decompr_buf) = tmp;
=======
if(lv_mem_get_size(LV_GC_ROOT(_lv_font_decompr_buf)) < buf_size) {
LV_GC_ROOT(_lv_font_decompr_buf) = lv_mem_realloc(LV_GC_ROOT(_lv_font_decompr_buf), buf_size);
LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_font_decompr_buf));
if(LV_GC_ROOT(_lv_font_decompr_buf) == NULL) return NULL;
>>>>>>> dev-v8
}

bool prefilter = fdsc->bitmap_format == LV_FONT_FMT_TXT_COMPRESSED ? true : false;
Expand Down
2 changes: 1 addition & 1 deletion src/lv_widgets/lv_meter.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/*********************
* INCLUDES
*********************/
#include <lvgl/src/lv_widgets/lv_meter.h>
#include "lv_meter.h"
#if LV_USE_METER != 0

#include "../lv_misc/lv_assert.h"
Expand Down
2 changes: 1 addition & 1 deletion src/lv_widgets/lv_objx_templ.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/*********************
* INCLUDES
*********************/
#include <lvgl/src/lv_misc/lv_assert.h>
#include "../lv_misc/lv_assert.h"
//#include "lv_templ.h" /*TODO uncomment this*/

#if defined(LV_USE_TEMPL) && LV_USE_TEMPL != 0
Expand Down

0 comments on commit 45d6fd2

Please sign in to comment.