From ad8b1ccd3e5bc9691041d0b2a1422ac7591a550f Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Mon, 24 May 2021 20:56:50 -0700
Subject: [PATCH] Significantly improved font code

---
 IDEA.md                         |   7 +-
 include/dawn/display/gui/font.h |   8 +--
 src/display/gui/font.c          | 110 ++++++++++++++------------------
 src/display/gui/font.h          |  42 ++++--------
 src/poker/render/frame.c        |   8 +--
 5 files changed, 71 insertions(+), 104 deletions(-)

diff --git a/IDEA.md b/IDEA.md
index e3d380cf..2903e09b 100644
--- a/IDEA.md
+++ b/IDEA.md
@@ -1,2 +1,7 @@
 - Make font measure take in a pointer to a primitive to offer auto buffering of verts
-- Make a clone of the string into font measure pointing only to real chars?
\ No newline at end of file
+- Make a clone of the string into font measure pointing only to real chars?
+
+- How to do text wrapping efficiently?
+  - Two pointers, one for current char and one for the last known text position.
+  - Start by measuring whole string, this will give me n chars and let me know straight away if text fits
+  - Half divide the pointer to try and find the mid point and figure out if I should go up or down, keep halfing until finding the below then iterate up
\ No newline at end of file
diff --git a/include/dawn/display/gui/font.h b/include/dawn/display/gui/font.h
index cff50344..ad9ddeab 100644
--- a/include/dawn/display/gui/font.h
+++ b/include/dawn/display/gui/font.h
@@ -41,11 +41,7 @@ typedef struct {
 
 typedef struct {
   int32_t length;
-  int32_t realChars;
-  float lineHeight, spaceSize;
-} fonttextinfo_t;
-
-typedef struct {
+  int32_t realLength;
   float width, height, scale;
   stbtt_aligned_quad *quads;
-} fontmeasure_t;
\ No newline at end of file
+} fonttextinfo_t;
\ No newline at end of file
diff --git a/src/display/gui/font.c b/src/display/gui/font.c
index 506ef0af..0a7a9b95 100644
--- a/src/display/gui/font.c
+++ b/src/display/gui/font.c
@@ -40,111 +40,95 @@ void fontInit(font_t *font, char *data) {
   free(pixels);
 }
 
-fonttextinfo_t fontGetTextInfo(font_t *font, char *text) {
-  float x, y;
-  char c;
-  int32_t i;
-  fonttextinfo_t info = {
-    .length = 0,
-    .realChars = 0,
-    .lineHeight = FONT_LINE_HEIGHT,
-    .spaceSize = FONT_SPACE_SIZE
-  };
-
-  // Count how many "real characters" are in the string.
-  i = 0;
-  while(c = text[i++]) {
-    info.length++;
-    if(c == FONT_SPACE) continue;
-    if(c == FONT_NEWLINE) continue;
-    info.realChars++;
-  }
-
-  return info;
+void fontDispose(font_t *font) {
+  textureDispose(&font->texture);
 }
 
-fontmeasure_t * fontTextMeasure(font_t *font, char *text, fonttextinfo_t *info, 
-  float scale
-) {
+
+fonttextinfo_t * fontGetTextInfo(font_t *font, char *text, float scale) {
   int32_t i, j;
   char c;
   float x, y;
   stbtt_aligned_quad *quad;
-  fontmeasure_t *measure;
 
-  scale *= FONT_SCALE_ADJUST;
-  measure = malloc(sizeof(fontmeasure_t));
-  measure->width = 0, measure->height = 0;
-  measure->scale = scale;
-  measure->quads = malloc(sizeof(stbtt_aligned_quad) * info->realChars);
+  // Create info buffer.
+  fonttextinfo_t *info = malloc(sizeof(fonttextinfo_t));
+  
+  info->length = 0;
+  info->realLength = 0;
 
+  // Count how many "real characters" are in the string.
+  i = 0;
+  while(c = text[i++]) {
+    info->length++;
+    if(c == FONT_SPACE) continue;
+    if(c == FONT_NEWLINE) continue;
+    info->realLength++;
+  }
+
+  // Now setup the size scales
+  info->quads = malloc(sizeof(stbtt_aligned_quad) * info->realLength);
+  info->scale = scale * FONT_SCALE_ADJUST;
+  info->width = 0, info->height = 0;
+
+  // Begin buffering quads.
   x = 0;
   y = FONT_INITIAL_LINE;
-
   i = 0, j = 0;
+
   while(c = text[i++]) {
+    // Spaces, don't quad just next
     if(c == FONT_SPACE) {
-      x += info->spaceSize;
+      x += FONT_SPACE_SIZE;
       continue;
     }
 
+    // Newlines reset X
     if(c == FONT_NEWLINE) {
-      y += info->lineHeight;
+      y += FONT_LINE_HEIGHT;
       x = 0;
       continue;
     }
   
     // Calculate the quad of the character, store into the array.
-    quad = measure->quads + j;
+    quad = info->quads + j;
     stbtt_GetBakedQuad(font->characterData,
       FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT,
       ((int32_t)c)-FONT_FIRST_CHAR, &x, &y, quad, FONT_FILL_MODE
     );
-    quad->x0 *= scale, quad->x1 *= scale;
-    quad->y0 *= scale, quad->y1 *= scale;
-    measure->width = mathMax(measure->width, quad->x1);
-    measure->height = mathMax(measure->height, quad->y1);
+    quad->x0 *= info->scale, quad->x1 *= info->scale;
+    quad->y0 *= info->scale, quad->y1 *= info->scale;
+    info->width = mathMax(info->width, quad->x1);
+    info->height = mathMax(info->height, quad->y1);
     j++;
   }
 
-  return measure;
+  return info;
 }
 
-void fontTextMeasureDispose(fontmeasure_t *measure) {
-  free(measure->quads);
-  free(measure);
+void fontTextInfoDispose(fonttextinfo_t *info) {
+  free(info->quads);
+  free(info);
 }
 
-void fontDispose(font_t *font) {
-  textureDispose(&font->texture);
-}
 
-void fontTextBufferFromMeasure(font_t *font, primitive_t *primitive, char *text,
-  fontmeasure_t *measure
-) {
+void fontTextBuffer(font_t *font,primitive_t *primitive,fonttextinfo_t *info) {
   stbtt_aligned_quad *quad;
-  int32_t i, j;
-  char c;
-
-  i = 0, j = 0;
-  while(c = text[i++]) {
-    if(c == FONT_SPACE) continue;
-    if(c == FONT_NEWLINE) continue;
-    quad = measure->quads + j;
+  int32_t i;
+  
+  for(i = 0; i < info->realLength; i++) {
+    quad = info->quads + i;
     quadBuffer(primitive, 0,
       quad->x0, quad->y0, quad->s0, quad->t0,
       quad->x1, quad->y1, quad->s1, quad->t1,
-      j*QUAD_VERTICE_COUNT, j*QUAD_INDICE_COUNT
+      i*QUAD_VERTICE_COUNT, i*QUAD_INDICE_COUNT
     );
-    j++;
   }
 }
 
-void fontTextInitFromMeasure(font_t *font, primitive_t *primitive, char *text,
-  fonttextinfo_t *info, fontmeasure_t *measure
-) {
+void fontTextInit(font_t *font, primitive_t *primitive, fonttextinfo_t *info) {
   primitiveInit(primitive,
-    QUAD_VERTICE_COUNT*info->realChars, QUAD_INDICE_COUNT*info->realChars
+    QUAD_VERTICE_COUNT * info->realLength, QUAD_INDICE_COUNT * info->realLength
   );
-  fontTextBufferFromMeasure(font, primitive, text, measure);
+  fontTextBuffer(font, primitive, info);
 }
\ No newline at end of file
diff --git a/src/display/gui/font.h b/src/display/gui/font.h
index 30b26b4e..2875e282 100644
--- a/src/display/gui/font.h
+++ b/src/display/gui/font.h
@@ -20,31 +20,28 @@
 void fontInit(font_t *font, char *data);
 
 /**
- * Generates information about how the given font will render the given text.
- * @param font Font to get the information for.
- * @param text Text that will be used to render
- * @return Some information about how the font will render the text.
+ * Clean up a previously loaded font
+ * @param font Loaded font.
  */
-fonttextinfo_t fontGetTextInfo(font_t *font, char *text);
+void fontDispose(font_t *Font);
+
 
 /**
  * Measures (and calculates the quads for) a text prior to rendering it.
  * 
  * @param font Font to use for rendering and measuring
  * @param text Text to measure/render.
- * @param info Info about the text being rendered / measured.
  * @param scale Scale of the text.
- * @returns Font measurement calculation.
+ * @returns Font info calculated.
  */
-fontmeasure_t * fontTextMeasure(font_t *font, char *text, fonttextinfo_t *info,
-  float scale
-);
+fonttextinfo_t * fontGetTextInfo(font_t *font, char *text, float scale);
 
 /**
- * Disposes a previously calculated font text measurement.
- * @param measure Measurement to dispose.
+ * Disposes a previously calculated font info struct..
+ * @param info Info to dispose.
  */
-void fontTextMeasureDispose(fontmeasure_t *measure);
+void fontTextInfoDispose(fonttextinfo_t *info);
+
 
 /**
  * Buffers the vertices of a font text onto a primitive. Requires some info
@@ -52,28 +49,15 @@ void fontTextMeasureDispose(fontmeasure_t *measure);
  * 
  * @param font Font to render.
  * @param primitive Primitive to render into.
- * @param text Text to render.
- * @param measure The precalculated measurement.
+ * @param info The precalculated text info.
  */
-void fontTextBufferFromMeasure(font_t *font, primitive_t *primitive, char *text,
-  fontmeasure_t *measure
-);
+void fontTextBuffer(font_t *font, primitive_t *primitive, fonttextinfo_t *info);
 
 /**
  * Initializes an uninitialized primitive for rendering.
  * 
  * @param font Font to render.
  * @param primitive Primitive to render into.
- * @param text Text to render.
  * @param info Text Info to use while rendering.
- * @param measure The pre calcuted font measurement.
  */
-void fontTextInitFromMeasure(font_t *font, primitive_t *primitive, char *text,
-  fonttextinfo_t *info, fontmeasure_t *measure
-);
-
-/**
- * Clean up a previously loaded font
- * @param font Loaded font.
- */
-void fontDispose(font_t *Font);
\ No newline at end of file
+void fontTextInit(font_t *font, primitive_t *primitive, fonttextinfo_t *info);
\ No newline at end of file
diff --git a/src/poker/render/frame.c b/src/poker/render/frame.c
index 0c0c378c..9a28b981 100644
--- a/src/poker/render/frame.c
+++ b/src/poker/render/frame.c
@@ -13,12 +13,10 @@ void pokerFrameInit(poker_t *poker, render_t *render) {
   frameBufferInit(&poker->frameWorld, render->width, render->height);
   frameBufferInit(&poker->frameGui, render->width, render->height);
 
-  fonttextinfo_t info;
+  fonttextinfo_t *info;
   char *text = "Hello\n World";
-  info = fontGetTextInfo(&poker->font, text);
-  fontmeasure_t *measure = fontTextMeasure(&poker->font, text, &info, 16);
-  fontTextInitFromMeasure(&poker->font, &bruh, text, &info, measure);
-  fontTextMeasureDispose(measure);
+  info = fontGetTextInfo(&poker->font, text, 16);
+  fontTextInit(&poker->font, &bruh, info);
 }
 
 void pokerFrameWorld(poker_t *poker, render_t *render) {