瀏覽代碼

Initial implementation of the text rendering

rexim 3 年之前
父節點
當前提交
16c2896d7a
共有 3 個文件被更改,包括 100 次插入1 次删除
  1. 5 1
      examples/3d.c
  2. 93 0
      olive.c
  3. 2 0
      test.c

+ 5 - 1
examples/3d.c

@@ -22,6 +22,7 @@ float cosf(float x);
 #define GRID_SIZE ((GRID_COUNT - 1)*GRID_PAD)
 #define CIRCLE_RADIUS 5
 #define Z_START 0.25
+#define ABOBA_PADDING 50
 
 uint32_t circle_colors[] = {
     0xFF2020FF,
@@ -49,7 +50,7 @@ uint32_t *render(float dt)
                 float x = ix*GRID_PAD - GRID_SIZE/2;
                 float y = iy*GRID_PAD - GRID_SIZE/2;
                 float z = Z_START + iz*GRID_PAD;
-                
+
                 float cx = 0.0;
                 float cz = Z_START + GRID_SIZE/2;
 
@@ -77,6 +78,9 @@ uint32_t *render(float dt)
         }
     }
 
+    size_t size = 8;
+    olivec_text(oc, "aboba", ABOBA_PADDING, HEIGHT - ABOBA_PADDING - default_font.height*size, default_font, size, 0xFFFFFFFF);
+
     return pixels;
 }
 

+ 93 - 0
olive.c

@@ -17,6 +17,78 @@
 #define OLIVEC_SIGN(T, x) ((T)((x) > 0) - (T)((x) < 0))
 #define OLIVEC_ABS(T, x) (OLIVEC_SIGN(T, x)*(x))
 
+typedef struct {
+    size_t width, height;
+    const char *glyphs;
+} Olivec_Font;
+
+#define DEFAULT_FONT_HEIGHT 5
+#define DEFAULT_FONT_WIDTH 5
+static char default_font_glyphs[128][DEFAULT_FONT_HEIGHT][DEFAULT_FONT_WIDTH] = {
+    ['a'] = {
+        {0, 1, 1, 0, 0},
+        {0, 0, 0, 1, 0},
+        {0, 1, 1, 1, 0},
+        {1, 0, 0, 1, 0},
+        {0, 1, 1, 1, 0},
+    },
+    ['b'] = {
+        {1, 0, 0, 0, 0},
+        {1, 0, 0, 0, 0},
+        {1, 1, 1, 0, 0},
+        {1, 0, 0, 1, 0},
+        {1, 1, 1, 0, 0},
+    },
+    ['c'] = {
+        {0, 1, 1, 0, 0},
+        {1, 0, 0, 1, 0},
+        {1, 0, 0, 0, 0},
+        {1, 0, 0, 1, 0},
+        {0, 1, 1, 0, 0},
+    },
+    ['d'] = {
+        {0, 0, 0, 1, 0},
+        {0, 0, 0, 1, 0},
+        {0, 1, 1, 1, 0},
+        {1, 0, 0, 1, 0},
+        {0, 1, 1, 1, 0},
+    },
+    ['e'] = {
+        {0, 1, 1, 0, 0},
+        {1, 0, 0, 1, 0},
+        {1, 1, 1, 1, 0},
+        {1, 0, 0, 0, 0},
+        {0, 1, 1, 1, 0},
+    },
+    ['f'] = {
+        {0, 0, 1, 1, 0},
+        {0, 1, 0, 0, 0},
+        {1, 1, 1, 1, 0},
+        {0, 1, 0, 0, 0},
+        {0, 1, 0, 0, 0},
+    },
+    ['p'] = {
+        {1, 1, 1, 0, 0},
+        {1, 0, 0, 1, 0},
+        {1, 1, 1, 0, 0},
+        {1, 0, 0, 0, 0},
+        {1, 0, 0, 0, 0},
+    },
+    ['o'] = {
+        {0, 1, 1, 0, 0},
+        {1, 0, 0, 1, 0},
+        {1, 0, 0, 1, 0},
+        {1, 0, 0, 1, 0},
+        {0, 1, 1, 0, 0},
+    },
+};
+
+static Olivec_Font default_font = {
+    .glyphs = &default_font_glyphs[0][0][0],
+    .width = DEFAULT_FONT_WIDTH,
+    .height = DEFAULT_FONT_HEIGHT,
+};
+
 typedef struct {
     uint32_t *pixels;
     size_t width;
@@ -37,6 +109,7 @@ OLIVECDEF void olivec_circle(Olivec_Canvas oc, int cx, int cy, int r, uint32_t c
 // Implement olivec_line in terms of olivec_triangle. This may make it easier to implement variable thiccness.
 OLIVECDEF void olivec_line(Olivec_Canvas oc, int x1, int y1, int x2, int y2, uint32_t color);
 OLIVECDEF void olivec_triangle(Olivec_Canvas oc, int x1, int y1, int x2, int y2, int x3, int y3, uint32_t color);
+OLIVECDEF void olivec_text(Olivec_Canvas oc, const char *text, int x, int y, Olivec_Font font, size_t size, uint32_t color);
 
 // The point of this function is to produce two ranges x1..x2 and y1..y2 that are guaranteed to be safe to iterate over the canvas of size pixels_width by pixels_height without any boundary checks.
 //
@@ -262,6 +335,26 @@ OLIVECDEF void olivec_triangle(Olivec_Canvas oc, int x1, int y1, int x2, int y2,
     }
 }
 
+OLIVECDEF void olivec_text(Olivec_Canvas oc, const char *text, int tx, int ty, Olivec_Font font, size_t glyph_size, uint32_t color)
+{
+    for (size_t i = 0; *text; ++i, ++text) {
+        int gx = tx + i*font.width*glyph_size;
+        int gy = ty;
+        const char *glyph = &font.glyphs[(*text)*sizeof(char)*font.width*font.height];
+        for (int dy = 0; (size_t) dy < font.height; ++dy) {
+            for (int dx = 0; (size_t) dx < font.width; ++dx) {
+                int px = gx + dx*glyph_size;
+                int py = gy + dy*glyph_size;
+                if (0 <= px && px < (int) oc.width && 0 <= py && py < (int) oc.height) {
+                    if (glyph[dy*font.width + dx]) {
+                        olivec_rect(oc, px, py, glyph_size, glyph_size, color);
+                    }
+                }
+            }
+        }
+    }
+}
+
 #endif // OLIVEC_IMPLEMENTATION
 
 // TODO: Built-in simple monospaced font

+ 2 - 0
test.c

@@ -233,6 +233,8 @@ Test_Case test_cases[] = {
 };
 #define TEST_CASES_COUNT (sizeof(test_cases)/sizeof(test_cases[0]))
 
+// TODO: add tests for text rendering
+
 int main(int argc, char **argv)
 {
     assert(argc >= 1);