fbcon: add support for draw different font sizes and colors
There is requirements to have display to support different font sizes,
colors. Different font sizes are using different factors for same font
size table. Different colors include different background colors and
foreground colors
Change-Id: I7ea611a6761d06e07ddb84ef5f57b03f3e9c731c
diff --git a/dev/fbcon/fbcon.c b/dev/fbcon/fbcon.c
index 885ce87..532ec10 100644
--- a/dev/fbcon/fbcon.c
+++ b/dev/fbcon/fbcon.c
@@ -47,13 +47,30 @@
int y;
};
+struct fb_color {
+ uint32_t fg;
+ uint32_t bg;
+};
+
static struct fbcon_config *config = NULL;
#define RGB565_BLACK 0x0000
#define RGB565_WHITE 0xffff
+#define RGB565_CYAN 0x07ff
+#define RGB565_BLUE 0x001f
+#define RGB565_SILVER 0xc618
+#define RGB565_YELLOW 0xffe0
+#define RGB565_ORANGE 0xfd20
+#define RGB565_RED 0xf800
#define RGB888_BLACK 0x000000
#define RGB888_WHITE 0xffffff
+#define RGB888_CYAN 0x00ffff
+#define RGB888_BLUE 0x0000FF
+#define RGB888_SILVER 0xc0c0c0
+#define RGB888_YELLOW 0xffff00
+#define RGB888_ORANGE 0xffa500
+#define RGB888_RED 0xff0000
#define FONT_WIDTH 5
#define FONT_HEIGHT 12
@@ -62,26 +79,50 @@
static uint32_t BGCOLOR;
static uint32_t FGCOLOR;
+static uint32_t SELECT_BGCOLOR;
static struct pos cur_pos;
static struct pos max_pos;
+static struct fb_color *fb_color_formats;
+static struct fb_color fb_color_formats_555[] = {
+ [FBCON_COMMON_MSG] = {RGB565_WHITE, RGB565_BLACK},
+ [FBCON_UNLOCK_TITLE_MSG] = {RGB565_CYAN, RGB565_BLACK},
+ [FBCON_TITLE_MSG] = {RGB565_WHITE, RGB565_BLACK},
+ [FBCON_SUBTITLE_MSG] = {RGB565_SILVER, RGB565_BLACK},
+ [FBCON_YELLOW_MSG] = {RGB565_YELLOW, RGB565_BLACK},
+ [FBCON_ORANGE_MSG] = {RGB565_ORANGE, RGB565_BLACK},
+ [FBCON_RED_MSG] = {RGB565_RED, RGB565_BLACK},
+ [FBCON_LINE_COLOR] = {RGB565_WHITE, RGB565_WHITE},
+ [FBCON_SELECT_MSG_BG_COLOR] = {RGB565_WHITE, RGB565_BLUE}};
+
+static struct fb_color fb_color_formats_888[] = {
+ [FBCON_COMMON_MSG] = {RGB888_WHITE, RGB888_BLACK},
+ [FBCON_UNLOCK_TITLE_MSG] = {RGB888_CYAN, RGB888_BLACK},
+ [FBCON_TITLE_MSG] = {RGB888_WHITE, RGB888_BLACK},
+ [FBCON_SUBTITLE_MSG] = {RGB888_SILVER, RGB888_BLACK},
+ [FBCON_YELLOW_MSG] = {RGB888_YELLOW, RGB888_BLACK},
+ [FBCON_ORANGE_MSG] = {RGB888_ORANGE, RGB888_BLACK},
+ [FBCON_RED_MSG] = {RGB888_RED, RGB888_BLACK},
+ [FBCON_LINE_COLOR] = {RGB888_WHITE, RGB888_WHITE},
+ [FBCON_SELECT_MSG_BG_COLOR] = {RGB888_WHITE, RGB888_BLUE}};
+
static void fbcon_drawglyph(char *pixels, uint32_t paint, unsigned stride,
- unsigned bpp, unsigned *glyph)
+ unsigned bpp, unsigned *glyph, unsigned scale_factor)
{
unsigned x, y, i, j, k;
unsigned data, temp;
uint32_t fg_color = paint;
- stride -= FONT_WIDTH * SCALE_FACTOR;
+ stride -= FONT_WIDTH * scale_factor;
data = glyph[0];
for (y = 0; y < FONT_HEIGHT / 2; ++y) {
temp = data;
- for (i = 0; i < SCALE_FACTOR; i++) {
+ for (i = 0; i < scale_factor; i++) {
data = temp;
for (x = 0; x < FONT_WIDTH; ++x) {
if (data & 1) {
- for (j = 0; j < SCALE_FACTOR; j++) {
+ for (j = 0; j < scale_factor; j++) {
fg_color = paint;
for (k = 0; k < bpp; k++) {
*pixels = (unsigned char) fg_color;
@@ -92,7 +133,7 @@
}
else
{
- for (j = 0; j < SCALE_FACTOR; j++) {
+ for (j = 0; j < scale_factor; j++) {
pixels = pixels + bpp;
}
}
@@ -105,11 +146,11 @@
data = glyph[1];
for (y = 0; y < FONT_HEIGHT / 2; ++y) {
temp = data;
- for (i = 0; i < SCALE_FACTOR; i++) {
+ for (i = 0; i < scale_factor; i++) {
data = temp;
for (x = 0; x < FONT_WIDTH; ++x) {
if (data & 1) {
- for (j = 0; j < SCALE_FACTOR; j++) {
+ for (j = 0; j < scale_factor; j++) {
fg_color = paint;
for (k = 0; k < bpp; k++) {
*pixels = (unsigned char) fg_color;
@@ -120,7 +161,7 @@
}
else
{
- for (j = 0; j < SCALE_FACTOR; j++) {
+ for (j = 0; j < scale_factor; j++) {
pixels = pixels + bpp;
}
}
@@ -132,6 +173,44 @@
}
+void fbcon_draw_msg_background(unsigned y_start, unsigned y_end,
+ uint32_t old_paint, int update)
+{
+ unsigned i, j;
+ uint32_t bg_color, check_color, tmp_color, tmp1_color;
+ char *pixels;
+ unsigned count = config->width * (FONT_HEIGHT * (y_end - y_start) - 1);
+
+ pixels = config->base;
+ pixels += y_start * ((config->bpp / 8) * FONT_HEIGHT * config->width);
+
+ if (update) {
+ bg_color = SELECT_BGCOLOR;
+ check_color = old_paint;
+ } else {
+ bg_color = old_paint;
+ check_color = SELECT_BGCOLOR;
+ }
+
+ for (i = 0; i < count; i++) {
+ tmp1_color = bg_color;
+ tmp_color = 0;
+ for (j = 0; j < (config->bpp / 8); j++) {
+ tmp_color |= *(pixels+j) << j*8;
+ }
+
+ if (tmp_color == check_color) {
+ for (j = 0; j < (config->bpp / 8); j++) {
+ *pixels = (unsigned char) tmp1_color;
+ tmp1_color = tmp1_color >> 8;
+ pixels++;
+ }
+ } else {
+ pixels += config->bpp / 8;
+ }
+ }
+}
+
static void fbcon_flush(void)
{
unsigned total_x, total_y;
@@ -167,13 +246,50 @@
fbcon_flush();
}
-/* TODO: take stride into account */
+void fbcon_draw_line()
+{
+ char *pixels;
+ uint32_t bg_color, tmp_color;
+ int i, j;
+
+ bg_color = fb_color_formats[FBCON_LINE_COLOR].bg;
+
+ pixels = config->base;
+ pixels += cur_pos.y * ((config->bpp / 8) * FONT_HEIGHT * config->width);
+ pixels += cur_pos.x * ((config->bpp / 8) * (FONT_WIDTH + 1));
+
+ for (i = 0; i < (int)config->width; i++) {
+ tmp_color = bg_color;
+ for (j = 0; j < (int)(config->bpp / 8); j++) {
+ *pixels = (unsigned char) tmp_color;
+ tmp_color = tmp_color >> 8;
+ pixels++;
+ }
+ }
+
+ cur_pos.y += 1;
+ cur_pos.x = 0;
+ if(cur_pos.y >= max_pos.y) {
+ cur_pos.y = max_pos.y - 1;
+ fbcon_scroll_up();
+ } else
+ fbcon_flush();
+}
+
+static void fbcon_set_colors(int type)
+{
+ BGCOLOR = fb_color_formats[type].bg;
+ FGCOLOR = fb_color_formats[type].fg;
+}
+
void fbcon_clear(void)
{
unsigned long i = 0, j = 0;
unsigned char *pixels = config->base;
unsigned count = config->width * config->height;
uint32_t bg_color;
+
+ fbcon_set_colors(FBCON_COMMON_MSG);
for (i = 0; i < count; i++) {
bg_color = BGCOLOR;
for (j = 0; j < (config->bpp / 8); j++) {
@@ -182,16 +298,11 @@
pixels++;
}
}
+ cur_pos.x = 0;
+ cur_pos.y = 0;
}
-
-static void fbcon_set_colors(unsigned bg, unsigned fg)
-{
- BGCOLOR = bg;
- FGCOLOR = fg;
-}
-
-void fbcon_putc(char c)
+void fbcon_putc_factor(char c, int type, unsigned scale_factor)
{
char *pixels;
@@ -213,18 +324,28 @@
return;
}
- pixels = config->base;
- pixels += cur_pos.y * SCALE_FACTOR * ((config->bpp / 8) * FONT_HEIGHT * config->width);
- pixels += cur_pos.x * SCALE_FACTOR * ((config->bpp / 8) * (FONT_WIDTH + 1));
- fbcon_drawglyph(pixels, FGCOLOR, config->stride, (config->bpp / 8),
- font5x12 + (c - 32) * 2);
-
- cur_pos.x++;
- if (cur_pos.x < max_pos.x)
+ if (cur_pos.x == 0 && (unsigned char)c == ' ' &&
+ type != FBCON_SUBTITLE_MSG &&
+ type != FBCON_TITLE_MSG)
return;
+ fbcon_set_colors(type);
+
+ pixels = config->base;
+ pixels += cur_pos.y * ((config->bpp / 8) * FONT_HEIGHT * config->width);
+ pixels += cur_pos.x * scale_factor * ((config->bpp / 8) * (FONT_WIDTH + 1));
+
+ fbcon_drawglyph(pixels, FGCOLOR, config->stride, (config->bpp / 8),
+ font5x12 + (c - 32) * 2, scale_factor);
+
+ cur_pos.x++;
+ if (cur_pos.x >= (int)(max_pos.x / scale_factor))
+ goto newline;
+
+ return;
+
newline:
- cur_pos.y++;
+ cur_pos.y += scale_factor;
cur_pos.x = 0;
if(cur_pos.y >= max_pos.y) {
cur_pos.y = max_pos.y - 1;
@@ -233,39 +354,57 @@
fbcon_flush();
}
+void fbcon_putc(char c)
+{
+ fbcon_putc_factor(c, FBCON_COMMON_MSG, SCALE_FACTOR);
+}
+
+uint32_t fbcon_get_current_line(void)
+{
+ return cur_pos.y;
+}
+
+uint32_t fbcon_get_max_x(void)
+{
+ return max_pos.x;
+}
+
+uint32_t fbcon_get_current_bg(void)
+{
+ return BGCOLOR;
+}
+
void fbcon_setup(struct fbcon_config *_config)
{
- uint32_t bg = 0;
- uint32_t fg = 0;
-
ASSERT(_config);
config = _config;
switch (config->format) {
case FB_FORMAT_RGB565:
- fg = RGB565_WHITE;
- bg = RGB565_BLACK;
+ fb_color_formats = fb_color_formats_555;
break;
- case FB_FORMAT_RGB888:
- fg = RGB888_WHITE;
- bg = RGB888_BLACK;
- break;
+ case FB_FORMAT_RGB888:
+ fb_color_formats = fb_color_formats_888;
+ break;
default:
dprintf(CRITICAL, "unknown framebuffer pixel format\n");
ASSERT(0);
break;
}
- fbcon_set_colors(bg, fg);
+ SELECT_BGCOLOR = fb_color_formats[FBCON_SELECT_MSG_BG_COLOR].bg;
+ fbcon_set_colors(FBCON_COMMON_MSG);
cur_pos.x = 0;
cur_pos.y = 0;
- max_pos.x = config->width / ((FONT_WIDTH + 1) * SCALE_FACTOR);
+ max_pos.x = config->width / (FONT_WIDTH+1);
max_pos.y = (config->height - 1) / FONT_HEIGHT;
+
#if !DISPLAY_SPLASH_SCREEN
fbcon_clear();
#endif
+
}
struct fbcon_config* fbcon_display(void)
diff --git a/include/dev/fbcon.h b/include/dev/fbcon.h
index e96b663..123532c 100644
--- a/include/dev/fbcon.h
+++ b/include/dev/fbcon.h
@@ -37,6 +37,25 @@
#define LOGO_IMG_MAGIC_SIZE sizeof(LOGO_IMG_MAGIC) - 1
#define LOGO_IMG_HEADER_SIZE 512
+enum fbcon_msg_type {
+ /* type for menu */
+ FBCON_COMMON_MSG = 0,
+ FBCON_UNLOCK_TITLE_MSG,
+ FBCON_TITLE_MSG,
+ FBCON_SUBTITLE_MSG,
+
+ /* type for warning */
+ FBCON_YELLOW_MSG,
+ FBCON_ORANGE_MSG,
+ FBCON_RED_MSG,
+
+ /* type for line color */
+ FBCON_LINE_COLOR,
+
+ /* and the select message's background */
+ FBCON_SELECT_MSG_BG_COLOR,
+};
+
typedef struct logo_img_header {
unsigned char magic[LOGO_IMG_MAGIC_SIZE]; // "SPLASH!!"
uint32_t width; // logo's width, little endian
@@ -74,5 +93,11 @@
void fbcon_clear(void);
struct fbcon_config* fbcon_display(void);
void fbcon_extract_to_screen(logo_img_header *header, void* address);
-
+void fbcon_putc_factor(char c, int type, unsigned scale_factor);
+void fbcon_draw_msg_background(unsigned y_start, unsigned y_end,
+ uint32_t paint, int update);
+void fbcon_draw_line(void);
+uint32_t fbcon_get_current_line(void);
+uint32_t fbcon_get_current_bg(void);
+uint32_t fbcon_get_max_x(void);
#endif /* __DEV_FBCON_H */