unlock rendering
[carveJwlIkooP6JGAAIwe30JlM.git] / font.h
diff --git a/font.h b/font.h
index eaba149b68d06bd7514fd9fc0b4d250ca06e3b2b..77eae7ced3dc9879ec7fd0ea7752606dbd485a4c 100644 (file)
--- a/font.h
+++ b/font.h
@@ -6,6 +6,58 @@
 #include "camera.h"
 #include "shaders/model_font.h"
 
+
+enum efont_SRglyph{
+   k_SRglyph_end           = 0x00, /* control characters */
+   k_SRglyph_ctrl_variant  = 0x01,
+   k_SRglyph_ctrl_size     = 0x02, /* normalized 0-1 */
+   k_SRglyph_ctrl_center   = 0x03, /* useful when text is scaled down */
+   k_SRglyph_ctrl_baseline = 0x04, /* . */
+   k_SRglyph_ctrl_top      = 0x05, /* . */
+   k_SRglyph_mod_circle    = 0x1e, /* surround and center next charater */
+   k_SRglyph_mod_square    = 0x1f, /* surround and center next character */
+   k_SRglyph_ascii_min     = 0x20, /* standard ascii */
+   k_SRglyph_ascii_max     = 0x7e,
+   k_SRglyph_ps4_square    = 0x7f,/* playstation buttons */
+   k_SRglyph_ps4_triangle  = 0x80,
+   k_SRglyph_ps4_circle    = 0x81,
+   k_SRglyph_ps4_cross     = 0x82,
+   k_SRglyph_xb1_x         = 0x83,/* xbox buttons */
+   k_SRglyph_xb1_y         = 0x84,
+   k_SRglyph_xb1_a         = 0x85,
+   k_SRglyph_xb1_b         = 0x86,
+   k_SRglyph_gen_ls        = 0x87,/* generic gamepad */
+   k_SRglyph_gen_lsh       = 0x88,
+   k_SRglyph_gen_lsv       = 0x89,
+   k_SRglyph_gen_lshv      = 0x8a,
+   k_SRglyph_gen_rs        = 0x8b,
+   k_SRglyph_gen_rsh       = 0x8c,
+   k_SRglyph_gen_rsv       = 0x8d,
+   k_SRglyph_gen_rshv      = 0x8e,
+   k_SRglyph_gen_lt        = 0x8f,
+   k_SRglyph_gen_rt        = 0x90,
+   k_SRglyph_gen_lb        = 0x91,
+   k_SRglyph_gen_rb        = 0x92,
+   k_SRglyph_gen_left      = 0x93,
+   k_SRglyph_gen_up        = 0x94,
+   k_SRglyph_gen_right     = 0x95,
+   k_SRglyph_gen_down      = 0x96,
+   k_SRglyph_gen_options   = 0x97,
+   k_SRglyph_gen_shareview = 0x98,
+   k_SRglyph_kbm_m0        = 0x99,/* mouse */
+   k_SRglyph_kbm_m1        = 0x9a,
+   k_SRglyph_kbm_m01       = 0x9b,
+   k_SRglyph_kbm_m2        = 0x9c,
+   k_SRglyph_kbm_m2s       = 0x9d,
+   k_SRglyph_kbm_shift     = 0x9e,/* modifiers */
+   k_SRglyph_kbm_ctrl      = 0x9f,
+   k_SRglyph_kbm_alt       = 0xa0,
+   k_SRglyph_kbm_space     = 0xa1,
+   k_SRglyph_kbm_return    = 0xa2,
+   k_SRglyph_kbm_escape    = 0xa3,
+   k_SRglyph_kbm_mousemove = 0xa4
+};
+
 typedef struct font3d font3d;
 struct font3d{
    mdl_context mdl;
@@ -31,32 +83,18 @@ VG_STATIC void font3d_load( font3d *font, const char *mdl_path, void *alloc )
    mdl_load_array( &font->mdl, &font->glyphs, "ent_glyph", alloc );
 
    vg_linear_clear( vg_mem.scratch );
-   mdl_load_mesh_block( &font->mdl, vg_mem.scratch );
 
    if( !mdl_arrcount( &font->mdl.textures ) )
-      vg_fatal_exit_loop( "No texture in font file" );
+      vg_fatal_error( "No texture in font file" );
 
    mdl_texture *tex0 = mdl_arritm( &font->mdl.textures, 0 );
    void *data = vg_linear_alloc( vg_mem.scratch, tex0->file.pack_size );
    mdl_fread_pack_file( &font->mdl, &tex0->file, data );
 
-   vg_acquire_thread_sync();
-   {
-      /* upload mesh */
-      mesh_upload( &font->mesh, 
-                     font->mdl.verts.data, font->mdl.verts.count,
-                     font->mdl.indices.data, font->mdl.indices.count );
-
-      /* upload first texture */
-      font->texture = vg_tex2d_new();
-
-      vg_tex2d_set_error();
-      vg_tex2d_qoi( data, tex0->file.pack_size,
-                    mdl_pstr( &font->mdl, tex0->file.pstr_path ));
-      vg_tex2d_nearest();
-      vg_tex2d_repeat();
-   }
-   vg_release_thread_sync();
+   mdl_async_load_glmesh( &font->mdl, &font->mesh );
+   vg_tex2d_load_qoi_async( data, tex0->file.pack_size, 
+                            VG_TEX2D_LINEAR|VG_TEX2D_CLAMP,
+                            &font->texture );
 
    mdl_close( &font->mdl );
 }
@@ -102,39 +140,121 @@ VG_STATIC ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 )
    return mdl_arritm( &font->glyphs, index );
 }
 
+struct font3d_render{
+   v4f offset;
+   font3d *font;
+   const u8 *u8pch;
+   u32 variant_id;
+};
+
 VG_STATIC 
-void font3d_simple_draw( font3d *font, u32 variant_id, const char *text
-                         camera *cam, m4x3f transform )
+void font3d_begin( font3d *font, u32 variant_id
+                    camera *cam, m4x3f transform, struct font3d_render *render )
 {
-   v3f offset;
-   v3_zero( offset );
+   q_identity( render->offset );
 
    m4x4f prev_mtx;
-
    m4x3_expand( transform, prev_mtx );
    m4x4_mul( cam->mtx_prev.pv, prev_mtx, prev_mtx );
 
    shader_model_font_uPvmPrev( prev_mtx );
    shader_model_font_uMdl( transform );
 
-   for( int i=0;; i++ ){
-      u32 c = text[i];
-      if(!c) break;
+   render->font = font;
+   render->variant_id = variant_id;
+}
 
-      ent_glyph *glyph = font3d_glyph( font, variant_id, c );
-      if( !glyph ) continue;
+VG_STATIC void font3d_draw( struct font3d_render *render )
+{
+   u32 max_chars = 512;
+   while( render->u8pch && max_chars ){
+      max_chars --;
 
-      if( glyph->indice_count ){
-         shader_model_font_uOffset( offset );
-         mesh_drawn( glyph->indice_start, glyph->indice_count );
+      u32 c0 = *render->u8pch, c1;
+      render->u8pch ++;
+
+      if( !c0 ) break;
+
+      ent_glyph *glyph0 = font3d_glyph( render->font, render->variant_id, c0 ),
+                *glyph1 = NULL;
+
+      /* multibyte characters */
+      if( c0 >= 1 && c0 < k_SRglyph_ascii_min ){
+         c1 = *render->u8pch;
+         if( !c1 ) break;
+         glyph1 = font3d_glyph( render->font, render->variant_id, c1 );
       }
-      offset[0] += glyph->size[0];
+
+      if( c0 == k_SRglyph_ctrl_variant ){
+         render->variant_id = c1;
+         render->u8pch ++;
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_size ){
+         render->offset[3] = (float)c1 * (1.0f/255.0f);
+         render->u8pch ++;
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_baseline ){
+         render->offset[1] = 0.0f;
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_center ){
+         if( glyph1 ){
+            float diff = glyph1->size[1] - glyph1->size[1]*render->offset[3];
+            render->offset[1] = diff * 0.5f;
+         }
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_top ){
+         if( glyph1 ){
+            float diff = glyph1->size[1] - glyph1->size[1]*render->offset[3];
+            render->offset[1] = diff;
+         }
+         continue;
+      }
+
+      if( !glyph0 ) continue;
+
+      if( glyph1 && (c0 == k_SRglyph_mod_square || c0 == k_SRglyph_mod_circle)){
+         v4f v0;
+         v2_sub( glyph0->size, glyph1->size, v0 );
+         v2_muladds( render->offset, v0, -0.5f, v0 );
+         v0[2] = render->offset[2];
+         v0[3] = render->offset[3];
+
+         shader_model_font_uOffset( v0 );
+         mesh_drawn( glyph0->indice_start, glyph0->indice_count );
+         continue;
+      }
+      else{
+         shader_model_font_uOffset( render->offset );
+         mesh_drawn( glyph0->indice_start, glyph0->indice_count );
+      }
+
+      render->offset[0] += glyph0->size[0]*render->offset[3];
    }
+
+   render->u8pch = NULL;
+}
+
+VG_STATIC 
+float font3d_simple_draw( font3d *font, u32 variant_id, const char *text, 
+                         camera *cam, m4x3f transform )
+{
+   if( !text ) return 0.0f;
+
+   struct font3d_render render;
+   font3d_begin( font, variant_id, cam, transform, &render );
+   render.u8pch = (u8*)text;
+   font3d_draw( &render );
+   return render.offset[0];
 }
 
 VG_STATIC 
 float font3d_string_width( font3d *font, u32 variant_id, const char *text )
 {
+   if( !text ) return 0.0f;
    float width = 0.0f;
    for( int i=0;; i++ ){
       u32 c = text[i];