Browse Source

added kerning support

Iver 4 months ago
parent
commit
8929b61feb

BIN
build/librasteriver.so


BIN
build/libsourparse.so


BIN
build/main.bin


BIN
compiled_libs/librasteriver.so


BIN
compiled_libs/libsourparse.so


+ 1 - 1
src/headers/functions.h

@@ -17,7 +17,7 @@ void RI_euler_rotation_to_quaternion(RI_vector_4f* quaternion, RI_vector_3f eule
 // Tick RasterIver.
 // Copies the window's texture (ri.frame_buffer.image_buffer) onto the screen, calls SDL_RenderPresent, handles SDL events, increases ri.frame by 1, and optionally clears the window's texture
 void RI_tick(int clear_window_texture_after_rendering); 
-void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, float size, char *text);
+void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, double size, char *text);
 void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color);
 RI_vector_2f v2_to_2f(RI_vector_2 v);
 RI_vector_2 v2f_to_2(RI_vector_2f v);

+ 7 - 1
src/headers/sourparse.h

@@ -3,6 +3,11 @@
 
 #include "stdint.h"
 
+typedef struct {
+    uint16_t left, right;
+    int16_t value; // kerning value for the above pair. If it's more than 0, the cahracters will be moved apart. If it's less than 0, the characters will be moved closer
+} SP_kerning_pair;
+
 typedef struct {
     int16_t ascender;
     int16_t descender;
@@ -40,7 +45,7 @@ typedef struct {
 } SP_glyph;
 
 typedef struct {
-    int current_byte, number_of_glyphs, *glyph_offsets; 
+    int current_byte, number_of_glyphs, number_of_kerning_pairs, *glyph_offsets; 
     uint16_t *unicode_to_glyph_indicies;
     float units_per_em;
     uint8_t *buffer;
@@ -49,6 +54,7 @@ typedef struct {
     SP_long_hor_metric *h_metrics;
     SP_hhea_table hhea_table;
     int16_t *left_side_bearings;
+    SP_kerning_pair *kerning_pairs; 
 } SP_font;
 
 SP_font* SP_load_font(char *filename);

+ 3 - 1
src/launch_program/main.c

@@ -13,7 +13,6 @@ int main(){
     
     // get RasterIver context
     RasterIver *ri = RI_get_ri();
-    ri->prefix = "--------------------------";
 
     ri->debug_memory = 0;
 
@@ -106,6 +105,9 @@ int main(){
 
         snprintf(fps_string, 64, "%.2f", fps);
         RI_render_text(cal_sans, ri->frame_buffer, (RI_vector_2f){0, 670}, 0xFFFFFFFF, 2, 20, fps_string);
+
+        RI_render_text(comic_sans, ri->frame_buffer, (RI_vector_2f){0, 300}, 0xFFFF00FF, 2, 60, "Traditionally Choice");
+        RI_render_text(comic_sans, ri->frame_buffer, (RI_vector_2f){0, 120}, 0xFFFF00FF, 2, 60, "itititititititititititititit");
         
         snprintf(fps_string, 64, "%.6f", delta_time);
         RI_render_text(cal_sans, ri->frame_buffer, (RI_vector_2f){0, 640}, 0xFFFFFFFF, 2, 20, fps_string);

+ 40 - 16
src/library/rasteriver.c

@@ -201,7 +201,7 @@ int intersects(RI_vector_2f a, RI_vector_2f b, RI_vector_2f c){
     return intersects_segments(a, b, c, d);
 }
 
-void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size, uint32_t color, int bezier_resolution, float units_per_em, SP_glyph *glyph){
+void render_glyph(RI_texture *target_texture, RI_vector_2f position, double size, uint32_t color, int bezier_resolution, double units_per_em, SP_glyph *glyph){
     // estimate
     int new_point_count = 0;
     int allocated_new_points = glyph->number_of_points * 3;
@@ -231,14 +231,14 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
             int cur = (point % (glyph->contour_end_indicies[contour] + 1 - point_start) + point_offset);
             int next = ((point + 1) % (glyph->contour_end_indicies[contour] + 1 - point_start) + point_offset);
 
-            new_points[new_point_count].x = (float)glyph->x_coords[cur] / units_per_em * size + position.x;
-            new_points[new_point_count].y = (float)glyph->y_coords[cur] / units_per_em * size + position.y;
+            new_points[new_point_count].x = (double)glyph->x_coords[cur] / units_per_em * size + position.x;
+            new_points[new_point_count].y = (double)glyph->y_coords[cur] / units_per_em * size + position.y;
 
             new_point_count++;
 
             // if current and next glyph are both on or off the curve, add a point between them-
             if ((glyph->flags[cur] & 1) == (glyph->flags[next] & 1)){
-                vector_2f_lerp((RI_vector_2f){(float)glyph->x_coords[cur] / units_per_em * size + position.x, (float)glyph->y_coords[cur] / units_per_em * size + position.y}, (RI_vector_2f){(float)glyph->x_coords[next] / units_per_em * size + position.x, (float)glyph->y_coords[next] / units_per_em * size + position.y}, &new_points[new_point_count], 0.5);
+                vector_2f_lerp((RI_vector_2f){(double)glyph->x_coords[cur] / units_per_em * size + position.x, (double)glyph->y_coords[cur] / units_per_em * size + position.y}, (RI_vector_2f){(double)glyph->x_coords[next] / units_per_em * size + position.x, (double)glyph->y_coords[next] / units_per_em * size + position.y}, &new_points[new_point_count], 0.5);
 
                 new_point_count++;
             }
@@ -265,7 +265,7 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
             RI_vector_2f prev_point = new_points[point];
 
             for (int i = 0; i < bezier_resolution; ++i){
-                float w = (float)(i + 1) / (float)bezier_resolution;
+                double w = (double)(i + 1) / (double)bezier_resolution;
                 
                 RI_vector_2f bez_point; 
                 
@@ -280,8 +280,8 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
         }
     }
 
-    for (int y = fmax((int)((float)glyph->y_min / (float)units_per_em * size) + position.y, 0.0); y < fmin((int)((float)glyph->y_max / (float)units_per_em * size) + position.y, target_texture->resolution.y); ++y){
-        for (int x = fmax((int)((float)glyph->x_min / (float)units_per_em * size) + position.x, 0.0); x < fmin((int)((float)glyph->x_max / (float)units_per_em * size) + position.x, target_texture->resolution.x); ++x){
+    for (int y = fmax((int)((double)glyph->y_min / (double)units_per_em * size) + position.y, 0.0); y < fmin((int)((double)glyph->y_max / (double)units_per_em * size) + position.y, target_texture->resolution.y); ++y){
+        for (int x = fmax((int)((double)glyph->x_min / (double)units_per_em * size) + position.x, 0.0); x < fmin((int)((double)glyph->x_max / (double)units_per_em * size) + position.x, target_texture->resolution.x); ++x){
             int intersections = 0;
             
             for (int contour = 0; contour < glyph->number_of_contours; ++contour){
@@ -304,7 +304,7 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
     RI_free(contour_ends);
 }
 
-void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, float size, char *text){
+void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, double size, char *text){
     int character_count = strlen(text);
     
     int current_advance_width = 0;
@@ -317,7 +317,7 @@ void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f posi
         
         SP_glyph *current_glyph = &font->glyphs[glyph];
         
-        glyph_position.x = position.x + font->h_metrics[glyph].left_side_bearing / font->units_per_em * size;
+        glyph_position.x = position.x;// + ((double)font->h_metrics[glyph].left_side_bearing / font->units_per_em * size);
         
         if (current_glyph->number_of_contours > 0){
             render_glyph(target_texture, glyph_position, size, color, bezier_resolution, font->units_per_em, current_glyph);
@@ -329,8 +329,8 @@ void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f posi
             for (int k = 0; k < current_glyph->number_of_components; k++){
                 int c_glyph = current_glyph->components[k].glyph_index;
                 
-                float offset_x = (float)current_glyph->components[k].arg1;
-                float offset_y = (float)current_glyph->components[k].arg2;
+                double offset_x = (double)current_glyph->components[k].arg1;
+                double offset_y = (double)current_glyph->components[k].arg2;
 
                 glyph_position.x += offset_x / font->units_per_em * size;
                 glyph_position.y += offset_y / font->units_per_em * size;
@@ -341,8 +341,32 @@ void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f posi
                 glyph_position.y -= offset_y / font->units_per_em * size;
             }
         }
+
+        // find kerning value
+        double kerning_offset = 0;
         
-        position.x += (float)(font->h_metrics[glyph].advance_width) / font->units_per_em * size;
+        if (character_i + 1 < character_count && font->number_of_kerning_pairs > 0){
+            uint32_t key = (glyph << 16) | (uint16_t)font->unicode_to_glyph_indicies[text[character_i + 1]];
+            
+            int low = 0;
+            int high = font->number_of_kerning_pairs - 1;
+            
+            while (low <= high) {
+                int mid = (low + high) / 2;
+                uint32_t midKey = (font->kerning_pairs[mid].left << 16) | font->kerning_pairs[mid].right;
+
+                if (midKey == key) {
+                    kerning_offset = (double)font->kerning_pairs[mid].value; // found it
+                    break;
+                } else if (midKey < key) {
+                    low = mid + 1;           // search right half
+                } else {
+                    high = mid - 1;          // search left half
+                }
+            }
+        }
+
+        position.x += (double)(font->h_metrics[glyph].advance_width + kerning_offset) / font->units_per_em * size;
     }
 }
 
@@ -635,7 +659,7 @@ double mod(double a, double b){
     return ret;
 }
 
-uint32_t multiply_rgb(uint32_t color, float factor) {
+uint32_t multiply_rgb(uint32_t color, double factor) {
     uint8_t a = (color >> 24) & 0xFF;
     uint8_t r = (color >> 16) & 0xFF;
     uint8_t g = (color >> 8)  & 0xFF;
@@ -1064,10 +1088,10 @@ int RI_render(RI_scene *scene, RI_texture *target_texture, int clear_texture){
                     double alpha = 1;
 
                     if (!(scene->flags & RI_SCENE_DONT_USE_AA) || !(mat->flags & RI_MATERIAL_DONT_USE_AA)){
-                        float total_inside = 0;
+                        double total_inside = 0;
                         
-                        for (float sub_y = 1.0 / (-scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_y < 1.0 / (scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_y += 1.0 / (scene->antialiasing_subsample_resolution / 2.0)){
-                            for (float sub_x = 1.0 / (-scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_x < 1.0 / (scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_x += 1.0 / (scene->antialiasing_subsample_resolution / 2.0)){
+                        for (double sub_y = 1.0 / (-scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_y < 1.0 / (scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_y += 1.0 / (scene->antialiasing_subsample_resolution / 2.0)){
+                            for (double sub_x = 1.0 / (-scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_x < 1.0 / (scene->antialiasing_subsample_resolution / 2.0) - 0.5; sub_x += 1.0 / (scene->antialiasing_subsample_resolution / 2.0)){
                                 w0 = ((pos_1->y - pos_2->y) * (pixel_x_index + sub_x - pos_2->x) + (pos_2->x - pos_1->x) * (pixel_y_index + sub_y - pos_2->y)) / denominator;
                                 w1 = ((pos_2->y - pos_0->y) * (pixel_x_index + sub_x - pos_0->x) + (pos_0->x - pos_2->x) * (pixel_y_index + sub_y - pos_0->y)) / denominator; 
                                 w2 = 1.0 - w0 - w1;