remove global active font and color (also fixes #693)

Fri, 18 Jul 2025 18:01:41 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 18 Jul 2025 18:01:41 +0200
changeset 214
9d460888a83e
parent 213
3d252dbd7c8e
child 215
a7c8e1727971

remove global active font and color (also fixes #693)

src/2d.c file | annotate | diff | comparison | revisions
src/Makefile file | annotate | diff | comparison | revisions
src/ascension/2d.h file | annotate | diff | comparison | revisions
src/ascension/camera.h file | annotate | diff | comparison | revisions
src/ascension/context.h file | annotate | diff | comparison | revisions
src/ascension/font.h file | annotate | diff | comparison | revisions
src/ascension/text.h file | annotate | diff | comparison | revisions
src/camera.c file | annotate | diff | comparison | revisions
src/context.c file | annotate | diff | comparison | revisions
src/font.c file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
test/snake/snake.c file | annotate | diff | comparison | revisions
--- a/src/2d.c	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/2d.c	Fri Jul 18 18:01:41 2025 +0200
@@ -28,7 +28,6 @@
 #include "ascension/2d.h"
 
 #include "ascension/constants.h"
-#include "ascension/context.h"
 #include "ascension/error.h"
 #include "ascension/shader.h"
 
@@ -173,8 +172,6 @@
     }
 
     rectangle->radius = (float)args.radius;
-    rectangle->color = asc_col_itof(asc_context.ink);
-    rectangle->border_color = asc_col_itof(args.border_color);
     rectangle->filled = args.filled;
     if (!args.filled && args.thickness == 0) {
         // when we do not fill the rectangle, we need a border
@@ -182,18 +179,21 @@
     } else {
         rectangle->thickness = args.thickness;
     }
+
     if (!args.filled && asc_memcmpz(&args.border_color, sizeof(args.border_color))) {
         // convenience fallback:
         // when we are drawing an outline but have no explicit border color,
-        // use the active ink
-        rectangle->border_color = rectangle->color;
+        // use the main color
+        args.border_color = args.color;
     }
+    rectangle->color = asc_col_itof(args.color);
+    rectangle->border_color = asc_col_itof(args.border_color);
 
     asc_ptr_cast(AscSceneNode, node, rectangle);
     asc_scene_node_init(node,
         ASC_SCENE_NODE_FUNCS(asc_rectangle),
         .pos2d = ASC_VEC2I(pos_x, pos_y),
-        .render_group = asc_context.ink.alpha < 255
+        .render_group = (args.filled && args.color.alpha < 255) || args.border_color.alpha < 255
                              ? ASC_RENDER_GROUP_2D_BLEND
                              : ASC_RENDER_GROUP_2D_OPAQUE
     );
@@ -326,8 +326,6 @@
         ellipsis->radii.y = (float) ry;
     }
 
-    ellipsis->color = asc_col_itof(asc_context.ink);
-    ellipsis->border_color = asc_col_itof(args.border_color);
     ellipsis->filled = args.filled;
     if (!args.filled && args.thickness == 0) {
         // when we do not fill the ellipsis, we need a border
@@ -335,18 +333,21 @@
     } else {
         ellipsis->thickness = args.thickness;
     }
+
     if (!args.filled && asc_memcmpz(&args.border_color, sizeof(args.border_color))) {
         // convenience fallback:
         // when we are drawing an outline but have no explicit border color,
-        // use the active ink
-        ellipsis->border_color = ellipsis->color;
+        // use the main color
+        args.border_color = args.color;
     }
+    ellipsis->color = asc_col_itof(args.color);
+    ellipsis->border_color = asc_col_itof(args.border_color);
 
     asc_ptr_cast(AscSceneNode, node, ellipsis);
     asc_scene_node_init(node,
         ASC_SCENE_NODE_FUNCS(asc_ellipsis),
         .pos2d = ASC_VEC2I(pos_x, pos_y),
-        .render_group = asc_context.ink.alpha < 255
+        .render_group = (args.filled && args.color.alpha < 255) || args.border_color.alpha < 255
                              ? ASC_RENDER_GROUP_2D_BLEND
                              : ASC_RENDER_GROUP_2D_OPAQUE
     );
--- a/src/Makefile	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/Makefile	Fri Jul 18 18:01:41 2025 +0200
@@ -46,9 +46,8 @@
 
 $(BUILD_DIR)/2d.o: 2d.c ascension/2d.h ascension/scene_node.h \
  ascension/datatypes.h ascension/transform.h ascension/mesh.h \
- ascension/constants.h ascension/context.h ascension/window.h \
- ascension/glcontext.h ascension/scene.h ascension/camera.h \
- ascension/input.h ascension/font.h ascension/error.h ascension/shader.h
+ ascension/constants.h ascension/error.h ascension/shader.h \
+ ascension/camera.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
@@ -141,9 +140,7 @@
 $(BUILD_DIR)/text.o: text.c ascension/text.h ascension/font.h \
  ascension/mesh.h ascension/datatypes.h ascension/texture.h \
  ascension/scene_node.h ascension/transform.h ascension/error.h \
- ascension/context.h ascension/window.h ascension/glcontext.h \
- ascension/scene.h ascension/camera.h ascension/input.h \
- ascension/shader.h ascension/constants.h
+ ascension/shader.h ascension/camera.h ascension/constants.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
--- a/src/ascension/2d.h	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/ascension/2d.h	Fri Jul 18 18:01:41 2025 +0200
@@ -57,11 +57,17 @@
      */
     unsigned int thickness;
     /**
+     * The main color to use.
+     * If filled is true, this is the fill color.
+     * If filled is false, and no border_color is specified, this is used as border color.
+     */
+    asc_col4i color;
+    /**
      * Border color to be used when thickness is larger than zero and filled is true.
      */
     asc_col4i border_color;
     /**
-     * If true, the rectangle will be filled with the active color.
+     * If true, the rectangle will be filled with the specified color.
      * If the thickness is larger than zero, an outline border with that thickness is drawn
      * using the border_color.
      */
@@ -119,11 +125,17 @@
      */
     unsigned int thickness;
     /**
+     * The main color to use.
+     * If filled is true, this is the fill color.
+     * If filled is false, and no border_color is specified, this is used as border color.
+     */
+    asc_col4i color;
+    /**
      * Border color to be used when thickness is larger than zero and filled is true.
      */
     asc_col4i border_color;
     /**
-     * If true, the ellipsis will be filled with the active color.
+     * If true, the ellipsis will be filled with the specified color.
      * If the thickness is larger than zero, an outline border with that thickness is drawn
      * using the border_color.
      */
--- a/src/ascension/camera.h	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/ascension/camera.h	Fri Jul 18 18:01:41 2025 +0200
@@ -72,6 +72,7 @@
      * Indicates whether the viewport for this camera shall be cleared before rendering.
      * The active drawing color will be used as the clear color (can be changed in the camera struct, afterward).
      */
+    asc_col4i clear_color;
     bool viewport_clear;
 };
 
--- a/src/ascension/context.h	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/ascension/context.h	Fri Jul 18 18:01:41 2025 +0200
@@ -58,9 +58,7 @@
     cxmutstr texture_path;
     AscInput input;
     AscWindow windows[ASC_MAX_WINDOWS];
-    AscFont active_font;
     unsigned char active_window;
-    asc_col4i ink;
     float frame_rate;
     float frame_factor;
     uint64_t frame_nanos;
@@ -70,12 +68,6 @@
 /** Global ascension context. */
 extern AscContext asc_context;
 
-/**
- * The currently active font.
- * @see asc_font()
- */
-#define asc_active_font asc_context.active_font
-
 #ifdef NDEBUG
 /**
  * The currently active window in the context.
@@ -107,13 +99,6 @@
  */
 bool asc_loop_next(void);
 
-/**
- * Sets the active drawing color.
- */
-#define asc_ink(color) asc_context.ink = (color)
-#define asc_ink_rgba(r,g,b,a) asc_context.ink = (asc_col4i){(r),(g),(b),(a)}
-#define asc_ink_rgb(r,g,b) asc_context.ink = (asc_col4i){(r),(g),(b),255u}
-
 void asc_set_font_path(const char *path);
 void asc_set_shader_path(const char *path);
 void asc_set_texture_path(const char *path);
--- a/src/ascension/font.h	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/ascension/font.h	Fri Jul 18 18:01:41 2025 +0200
@@ -45,23 +45,12 @@
     /**
      * Point size.
      */
-    int size;
+    unsigned int size;
 } AscFont;
 
-/**
- * Activates a font with the given style and size.
- *
- * The font is cached and activated faster the next time you call this
- * function with the same arguments. However, when you reach the maximum
- * number of fonts, the cache is completely cleared and rebuilt.
- *
- * That means in general, that you should not be using too many fonts of
- * different sizes at the same time.
- *
- * @param style the style
- * @param size the point size
- */
-void asc_font(enum AscFontStyle style, int size);
+static inline AscFont asc_font(enum AscFontStyle style, unsigned int size) {
+    return (AscFont) {style, size};
+}
 
 /**
  * Loads the specified font.
--- a/src/ascension/text.h	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/ascension/text.h	Fri Jul 18 18:01:41 2025 +0200
@@ -63,10 +63,12 @@
 #define ASC_TEXT_CENTERED_FLAG  0x04
 
 struct asc_text_create_args {
+    AscFont font;
     int x;
     int y;
     const char *name;
     const char *text;
+    asc_col4i color;
     enum asc_text_alignment alignment;
     unsigned short max_width;
     bool centered;
--- a/src/camera.c	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/camera.c	Fri Jul 18 18:01:41 2025 +0200
@@ -47,7 +47,7 @@
     camera->viewport_update_func = args.viewport_update_func;
     camera->projection_update_func = args.projection_update_func;
     camera->viewport_clear = args.viewport_clear;
-    camera->clear_color = asc_col_itof(asc_context.ink);
+    camera->clear_color = asc_col_itof(args.clear_color);
 }
 
 void asc_camera_ortho(AscCamera *camera, asc_rect rect) {
--- a/src/context.c	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/context.c	Fri Jul 18 18:01:41 2025 +0200
@@ -61,10 +61,6 @@
     // initialize the font cache
     asc_font_cache_init();
 
-    // set a default font but do not load it
-    asc_context.active_font.style = ASC_FONT_REGULAR;
-    asc_context.active_font.size = 14;
-
     // no window, yet
     asc_context.active_window = ASC_MAX_WINDOWS;
 
--- a/src/font.c	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/font.c	Fri Jul 18 18:01:41 2025 +0200
@@ -34,11 +34,6 @@
 #include <math.h>
 #include <cx/array_list.h>
 
-void asc_font(enum AscFontStyle style, int size) {
-    asc_context.active_font.style = style;
-    asc_context.active_font.size = size;
-}
-
 static const char *asc_font_filename(enum AscFontStyle style) {
     switch (style) {
         case ASC_FONT_REGULAR:
--- a/src/text.c	Thu Jul 17 20:26:39 2025 +0200
+++ b/src/text.c	Fri Jul 18 18:01:41 2025 +0200
@@ -28,7 +28,6 @@
 #include "ascension/text.h"
 
 #include "ascension/error.h"
-#include "ascension/context.h"
 #include "ascension/shader.h"
 #include "ascension/constants.h"
 
@@ -153,8 +152,15 @@
     // text properties
     node->flags = args.alignment; // use flags variable to save some space
     text->max_width = args.max_width;
-    text->font = asc_active_font;
-    text->color = asc_context.ink;
+    text->font = args.font;
+    if (text->font.size == 0) {
+        text->font.size = 12;
+    }
+    if (asc_memcmpz(&args.color, sizeof(asc_col4i))) {
+        text->color = ASC_RGB(255, 255, 255);
+    } else {
+        text->color = args.color;
+    }
     if (args.text == NULL) {
         text->text = cx_mutstr(strdup(" "));
     } else {
--- a/test/snake/snake.c	Thu Jul 17 20:26:39 2025 +0200
+++ b/test/snake/snake.c	Fri Jul 18 18:01:41 2025 +0200
@@ -128,21 +128,23 @@
 }
 
 static void create_fps_counter(void) {
-    asc_font(ASC_FONT_REGULAR, 12);
-    asc_ink_rgb(255, 255, 255);
-    AscSceneNode *node = asc_text(.name = "FPS Counter");
+    AscSceneNode *node = asc_text(
+        .name = "FPS Counter",
+        .color = ASC_RGB(255, 255, 255),
+        .font = asc_font(ASC_FONT_REGULAR, 12),
+    );
     asc_behavior_add(node, .func = update_fps_counter, .interval = asc_seconds(1));
     asc_behavior_add(node, tie_fps_counter_to_corner);
     asc_ui_add_node(node);
 }
 
 static void create_score_counter(void) {
-    asc_font(ASC_FONT_BOLD, 16);
-    asc_ink_rgb(0, 255, 0);
     AscSceneNode *node = asc_text(
         .name = "Score Counter",
         .x = 10, .y = 10,
-        .text = "Score: 0"
+        .text = "Score: 0",
+        .color = ASC_RGB(0, 255, 0),
+        .font = asc_font(ASC_FONT_BOLD, 16),
     );
     asc_ui_add_node(node);
 }
@@ -180,10 +182,10 @@
     AscSceneNode *gamefield = asc_scene_node_empty();
     for (unsigned x = 0; x < game_field_size; x+=game_field_tile_size) {
         for (unsigned y = 0; y < game_field_size; y+=game_field_tile_size) {
-            asc_ink_rgb(0, 128, 255);
             AscSceneNode *tile = asc_rectangle(
                 .x = x, .y = y, .filled = true, .thickness = 1,
                 .width = game_field_tile_size, .height = game_field_tile_size,
+                .color = ASC_RGB(0, 128, 255),
                 .border_color = ASC_RGB(64, 196, 255),
             );
             asc_scene_node_link(gamefield, tile);
@@ -242,7 +244,6 @@
         .type = ASC_CAMERA_ORTHO,
         .projection_update_func = asc_camera_ortho_update_size
     );
-    asc_ink_rgb(0, 128, 90);
     asc_scene_init(MAIN_SCENE,
         .type = ASC_CAMERA_ORTHO,
         .ortho.rect = ASC_RECT(
@@ -252,6 +253,7 @@
             game_field_size+game_field_tile_size
         ),
         .viewport_clear = true,
+        .clear_color = ASC_RGB(0, 128, 90),
         .viewport_update_func = update_viewport_for_window_resize
     );
 

mercurial