// File: /workspace/github_c_makefile_star2_O0/ggerganov[P]font-rasterizer/main.c
// Function: main
int main(int argc, const char * argv[]) {
    if (argc < 3) {
        printf("usage: %s font.ttf height [width]\n", argv[0]);
        printf("\n");
        printf("       rasterizes the provided ttf font into cells with specified height in pixels\n");
        printf("       if width is provided, it overrides the auto detected value\n");
        printf("       the generated raster data is printed on the standard output\n");
        return -1;
    }

    const char * fontFName = argv[1];
    int height = atoi(argv[2]);
    int width = argc > 3 ? atoi(argv[3]) : 0;

    unsigned char* fontBuffer;

    /* load font file */
    {
        long size;
        FILE* fontFile = fopen(argv[1], "rb");
        fseek(fontFile, 0, SEEK_END);
        size = ftell(fontFile);
        fseek(fontFile, 0, SEEK_SET);

        fontBuffer = malloc(size);

        fread(fontBuffer, size, 1, fontFile);
        fclose(fontFile);
    }

    /* prepare font */
    stbtt_fontinfo info;
    if (!stbtt_InitFont(&info, fontBuffer, 0)) {
        printf("failed to load ttf font\n");
        return -2;
    }

    int b_w = 0; /* bitmap width */
    int b_h = height; /* bitmap height */
    int c_w = width; /* char width */
    int c_h = height; /* char height */

    /* calculate font scaling */
    float scale = stbtt_ScaleForPixelHeight(&info, c_h);

    if (c_w == 0) {
        /* determine max char width */
        for (unsigned char ch = 0; ch < 128; ++ch) {
            int ax;
            int lsb;
            stbtt_GetCodepointHMetrics(&info, ch, &ax, &lsb);
            if (c_w < ax*scale) {
                c_w = ax*scale;
            }
        }
    }

    b_w = 128*c_w;

    /* create a bitmap for the phrase */
    unsigned char* bitmap = calloc(b_w*b_h, sizeof(unsigned char));

    int x = 0, maxx = 0;
    int ascent, descent, lineGap;
    stbtt_GetFontVMetrics(&info, &ascent, &descent, &lineGap);

    ascent *= scale;
    descent *= scale;

    /* begin C constants output */
    printf("static const int FONT_SIZE_X = %d;\n", c_w);
    printf("static const int FONT_SIZE_Y = %d;\n\n", c_h);
    printf("static const unsigned char kFontRaster[128][FONT_SIZE_Y*FONT_SIZE_X] = {\n");

    for (unsigned char ch = 0; ch < 128; ++ch) {
        /* how wide is this character */
        int ax;
        int lsb;
        stbtt_GetCodepointHMetrics(&info, ch, &ax, &lsb);

        /* get bounding box for character (may be offset to account for chars that dip above or below the line */
        int c_x1, c_y1, c_x2, c_y2;
        stbtt_GetCodepointBitmapBox(&info, ch, scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);

        /* compute y (different characters have different heights */
        int y = ascent + c_y1;
        if (y < 0) y = 0;

        /* render character (stride and offset is important here) */
        int byteOffset = x + (lsb*scale) + (y*b_w);
        stbtt_MakeCodepointBitmap(&info, bitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, b_w, scale, scale, ch);

        /* output C array data */
        printf("    {");
        for (int yy = 0; yy < c_h; ++yy) {
            for (int xx = 0; xx < c_w; ++xx) {
                int v = bitmap[byteOffset + (yy - y)*b_w + xx];
                printf(" %3d,", v);
                if (v > 0 && xx > maxx) {
                    maxx = xx;
                }
            }
        }
        printf(" }, // U+%04d\n", ch);

        /* advance x */
        //x += ax*scale; // use true character width
        x += c_w; // force mono-space width

        /* add kerning */
        if (ch < 127) {
            int kern;
            kern = stbtt_GetCodepointKernAdvance(&info, ch, ch + 1);
            x += kern*scale;
        }
    }

    printf("};\n");

    if (maxx + 1 < c_w) {
        printf("// warning : max character width was %d. consider lowering the width parameter to this value\n", maxx + 1);
    }

    /* save out a 1 channel image */
    {
        char tmp[128];
        snprintf(tmp, 128, "raster-h%d.png", c_h);
        stbi_write_png(tmp, b_w, b_h, 1, bitmap, b_w);
    }

    free(fontBuffer);
    free(bitmap);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x3, -0x8(%rbp)
jge 0xcf08
movq -0x10(%rbp), %rax
movq (%rax), %rsi
leaq 0x9a7b(%rip), %rdi      # 0x16938
movb $0x0, %al
callq 0x1080
leaq 0x9bce(%rip), %rdi      # 0x16a99
movb $0x0, %al
callq 0x1080
leaq 0x9a82(%rip), %rdi      # 0x1695b
movb $0x0, %al
callq 0x1080
leaq 0x9ac8(%rip), %rdi      # 0x169af
movb $0x0, %al
callq 0x1080
leaq 0x9afd(%rip), %rdi      # 0x169f2
movb $0x0, %al
callq 0x1080
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xd4dc
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x11a0
movl %eax, -0x1c(%rbp)
cmpl $0x3, -0x8(%rbp)
jle 0xcf3f
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x11a0
movl %eax, -0x1d4(%rbp)
jmp 0xcf49
xorl %eax, %eax
movl %eax, -0x1d4(%rbp)
jmp 0xcf49
movl -0x1d4(%rbp), %eax
movl %eax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0x9ad5(%rip), %rsi      # 0x16a36
callq 0x1180
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x2, %edx
callq 0x1150
movq -0x38(%rbp), %rdi
callq 0x1120
movq %rax, -0x30(%rbp)
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x1150
movq -0x30(%rbp), %rdi
callq 0x1140
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rcx
movl $0x1, %edx
callq 0x1040
movq -0x38(%rbp), %rdi
callq 0x1060
movq -0x28(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
xorl %edx, %edx
callq 0x97c0
cmpl $0x0, %eax
jne 0xcff5
leaq 0x9a57(%rip), %rdi      # 0x16a39
movb $0x0, %al
callq 0x1080
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0xd4dc
movl $0x0, -0xdc(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0xe0(%rbp)
movl -0x20(%rbp), %eax
movl %eax, -0xe4(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0xe8(%rbp)
cvtsi2ssl -0xe8(%rbp), %xmm0
leaq -0xd8(%rbp), %rdi
callq 0x6c40
movss %xmm0, -0xec(%rbp)
cmpl $0x0, -0xe4(%rbp)
jne 0xd0c4
movb $0x0, -0xed(%rbp)
movzbl -0xed(%rbp), %eax
cmpl $0x80, %eax
jge 0xd0c2
movzbl -0xed(%rbp), %esi
leaq -0xd8(%rbp), %rdi
leaq -0xf4(%rbp), %rdx
leaq -0xf8(%rbp), %rcx
callq 0x68c0
cvtsi2ssl -0xe4(%rbp), %xmm1
cvtsi2ssl -0xf4(%rbp), %xmm0
mulss -0xec(%rbp), %xmm0
ucomiss %xmm1, %xmm0
jbe 0xd0b0
cvtsi2ssl -0xf4(%rbp), %xmm0
mulss -0xec(%rbp), %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0xe4(%rbp)
jmp 0xd0b2
movb -0xed(%rbp), %al
addb $0x1, %al
movb %al, -0xed(%rbp)
jmp 0xd04a
jmp 0xd0c4
movl -0xe4(%rbp), %eax
shll $0x7, %eax
movl %eax, -0xdc(%rbp)
movl -0xdc(%rbp), %eax
imull -0xe0(%rbp), %eax
movslq %eax, %rdi
movl $0x1, %esi
callq 0x1110
movq %rax, -0x100(%rbp)
movl $0x0, -0x104(%rbp)
movl $0x0, -0x108(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0x10c(%rbp), %rsi
leaq -0x110(%rbp), %rdx
leaq -0x114(%rbp), %rcx
callq 0x6910
movss -0xec(%rbp), %xmm1
cvtsi2ssl -0x10c(%rbp), %xmm0
mulss %xmm1, %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x10c(%rbp)
movss -0xec(%rbp), %xmm1
cvtsi2ssl -0x110(%rbp), %xmm0
mulss %xmm1, %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x110(%rbp)
movl -0xe4(%rbp), %esi
leaq 0x98e0(%rip), %rdi      # 0x16a52
movb $0x0, %al
callq 0x1080
movl -0xe8(%rbp), %esi
leaq 0x98f0(%rip), %rdi      # 0x16a76
movb $0x0, %al
callq 0x1080
leaq 0x9907(%rip), %rdi      # 0x16a9b
movb $0x0, %al
callq 0x1080
movb $0x0, -0x115(%rbp)
movzbl -0x115(%rbp), %eax
cmpl $0x80, %eax
jge 0xd43f
movzbl -0x115(%rbp), %esi
leaq -0xd8(%rbp), %rdi
leaq -0x11c(%rbp), %rdx
leaq -0x120(%rbp), %rcx
callq 0x68c0
movzbl -0x115(%rbp), %esi
movss -0xec(%rbp), %xmm0
movss -0xec(%rbp), %xmm1
leaq -0xd8(%rbp), %rdi
leaq -0x124(%rbp), %rdx
leaq -0x128(%rbp), %rcx
leaq -0x12c(%rbp), %r8
leaq -0x130(%rbp), %r9
callq 0x6f80
movl -0x10c(%rbp), %eax
addl -0x128(%rbp), %eax
movl %eax, -0x134(%rbp)
cmpl $0x0, -0x134(%rbp)
jge 0xd239
movl $0x0, -0x134(%rbp)
cvtsi2ssl -0x104(%rbp), %xmm1
cvtsi2ssl -0x120(%rbp), %xmm0
movss -0xec(%rbp), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movl -0x134(%rbp), %eax
imull -0xdc(%rbp), %eax
cvtsi2ss %eax, %xmm1
addss %xmm1, %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x138(%rbp)
movq -0x100(%rbp), %rsi
movslq -0x138(%rbp), %rax
addq %rax, %rsi
movl -0x12c(%rbp), %edx
subl -0x124(%rbp), %edx
movl -0x130(%rbp), %ecx
subl -0x128(%rbp), %ecx
movl -0xdc(%rbp), %r8d
movss -0xec(%rbp), %xmm0
movss -0xec(%rbp), %xmm1
movzbl -0x115(%rbp), %r9d
leaq -0xd8(%rbp), %rdi
callq 0x7fc0
leaq 0x9812(%rip), %rdi      # 0x16ae5
movb $0x0, %al
callq 0x1080
movl $0x0, -0x13c(%rbp)
movl -0x13c(%rbp), %eax
cmpl -0xe8(%rbp), %eax
jge 0xd3aa
movl $0x0, -0x140(%rbp)
movl -0x140(%rbp), %eax
cmpl -0xe4(%rbp), %eax
jge 0xd394
movq -0x100(%rbp), %rax
movl -0x138(%rbp), %ecx
movl -0x13c(%rbp), %edx
subl -0x134(%rbp), %edx
imull -0xdc(%rbp), %edx
addl %edx, %ecx
addl -0x140(%rbp), %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x144(%rbp)
movl -0x144(%rbp), %esi
leaq 0x9797(%rip), %rdi      # 0x16aeb
movb $0x0, %al
callq 0x1080
cmpl $0x0, -0x144(%rbp)
jle 0xd37e
movl -0x140(%rbp), %eax
cmpl -0x108(%rbp), %eax
jle 0xd37e
movl -0x140(%rbp), %eax
movl %eax, -0x108(%rbp)
jmp 0xd380
movl -0x140(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x140(%rbp)
jmp 0xd300
jmp 0xd396
movl -0x13c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x13c(%rbp)
jmp 0xd2e4
movzbl -0x115(%rbp), %esi
leaq 0x9739(%rip), %rdi      # 0x16af1
movb $0x0, %al
callq 0x1080
movl -0xe4(%rbp), %eax
addl -0x104(%rbp), %eax
movl %eax, -0x104(%rbp)
movzbl -0x115(%rbp), %eax
cmpl $0x7f, %eax
jge 0xd42a
movzbl -0x115(%rbp), %esi
movzbl -0x115(%rbp), %edx
addl $0x1, %edx
leaq -0xd8(%rbp), %rdi
callq 0x6850
movl %eax, -0x148(%rbp)
cvtsi2ssl -0x148(%rbp), %xmm0
movss -0xec(%rbp), %xmm2
cvtsi2ssl -0x104(%rbp), %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x104(%rbp)
jmp 0xd42c
movb -0x115(%rbp), %al
addb $0x1, %al
movb %al, -0x115(%rbp)
jmp 0xd1a2
leaq 0x96ba(%rip), %rdi      # 0x16b00
movb $0x0, %al
callq 0x1080
movl -0x108(%rbp), %eax
addl $0x1, %eax
cmpl -0xe4(%rbp), %eax
jge 0xd475
movl -0x108(%rbp), %esi
addl $0x1, %esi
leaq 0x9696(%rip), %rdi      # 0x16b04
movb $0x0, %al
callq 0x1080
leaq -0x1d0(%rbp), %rdi
movl -0xe8(%rbp), %ecx
movl $0x80, %esi
leaq 0x96d4(%rip), %rdx      # 0x16b62
movb $0x0, %al
callq 0x1090
leaq -0x1d0(%rbp), %rdi
movl -0xdc(%rbp), %esi
movl -0xe0(%rbp), %edx
movq -0x100(%rbp), %r8
movl -0xdc(%rbp), %r9d
movl $0x1, %ecx
callq 0x3800
movq -0x28(%rbp), %rdi
callq 0x1030
movq -0x100(%rbp), %rdi
callq 0x1030
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
nopl (%rax,%rax)