// File: /workspace/github_c_makefile_star2_O1/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 $0xa8, %rsp
movq %rsi, %r12
movq %rdi, %r13
movq 0x30(%rsi), %rax
leaq -0xd0(%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 0x2260
movq %rax, %r15
movq %rax, 0x8(%rbx)
movq 0x8(%r12), %rsi
movq %rax, %rdi
callq 0x21a0
movb $0x66, -0x2(%r15,%r14)
movw $0x6473, -0x4(%r15,%r14) # imm = 0x6473
movq %r13, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x6dd9
movl 0x34(%rbx), %eax
cmpq $0xfffffff, %rax        # imm = 0xFFFFFFF
je 0x7483
movq %r13, -0x80(%rbp)
movq 0x38(%r13), %rcx
leaq (%rax,%rax,2), %rax
shlq $0x4, %rax
movzwl 0x12(%rcx,%rax), %eax
movq %rax, -0x78(%rbp)
movq 0x8(%r12), %rdi
leaq 0x13a39(%rip), %rsi     # 0x1aa21
callq 0x2210
testq %rax, %rax
je 0x74a2
movq %rax, %r13
movq %r12, -0x88(%rbp)
xorl %eax, %eax
leaq -0x48(%rbp), %rbx
movq %rax, (%rbx)
leaq -0x70(%rbp), %r14
movq %rax, (%r14)
movl $0x2000, %edi           # imm = 0x2000
callq 0x2260
movq %rax, %r15
movq %rbx, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x258c
cmpq $-0x1, %rax
je 0x7383
xorps %xmm0, %xmm0
movss %xmm0, -0x2c(%rbp)
xorl %ebx, %ebx
leaq 0x139dd(%rip), %r12     # 0x1aa23
leaq 0x139d1(%rip), %r14     # 0x1aa1e
leaq 0x139e5(%rip), %rdi     # 0x1aa39
movq $0x0, -0x50(%rbp)
movq $0x0, -0x40(%rbp)
movq $0x0, -0x38(%rbp)
movq %r13, -0x98(%rbp)
movq %r15, -0x90(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xd0(%rbp)
cmpb $0x63, (%rax)
jne 0x70b1
movl $0x1, %ecx
cmpq $0x4, %rcx
je 0x719f
movb (%rcx,%r14), %dl
leaq 0x1(%rcx), %rsi
cmpb %dl, (%rax,%rcx)
movq %rsi, %rcx
je 0x708f
testb %dl, %dl
je 0x719f
cmpb $0x6b, (%rax)
jne 0x734f
movl $0x1, %ecx
cmpq $0x7, %rcx
je 0x70dc
movb (%rcx,%rdi), %dl
leaq 0x1(%rcx), %rsi
cmpb %dl, (%rax,%rcx)
movq %rsi, %rcx
je 0x70bf
testb %dl, %dl
jne 0x734f
cmpb $0x6b, (%rax)
jne 0x710e
movl $0x1, %ecx
cmpq $0x8, %rcx
je 0x732e
leaq 0x13988(%rip), %rdx     # 0x1aa7f
movb (%rcx,%rdx), %dl
leaq 0x1(%rcx), %rsi
cmpb %dl, (%rax,%rcx)
movq %rsi, %rcx
je 0x70e6
testb %dl, %dl
je 0x732e
movq -0x38(%rbp), %r12
movq -0x40(%rbp), %r15
leaq -0xd0(%rbp), %rbx
movq %rbx, %rdi
callq 0x6eaa
movq %rax, %r13
movq %rbx, %rdi
callq 0x6eaa
cmpq $0xff, %r13
jg 0x7445
movq %rax, %rbx
cmpq $0x100, %rax            # imm = 0x100
jge 0x7445
shll $0x8, %r13d
orl %r13d, %ebx
leaq -0xd0(%rbp), %rdi
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12eb9(%rip), %xmm0    # 0x1a028
movw %bx, (%r12,%r15,8)
movss %xmm0, 0x4(%r12,%r15,8)
leaq 0x1(%r15), %rax
movq %rax, -0x40(%rbp)
movq -0x90(%rbp), %r15
movq -0x98(%rbp), %r13
xorl %ebx, %ebx
leaq 0x13889(%rip), %r12     # 0x1aa23
jmp 0x734f
cmpb $0x63, (%rax)
jne 0x71ca
xorl %ecx, %ecx
cmpq $0x4, %rcx
je 0x7318
movb 0x1(%rcx,%r12), %dl
leaq 0x1(%rcx), %rsi
cmpb %dl, 0x1(%rax,%rcx)
movq %rsi, %rcx
je 0x71a6
testb %dl, %dl
je 0x7318
leaq -0xd0(%rbp), %r12
movq %r12, %rdi
callq 0x6eaa
movq %rax, %rbx
movq %r12, %rdi
callq 0x6eaa
xorps %xmm1, %xmm1
cvtsi2ss %rax, %xmm1
movss 0x12e34(%rip), %xmm0    # 0x1a028
mulss %xmm0, %xmm1
movss %xmm1, -0x68(%rbp)
movq %r12, %rdi
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12e13(%rip), %xmm0    # 0x1a028
movss %xmm0, -0x64(%rbp)
movq %r12, %rdi
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12df6(%rip), %xmm0    # 0x1a028
movss %xmm0, -0x60(%rbp)
movq %r12, %rdi
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12dd9(%rip), %xmm0    # 0x1a028
movss %xmm0, -0x58(%rbp)
movq %r12, %rdi
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12dbc(%rip), %xmm0    # 0x1a028
movss %xmm0, -0x5c(%rbp)
movq %r12, %rdi
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12d9f(%rip), %xmm0    # 0x1a028
movss %xmm0, -0x54(%rbp)
movq %r12, %rdi
leaq 0x1378b(%rip), %r12     # 0x1aa23
callq 0x6eaa
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
mulss 0x12d7b(%rip), %xmm0    # 0x1a028
movss -0x2c(%rbp), %xmm1
movss -0x58(%rbp), %xmm2
maxss %xmm2, %xmm1
movss %xmm1, -0x2c(%rbp)
movzbl %bl, %eax
shll $0x5, %eax
movb %bl, (%r15,%rax)
xorl %ebx, %ebx
movss -0x68(%rbp), %xmm1
movss %xmm1, 0x4(%r15,%rax)
movss -0x64(%rbp), %xmm1
movss %xmm1, 0x8(%r15,%rax)
movss -0x60(%rbp), %xmm1
movss %xmm1, 0xc(%r15,%rax)
movss %xmm2, 0x10(%r15,%rax)
movss -0x5c(%rbp), %xmm1
movss %xmm1, 0x14(%r15,%rax)
movss -0x54(%rbp), %xmm1
movss %xmm1, 0x18(%r15,%rax)
movss %xmm0, 0x1c(%r15,%rax)
jmp 0x734f
leaq -0xd0(%rbp), %rdi
callq 0x6eaa
testq %rax, %rax
jne 0x734f
jmp 0x7464
leaq -0xd0(%rbp), %rdi
callq 0x6eaa
movq %rax, -0x50(%rbp)
leaq (,%rax,8), %rdi
callq 0x2260
movq %rax, -0x38(%rbp)
movq -0x48(%rbp), %rdi
callq 0x2220
movq %rbx, -0x48(%rbp)
movq %rbx, -0x70(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0x70(%rbp), %rsi
movq %r13, %rdx
callq 0x258c
cmpq $-0x1, %rax
leaq 0x136be(%rip), %rdi     # 0x1aa39
jne 0x707a
jmp 0x73a3
movq $0x0, -0x40(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x2c(%rbp)
movq $0x0, -0x38(%rbp)
movq $0x0, -0x50(%rbp)
movq -0x40(%rbp), %r13
cmpq %r13, -0x50(%rbp)
movq -0x88(%rbp), %r14
jne 0x74c1
testq %r13, %r13
movq -0x38(%rbp), %r12
je 0x73e8
leaq (%r12,%r13,8), %rbx
bsrq %r13, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x18be6
movq %r12, %rdi
movq %rbx, %rsi
callq 0x18cdf
leal 0x2030(,%r13,8), %eax
movl %eax, 0x30(%r14)
leaq -0xd0(%rbp), %rdx
movq -0x78(%rbp), %rax
movq %rax, (%rdx)
movss -0x2c(%rbp), %xmm0
movss %xmm0, 0x8(%rdx)
movl $0x0, 0xc(%rdx)
movq $0x100, 0x10(%rdx)      # imm = 0x100
movq %r13, 0x18(%rdx)
movq %r15, 0x20(%rdx)
movq %r12, 0x28(%rdx)
movq -0x80(%rbp), %rdi
movq %r14, %rsi
callq 0x6c83
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x135f5(%rip), %rdi     # 0x1aa41
leaq 0x13461(%rip), %rsi     # 0x1a8b4
leaq 0x1358d(%rip), %rcx     # 0x1a9e7
movl $0xbf, %edx
callq 0x2120
leaq 0x135be(%rip), %rdi     # 0x1aa29
leaq 0x13442(%rip), %rsi     # 0x1a8b4
leaq 0x1356e(%rip), %rcx     # 0x1a9e7
movl $0xa3, %edx
callq 0x2120
leaq 0x1353c(%rip), %rdi     # 0x1a9c6
leaq 0x13423(%rip), %rsi     # 0x1a8b4
leaq 0x1354f(%rip), %rcx     # 0x1a9e7
movl $0x92, %edx
callq 0x2120
leaq 0x1356b(%rip), %rdi     # 0x1aa14
leaq 0x13404(%rip), %rsi     # 0x1a8b4
leaq 0x13530(%rip), %rcx     # 0x1a9e7
movl $0x98, %edx
callq 0x2120
leaq 0x13599(%rip), %rdi     # 0x1aa61
leaq 0x133e5(%rip), %rsi     # 0x1a8b4
leaq 0x13511(%rip), %rcx     # 0x1a9e7
movl $0xcb, %edx
callq 0x2120