// File: /workspace/github_c_makefile_star2_O2/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 $0x98, %rsp
movq %rsi, %r12
movq %rdi, %r13
movq 0x30(%rsi), %rax
leaq -0xc0(%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 0x22b0
movq %rax, %r15
movq %rax, 0x8(%rbx)
movq 0x8(%r12), %rsi
movq %rax, %rdi
callq 0x21d0
movb $0x66, -0x2(%r15,%r14)
movw $0x6473, -0x4(%r15,%r14) # imm = 0x6473
movq %r13, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x62c9
movl 0x34(%rbx), %eax
cmpq $0xfffffff, %rax        # imm = 0xFFFFFFF
je 0x681e
movq %r13, -0x80(%rbp)
movq 0x38(%r13), %rcx
imulq $0x30, %rax, %rax
movzwl 0x12(%rcx,%rax), %eax
movq %rax, -0x78(%rbp)
movq %r12, -0x88(%rbp)
movq 0x8(%r12), %rdi
leaq 0xd53c(%rip), %rsi      # 0x13a01
callq 0x2250
testq %rax, %rax
je 0x683d
movq %rax, %r12
leaq -0x38(%rbp), %rax
andq $0x0, (%rax)
leaq -0x70(%rbp), %rax
andq $0x0, (%rax)
movl $0x2000, %edi           # imm = 0x2000
callq 0x22b0
movq %rax, %r15
xorps %xmm0, %xmm0
movss %xmm0, -0x2c(%rbp)
movq $0x0, -0x48(%rbp)
leaq -0xc0(%rbp), %r13
movq $0x0, -0x40(%rbp)
movq $0x0, -0x68(%rbp)
leaq -0x38(%rbp), %rdi
leaq -0x70(%rbp), %rsi
movq %r12, %rdx
callq 0x255c
cmpq $-0x1, %rax
je 0x6765
movq -0x38(%rbp), %rbx
movq %rbx, -0xc0(%rbp)
movq %rbx, %rdi
leaq 0xd4b5(%rip), %rsi      # 0x139fe
callq 0x63e9
testb %al, %al
je 0x6580
movq %rbx, %rdi
leaq 0xd4a7(%rip), %rsi      # 0x13a03
callq 0x63e9
movl %eax, %ebx
movq %r13, %rdi
callq 0x639a
movq %rax, %r14
testb %bl, %bl
je 0x65d4
testq %r14, %r14
jne 0x674d
jmp 0x67e0
movq %rbx, %rdi
leaq 0xd48f(%rip), %rsi      # 0x13a19
callq 0x63e9
testb %al, %al
je 0x674d
movq %rbx, %rdi
leaq 0xd4be(%rip), %rsi      # 0x13a5f
callq 0x63e9
movl %eax, %ebx
movq %r13, %rdi
callq 0x639a
movq %rax, %r14
testb %bl, %bl
je 0x66f3
movq %r14, %rdi
shlq $0x3, %rdi
callq 0x22b0
movq %rax, -0x48(%rbp)
movq %r14, -0x68(%rbp)
jmp 0x674d
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm1
movss 0xca43(%rip), %xmm0     # 0x1302c
mulss %xmm0, %xmm1
movss %xmm1, -0x60(%rbp)
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xca25(%rip), %xmm0     # 0x1302c
movss %xmm0, -0x5c(%rbp)
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xca0b(%rip), %xmm0     # 0x1302c
movss %xmm0, -0x58(%rbp)
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xc9f1(%rip), %xmm0     # 0x1302c
movss %xmm0, -0x50(%rbp)
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xc9d7(%rip), %xmm0     # 0x1302c
movss %xmm0, -0x54(%rbp)
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xc9bd(%rip), %xmm0     # 0x1302c
movss %xmm0, -0x4c(%rbp)
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xc9a3(%rip), %xmm0     # 0x1302c
movss -0x2c(%rbp), %xmm1
movss -0x50(%rbp), %xmm2
maxss %xmm2, %xmm1
movss %xmm1, -0x2c(%rbp)
movzbl %r14b, %eax
shll $0x5, %eax
movb %r14b, (%r15,%rax)
movss -0x60(%rbp), %xmm1
movss %xmm1, 0x4(%r15,%rax)
movss -0x5c(%rbp), %xmm1
movss %xmm1, 0x8(%r15,%rax)
movss -0x58(%rbp), %xmm1
movss %xmm1, 0xc(%r15,%rax)
movss %xmm2, 0x10(%r15,%rax)
movss -0x54(%rbp), %xmm1
movss %xmm1, 0x14(%r15,%rax)
movss -0x4c(%rbp), %xmm1
movss %xmm1, 0x18(%r15,%rax)
movss %xmm0, 0x1c(%r15,%rax)
jmp 0x674d
movq %r13, %rdi
callq 0x639a
cmpq $0xff, %r14
jg 0x67ff
movq %rax, %rbx
cmpq $0x100, %rax            # imm = 0x100
jge 0x67ff
shll $0x8, %r14d
orl %r14d, %ebx
movq %r13, %rdi
callq 0x639a
cvtsi2ss %rax, %xmm0
mulss 0xc8f9(%rip), %xmm0     # 0x1302c
movq -0x48(%rbp), %rax
movq -0x40(%rbp), %rcx
movw %bx, (%rax,%rcx,8)
movss %xmm0, 0x4(%rax,%rcx,8)
leaq 0x1(%rcx), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
callq 0x2260
andq $0x0, -0x38(%rbp)
andq $0x0, -0x70(%rbp)
jmp 0x651a
movq -0x40(%rbp), %r14
cmpq %r14, -0x68(%rbp)
jne 0x685c
movq -0x48(%rbp), %rbx
leaq (%rbx,%r14,8), %rsi
movq %rbx, %rdi
callq 0x114d2
leal 0x2030(,%r14,8), %eax
movq -0x88(%rbp), %rsi
movl %eax, 0x30(%rsi)
leaq -0xc0(%rbp), %rdx
movq -0x78(%rbp), %rax
movq %rax, (%rdx)
movss -0x2c(%rbp), %xmm0
movss %xmm0, 0x8(%rdx)
andl $0x0, 0xc(%rdx)
movq $0x100, 0x10(%rdx)      # imm = 0x100
movq %r14, 0x18(%rdx)
movq %r15, 0x20(%rdx)
movq %rbx, 0x28(%rdx)
movq -0x80(%rbp), %rdi
callq 0x61e5
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xd222(%rip), %rdi      # 0x13a09
leaq 0xd0a6(%rip), %rsi      # 0x13894
leaq 0xd1d2(%rip), %rcx      # 0x139c7
movl $0xa3, %edx
callq 0x2140
leaq 0xd21b(%rip), %rdi      # 0x13a21
leaq 0xd087(%rip), %rsi      # 0x13894
leaq 0xd1b3(%rip), %rcx      # 0x139c7
movl $0xbf, %edx
callq 0x2140
leaq 0xd181(%rip), %rdi      # 0x139a6
leaq 0xd068(%rip), %rsi      # 0x13894
leaq 0xd194(%rip), %rcx      # 0x139c7
movl $0x92, %edx
callq 0x2140
leaq 0xd1b0(%rip), %rdi      # 0x139f4
leaq 0xd049(%rip), %rsi      # 0x13894
leaq 0xd175(%rip), %rcx      # 0x139c7
movl $0x98, %edx
callq 0x2140
leaq 0xd1de(%rip), %rdi      # 0x13a41
leaq 0xd02a(%rip), %rsi      # 0x13894
leaq 0xd156(%rip), %rcx      # 0x139c7
movl $0xcb, %edx
callq 0x2140