1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 12:28:09 +00:00

trezor.ui: add antialiasing to display.avatar

This commit is contained in:
Pavol Rusnak 2017-09-05 00:19:31 +02:00
parent ed581a5b36
commit fb2eff7ced
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

View File

@ -39,14 +39,19 @@ static int DISPLAY_OFFSET[2] = {0, 0};
// common display functions // common display functions
static void set_color_table(uint16_t colortable[16], uint16_t fgcolor, uint16_t bgcolor) static inline uint16_t interpolate_color(uint16_t color0, uint16_t color1, uint8_t step)
{ {
uint8_t cr, cg, cb; uint8_t cr, cg, cb;
cr = (((color0 & 0xF800) >> 11) * step + ((color1 & 0xF800) >> 11) * (15 - step)) / 15;
cg = (((color0 & 0x07E0) >> 5) * step + ((color1 & 0x07E0) >> 5) * (15 - step)) / 15;
cb = ((color0 & 0x001F) * step + (color1 & 0x001F) * (15 - step)) / 15;
return (cr << 11) | (cg << 5) | cb;
}
static inline void set_color_table(uint16_t colortable[16], uint16_t fgcolor, uint16_t bgcolor)
{
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
cr = (((fgcolor & 0xF800) >> 11) * i + ((bgcolor & 0xF800) >> 11) * (15 - i)) / 15; colortable[i] = interpolate_color(fgcolor, bgcolor, i);
cg = (((fgcolor & 0x07E0) >> 5) * i + ((bgcolor & 0x07E0) >> 5) * (15 - i)) / 15;
cb = ((fgcolor & 0x001F) * i + (bgcolor & 0x001F) * (15 - i)) / 15;
colortable[i] = (cr << 11) | (cg << 5) | cb;
} }
} }
@ -147,17 +152,23 @@ void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, uint
} }
} }
static void inflate_callback_image(uint8_t byte, uint32_t pos, void *userdata) static void inflate_callback_image(uint8_t byte1, uint32_t pos, void *userdata)
{ {
int w = ((int *)userdata)[0]; static uint8_t byte0;
int x0 = ((int *)userdata)[1]; if (pos % 2 == 0) {
int x1 = ((int *)userdata)[2]; byte0 = byte1;
int y0 = ((int *)userdata)[3]; return;
int y1 = ((int *)userdata)[4]; }
int px = (pos / 2) % w; const int w = ((const int *)userdata)[0];
int py = (pos / 2) / w; const int x0 = ((const int *)userdata)[1];
const int x1 = ((const int *)userdata)[2];
const int y0 = ((const int *)userdata)[3];
const int y1 = ((const int *)userdata)[4];
const int px = (pos / 2) % w;
const int py = (pos / 2) / w;
if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { if (px >= x0 && px <= x1 && py >= y0 && py <= y1) {
DATA(byte); DATA(byte0);
DATA(byte1);
} }
} }
@ -168,35 +179,57 @@ void display_image(int x, int y, int w, int h, const void *data, int datalen)
int x0, y0, x1, y1; int x0, y0, x1, y1;
clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1);
display_set_window(x0, y0, x1, y1); display_set_window(x0, y0, x1, y1);
int userdata[5]; int userdata[5] = {w, x0 - x, x1 - x, y0 - y, y1 - y};
userdata[0] = w;
userdata[1] = x0 - x;
userdata[2] = x1 - x;
userdata[3] = y0 - y;
userdata[4] = y1 - y;
sinf_inflate(data, datalen, inflate_callback_image, userdata); sinf_inflate(data, datalen, inflate_callback_image, userdata);
} }
static void inflate_callback_avatar(uint8_t byte, uint32_t pos, void *userdata) static void inflate_callback_avatar(uint8_t byte1, uint32_t pos, void *userdata)
{ {
int w = ((int *)userdata)[0]; #define AVATAR_BORDER_SIZE 4
int x0 = ((int *)userdata)[1]; #define AVATAR_BORDER_LOW (AVATAR_IMAGE_SIZE / 2 - AVATAR_BORDER_SIZE) * (AVATAR_IMAGE_SIZE / 2 - AVATAR_BORDER_SIZE)
int x1 = ((int *)userdata)[2]; #define AVATAR_BORDER_HIGH (AVATAR_IMAGE_SIZE / 2) * (AVATAR_IMAGE_SIZE / 2)
int y0 = ((int *)userdata)[3]; #define AVATAR_ANTIALIAS 1
int y1 = ((int *)userdata)[4]; static uint8_t byte0;
int fgcolor = ((int *)userdata)[5]; if (pos % 2 == 0) {
int bgcolor = ((int *)userdata)[6]; byte0 = byte1;
int px = (pos / 2) % w; return;
int py = (pos / 2) / w; }
const int w = ((const int *)userdata)[0];
const int x0 = ((const int *)userdata)[1];
const int x1 = ((const int *)userdata)[2];
const int y0 = ((const int *)userdata)[3];
const int y1 = ((const int *)userdata)[4];
const int fgcolor = ((const int *)userdata)[5];
const int bgcolor = ((const int *)userdata)[6];
const int px = (pos / 2) % w;
const int py = (pos / 2) / w;
if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { if (px >= x0 && px <= x1 && py >= y0 && py <= y1) {
int d = (px - w / 2) * (px - w / 2) + (py - w / 2) * (py - w / 2); int d = (px - w / 2) * (px - w / 2) + (py - w / 2) * (py - w / 2);
if (d < 70 * 70) { // inside circle // inside border area
DATA(byte); if (d < AVATAR_BORDER_LOW) {
DATA(byte0);
DATA(byte1);
} else } else
if (d >= 72 * 72) { // outside circle // outside border area
DATA((bgcolor >> 8 * (1 - pos % 2)) & 0xFF); if (d > AVATAR_BORDER_HIGH) {
} else { // circle DATA(bgcolor >> 8);
DATA((fgcolor >> 8 * (1 - pos % 2)) & 0xFF); DATA(bgcolor & 0xFF);
// border area
} else {
#if AVATAR_ANTIALIAS
d = 31 * (d - AVATAR_BORDER_LOW) / (AVATAR_BORDER_HIGH - AVATAR_BORDER_LOW);
uint16_t c;
if (d >= 16) {
c = interpolate_color(bgcolor, fgcolor, d - 16);
} else {
c = interpolate_color(fgcolor, (byte0 << 8) | byte1 , d);
}
DATA(c >> 8);
DATA(c & 0xFF);
#else
DATA(fgcolor >> 8);
DATA(fgcolor & 0xFF);
#endif
} }
} }
} }
@ -208,27 +241,20 @@ void display_avatar(int x, int y, const void *data, int datalen, uint16_t fgcolo
int x0, y0, x1, y1; int x0, y0, x1, y1;
clamp_coords(x, y, AVATAR_IMAGE_SIZE, AVATAR_IMAGE_SIZE, &x0, &y0, &x1, &y1); clamp_coords(x, y, AVATAR_IMAGE_SIZE, AVATAR_IMAGE_SIZE, &x0, &y0, &x1, &y1);
display_set_window(x0, y0, x1, y1); display_set_window(x0, y0, x1, y1);
int userdata[7]; int userdata[7] = {AVATAR_IMAGE_SIZE, x0 - x, x1 - x, y0 - y, y1 - y, fgcolor, bgcolor};
userdata[0] = AVATAR_IMAGE_SIZE;
userdata[1] = x0 - x;
userdata[2] = x1 - x;
userdata[3] = y0 - y;
userdata[4] = y1 - y;
userdata[5] = fgcolor;
userdata[6] = bgcolor;
sinf_inflate(data, datalen, inflate_callback_avatar, userdata); sinf_inflate(data, datalen, inflate_callback_avatar, userdata);
} }
static void inflate_callback_icon(uint8_t byte, uint32_t pos, void *userdata) static void inflate_callback_icon(uint8_t byte, uint32_t pos, void *userdata)
{ {
uint16_t *colortable = (uint16_t *)(((int *)userdata) + 5); const uint16_t *colortable = (const uint16_t *)(((const int *)userdata) + 5);
int w = ((int *)userdata)[0]; const int w = ((const int *)userdata)[0];
int x0 = ((int *)userdata)[1]; const int x0 = ((const int *)userdata)[1];
int x1 = ((int *)userdata)[2]; const int x1 = ((const int *)userdata)[2];
int y0 = ((int *)userdata)[3]; const int y0 = ((const int *)userdata)[3];
int y1 = ((int *)userdata)[4]; const int y1 = ((const int *)userdata)[4];
int px = (pos * 2) % w; const int px = (pos * 2) % w;
int py = (pos * 2) / w; const int py = (pos * 2) / w;
if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { if (px >= x0 && px <= x1 && py >= y0 && py <= y1) {
DATA(colortable[byte >> 4] >> 8); DATA(colortable[byte >> 4] >> 8);
DATA(colortable[byte >> 4] & 0xFF); DATA(colortable[byte >> 4] & 0xFF);
@ -245,12 +271,7 @@ void display_icon(int x, int y, int w, int h, const void *data, int datalen, uin
int x0, y0, x1, y1; int x0, y0, x1, y1;
clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1);
display_set_window(x0, y0, x1, y1); display_set_window(x0, y0, x1, y1);
int userdata[5 + 16 * sizeof(uint16_t) / sizeof(int)]; int userdata[5 + 16 * sizeof(uint16_t) / sizeof(int)] = {w, x0 - x, x1 - x, y0 - y, y1 - y};
userdata[0] = w;
userdata[1] = x0 - x;
userdata[2] = x1 - x;
userdata[3] = y0 - y;
userdata[4] = y1 - y;
set_color_table((uint16_t *)(userdata + 5), fgcolor, bgcolor); set_color_table((uint16_t *)(userdata + 5), fgcolor, bgcolor);
sinf_inflate(data, datalen, inflate_callback_icon, userdata); sinf_inflate(data, datalen, inflate_callback_icon, userdata);
} }