Browse Source

added data from hhea and hmtx tables

IverMartinson 4 months ago
parent
commit
688729c653
6 changed files with 73 additions and 2 deletions
  1. BIN
      build/libsourparse.so
  2. BIN
      build/main.bin
  3. 2 1
      readme.md
  4. 23 0
      src/headers/sourparse.h
  5. 1 1
      src/launch_program/main.c
  6. 47 0
      src/library/sourparse.c

BIN
build/libsourparse.so


BIN
build/main.bin


+ 2 - 1
readme.md

@@ -9,4 +9,5 @@ World's Best TTF Parser, 2025
 - [x] [NOTE: not doing this. It's fine for the user to just read it themselves] read composite glyphs' child glyphs into memory as positions (I actualy might make it just be references to glyphs and then just compute the values at runtime, but with a whole ttf file loaded i think its only like 1mb super maximum of memory so it really doesn't matter)
 - [x] [NOTE: not doing this. It's fine for the user to just read it themselves] read composite glyphs' child glyphs into memory as positions (I actualy might make it just be references to glyphs and then just compute the values at runtime, but with a whole ttf file loaded i think its only like 1mb super maximum of memory so it really doesn't matter)
 - [ ] add support for other formats
 - [ ] add support for other formats
 - [ ] add complete TTF support (all the platforms and encodings. Well not the deprecated/obscure ones probably)
 - [ ] add complete TTF support (all the platforms and encodings. Well not the deprecated/obscure ones probably)
-- [x] read glyph position data (kerning, width to move, etc)
+- [x] read glyph position data (kerning, width to move, etc)
+- [ ] add composite glyph transforms besides position

+ 23 - 0
src/headers/sourparse.h

@@ -3,6 +3,26 @@
 
 
 #include "stdint.h"
 #include "stdint.h"
 
 
+typedef struct {
+    int16_t ascender;
+    int16_t descender;
+    int16_t line_gap;
+    uint16_t advance_max_width;
+    int16_t min_left_side_bearing;
+    int16_t min_right_side_bearing;
+    int16_t x_max_extent;
+    int16_t carat_slope_rise;
+    int16_t carat_slope_run;
+    int16_t carat_offset;
+    int16_t metric_data_format;
+    uint16_t number_of_h_metrics;
+} SP_hhea_table;
+
+typedef struct {
+    uint16_t advance_width;
+    int16_t left_side_bearing;
+} SP_long_hor_metric;
+
 typedef struct {
 typedef struct {
     int scale_x, scale01, scale10, scale_y;
     int scale_x, scale01, scale10, scale_y;
     int glyph_index;
     int glyph_index;
@@ -25,6 +45,9 @@ typedef struct {
     uint8_t *buffer;
     uint8_t *buffer;
     SP_glyph *glyphs;
     SP_glyph *glyphs;
     int16_t index_to_loca_format;
     int16_t index_to_loca_format;
+    SP_long_hor_metric *h_metrics;
+    SP_hhea_table hhea_table;
+    int16_t *left_side_bearings;
 } SP_font;
 } SP_font;
 
 
 SP_font* SP_load_font(char *filename);
 SP_font* SP_load_font(char *filename);

+ 1 - 1
src/launch_program/main.c

@@ -3,7 +3,7 @@
 int main(){
 int main(){
     SP_font *cal_sans = SP_load_font("fonts/CalSans-Regular.ttf");
     SP_font *cal_sans = SP_load_font("fonts/CalSans-Regular.ttf");
     // SP_font *jetbrains_mono = SP_load_font("fonts/JetBrainsMono-Regular.ttf");
     // SP_font *jetbrains_mono = SP_load_font("fonts/JetBrainsMono-Regular.ttf");
-    
+
     SP_free_font(cal_sans);
     SP_free_font(cal_sans);
     // SP_free_font(jetbrains_mono);
     // SP_free_font(jetbrains_mono);
 
 

+ 47 - 0
src/library/sourparse.c

@@ -278,6 +278,8 @@ SP_font* SP_load_font(char *filename){
     int cmap_offset = 0;
     int cmap_offset = 0;
     int loca_offset = 0;
     int loca_offset = 0;
     int head_offset = 0;
     int head_offset = 0;
+    int hhea_offset = 0;
+    int hmtx_offset = 0;
 
 
     for (int i = 0; i < (int)number_of_tables; ++i){
     for (int i = 0; i < (int)number_of_tables; ++i){
         char tag[5]; get_tag(font, tag);
         char tag[5]; get_tag(font, tag);
@@ -304,6 +306,14 @@ SP_font* SP_load_font(char *filename){
         else if (strcmp(tag, "head") == 0){
         else if (strcmp(tag, "head") == 0){
             head_offset = (int)offset;
             head_offset = (int)offset;
         }
         }
+
+        else if (strcmp(tag, "hhea") == 0){
+            hhea_offset = (int)offset;
+        }
+
+        else if (strcmp(tag, "hmtx") == 0){
+            hmtx_offset = (int)offset;
+        }
     }
     }
 
 
     // head table
     // head table
@@ -435,6 +445,43 @@ SP_font* SP_load_font(char *filename){
         font->current_byte = last_byte_offset;
         font->current_byte = last_byte_offset;
     }
     }
 
 
+    // hhea table
+    font->current_byte = hhea_offset;
+    
+    skip_32(font); // skip version
+
+    font->hhea_table.ascender = get_i16(font); // typographic ascent
+    font->hhea_table.descender = get_i16(font); // typographic descent
+    font->hhea_table.line_gap = get_i16(font); // typographic line gap
+    font->hhea_table.advance_max_width = get_u16(font); // max advance width for entry in hmtx table
+    font->hhea_table.min_left_side_bearing = get_i16(font); // "Minimum left sidebearing value in 'hmtx' table for glyphs with contours (empty glyphs should be ignored)."
+    font->hhea_table.min_right_side_bearing = get_i16(font); // "Minimum right sidebearing value; calculated as min(aw - (lsb + xMax - xMin)) for glyphs with contours (empty glyphs should be ignored)."
+    font->hhea_table.x_max_extent = get_i16(font); // "Max(lsb + (xMax - xMin))"
+    font->hhea_table.carat_slope_rise = get_i16(font); // used to calculate the slope of the cursor (1 for vertical)
+    font->hhea_table.carat_slope_run = get_i16(font); // 0 for vertical
+    font->hhea_table.carat_offset = get_i16(font); // "The amount by which a slanted highlight on a glyph needs to be shifted to produce the best appearance. Set to 0 for non-slanted fonts"
+    //                                       ^^^^too tired to make this simpler
+    skip_32(font); // skip reserved
+    skip_32(font); // (why is there reserved in the first place? for extra stuff later on? just add it to the end?)
+    font->hhea_table.metric_data_format = get_i16(font); // "0 for current format" (?)
+    font->hhea_table.number_of_h_metrics = get_u16(font); // h_metric entry count in hmtx table
+
+    // hmtx table
+    font->current_byte = hmtx_offset;
+
+    font->h_metrics = malloc(sizeof(SP_long_hor_metric) * font->number_of_glyphs); // advance width and left side bearings for each glyph
+    font->left_side_bearings = malloc(sizeof(int16_t) * font->number_of_glyphs); // left side bearings for glyphs with IDs >= number_of_h_metrics
+    // ^^^^^^^^^^^^^^^^^^^ this is useful for monospaced fonts where most everything has the same left side bearing. it saves on memory
+    // ^^^^^^^^^^^^^^^^^^^ when number_of_h_metrics is < number of glyphs, the last advance width applies to all
+    // ^^^^^^^^^^^^^^^^^^^ to make this easier on the user -- and because memory really isn't a problem anymore -- I'll only use h_metrics and make it the size of number of glyphs
+
+    int number_of_glyphs_that_arent_in_h_metrics = font->number_of_glyphs - font->hhea_table.number_of_h_metrics;
+
+    for (int i = 0; i < font->number_of_glyphs; ++i){
+        if (number_of_glyphs_that_arent_in_h_metrics == 0) font->h_metrics[i] = (SP_long_hor_metric){get_u16(font), get_i16(font)}; 
+        else font->h_metrics[i] = (SP_long_hor_metric){font->h_metrics[font->hhea_table.number_of_h_metrics - 1].advance_width, get_i16(font)}; 
+    }
+
     // read glyphs
     // read glyphs
     font->current_byte = glyph_offset;
     font->current_byte = glyph_offset;