summaryrefslogtreecommitdiff
path: root/kc/core/video.c
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2023-02-05 12:00:29 +0000
committerAda Christine <adachristine18@gmail.com>2023-02-05 12:00:29 +0000
commit05223a4bf6a3927ac638617d2e85bf3d0a348cb2 (patch)
tree1ed1aa6a4b4f9857fe580256f1924b71f0bdc028 /kc/core/video.c
parent90515f75de3a428f10d022469b641f27be61bb89 (diff)
render glyphs to bitmap and copy
Diffstat (limited to 'kc/core/video.c')
-rw-r--r--kc/core/video.c95
1 files changed, 81 insertions, 14 deletions
diff --git a/kc/core/video.c b/kc/core/video.c
index 383cee0..ec1edf3 100644
--- a/kc/core/video.c
+++ b/kc/core/video.c
@@ -47,12 +47,12 @@
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
-static const int FONT_WIDTH = 8;
-static const int FONT_HEIGHT = 13;
-static const int CELL_WIDTH = 9;
-static const int CELL_HEIGHT = 14;
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 13
+#define CELL_WIDTH 9
+#define CELL_HEIGHT 14
-static const int CHARACTER_OFFSET = 32;
+#define CHARACTER_OFFSET 32
static const unsigned char ascii_characters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
@@ -164,7 +164,7 @@ struct video_dimensions
int32_t height;
};
-struct video_rectangle
+struct video_rect
{
struct video_point pos;
struct video_dimensions size;
@@ -210,6 +210,7 @@ static struct video_bitmap framebuffer_bitmap;
static struct console_state console_state;
static void *pixel_addr(struct video_bitmap *bitmap, struct video_point pos);
+static void pixel_set(struct video_bitmap *bitmap, struct video_point pos, struct video_color color);
static int pixel_put(struct video_color color, int xpos, int ypos);
static int character_draw(int c);
@@ -266,7 +267,15 @@ static int pixel_put(struct video_color color, int xpos, int ypos)
static void *pixel_addr(struct video_bitmap *bitmap, struct video_point pos)
{
int32_t offset = pos.y * bitmap->pitch + pos.x * bitmap->bpp;
- return offset + (char *)framebuffer_bitmap.buffer;
+ return offset + (char *)bitmap->buffer;
+}
+
+static void pixel_set(struct video_bitmap *bitmap, struct video_point pos, struct video_color color)
+{
+ struct video_pixel_bgra32 *pixel = pixel_addr(bitmap, pos);
+ pixel->red = color.red;
+ pixel->green = color.green;
+ pixel->blue = color.blue;
}
static void console_feed_line()
@@ -296,20 +305,78 @@ int video_putchar(int c)
return 0;
}
+static size_t min_sz(size_t left, size_t right)
+{
+ return (left < right) ? left : right;
+}
+
+static void bitmap_copy(struct video_bitmap *dest, struct video_bitmap *src, struct video_point dest_pos, struct video_rect src_rect)
+{
+ void * (*copy_func)(void *, const void *, size_t) = memcpy;
+
+ if (dest == src)
+ {
+ copy_func = memmove;
+ }
+
+ for (int i = 0; i < src_rect.size.height; i++)
+ {
+ struct video_point line_pos = {dest_pos.x, dest_pos.y + i};
+ struct video_point src_line_pos = {src_rect.pos.x, src_rect.pos.y + i};
+
+ if ((unsigned)(dest_pos.y + i) > dest->height)
+ {
+ break;
+ }
+
+ size_t dest_stride = (dest->width - dest_pos.x) * dest->bpp;
+ size_t src_stride = (src_rect.size.width - src_rect.pos.x) * src->bpp;
+
+ void *dest_addr = pixel_addr(dest, line_pos);
+ void *src_addr = pixel_addr(src, src_line_pos);
+
+ copy_func(dest_addr, src_addr, min_sz(dest_stride, src_stride));
+ }
+}
+
+static struct video_color glyph_pixel(int c, struct video_point pos, struct video_color foreground, struct video_color background)
+{
+ int index = c - CHARACTER_OFFSET;
+ return ascii_characters[index][FONT_HEIGHT - 1 - pos.y] & (1 << (FONT_WIDTH - 1 - pos.x)) ? foreground : background;
+}
+
int character_draw(int c)
{
- for (int i = 0; i < FONT_HEIGHT; i++)
+ struct video_pixel_bgra32 buffer[FONT_HEIGHT][FONT_WIDTH] = {{0}};
+ struct video_bitmap glyph =
+ {
+ framebuffer_bitmap.format,
+ FONT_HEIGHT,
+ FONT_WIDTH,
+ framebuffer_bitmap.bpp,
+ FONT_WIDTH * framebuffer_bitmap.bpp,
+ buffer
+ };
+
+ struct video_rect glyph_rect = { { 0, 0 }, { glyph.width, glyph.height } };
+
+ struct video_point glyph_pos = {0};
+ struct video_point framebuffer_pos =
+ {
+ console_state.cursor_column * CELL_WIDTH,
+ console_state.cursor_line * CELL_HEIGHT
+ };
+
+ (void)c;
+ for (glyph_pos.y = 0; glyph_pos.y < FONT_HEIGHT; glyph_pos.y++)
{
- for (int j = 0; j < FONT_WIDTH; j++)
+ for (glyph_pos.x = 0; glyph_pos.x < FONT_WIDTH; glyph_pos.x++)
{
- int top = console_state.cursor_line * CELL_HEIGHT;
- int left = console_state.cursor_column * CELL_WIDTH;
- pixel_put(ascii_characters[c - CHARACTER_OFFSET][i] & (1 << j) ? console_state.foreground : console_state.background,
- left + FONT_WIDTH - j,
- top + FONT_HEIGHT - i);
+ pixel_set(&glyph, glyph_pos, glyph_pixel(c, glyph_pos, console_state.foreground, console_state.background));
}
}
+ bitmap_copy(&framebuffer_bitmap, &glyph, framebuffer_pos, glyph_rect);
return 0;
}