// File: /workspace/github_c_makefile_star2_O3/FredTheDino[P]Fog/src/engine/unix_assets.cpp
// Function: load_font(AssetFile*, Asset::Header*)
void load_font(AssetFile *file, Asset::Header *header) {
    Asset::Font font = {};
    {
        Asset::Header sdf_header = *header;
        sdf_header.asset_id = 0xFFFFFFF;  // Invalid value
        sdf_header.type = Asset::Type::TEXTURE;
        sdf_header.file_path = (char *) malloc(header->file_path_length);
        strcpy(sdf_header.file_path, header->file_path);
        sdf_header.file_path[header->file_path_length - 2] = 'f';
        sdf_header.file_path[header->file_path_length - 3] = 'd';
        sdf_header.file_path[header->file_path_length - 4] = 's';
        load_texture(file, &sdf_header, false);
        assert(sdf_header.asset_id != 0xFFFFFFF);
        font.texture = file->assets[sdf_header.asset_id].image.id;
    }
    float inv_width  = 1.0 / OPENGL_TEXTURE_WIDTH;
    float inv_height = 1.0 / OPENGL_TEXTURE_HEIGHT;
    FILE *font_file = fopen(header->file_path, "r");
    assert(font_file);
    char *read_line = nullptr;
    size_t size = 0;

    font.glyphs = (Asset::Font::Glyph *) malloc(font.num_glyphs * sizeof(Asset::Font::Glyph));
    long expected_glyphs = 0, expected_kernings = 0;
    while (getline(&read_line, &size, font_file) != -1) {
        char *line = read_line;
        if (starts_with(line, "char")) {
            if (starts_with(line, "chars")) {
                expected_glyphs = read_next_long(&line);
                assert(expected_glyphs);
            } else {
                Asset::Font::Glyph g = {
                    // id
                    (u8) read_next_long(&line),
                    // x, y
                    read_next_long(&line) * inv_width,
                    read_next_long(&line) * inv_height,
                    // w, h
                    read_next_long(&line) * inv_width,
                    read_next_long(&line) * inv_height,
                    // xo, yo
                    read_next_long(&line) * inv_width,
                    read_next_long(&line) * inv_height,
                    // advance
                    read_next_long(&line) * inv_width
                };
                font.height = std::max(g.h, font.height);
                font.glyphs[g.id] = g;
            }
        } else if (starts_with(line, "kerning")) {
            if (starts_with(line, "kernings")) {
                expected_kernings = read_next_long(&line);
                font.kernings = (Asset::Font::Kerning *) malloc(expected_kernings *
                                                  sizeof(Asset::Font::Kerning));
            } else {
                long first = read_next_long(&line);
                long second = read_next_long(&line);
                assert(first <= 0xFF && second <= 0xFF);
                font.kernings[font.num_kernings++] = {
                    (u16) (first << 8 | second),
                    read_next_long(&line) * inv_width
                };
            }
        }

        free(read_line);
        read_line = nullptr;
        size = 0;
    }
    assert(expected_kernings == font.num_kernings);
    std::sort(font.kernings, font.kernings + font.num_kernings);

    header->asset_size = sizeof(Asset::Data) +
                         sizeof(Asset::Font::Kerning) * font.num_kernings +
                         sizeof(Asset::Font::Glyph)   * font.num_glyphs;
    Asset::Data asset = {.font = font};
    add_asset_to_file(file, header, &asset);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rsi, %r12
movq %rdi, %r13
movq 0x30(%rsi), %rax
leaq -0xe0(%rbp), %rbx
movq %rax, 0x30(%rbx)
movups (%rsi), %xmm0
movups 0x10(%rsi), %xmm1
movups 0x20(%rsi), %xmm2
movaps %xmm0, (%rbx)
movaps %xmm2, 0x20(%rbx)
movaps %xmm1, 0x10(%rbx)
movl $0xfffffff, 0x34(%rbx)  # imm = 0xFFFFFFF
movl $0x1, (%rbx)
movq 0x10(%rsi), %r14
movq %r14, %rdi
callq 0x2270
movq %rax, %r15
movq %rax, 0x8(%rbx)
movq 0x8(%r12), %rsi
movq %rax, %rdi
callq 0x21b0
movb $0x66, -0x2(%r15,%r14)
movw $0x6473, -0x4(%r15,%r14) # imm = 0x6473
movq %r13, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x6d17
movl 0x34(%rbx), %eax
cmpq $0xfffffff, %rax        # imm = 0xFFFFFFF
je 0x7381
movq 0x38(%r13), %rcx
leaq (%rax,%rax,2), %rax
shlq $0x4, %rax
movzwl 0x12(%rcx,%rax), %eax
movq %rax, -0x70(%rbp)
movq 0x8(%r12), %rdi
leaq 0x12aff(%rip), %rsi     # 0x19a21
callq 0x2220
testq %rax, %rax
je 0x73a0
movq %rax, %rbx
xorl %eax, %eax
leaq -0x38(%rbp), %r15
movq %rax, (%r15)
leaq -0x90(%rbp), %r14
movq %rax, (%r14)
movl $0x2000, %edi           # imm = 0x2000
callq 0x2270
movq %rax, -0x80(%rbp)
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x257c
cmpq $-0x1, %rax
je 0x72da
movq %r13, -0x98(%rbp)
movq %r12, -0xa0(%rbp)
xorps %xmm0, %xmm0
leaq 0x12a9a(%rip), %r13     # 0x19a1e
leaq 0x12a98(%rip), %r14     # 0x19a23
leaq -0x38(%rbp), %r12
leaq 0x12aa3(%rip), %r15     # 0x19a39
leaq 0x12ae2(%rip), %rsi     # 0x19a7f
movq $0x0, -0x78(%rbp)
movq $0x0, -0x48(%rbp)
movq $0x0, -0x40(%rbp)
movq %rbx, -0x88(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0xe0(%rbp)
movb $0x63, %dl
xorl %ecx, %ecx
movss %xmm0, -0x2c(%rbp)
cmpb %dl, (%rax,%rcx)
jne 0x7018
movb 0x1(%rcx,%r13), %dl
incq %rcx
cmpq $0x4, %rcx
jne 0x6fd0
movb $0x63, %dl
xorl %ecx, %ecx
cmpb %dl, (%rax,%rcx)
jne 0x7073
movb 0x1(%rcx,%r14), %dl
incq %rcx
cmpq $0x5, %rcx
jne 0x6fe7
leaq -0xe0(%rbp), %rdi
callq 0x6de8
testq %rax, %rax
jne 0x7243
jmp 0x7343
movb $0x6b, %cl
xorl %edx, %edx
cmpb %cl, (%rax,%rdx)
jne 0x7243
movb 0x1(%rdx,%r15), %cl
incq %rdx
cmpq $0x7, %rdx
jne 0x701c
movb $0x6b, %dl
xorl %ecx, %ecx
cmpb %dl, (%rax,%rcx)
jne 0x71c2
movb 0x1(%rcx,%rsi), %dl
incq %rcx
cmpq $0x8, %rcx
jne 0x7037
leaq -0xe0(%rbp), %rdi
callq 0x6de8
movq %rax, -0x78(%rbp)
leaq (,%rax,8), %rdi
callq 0x2270
movq %rax, -0x40(%rbp)
jmp 0x7243
leaq -0xe0(%rbp), %r12
movq %r12, %rdi
callq 0x6de8
movq %rax, %rbx
movq %r12, %rdi
callq 0x6de8
xorps %xmm1, %xmm1
cvtsi2ss %rax, %xmm1
movss 0x11f8b(%rip), %xmm0    # 0x19028
mulss %xmm0, %xmm1
movss %xmm1, -0x50(%rbp)
movq %r12, %rdi
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11f6a(%rip), %xmm0    # 0x19028
movss %xmm0, -0x64(%rbp)
movq %r12, %rdi
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11f4d(%rip), %xmm0    # 0x19028
movss %xmm0, -0x60(%rbp)
movq %r12, %rdi
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11f30(%rip), %xmm0    # 0x19028
movss %xmm0, -0x58(%rbp)
movq %r12, %rdi
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11f13(%rip), %xmm0    # 0x19028
movss %xmm0, -0x5c(%rbp)
movq %r12, %rdi
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11ef6(%rip), %xmm0    # 0x19028
movss %xmm0, -0x54(%rbp)
movq %r12, %rdi
leaq -0x38(%rbp), %r12
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11ed5(%rip), %xmm0    # 0x19028
movss -0x2c(%rbp), %xmm1
movss -0x58(%rbp), %xmm2
maxss %xmm2, %xmm1
movss %xmm1, -0x2c(%rbp)
movzbl %bl, %eax
shll $0x5, %eax
movq -0x80(%rbp), %rcx
movb %bl, (%rcx,%rax)
movq -0x88(%rbp), %rbx
movss -0x50(%rbp), %xmm1
movss %xmm1, 0x4(%rcx,%rax)
movss -0x64(%rbp), %xmm1
movss %xmm1, 0x8(%rcx,%rax)
movss -0x60(%rbp), %xmm1
movss %xmm1, 0xc(%rcx,%rax)
movss %xmm2, 0x10(%rcx,%rax)
movss -0x5c(%rbp), %xmm1
movss %xmm1, 0x14(%rcx,%rax)
movss -0x54(%rbp), %xmm1
movss %xmm1, 0x18(%rcx,%rax)
movss %xmm0, 0x1c(%rcx,%rax)
jmp 0x7243
leaq -0xe0(%rbp), %rbx
movq %rbx, %rdi
callq 0x6de8
movq %rax, %r12
movq %rbx, %rdi
callq 0x6de8
cmpq $0xff, %r12
jg 0x7362
movq %rax, %rbx
cmpq $0x100, %rax            # imm = 0x100
jge 0x7362
shll $0x8, %r12d
orl %r12d, %ebx
leaq -0xe0(%rbp), %rdi
callq 0x6de8
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x11e0d(%rip), %xmm0    # 0x19028
movq -0x48(%rbp), %rax
movq -0x40(%rbp), %rdx
movw %bx, (%rdx,%rax,8)
movq %rdx, -0x40(%rbp)
movss %xmm0, 0x4(%rdx,%rax,8)
incq %rax
movq %rax, -0x48(%rbp)
movq -0x88(%rbp), %rbx
leaq -0x38(%rbp), %r12
movq -0x38(%rbp), %rdi
callq 0x2230
xorl %eax, %eax
movq %rax, -0x38(%rbp)
movq %rax, -0x90(%rbp)
movq %r12, %rdi
leaq -0x90(%rbp), %rsi
movq %rbx, %rdx
callq 0x257c
cmpq $-0x1, %rax
movss -0x2c(%rbp), %xmm0
leaq 0x12804(%rip), %rsi     # 0x19a7f
jne 0x6fbc
movq -0x40(%rbp), %rbx
movq -0x48(%rbp), %r14
cmpq %r14, -0x78(%rbp)
jne 0x73bf
testq %r14, %r14
movq -0xa0(%rbp), %r12
movq -0x98(%rbp), %r13
movq -0x70(%rbp), %r15
je 0x72e8
leaq (%rbx,%r14,8), %rsi
movq %rsi, -0x50(%rbp)
bsrq %r14, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %rbx, %rdi
callq 0x178e4
movq %rbx, %rdi
movq -0x50(%rbp), %rsi
callq 0x179dd
movss -0x2c(%rbp), %xmm0
jmp 0x72eb
xorps %xmm0, %xmm0
xorl %ebx, %ebx
xorl %r14d, %r14d
movq -0x70(%rbp), %r15
jmp 0x72eb
xorl %r14d, %r14d
leal 0x2030(,%r14,8), %eax
movl %eax, 0x30(%r12)
leaq -0xe0(%rbp), %rdx
movq %r15, (%rdx)
movss %xmm0, 0x8(%rdx)
movl $0x0, 0xc(%rdx)
movq $0x100, 0x10(%rdx)      # imm = 0x100
movq %r14, 0x18(%rdx)
movq -0x80(%rbp), %rax
movq %rax, 0x20(%rdx)
movq %rbx, 0x28(%rdx)
movq %r13, %rdi
movq %r12, %rsi
callq 0x6bba
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x126df(%rip), %rdi     # 0x19a29
leaq 0x12563(%rip), %rsi     # 0x198b4
leaq 0x1268f(%rip), %rcx     # 0x199e7
movl $0xa3, %edx
callq 0x2120
leaq 0x126d8(%rip), %rdi     # 0x19a41
leaq 0x12544(%rip), %rsi     # 0x198b4
leaq 0x12670(%rip), %rcx     # 0x199e7
movl $0xbf, %edx
callq 0x2120
leaq 0x1263e(%rip), %rdi     # 0x199c6
leaq 0x12525(%rip), %rsi     # 0x198b4
leaq 0x12651(%rip), %rcx     # 0x199e7
movl $0x92, %edx
callq 0x2120
leaq 0x1266d(%rip), %rdi     # 0x19a14
leaq 0x12506(%rip), %rsi     # 0x198b4
leaq 0x12632(%rip), %rcx     # 0x199e7
movl $0x98, %edx
callq 0x2120
leaq 0x1269b(%rip), %rdi     # 0x19a61
leaq 0x124e7(%rip), %rsi     # 0x198b4
leaq 0x12613(%rip), %rcx     # 0x199e7
movl $0xcb, %edx
callq 0x2120