kopia lustrzana https://github.com/OpenRTX/OpenRTX
Merge graphics_* into a single compilation unit
The specialized graphics libraries ended up sharing the majority of the code, now they have been merged into a single library so that the graphics development can be done quicker without leaving any of the platforms behind.replace/eb06f1c293bc7cd0e17daeea6fb843b09256309d
rodzic
f0862abac1
commit
d56fafe1a2
19
meson.build
19
meson.build
|
@ -16,6 +16,7 @@ openrtx_src = ['openrtx/src/bootstrap.c',
|
|||
'openrtx/src/ui.c',
|
||||
'openrtx/src/threads.c',
|
||||
'openrtx/src/battery.c',
|
||||
'openrtx/src/graphics.c',
|
||||
'openrtx/src/calibUtils.c']
|
||||
|
||||
|
||||
|
@ -153,12 +154,6 @@ linux_src = src + ['platform/targets/linux/emulator/emulator.c',
|
|||
|
||||
linux_def = def + {'SCREEN_WIDTH': '160', 'SCREEN_HEIGHT': '128', 'PIX_FMT_RGB565': ''}
|
||||
|
||||
if 'PIX_FMT_RGB565' in linux_def
|
||||
linux_src = linux_src + ['openrtx/src/graphics/graphics_rgb565.c']
|
||||
elif 'PIX_FMT_BW' in linux_def
|
||||
linux_src = linux_src + ['openrtx/src/graphics/graphics_bw.c']
|
||||
endif
|
||||
|
||||
linux_inc = inc + ['rtos/uC-OS3/Ports/POSIX',
|
||||
'rtos/uC-CPU/Posix',
|
||||
'platform/targets/linux',
|
||||
|
@ -182,8 +177,7 @@ md380_src = src + stm32f405_src + ['platform/drivers/display/HX83XX_MDx.c',
|
|||
'platform/drivers/baseband/pll_MD3x0.c',
|
||||
'platform/drivers/baseband/rtx_MD3x0.c',
|
||||
'platform/drivers/baseband/HR-C5000_MD3x0.c',
|
||||
'platform/targets/MD-380/platform.c',
|
||||
'openrtx/src/graphics/graphics_rgb565.c']
|
||||
'platform/targets/MD-380/platform.c']
|
||||
|
||||
md380_inc = inc + stm32f405_inc + ['platform/targets/MD-380']
|
||||
md380_def = def + stm32f405_def + {'PLATFORM_MD380': ''}
|
||||
|
@ -199,8 +193,7 @@ md390_src = src + stm32f405_src + ['platform/drivers/display/HX83XX_MDx.c',
|
|||
'platform/drivers/baseband/pll_MD3x0.c',
|
||||
'platform/drivers/baseband/rtx_MD3x0.c',
|
||||
'platform/drivers/baseband/HR-C5000_MD3x0.c',
|
||||
'platform/targets/MD-390/platform.c',
|
||||
'openrtx/src/graphics/graphics_rgb565.c']
|
||||
'platform/targets/MD-390/platform.c']
|
||||
|
||||
md390_inc = inc + stm32f405_inc + ['platform/targets/MD-390']
|
||||
md390_def = def + stm32f405_def + {'PLATFORM_MD390': ''}
|
||||
|
@ -213,8 +206,7 @@ mduv380_src = src + stm32f405_src + ['platform/drivers/display/HX83XX_MDx.c',
|
|||
'platform/drivers/NVM/nvmem_MDUV3x0.c',
|
||||
'platform/drivers/ADC/ADC1_MDx.c',
|
||||
'platform/drivers/baseband/rtx_UV3x0.c',
|
||||
'platform/targets/MD-UV380/platform.c',
|
||||
'openrtx/src/graphics/graphics_rgb565.c']
|
||||
'platform/targets/MD-UV380/platform.c']
|
||||
|
||||
mduv380_inc = inc + stm32f405_inc + ['platform/targets/MD-UV380']
|
||||
mduv380_def = def + stm32f405_def + {'PLATFORM_MDUV380': ''}
|
||||
|
@ -224,8 +216,7 @@ mduv380_def = def + stm32f405_def + {'PLATFORM_MDUV380': ''}
|
|||
gd77_src = src + mk22fn512_src + ['platform/targets/GD77/platform.c',
|
||||
'platform/drivers/display/UC1701_GD77.c',
|
||||
'platform/drivers/keyboard/keyboard_GD77.c',
|
||||
'platform/drivers/baseband/rtx_GDx.c',
|
||||
'openrtx/src/graphics/graphics_bw.c']
|
||||
'platform/drivers/baseband/rtx_GDx.c']
|
||||
|
||||
gd77_inc = inc + mk22fn512_inc + ['platform/targets/GD77']
|
||||
gd77_def = def + mk22fn512_def + {'PLATFORM_GD77': ''}
|
||||
|
|
|
@ -18,18 +18,19 @@
|
|||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* This source file provides an RGB implementation for the graphics.h interface
|
||||
* It is suitable for color displays, it will have grayscale and B/W counterparts
|
||||
* This source file provides an implementation for the graphics.h interface
|
||||
* It is suitable for both color, grayscale and B/W display
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <hwconfig.h>
|
||||
#include "display.h"
|
||||
#include "graphics.h"
|
||||
#include <display.h>
|
||||
#include <graphics.h>
|
||||
|
||||
/* This graphics driver is meant for an RGB565 little endian pixel format.
|
||||
#ifdef PIX_FMT_RGB565
|
||||
/* This specialization is meant for an RGB565 little endian pixel format.
|
||||
* Thus, to accomodate for the endianness, the fields in struct rgb565_t have to
|
||||
* be written in reversed order.
|
||||
*
|
||||
|
@ -44,14 +45,64 @@ typedef struct
|
|||
uint16_t r : 5;
|
||||
} rgb565_t;
|
||||
|
||||
rgb565_t _true2highColor(color_t true_color)
|
||||
{
|
||||
rgb565_t high_color;
|
||||
high_color.r = true_color.r >> 3;
|
||||
high_color.g = true_color.g >> 2;
|
||||
high_color.b = true_color.b >> 3;
|
||||
|
||||
return high_color;
|
||||
}
|
||||
|
||||
#define PIXEL_T rgb565_t
|
||||
#elif defined PIX_FMT_BW
|
||||
/**
|
||||
* This specialization is meant for black and white pixel format.
|
||||
* It is suitable for monochromatic displays with 1 bit per pixel,
|
||||
* it will have RGB and grayscale counterparts
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WHITE = 0,
|
||||
BLACK = 1,
|
||||
} bw_t;
|
||||
|
||||
bw_t _color2bw(color_t true_color)
|
||||
{
|
||||
if(true_color.r == 0 &&
|
||||
true_color.g == 0 &&
|
||||
true_color.b == 0)
|
||||
return WHITE;
|
||||
else
|
||||
return BLACK;
|
||||
}
|
||||
|
||||
#define PIXEL_T uint8_t
|
||||
#else
|
||||
#error Please define a pixel format type into hwconfig.h or meson.build
|
||||
#endif
|
||||
|
||||
bool initialized = 0;
|
||||
rgb565_t *buf;
|
||||
PIXEL_T *buf;
|
||||
uint16_t fbSize;
|
||||
|
||||
void gfx_init()
|
||||
{
|
||||
display_init();
|
||||
buf = (rgb565_t *)(display_getFrameBuffer());
|
||||
buf = (PIXEL_T *)(display_getFrameBuffer());
|
||||
initialized = 1;
|
||||
|
||||
// Calculate framebuffer size
|
||||
#ifdef PIX_FMT_RGB565
|
||||
fbSize = SCREEN_HEIGHT * SCREEN_WIDTH * sizeof(PIXEL_T);
|
||||
#elif defined PIX_FMT_BW
|
||||
fbSize = (SCREEN_HEIGHT * SCREEN_WIDTH) / 8;
|
||||
/* Compensate for eventual truncation error in division */
|
||||
if((fbSize * 8) < (SCREEN_HEIGHT * SCREEN_WIDTH)) fbSize += 1;
|
||||
fbSize *= sizeof(uint8_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
void gfx_terminate()
|
||||
|
@ -75,22 +126,12 @@ bool gfx_renderingInProgress()
|
|||
return display_renderingInProgress();
|
||||
}
|
||||
|
||||
rgb565_t _true2highColor(color_t true_color)
|
||||
{
|
||||
rgb565_t high_color;
|
||||
high_color.r = true_color.r >> 3;
|
||||
high_color.g = true_color.g >> 2;
|
||||
high_color.b = true_color.b >> 3;
|
||||
|
||||
return high_color;
|
||||
}
|
||||
|
||||
void gfx_clearRows(uint8_t startRow, uint8_t endRow)
|
||||
{
|
||||
if(!initialized) return;
|
||||
if(endRow < startRow) return;
|
||||
uint16_t start = startRow * SCREEN_WIDTH * sizeof(rgb565_t);
|
||||
uint16_t height = endRow - startRow * SCREEN_WIDTH * sizeof(rgb565_t);
|
||||
uint16_t start = startRow * SCREEN_WIDTH * sizeof(PIXEL_T);
|
||||
uint16_t height = endRow - startRow * SCREEN_WIDTH * sizeof(PIXEL_T);
|
||||
// Set the specified rows to 0x00 = make the screen black
|
||||
memset(buf + start, 0x00, height);
|
||||
}
|
||||
|
@ -99,39 +140,46 @@ void gfx_clearScreen()
|
|||
{
|
||||
if(!initialized) return;
|
||||
// Set the whole framebuffer to 0x00 = make the screen black
|
||||
memset(buf, 0x00, sizeof(rgb565_t) * SCREEN_WIDTH * SCREEN_HEIGHT);
|
||||
memset(buf, 0x00, fbSize);
|
||||
}
|
||||
|
||||
void gfx_fillScreen(color_t color)
|
||||
{
|
||||
if(!initialized) return;
|
||||
rgb565_t color_565 = _true2highColor(color);
|
||||
for(int y = 0; y < SCREEN_HEIGHT; y++)
|
||||
{
|
||||
for(int x = 0; x < SCREEN_WIDTH; x++)
|
||||
{
|
||||
buf[x + y*SCREEN_WIDTH] = color_565;
|
||||
point_t pos = {x, y};
|
||||
gfx_setPixel(pos, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_setPixel(point_t pos, color_t color)
|
||||
inline void gfx_setPixel(point_t pos, color_t color)
|
||||
{
|
||||
if (pos.x >= SCREEN_WIDTH || pos.y >= SCREEN_HEIGHT)
|
||||
return; // off the screen
|
||||
|
||||
#ifdef PIX_FMT_RGB565
|
||||
buf[pos.x + pos.y*SCREEN_WIDTH] = _true2highColor(color);
|
||||
#elif defined PIX_FMT_BW
|
||||
uint16_t cell = (pos.x + pos.y*SCREEN_WIDTH) / 8;
|
||||
uint16_t elem = (pos.x + pos.y*SCREEN_WIDTH) % 8;
|
||||
buf[cell] &= ~(1 << elem);
|
||||
buf[cell] |= (_color2bw(color) << elem);
|
||||
#endif
|
||||
}
|
||||
|
||||
void gfx_drawLine(point_t start, point_t end, color_t color)
|
||||
{
|
||||
if(!initialized) return;
|
||||
rgb565_t color_565 = _true2highColor(color);
|
||||
for(int y = start.y; y <= end.y; y++)
|
||||
{
|
||||
for(int x = start.x; x <= end.x; x++)
|
||||
{
|
||||
buf[x + y*SCREEN_WIDTH] = color_565;
|
||||
point_t pos = {x, y};
|
||||
gfx_setPixel(pos, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +187,6 @@ void gfx_drawLine(point_t start, point_t end, color_t color)
|
|||
void gfx_drawRect(point_t start, uint16_t width, uint16_t height, color_t color, bool fill)
|
||||
{
|
||||
if(!initialized) return;
|
||||
rgb565_t color_565 = _true2highColor(color);
|
||||
uint16_t x_max = start.x + width - 1;
|
||||
uint16_t y_max = start.y + height - 1;
|
||||
bool perimeter = 0;
|
||||
|
@ -152,7 +199,11 @@ void gfx_drawRect(point_t start, uint16_t width, uint16_t height, color_t color,
|
|||
if(y == start.y || y == y_max || x == start.x || x == x_max) perimeter = 1;
|
||||
else perimeter = 0;
|
||||
// If fill is false, draw only rectangle perimeter
|
||||
if(fill || perimeter) buf[x + y*SCREEN_WIDTH] = color_565;
|
||||
if(fill || perimeter)
|
||||
{
|
||||
point_t pos = {x, y};
|
||||
gfx_setPixel(pos, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,8 +264,6 @@ static inline uint16_t get_reset_x(textAlign_t alignment,
|
|||
|
||||
void gfx_print(point_t start, const char *text, fontSize_t size, textAlign_t alignment, color_t color) {
|
||||
|
||||
rgb565_t color_565 = _true2highColor(color);
|
||||
|
||||
GFXfont f = fonts[size];
|
||||
|
||||
size_t len = strlen(text);
|
||||
|
@ -261,9 +310,15 @@ void gfx_print(point_t start, const char *text, fontSize_t size, textAlign_t ali
|
|||
bits = bitmap[bo++];
|
||||
}
|
||||
if (bits & 0x80) {
|
||||
if (start.y + yo + yy < SCREEN_HEIGHT && start.x + xo + xx < SCREEN_WIDTH && start.y + yo + yy > 0 && start.x + xo + xx > 0)
|
||||
buf[(start.y + yo + yy) * SCREEN_WIDTH +
|
||||
start.x + xo + xx] = color_565;
|
||||
if (start.y + yo + yy < SCREEN_HEIGHT &&
|
||||
start.x + xo + xx < SCREEN_WIDTH &&
|
||||
start.y + yo + yy > 0 &&
|
||||
start.x + xo + xx > 0)
|
||||
{
|
||||
point_t pos = {start.x + xo + xx, start.y + yo + yy};
|
||||
gfx_setPixel(pos, color);
|
||||
|
||||
}
|
||||
}
|
||||
bits <<= 1;
|
||||
}
|
||||
|
@ -295,20 +350,25 @@ void gfx_print(point_t start, const char *text, fontSize_t size, textAlign_t ali
|
|||
*/
|
||||
void gfx_drawBattery(point_t start, uint16_t width, uint16_t height, float percentage) {
|
||||
color_t white = {255, 255, 255};
|
||||
color_t green = {0, 255, 0 };
|
||||
color_t yellow = {250, 180, 19 };
|
||||
color_t red = {255, 0, 0 };
|
||||
color_t black = {0, 0, 0 };
|
||||
|
||||
// Cap percentage to 1
|
||||
percentage = (percentage > 1.0f) ? 1.0f : percentage;
|
||||
|
||||
#ifdef PIX_FMT_RGB565
|
||||
color_t green = {0, 255, 0 };
|
||||
color_t yellow = {250, 180, 19 };
|
||||
color_t red = {255, 0, 0 };
|
||||
|
||||
// Select color according to percentage
|
||||
color_t bat_color = yellow;
|
||||
if (percentage < 0.3)
|
||||
bat_color = red;
|
||||
else if (percentage > 0.6)
|
||||
bat_color = green;
|
||||
#elif defined PIX_FMT_BW
|
||||
color_t bat_color = white;
|
||||
#endif
|
||||
|
||||
// Draw the battery outline
|
||||
gfx_drawRect(start, width, height, white, false);
|
|
@ -1,326 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 by Federico Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN, *
|
||||
* Silvano Seva IU2KWO *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* This source file provides a black and white implementation for the graphics.h interface
|
||||
* It is suitable for monochromatic displays with 1 bit per pixel,
|
||||
* it will have RGB and grayscale counterparts
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "display.h"
|
||||
#include "graphics.h"
|
||||
#include "hwconfig.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WHITE = 0,
|
||||
BLACK = 1,
|
||||
} bw_t;
|
||||
|
||||
bool initialized = 0;
|
||||
uint8_t *buf;
|
||||
uint16_t fbSize;
|
||||
|
||||
void gfx_init()
|
||||
{
|
||||
display_init();
|
||||
buf = (uint8_t *)(display_getFrameBuffer());
|
||||
// Calculate framebuffer size
|
||||
fbSize = (SCREEN_HEIGHT * SCREEN_WIDTH) / 8;
|
||||
/* Compensate for eventual truncation error in division */
|
||||
if((fbSize * 8) < (SCREEN_HEIGHT * SCREEN_WIDTH)) fbSize += 1;
|
||||
fbSize *= sizeof(uint8_t);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
void gfx_terminate()
|
||||
{
|
||||
display_terminate();
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
void gfx_renderRows(uint8_t startRow, uint8_t endRow)
|
||||
{
|
||||
display_renderRows(startRow, endRow);
|
||||
}
|
||||
|
||||
void gfx_render()
|
||||
{
|
||||
display_render();
|
||||
}
|
||||
|
||||
bool gfx_renderingInProgress()
|
||||
{
|
||||
return display_renderingInProgress();
|
||||
}
|
||||
|
||||
bw_t _color2bw(color_t true_color)
|
||||
{
|
||||
if(true_color.r == 0 &&
|
||||
true_color.g == 0 &&
|
||||
true_color.b == 0)
|
||||
return WHITE;
|
||||
else
|
||||
return BLACK;
|
||||
}
|
||||
|
||||
void gfx_clearScreen()
|
||||
{
|
||||
if(!initialized) return;
|
||||
// Set the whole framebuffer to 0x00 = make the screen white
|
||||
memset(buf, 0x00, fbSize);
|
||||
}
|
||||
|
||||
void gfx_fillScreen(color_t color)
|
||||
{
|
||||
if(!initialized) return;
|
||||
bw_t bw = _color2bw(color);
|
||||
if(bw == WHITE)
|
||||
memset(buf, 0x00, fbSize);
|
||||
else if(bw == BLACK)
|
||||
memset(buf, 0xFF, fbSize);
|
||||
}
|
||||
|
||||
void _bw_setPixel(point_t pos, bw_t bw)
|
||||
{
|
||||
/*
|
||||
* Black and white 1bpp format: framebuffer is an array of uint8_t, where
|
||||
* each cell contains the values of eight pixels, one per bit.
|
||||
*/
|
||||
uint16_t cell = (pos.x + pos.y*SCREEN_WIDTH) / 8;
|
||||
uint16_t elem = (pos.x + pos.y*SCREEN_WIDTH) % 8;
|
||||
buf[cell] &= ~(1 << elem);
|
||||
buf[cell] |= (bw << elem);
|
||||
}
|
||||
|
||||
void gfx_setPixel(point_t pos, color_t color)
|
||||
{
|
||||
if (pos.x >= SCREEN_WIDTH || pos.y >= SCREEN_HEIGHT)
|
||||
return; // off the screen
|
||||
bw_t bw = _color2bw(color);
|
||||
_bw_setPixel(pos, bw);
|
||||
}
|
||||
|
||||
void gfx_drawLine(point_t start, point_t end, color_t color)
|
||||
{
|
||||
if(!initialized) return;
|
||||
bw_t bw = _color2bw(color);
|
||||
for(int y = start.y; y <= end.y; y++)
|
||||
{
|
||||
for(int x = start.x; x <= end.x; x++)
|
||||
{
|
||||
point_t pos = {x, y};
|
||||
_bw_setPixel(pos, bw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_drawRect(point_t start, uint16_t width, uint16_t height, color_t color, bool fill)
|
||||
{
|
||||
if(!initialized) return;
|
||||
bw_t bw = _color2bw(color);
|
||||
uint16_t x_max = start.x + width;
|
||||
uint16_t y_max = start.y + height;
|
||||
bool perimeter = 0;
|
||||
if(x_max > (SCREEN_WIDTH - 1)) x_max = SCREEN_WIDTH - 1;
|
||||
if(y_max > (SCREEN_HEIGHT - 1)) y_max = SCREEN_HEIGHT - 1;
|
||||
for(int y = start.y; y < y_max; y++)
|
||||
{
|
||||
for(int x = start.x; x < x_max; x++)
|
||||
{
|
||||
if(y == start.y || y == y_max-1 || x == start.x || x == x_max-1) perimeter = 1;
|
||||
else perimeter = 0;
|
||||
// If fill is false, draw only rectangle perimeter
|
||||
if(fill || perimeter)
|
||||
{
|
||||
point_t pos = {x, y};
|
||||
_bw_setPixel(pos, bw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_drawHLine(uint16_t y, uint16_t height, color_t color)
|
||||
{
|
||||
point_t start = {0, y};
|
||||
gfx_drawRect(start, SCREEN_WIDTH, height, color, 1);
|
||||
}
|
||||
|
||||
void gfx_drawVLine(uint16_t x, uint16_t width, color_t color)
|
||||
{
|
||||
point_t start = {x, 0};
|
||||
gfx_drawRect(start, width, SCREEN_HEIGHT, color, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the pixel size of the first text line
|
||||
* @param f: font used as the source of glyphs
|
||||
* @param text: the input text
|
||||
* @param length: the length of the input text, used for boundary checking
|
||||
*/
|
||||
static inline uint16_t get_line_size(GFXfont f,
|
||||
const char *text,
|
||||
uint16_t length) {
|
||||
uint16_t line_size = 0;
|
||||
for(unsigned i = 0;
|
||||
i < length && text[i] != '\n' && text[i] != '\r';
|
||||
i++) {
|
||||
GFXglyph glyph = f.glyph[text[i] - f.first];
|
||||
if (line_size + glyph.xAdvance < SCREEN_WIDTH)
|
||||
line_size += glyph.xAdvance;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return line_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the start x coordinate of a new line of given pixel size
|
||||
* @param alinment: enum representing the text alignment
|
||||
* @param line_size: the size of the current text line in pixels
|
||||
*/
|
||||
static inline uint16_t get_reset_x(textAlign_t alignment,
|
||||
uint16_t line_size,
|
||||
uint16_t startx) {
|
||||
switch(alignment)
|
||||
{
|
||||
case TEXT_ALIGN_LEFT:
|
||||
return startx;
|
||||
case TEXT_ALIGN_CENTER:
|
||||
return (SCREEN_WIDTH - line_size)/2;
|
||||
case TEXT_ALIGN_RIGHT:
|
||||
return SCREEN_WIDTH - line_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gfx_print(point_t start, const char *text, fontSize_t size, textAlign_t alignment, color_t color) {
|
||||
|
||||
bw_t bw = _color2bw(color);
|
||||
|
||||
GFXfont f = fonts[size];
|
||||
|
||||
size_t len = strlen(text);
|
||||
|
||||
// Compute size of the first row in pixels
|
||||
uint16_t line_size = get_line_size(f, text, len);
|
||||
uint16_t reset_x = get_reset_x(alignment, line_size, start.x);
|
||||
start.x = reset_x;
|
||||
|
||||
/* For each char in the string */
|
||||
for(unsigned i = 0; i < len; i++) {
|
||||
char c = text[i];
|
||||
GFXglyph glyph = f.glyph[c - f.first];
|
||||
uint8_t *bitmap = f.bitmap;
|
||||
|
||||
uint16_t bo = glyph.bitmapOffset;
|
||||
uint8_t w = glyph.width, h = glyph.height;
|
||||
int8_t xo = glyph.xOffset,
|
||||
yo = glyph.yOffset;
|
||||
uint8_t xx, yy, bits = 0, bit = 0;
|
||||
|
||||
// Handle newline and carriage return
|
||||
if (c == '\n') {
|
||||
start.x = reset_x;
|
||||
start.y += f.yAdvance;
|
||||
continue;
|
||||
} else if (c == '\r') {
|
||||
start.x = reset_x;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle wrap around
|
||||
if (start.x + glyph.xAdvance > SCREEN_WIDTH) {
|
||||
// Compute size of the first row in pixels
|
||||
line_size = get_line_size(f, text, len);
|
||||
start.x = reset_x = get_reset_x(alignment, line_size, start.x);
|
||||
start.y += f.yAdvance;
|
||||
}
|
||||
|
||||
// Draw bitmap
|
||||
for (yy = 0; yy < h; yy++) {
|
||||
for (xx = 0; xx < w; xx++) {
|
||||
if (!(bit++ & 7)) {
|
||||
bits = bitmap[bo++];
|
||||
}
|
||||
if (bits & 0x80) {
|
||||
if (start.y + yo + yy < SCREEN_HEIGHT && start.x + xo + xx < SCREEN_WIDTH && start.y + yo + yy > 0 && start.x + xo + xx > 0) {
|
||||
point_t pos = {start.x + xo + xx, start.y + yo + yy};
|
||||
_bw_setPixel(pos, bw);
|
||||
}
|
||||
}
|
||||
bits <<= 1;
|
||||
}
|
||||
}
|
||||
start.x += glyph.xAdvance;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to draw battery of arbitrary size
|
||||
* starting coordinates are relative to the top left point.
|
||||
*
|
||||
* **************** |
|
||||
* * * |
|
||||
* * ******* * |
|
||||
* * ******* ** |
|
||||
* * ******* ** | <-- Height (px)
|
||||
* * ******* * |
|
||||
* * * |
|
||||
* **************** |
|
||||
*
|
||||
* __________________
|
||||
*
|
||||
* ^
|
||||
* |
|
||||
*
|
||||
* Width (px)
|
||||
*
|
||||
*/
|
||||
void gfx_drawBattery(point_t start, uint16_t width, uint16_t height, float percentage) {
|
||||
color_t white = {255, 255, 255};
|
||||
color_t black = {0, 0, 0 };
|
||||
|
||||
// Cap percentage to 1
|
||||
percentage = (percentage > 1.0f) ? 1.0f : percentage;
|
||||
|
||||
// Draw the battery outline
|
||||
gfx_drawRect(start, width, height, white, false);
|
||||
|
||||
// Draw the battery fill
|
||||
point_t fill_start = {start.x + 2, start.y + 2};
|
||||
gfx_drawRect(fill_start, (int)(((float)(width - 4)) * percentage), height - 4, white, true);
|
||||
|
||||
// Round corners
|
||||
point_t top_left = start;
|
||||
point_t top_right = {start.x + width - 1, start.y};
|
||||
point_t bottom_left = {start.x, start.y + height - 1};
|
||||
point_t bottom_right = {start.x + width - 1, start.y + height - 1};
|
||||
gfx_setPixel(top_left, black);
|
||||
gfx_setPixel(top_right, black);
|
||||
gfx_setPixel(bottom_left, black);
|
||||
gfx_setPixel(bottom_right, black);
|
||||
|
||||
// Draw the button
|
||||
point_t button_start = {start.x + width, start.y + height / 2 - (height / 8) - 1 + (height % 2)};
|
||||
point_t button_end = {start.x + width, start.y + height / 2 + (height / 8)};
|
||||
gfx_drawLine(button_start, button_end, white);
|
||||
}
|
|
@ -43,11 +43,6 @@
|
|||
#define SCREEN_HEIGHT 128
|
||||
#endif
|
||||
|
||||
#if !defined(PIX_FMT_BW) && !defined(PIX_FMT_GRAYSC) && !defined(PIX_FMT_RGB565)
|
||||
#warning No pixel format defined, defaulting to RGB565
|
||||
#define PIX_FMT_RGB565
|
||||
#endif
|
||||
|
||||
#ifdef PIX_FMT_RGB565
|
||||
#define PIXEL_FORMAT SDL_PIXELFORMAT_RGB565
|
||||
#define PIXEL_SIZE uint16_t
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#define SCREEN_WIDTH 128
|
||||
#define SCREEN_HEIGHT 64
|
||||
|
||||
/* Screen pixel format */
|
||||
#define PIX_FMT_BW
|
||||
|
||||
/* Battery type */
|
||||
#define BAT_LIPO_2S
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define SCREEN_WIDTH 160
|
||||
#define SCREEN_HEIGHT 128
|
||||
|
||||
/* Screen pixel format */
|
||||
#define PIX_FMT_RGB565
|
||||
|
||||
/* Screen needs x-axis mirroring */
|
||||
#define DISPLAY_MIRROR_X
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define SCREEN_WIDTH 160
|
||||
#define SCREEN_HEIGHT 128
|
||||
|
||||
/* Screen pixel format */
|
||||
#define PIX_FMT_RGB565
|
||||
|
||||
/* Battery type */
|
||||
#define BAT_LIPO_2S
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define SCREEN_WIDTH 160
|
||||
#define SCREEN_HEIGHT 128
|
||||
|
||||
/* Screen pixel format */
|
||||
#define PIX_FMT_RGB565
|
||||
|
||||
/* Battery type */
|
||||
#define BAT_LIPO_2S
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue