os-workshop

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 124ebe7a6eebce9150d949189b9e535138b8be3b
parent 3b15f7a132033d76091d6c3096b15ab7a36f0180
Author: Brian Swetland <swetland@frotz.net>
Date:   Thu, 12 May 2022 18:09:55 -0700

libgfx: add text surface routines

Diffstat:
Mlibgfx/inc/gfx/gfx.h | 16++++++++++++++++
Mlibgfx/src/gfx.c | 13++++++++++++-
Alibgfx/src/txt.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mproject/gfx.lib.mk | 2+-
4 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/libgfx/inc/gfx/gfx.h b/libgfx/inc/gfx/gfx.h @@ -40,5 +40,21 @@ static inline void gfx_putc(gfx_surface_t* gs, uint32_t x, uint32_t y, uint32_t gs->putc(gs, x, y, ch); } +void gfx_fill(gfx_surface_t* gs, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1); +void gfx_clear(gfx_surface_t* gs); void gfx_puts(gfx_surface_t* gs, uint32_t x, uint32_t y, const char* s); void gfx_printf(gfx_surface_t* gs, uint32_t x, uint32_t y, const char* fmt, ...); + + +typedef struct txt_surface { + gfx_surface_t *gs; + uint32_t cw; + uint32_t ch; + uint32_t cx; + uint32_t cy; +} txt_surface_t; + +void txt_init(txt_surface_t *ts, gfx_surface_t *gs); +void txt_puts(txt_surface_t *ts, const char *s); +void txt_printf(txt_surface_t *ts, const char *fmt, ...); +void txt_goto(txt_surface_t *ts, uint32_t cx, uint32_t cy); diff --git a/libgfx/src/gfx.c b/libgfx/src/gfx.c @@ -34,7 +34,7 @@ static void hline16(gfx_surface_t *gs, uint32_t x0, uint32_t y, uint32_t x1) { if (unlikely((x1 > gs->width))) { x1 = gs->width; } - uint16_t *pixels = gs->pixels + x0 + y * gs->stride; + uint16_t *pixels = ((uint16_t*)gs->pixels) + x0 + y * gs->stride; uint16_t *end = pixels + x1 - x0; uint32_t c = gs->fgcolor; while (pixels < end) { @@ -89,6 +89,17 @@ void gfx_init_display(gfx_surface_t *gs) { gfx_init(gs); } +void gfx_fill(gfx_surface_t* gs, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) { + while (y0 < y1) { + gs->hline(gs, x0, y0, x1); + y0++; + } +} + +void gfx_clear(gfx_surface_t* gs) { + gfx_fill(gs, 0, 0, gs->width, gs->height); +} + void gfx_puts(gfx_surface_t *gs, uint32_t x, uint32_t y, const char* s) { while (*s) { gs->putc(gs, x, y, *s++); diff --git a/libgfx/src/txt.c b/libgfx/src/txt.c @@ -0,0 +1,63 @@ +// Copyright 2022, Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0 + +#include <stdio.h> +#include <stdarg.h> + +#include <gfx/gfx.h> +#include <compiler.h> +#include <hw/platform.h> + +#define CH_WIDTH 8 +#define CH_HEIGHT 16 + +void txt_init(txt_surface_t *ts, gfx_surface_t *gs) { + ts->gs = gs; + ts->cw = gs->width / CH_WIDTH; + ts->ch = gs->height / CH_HEIGHT; + ts->cx = 0; + ts->cy = 0; +}; + +void txt_goto(txt_surface_t *ts, uint32_t cx, uint32_t cy) { + if (cx >= ts->cw) { + cx = ts->cw - 1; + } + if (cy >= ts->ch) { + cx = ts->ch - 1; + } + ts->cx = cx; + ts->cy = cy; +} + +void txt_putc(txt_surface_t *ts, uint32_t ch) { + if ((ch == '\r') || (ch == '\n')) { +newline: + ts->cx = 0; + ts->cy++; + if (ts->cy >= ts->ch) { + ts->cy = 0; + } + return; + } + gfx_putc(ts->gs, ts->cx * CH_WIDTH, ts->cy * CH_HEIGHT, ch); + ts->cx++; + if (ts->cx >= ts->cw) { + goto newline; + } +} + +void txt_puts(txt_surface_t *ts, const char *s) { + while (*s) { + txt_putc(ts, *s++); + } +} + +void txt_printf(txt_surface_t *ts, const char *fmt, ...) { + char msg[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + txt_puts(ts, msg); +} diff --git a/project/gfx.lib.mk b/project/gfx.lib.mk @@ -1,6 +1,6 @@ MOD_NAME := gfx -MOD_SRC := libgfx/src/gfx.c +MOD_SRC := libgfx/src/gfx.c libgfx/src/txt.c MOD_SRC += external/vgafonts.c MOD_LIB := c