diff --git a/README.md b/README.md index 8ac137b..472975b 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ This can still be considered work in progress. API should be 90% stable. To use HAGL you must provide a backend. The backend must provide atleast a function for putting a pixel. If nothing else is provided all higher level graphical functions will use this function to draw the primitives. While proper documentation is lacking see the example backend implementations for [GD](https://github.com/tuupola/hagl_gd), [SDL2](https://github.com/tuupola/hagl_sdl2), [ESP-IDF (Ilitek, Sitronix, Galaxycore)](https://github.com/tuupola/hagl_esp_mipi), [ESP-IDF (Solomon)](https://github.com/tuupola/hagl_esp_solomon), [Nuclei RISC-V SDK](https://github.com/tuupola/hagl_gd32v_mipi) and [Raspberry Pi Pico SDK](https://github.com/tuupola/hagl_pico_mipi). - ## Usage High level functions are pretty self explanatory. For example applications see [Pico Effects](https://github.com/tuupola/pico_effects), [ESP Effects](https://github.com/tuupola/esp_effects), [SDL2 Effects](https://github.com/tuupola/sdl2_effects), [ESP GFX](https://github.com/tuupola/esp_gfx), and [GD32V Effects](https://github.com/tuupola/gd32v_effects/). @@ -58,20 +57,21 @@ color_t color = hagl_color(display, r, g, b); ```c for (uint32_t i = 1; i < 100000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; color_t color = rand() % 0xffff; hagl_put_pixel(display, x0, y0, color); } ``` + ![Random pixels](https://appelsiini.net/img/2020/hagl-put-pixel-gh.png) ## Get a pixel ```c -int16_t x0 = rand() % DISPLAY_WIDTH; -int16_t y0 = rand() % DISPLAY_HEIGHT; +int16_t x0 = rand() % display->width; +int16_t y0 = rand() % display->height; color_t pixel = hagl_get_pixel(display, x0, y0); ``` @@ -80,13 +80,12 @@ Note that if requesting coordinates outside the clip window color black is retur ### Draw a line - ```c for (uint16_t i = 1; i < 1000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t x1 = rand() % DISPLAY_WIDTH; - int16_t y1 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; + int16_t x1 = rand() % display->width; + int16_t y1 = rand() % display->height; color_t color = rand() % 0xffff; hagl_draw_line(display, x0, y0, x1, y1, color); @@ -99,10 +98,10 @@ for (uint16_t i = 1; i < 1000; i++) { ```c for (uint16_t i = 1; i < 1000; i++) { - int16_t x0 = rand() % (DISPLAY_WIDTH / 2); - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t x1 = rand() % (DISPLAY_WIDTH / 2); - int16_t width = rand() % (DISPLAY_WIDTH - x0); + int16_t x0 = rand() % (display->width / 2); + int16_t y0 = rand() % display->height; + int16_t x1 = rand() % (display->width / 2); + int16_t width = rand() % (display->width - x0); color_t color = rand() % 0xffff; /* First two are aliases. */ @@ -119,10 +118,10 @@ for (uint16_t i = 1; i < 1000; i++) { ```c for (uint16_t i = 1; i < 1000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % (DISPLAY_HEIGHT / 2); - int16_t y1 = rand() % (DISPLAY_HEIGHT / 2); - int16_t height = rand() % (DISPLAY_HEIGHT - y0); + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % (display->height / 2); + int16_t y1 = rand() % (display->height / 2); + int16_t height = rand() % (display->height - y0); color_t color = rand() % 0xffff; /* First two are aliases. */ @@ -139,9 +138,9 @@ for (uint16_t i = 1; i < 1000; i++) { ```c for (uint16_t i = 1; i < 500; i++) { - int16_t x0 = DISPLAY_WIDTH / 2; - int16_t y0 = DISPLAY_HEIGHT / 2; - int16_t radius = rand() % DISPLAY_WIDTH; + int16_t x0 = display->width / 2; + int16_t y0 = display->height / 2; + int16_t radius = rand() % display->width; color_t color = rand() % 0xffff; hagl_draw_circle(display, x0, y0, radius, color); @@ -154,8 +153,8 @@ for (uint16_t i = 1; i < 500; i++) { ```c for (uint16_t i = 1; i < 500; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; int16_t radius = rand() % 100; color_t color = rand() % 0xffff; @@ -169,10 +168,10 @@ for (uint16_t i = 1; i < 500; i++) { ```c for (uint16_t i = 1; i < 500; i++) { - int16_t x0 = DISPLAY_WIDTH / 2; - int16_t y0 = DISPLAY_HEIGHT / 2; - int16_t rx = rand() % DISPLAY_WIDTH; - int16_t ry = rand() % DISPLAY_HEIGHT; + int16_t x0 = display->width / 2; + int16_t y0 = display->height / 2; + int16_t rx = rand() % display->width; + int16_t ry = rand() % display->height; color_t color = rand() % 0xffff; hagl_draw_ellipse(display, x0, y0, rx, ry, color); @@ -185,10 +184,10 @@ for (uint16_t i = 1; i < 500; i++) { ```c for (uint16_t i = 1; i < 500; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t rx = rand() % DISPLAY_WIDTH / 4; - int16_t ry = rand() % DISPLAY_HEIGHT / 4; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; + int16_t rx = rand() % display->width / 4; + int16_t ry = rand() % display->height / 4; color_t color = rand() % 0xffff; hagl_fill_ellipse(display, x0, y0, rx, ry, color); @@ -200,12 +199,12 @@ for (uint16_t i = 1; i < 500; i++) { ### Draw a triangle ```c -int16_t x0 = rand() % DISPLAY_WIDTH; -int16_t y0 = rand() % DISPLAY_HEIGHT; -int16_t x1 = rand() % DISPLAY_WIDTH; -int16_t y1 = rand() % DISPLAY_HEIGHT; -int16_t x2 = rand() % DISPLAY_WIDTH; -int16_t y2 = rand() % DISPLAY_HEIGHT; +int16_t x0 = rand() % display->width; +int16_t y0 = rand() % display->height; +int16_t x1 = rand() % display->width; +int16_t y1 = rand() % display->height; +int16_t x2 = rand() % display->width; +int16_t y2 = rand() % display->height; color_t color = rand() % 0xffff; hagl_draw_triangle(display, x0, y0, x1, y1, x2, y2, color); @@ -216,12 +215,12 @@ hagl_draw_triangle(display, x0, y0, x1, y1, x2, y2, color); ### Draw a filled triangle ```c -int16_t x0 = rand() % DISPLAY_WIDTH; -int16_t y0 = rand() % DISPLAY_HEIGHT; -int16_t x1 = rand() % DISPLAY_WIDTH; -int16_t y1 = rand() % DISPLAY_HEIGHT; -int16_t x2 = rand() % DISPLAY_WIDTH; -int16_t y2 = rand() % DISPLAY_HEIGHT; +int16_t x0 = rand() % display->width; +int16_t y0 = rand() % display->height; +int16_t x1 = rand() % display->width; +int16_t y1 = rand() % display->height; +int16_t x2 = rand() % display->width; +int16_t y2 = rand() % display->height; color_t color = rand() % 0xffff; hagl_fill_triangle(display, x0, y0, x1, y1, x2, y2, color); @@ -233,12 +232,12 @@ hagl_fill_triangle(display, x0, y0, x1, y1, x2, y2, color); ```c for (uint16_t i = 1; i < 50; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t x1 = rand() % DISPLAY_WIDTH; - int16_t y1 = rand() % DISPLAY_HEIGHT; - int16_t w = rand() % DISPLAY_WIDTH / 2; - int16_t h = rand() % DISPLAY_HEIGHT / 2; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; + int16_t x1 = rand() % display->width; + int16_t y1 = rand() % display->height; + int16_t w = rand() % display->width / 2; + int16_t h = rand() % display->height / 2; color_t color = rand() % 0xffff; /* First two are aliases. */ @@ -255,12 +254,12 @@ for (uint16_t i = 1; i < 50; i++) { ```c for (uint16_t i = 1; i < 10; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t x1 = rand() % DISPLAY_WIDTH; - int16_t y1 = rand() % DISPLAY_HEIGHT; - int16_t w = rand() % DISPLAY_WIDTH / 2; - int16_t h = rand() % DISPLAY_HEIGHT / 2; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; + int16_t x1 = rand() % display->width; + int16_t y1 = rand() % display->height; + int16_t w = rand() % display->width / 2; + int16_t h = rand() % display->height / 2; color_t color = rand() % 0xffff; /* First two are aliases. */ @@ -273,17 +272,16 @@ for (uint16_t i = 1; i < 10; i++) { ![Random filled rectangle](https://appelsiini.net/img/2020/pod-fill-rectangle.png) - ### Draw a rounded rectangle ```c for (uint16_t i = 1; i < 30; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t x1 = rand() % DISPLAY_WIDTH; - int16_t y1 = rand() % DISPLAY_HEIGHT; - int16_t w = rand() % DISPLAY_WIDTH / 2; - int16_t h = rand() % DISPLAY_HEIGHT / 2; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; + int16_t x1 = rand() % display->width; + int16_t y1 = rand() % display->height; + int16_t w = rand() % display->width / 2; + int16_t h = rand() % display->height / 2; int16_t r = 10 color_t color = rand() % 0xffff; @@ -301,12 +299,12 @@ for (uint16_t i = 1; i < 30; i++) { ```c for (uint16_t i = 1; i < 30; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; - int16_t x1 = rand() % DISPLAY_WIDTH; - int16_t y1 = rand() % DISPLAY_HEIGHT; - int16_t w = rand() % DISPLAY_WIDTH / 2; - int16_t h = rand() % DISPLAY_HEIGHT / 2; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; + int16_t x1 = rand() % display->width; + int16_t y1 = rand() % display->height; + int16_t w = rand() % display->width / 2; + int16_t h = rand() % display->height / 2; int16_t r = 10 color_t color = rand() % 0xffff; @@ -325,16 +323,16 @@ for (uint16_t i = 1; i < 30; i++) { You can draw polygons with unlimited number of vertices which are passed as an array. Pass the number of vertices as the first argument. ```c -int16_t x0 = rand() % DISPLAY_WIDTH; -int16_t y0 = rand() % DISPLAY_HEIGHT; -int16_t x1 = rand() % DISPLAY_WIDTH; -int16_t y1 = rand() % DISPLAY_HEIGHT; -int16_t x2 = rand() % DISPLAY_WIDTH; -int16_t y2 = rand() % DISPLAY_HEIGHT; -int16_t x3 = rand() % DISPLAY_WIDTH; -int16_t y3 = rand() % DISPLAY_HEIGHT; -int16_t x4 = rand() % DISPLAY_WIDTH; -int16_t y4 = rand() % DISPLAY_HEIGHT; +int16_t x0 = rand() % display->width; +int16_t y0 = rand() % display->height; +int16_t x1 = rand() % display->width; +int16_t y1 = rand() % display->height; +int16_t x2 = rand() % display->width; +int16_t y2 = rand() % display->height; +int16_t x3 = rand() % display->width; +int16_t y3 = rand() % display->height; +int16_t x4 = rand() % display->width; +int16_t y4 = rand() % display->height; color_t color = rand() % 0xffff; int16_t vertices[10] = {x0, y0, x1, y1, x2, y2, x3, y3, x4, y4}; @@ -348,16 +346,16 @@ hagl_draw_polygon(display, 5, vertices, color); You can draw filled polygons with up to 64 vertices which are passed as an array. First argument is the number of vertices. Polygon does **not** have to be concave. ```c -int16_t x0 = rand() % DISPLAY_WIDTH; -int16_t y0 = rand() % DISPLAY_HEIGHT; -int16_t x1 = rand() % DISPLAY_WIDTH; -int16_t y1 = rand() % DISPLAY_HEIGHT; -int16_t x2 = rand() % DISPLAY_WIDTH; -int16_t y2 = rand() % DISPLAY_HEIGHT; -int16_t x3 = rand() % DISPLAY_WIDTH; -int16_t y3 = rand() % DISPLAY_HEIGHT; -int16_t x4 = rand() % DISPLAY_WIDTH; -int16_t y4 = rand() % DISPLAY_HEIGHT; +int16_t x0 = rand() % display->width; +int16_t y0 = rand() % display->height; +int16_t x1 = rand() % display->width; +int16_t y1 = rand() % display->height; +int16_t x2 = rand() % display->width; +int16_t y2 = rand() % display->height; +int16_t x3 = rand() % display->width; +int16_t y3 = rand() % display->height; +int16_t x4 = rand() % display->width; +int16_t y4 = rand() % display->height; color_t color = rand() % 0xffff; int16_t vertices[10] = {x0, y0, x1, y1, x2, y2, x3, y3, x4, y4}; @@ -366,15 +364,14 @@ hagl_fill_polygon(display, 5, vertices, color); ![Random filled polygon](https://appelsiini.net/img/2020/pod-fill-polygon.png) - ### Put a single char The library supports Unicode fonts in fontx format. It only includes three fonts by default. You can find more at [tuupola/embedded-fonts](https://github.com/tuupola/embedded-fonts) repository. ```c for (uint16_t i = 1; i < 10000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; color_t color = rand() % 0xffff; char code = rand() % 255; @@ -390,8 +387,8 @@ The library supports Unicode fonts in fontx format. It only includes three fonts ```c for (uint16_t i = 1; i < 10000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; color_t color = rand() % 0xffff; hagl_put_text(display, u"YO! MTV raps.", x0, y0, color, font6x9); @@ -409,8 +406,8 @@ hagl_bitmap_t bitmap; bitmap.buffer = (uint8_t *) malloc(6 * 9 * sizeof(color_t)); for (uint16_t i = 1; i < 20000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; color_t color = rand() % 0xffff; uint16_t code = rand() % 0xffff; hagl_get_glyph(display, code, color, &bitmap, font6x9); @@ -423,7 +420,6 @@ for (uint16_t i = 1; i < 20000; i++) { ![Random blits](https://appelsiini.net/img/2020/hagl-blit.png) - ### Blit a bitmap scaled up or down Scale blit copies and scales a [bitmap](https://github.com/tuupola/hagl/blob/master/bitmap.c) to the surface. This example uses a glyph bitmap which is extracted from a font. @@ -433,8 +429,8 @@ hagl_bitmap_t bitmap; bitmap.buffer = (uint8_t *) malloc(6 * 9 * sizeof(color_t)); for (uint16_t i = 1; i < 20000; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; color_t color = rand() % 0xffff; uint16_t code = rand() % 0xffff; hagl_get_glyph(display, code, color, &bitmap, font6x9); @@ -452,11 +448,11 @@ for (uint16_t i = 1; i < 20000; i++) { You can restrict the area of drawing by setting a clip window. ```c -hagl_set_clip(display, 0, 40, DISPLAY_WIDTH, DISPLAY_HEIGHT - 40); +hagl_set_clip(display, 0, 40, display->width, display->height - 40); for (uint16_t i = 1; i < 500; i++) { - int16_t x0 = rand() % DISPLAY_WIDTH; - int16_t y0 = rand() % DISPLAY_HEIGHT; + int16_t x0 = rand() % display->width; + int16_t y0 = rand() % display->height; int16_t radius = rand() % 100; color_t color = rand() % 0xffff; diff --git a/include/hagl.h b/include/hagl.h index 5ad2bfc..ef01700 100644 --- a/include/hagl.h +++ b/include/hagl.h @@ -62,7 +62,12 @@ extern "C" { #define ABS(x) ((x) > 0 ? (x) : -(x)) -#define HAGL_CHAR_BUFFER_SIZE (16 * 16 * DISPLAY_DEPTH / 2) +/* TODO find a more elegant solution to define char buffer size */ +/* and keep memory allocation static, as we should avoid using malloc() */ +/* #define HAGL_CHAR_BUFFER_SIZE (16 * 16 * DISPLAY_DEPTH / 2) */ +#ifndef HAGL_CHAR_BUFFER_SIZE +#define HAGL_CHAR_BUFFER_SIZE (1024) +#endif #define HAGL_OK (0) #define HAGL_ERR_GENERAL (1) diff --git a/src/hagl.c b/src/hagl.c index 8c0a94f..0f8f0df 100644 --- a/src/hagl.c +++ b/src/hagl.c @@ -59,8 +59,8 @@ hagl_clear(void *_surface) uint16_t x1 = surface->clip.x1; uint16_t y1 = surface->clip.y1; - hagl_set_clip(surface, 0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1); - hagl_fill_rectangle(surface, 0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1, 0x00); + hagl_set_clip(surface, 0, 0, surface->width - 1, surface->height - 1); + hagl_fill_rectangle(surface, 0, 0, surface->width - 1, surface->height - 1, 0x00); hagl_set_clip(surface, x0, y0, x1, y1); } @@ -71,7 +71,7 @@ hagl_init(void) memset(&backend, 0, sizeof(hagl_backend_t)); hagl_hal_init(&backend); - hagl_set_clip(&backend, 0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1); + hagl_set_clip(&backend, 0, 0, backend.width - 1, backend.height - 1); return &backend; }; diff --git a/src/hagl_char.c b/src/hagl_char.c index 1786fae..ae6aecb 100644 --- a/src/hagl_char.c +++ b/src/hagl_char.c @@ -39,8 +39,9 @@ SPDX-License-Identifier: MIT #include "fontx.h" uint8_t -hagl_get_glyph(void const *surface, wchar_t code, color_t color, hagl_bitmap_t *bitmap, const uint8_t *font) +hagl_get_glyph(void const *_surface, wchar_t code, color_t color, hagl_bitmap_t *bitmap, const uint8_t *font) { + const hagl_surface_t *surface = _surface; uint8_t status, set; fontx_glyph_t glyph; @@ -51,7 +52,7 @@ hagl_get_glyph(void const *surface, wchar_t code, color_t color, hagl_bitmap_t * } /* Initialise bitmap dimensions. */ - bitmap->depth = DISPLAY_DEPTH; + bitmap->depth = surface->depth; bitmap->width = glyph.width; bitmap->height = glyph.height; bitmap->pitch = bitmap->width * (bitmap->depth / 8); @@ -75,8 +76,9 @@ hagl_get_glyph(void const *surface, wchar_t code, color_t color, hagl_bitmap_t * } uint8_t -hagl_put_char(void const *surface, wchar_t code, int16_t x0, int16_t y0, color_t color, const uint8_t *font) +hagl_put_char(void const *_surface, wchar_t code, int16_t x0, int16_t y0, color_t color, const uint8_t *font) { + const hagl_surface_t *surface = _surface; uint8_t set, status; color_t buffer[HAGL_CHAR_BUFFER_SIZE]; hagl_bitmap_t bitmap; @@ -90,7 +92,7 @@ hagl_put_char(void const *surface, wchar_t code, int16_t x0, int16_t y0, color_t bitmap.width = glyph.width, bitmap.height = glyph.height, - bitmap.depth = DISPLAY_DEPTH, + bitmap.depth = surface->depth, bitmap_init(&bitmap, (uint8_t *)buffer); diff --git a/src/hagl_image.c b/src/hagl_image.c index 4f27535..b32bf10 100644 --- a/src/hagl_image.c +++ b/src/hagl_image.c @@ -71,9 +71,9 @@ tjpgd_data_writer(JDEC *decoder, void *bitmap, JRECT *rectangle) hagl_bitmap_t block = { .width = width, .height = height, - .depth = DISPLAY_DEPTH, - .pitch = width * (DISPLAY_DEPTH / 8), - .size = width * (DISPLAY_DEPTH / 8) * height, + .depth = device->surface->depth, + .pitch = width * (device->surface->depth / 8), + .size = width * (device->surface->depth / 8) * height, .buffer = (uint8_t *)bitmap }; diff --git a/src/hagl_polygon.c b/src/hagl_polygon.c index 6cb9488..8ab6438 100644 --- a/src/hagl_polygon.c +++ b/src/hagl_polygon.c @@ -35,9 +35,9 @@ SPDX-License-Identifier: MIT #include #include "hagl/color.h" +#include "hagl/surface.h" +#include "hagl/line.h" #include "hagl/hline.h" -/* TODO: remove after getting DISPLAY_HEIGHT from surface */ -#include "hagl.h" void hagl_draw_polygon(void const *surface, int16_t amount, int16_t *vertices, color_t color) @@ -65,8 +65,9 @@ hagl_draw_polygon(void const *surface, int16_t amount, int16_t *vertices, color_ /* Adapted from http://alienryderflex.com/polygon_fill/ */ void -hagl_fill_polygon(void const *surface, int16_t amount, int16_t *vertices, color_t color) +hagl_fill_polygon(void const *_surface, int16_t amount, int16_t *vertices, color_t color) { + const hagl_surface_t *surface = _surface; uint16_t nodes[64]; int16_t y; @@ -75,7 +76,7 @@ hagl_fill_polygon(void const *surface, int16_t amount, int16_t *vertices, color_ float x1; float y1; - int16_t miny = DISPLAY_HEIGHT; + int16_t miny = surface->height; int16_t maxy = 0; for (uint8_t i = 0; i < amount; i++) {