diff options
Diffstat (limited to 'font.c')
| -rw-r--r-- | font.c | 211 |
1 files changed, 211 insertions, 0 deletions
@@ -0,0 +1,211 @@ +#include "freetype/fttypes.h" +#include <wayland-client.h> +#include <ft2build.h> +#include <stdint.h> +#include <string.h> +#include FT_FREETYPE_H +#include <stdlib.h> +#include <time.h> + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include "utf_8.h" + +static int canvas_width = 0; +static int canvas_height = 0; +#define COLOR 3 + +double now_sec(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec + ts.tv_nsec * 1e-9; +} + +typedef struct { + int rows; + int width; + int advance_x; + int advance_y; + int bitmap_top; + int bitmap_left; + unsigned char *buffer; +}CachedGlyph; + +static CachedGlyph ascii_cache[256] = {0}; + +CachedGlyph *get_glyph(FT_Face face, uint32_t codepoint) +{ + if (codepoint < 256) + { + return &ascii_cache[codepoint]; + } + else { + printf("Ohno."); + return 0; + } +} + +int load_font(FT_Library library, char *path, FT_Face *face) +{ + int error; + error = FT_New_Face(library, path, 0, face); + if (error) + { + printf("Error while loading font"); + return 1; + } + error = FT_Set_Char_Size(*face, 0, 48*64, 300, 300); + if (error) + { + printf("Error during setting char size %d", error); + return 1; + } + + for (int i = 0; i < 255; i++) + { + int error; + int glyph_index = 0; + glyph_index = FT_Get_Char_Index(*face, i); + error = FT_Load_Glyph(*face, glyph_index, FT_LOAD_RENDER); + if (error) + { + printf("Error during LoadGlyph %d", error); + continue; + } + FT_GlyphSlot slot = (*face)->glyph; + + CachedGlyph val = { + .rows = slot->bitmap.rows, + .width = slot->bitmap.width, + .advance_x = slot->advance.x, + .advance_y = slot->advance.y, + .bitmap_top = slot->bitmap_top, + .bitmap_left = slot->bitmap_left, + }; + size_t bytes = slot->bitmap.rows * abs(slot->bitmap.pitch) * COLOR; + val.buffer = malloc(bytes); + + for (int r = 0; r < val.rows; r++) + { + unsigned char *src = slot->bitmap.buffer + r * abs(slot->bitmap.pitch); + unsigned char *target = val.buffer + r * abs(slot->bitmap.pitch) * COLOR; + + for (int c = 0; c < val.width; c++) + { + unsigned char alpha = src[c]; + target[c * COLOR + 0] = alpha; + target[c * COLOR + 1] = alpha; + target[c * COLOR + 2] = alpha; + } + } + ascii_cache[i] = val; + } + return 0; +} + +int dumbRenderer(FT_Face face, unsigned int codepoint, unsigned char *canvas, int pen_x, int pen_y) +{ + int x = 0; + int y = 0; + CachedGlyph *glyph = get_glyph(face, codepoint); + int dst_x = pen_x + glyph->bitmap_left; + int dst_y = pen_y - glyph->bitmap_top; + + for (y = 0; y < glyph->rows; y++) + { + int target_y = dst_y + y; + int dst_idx = (target_y * canvas_width + dst_x) * COLOR; + unsigned char *row = glyph->buffer + y * abs(glyph->width * COLOR); + memcpy(&canvas[dst_idx], row, glyph->width * COLOR); + // stupe loop + // for (x = 0; x < bitmap.width; x++) + // { + // int target_x = dst_x + x; + // int idx = (target_y * width + target_x) * COLOR; + // unsigned char alpha = row[x]; + // canvas[idx + 0] |= alpha; + // canvas[idx + 1] |= alpha; + // canvas[idx + 2] |= alpha; + // } + } + return (glyph->advance_x >> 6); +} + +int main(int argc, char **argv) +{ + double t0 = now_sec(); + FT_Library library; + FT_Face face; + int error = FT_Init_FreeType(&library); + if (error) + return 1; + // shut up gemini this is where my fonts live + error = load_font(library, "/usr/share/fonts/ubuntu/UbuntuMono-R.ttf", &face); + printf("sucees\n"); + if (error) + return 1; + double t1 = now_sec(); + + // ARGV[1] to Glyph Index Array + uint32_t state = 0; + uint32_t codep = 0; + int glyph_count = 0; + int string_len = strlen(argv[1]); + FT_UInt target_string[string_len + 1]; + for (int i = 0; i < string_len; i++) { + utf8_decode(&state, &codep, (uint8_t)argv[1][i]); + if (state == UTF8_REJECT) + printf("Invalid utf8 char: %u\n", (uint8_t)argv[1][i]); + else if (state == UTF8_ACCEPT) + { + target_string[glyph_count] = codep; + glyph_count += 1; + } + } + target_string[glyph_count] = 0; + double t2 = now_sec(); + + unsigned int *cp = &target_string[0]; + char *fname = "out2.ppm"; + + CachedGlyph *test = get_glyph(face, 65); + int padding = 80; + canvas_width = ((test->advance_x >> 6) * glyph_count) + padding; + printf("width set!"); + canvas_height = 360; + unsigned char *canvas = calloc(canvas_width * canvas_height * COLOR, sizeof(unsigned char)); + int pen_x = 20; + int pen_y = canvas_height / 2; + printf("Malloc succees"); + + for (int i = 0; i < 200; i++) + { // benchmaxxing + unsigned int *cp = &target_string[0]; + pen_x = 20; + double t2 = now_sec(); + for (; *cp; cp++) { + pen_x += dumbRenderer(face, *cp, canvas, pen_x, pen_y); + } + double t3 = now_sec(); + printf("Render: %.6f ms\n", (t3 - t2) * 1000.0); + } + //for (; *cp; cp++) + //{ + // pen_x += dumbRenderer(face, *cp, canvas, pen_x, pen_y); + //} + + double t3 = now_sec(); + int fd = open(fname, O_CREAT | O_RDWR | O_TRUNC); + dprintf(fd, "P6\n%d %d\n255\n", canvas_width, canvas_height); + write(fd, canvas, canvas_width * canvas_height * COLOR); + double t4 = now_sec(); + + printf("Font Load: %.6f ms\n", (t1 - t0) * 1000.0); + printf("UTF-8 parse: %.6f ms\n", (t2 - t1) * 1000.0); + printf("Render: %.6f ms\n", (t3 - t2) * 1000.0); + printf("Write to file: %.6f ms\n", (t4 - t3) * 1000.0); + + close(fd); + free(canvas); +} |
