ifndef                  _FONTS_ASM
_FONTS_ASM              equ     1

; ------------------------------------------------------
; Includes
                        include Textures.asm
                        include Ortho_Matrices.asm

; ------------------------------------------------------
; Structures
BITMAP_FONT             struct
Nbr_Chars               dword   ?
Pos_Table               dword   ?
Size_Table              dword   ?
Ascii_Table             dword   ?
Orig_Width              dword   ?
Orig_Height             dword   ?
Orig_Datas              dword   ?
Height                  dword   ?
Texture_Size            dword   ?
Textures                dword   ?
Textures_Ids            dword   ?
Color_Key               dword   ?
BITMAP_FONT             ends

ifndef                  RGB
RGB                     struct
r                       real4   ?
g                       real4   ?
b                       real4   ?
RGB                     ends
endif

ifndef                  RGBA
RGBA                    struct
r                       real4   ?
g                       real4   ?
b                       real4   ?
a                       real4   ?
RGBA                    ends
endif

; ------------------------------------------------------
; Name: Destroy_Font()
; Desc: Delete a previously created font
Destroy_Font            proc    Font_List:dword
                        mov     eax, Font_List
                        .if     eax != 0
                                invoke  glDeleteLists, eax, 256
                        .endif
                        ret
Destroy_Font            endp

; ------------------------------------------------------
; Name: Create_Font_Outlines()
; Desc: Obtain a 3D font to use with opengl
; Font_Type = WGL_FONT_LINES or WGL_FONT_POLYGONS
Create_Font_Outlines    proc    Font_Name:dword, Font_Size:dword, Font_Type:dword, Font_Weight:dword
                        local   _Font_List:dword
                        local   _hFont:dword

                        ; Create the fonts
                        invoke  glGenLists, 256
                        mov     _Font_List, eax
                        .if     eax != 0
                                mov     eax, Font_Size
                                neg     eax
                                invoke  CreateFont, eax, 0, 0, 0, Font_Weight, 0 , 0 , 0, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, Font_Name
                                .if     eax == 0
                                        invoke  Destroy_Font, _Font_List
                                        xor     eax, eax
                                        ret
                                .endif
                                mov     _hFont, eax
                                invoke  SelectObject, g_window.hDC, eax
                                invoke  wglUseFontOutlines, g_window.hDC, 0, 255, _Font_List, CFLT(0.001), CFLT(0.2), Font_Type, NULL
                                invoke  DeleteObject, _hFont
                                mov     eax, _Font_List
                        .endif
                        ret
Create_Font_Outlines    endp

; ------------------------------------------------------
; Name: Create_Font_Outlines()
; Desc: Obtain a bitmap font to use with opengl
Create_Font_Bitmap      proc    Font_Name:dword, Font_Size:dword, Font_Weight:dword
                        local   _Font_List:dword
                        local   _hFont:dword

                        ; Create the fonts
                        invoke  glGenLists, 256
                        mov     _Font_List, eax
                        .if     eax != 0
                                mov     eax, Font_Size
                                neg     eax
                                invoke  CreateFont, eax, 0, 0, 0, Font_Weight, 0 , 0 , 0, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, Font_Name
                                .if     eax == 0
                                        invoke  Destroy_Font, _Font_List
                                        xor     eax, eax
                                        ret
                                .endif
                                mov     _hFont, eax
                                invoke  SelectObject, g_window.hDC, eax
                                invoke  wglUseFontBitmaps, g_window.hDC, 0, 255, _Font_List
                                invoke  DeleteObject, _hFont
                                mov     eax, _Font_List
                        .endif
                        ret
Create_Font_Bitmap      endp

; ------------------------------------------------------
; Name: Display_3D_Text()
; Desc: Display a line of text in 3D
Display_3D_Text         proc    Font_List:dword, Text:dword, TextLen:dword
                        ; Display the letters
                        invoke  glListBase, Font_List
                        invoke  glCallLists, TextLen, GL_BYTE, Text
                        ret
Display_3D_Text         endp

; ------------------------------------------------------
; Name: Display_2D_Text()
; Desc: Display a line of text
Display_2D_Text         proc    X:real4, Y:real4, Font_List:dword, Text:dword, TextLen:dword
                        invoke  glRasterPos2f, X, Y
                        invoke  glListBase, Font_List
                        invoke  glCallLists, TextLen, GL_BYTE, Text
                        ret
Display_2D_Text         endp

; ------------------------------------------------------
; Name: Create_Bitmap_Font()
; Desc: Create the textures for a given bitmap font
Create_Bitmap_Font      proc    uses ebx esi edi Font_Struct:dword
                        local   _Real_Width:dword

                        mov     esi, Font_Struct

                        ; Alloc the mem for the textures ids
                        mov     ebx, [esi + BITMAP_FONT.Nbr_Chars]
                        shl     ebx, 2                                          ; Alloc dwords
                        mov     [esi + BITMAP_FONT.Textures], ALLOCMEM(ebx)
                        mov     [esi + BITMAP_FONT.Textures_Ids], ALLOCMEM(ebx)

                        mov     eax, [esi + BITMAP_FONT.Orig_Width]
                        shl     eax, 2
                        mov     [esi + BITMAP_FONT.Orig_Width], eax

                        ; Alloc the memory for the textures
                        mov     ebx, [esi + BITMAP_FONT.Texture_Size]
                        shl     ebx, 2                                          ; RGBA
                        mov     _Real_Width, ebx
                        imul    ebx,  ebx
                        mov     edi, [esi + BITMAP_FONT.Textures]
                        mov     ecx, [esi + BITMAP_FONT.Nbr_Chars]
_Create_List:                   push    ecx     
                                mov     [edi], ALLOCMEM(ebx)
                                add     edi, 4
                                pop     ecx
                        loop    _Create_List

                        ; Copy the chars into the memory
                        xor     ebx, ebx
                        .while  ebx < [esi + BITMAP_FONT.Nbr_Chars]
                                push    ebx
                                mov     edi, [esi + BITMAP_FONT.Pos_Table]
                                mov     ecx, [edi + ebx * 4]
                                mov     edi, [esi + BITMAP_FONT.Orig_Datas]
                                lea     ecx, [edi + ecx * 4]                    ; ecx = Source
                                mov     edi, [esi + BITMAP_FONT.Textures]
                                mov     eax, [edi + ebx * 4]
                                
                                ;mov    edx, [esi + BITMAP_FONT.Height]
                                ;,sub   edx, [esi + BITMAP_FONT.Orig_Height]
                                ;imul   edx, _Real_Width
                                ;add    ecx, edx
                                
                                mov     edi, [esi + BITMAP_FONT.Size_Table]
                                mov     ebx, [edi + ebx * 4]                    ; ebx = Size X
                                mov     edi, eax                                ; eax was Dest
                                xor     eax, eax
_Copy_Font_Letter_Y:            push    eax
                                        push    ecx
                                        push    edi
                                        xor     edx, edx
_Copy_Font_Letter_X:                    push    edx
                                        mov     eax, [ecx]
                                        and     eax, 000ffffffh
                                        mov     edx, [esi + BITMAP_FONT.Color_Key]
                                        and     edx, 000ffffffh
                                        cmp     edx, eax
                                        jne     _No_Set_Alpha
                                        mov     eax, 0ff000000h                 ; Turn alpha channel on for this color
_No_Set_Alpha:                          xor     eax, 0ff000000h
                                        add     ecx, 4
                                        stosd
                                        pop     edx
                                        inc     edx
                                        cmp     edx, ebx
                                        jne     _Copy_Font_Letter_X
                                        pop     edi
                                        pop     ecx
                                        add     ecx, [esi + BITMAP_FONT.Orig_Width]
                                        add     edi, _Real_Width
                                pop     eax
                                inc     eax
                                cmp     eax, [esi + BITMAP_FONT.Orig_Height]
                                jne     _Copy_Font_Letter_Y

                                pop     ebx
                                inc     ebx
                        .endw

                        ; Send the textures to opengl
                        mov     edi, [esi + BITMAP_FONT.Textures]
                        mov     ebx, [esi + BITMAP_FONT.Textures_Ids]
                        mov     ecx, [esi + BITMAP_FONT.Nbr_Chars]
_Send_Font:                     push    ecx
                                invoke  Create_2D_Texture, [edi], [esi + BITMAP_FONT.Texture_Size], TRUE, GL_RGBA, GL_RGBA
                                mov     [ebx], eax
                                add     ebx, 4
                                add     edi, 4
                                .if     eax == FALSE
                                        mov     ebx, FALSE
                                        jmp     _Err_Font
                                .endif
                                pop     ecx
                        loop    _Send_Font
                        mov     ebx, TRUE
_Err_Font:
                        ; Remove the temporary letters
                        mov     edi, [esi + BITMAP_FONT.Textures]
                        mov     ecx, [esi + BITMAP_FONT.Nbr_Chars]
_Destroy_List:                  push    ecx
                                FREEMEM dword ptr [edi]
                                add     edi, 4
                                pop     ecx
                        loop    _Destroy_List
                        mov     eax, ebx
                        ret
Create_Bitmap_Font      endp

; ------------------------------------------------------
; Name: Destroy_Bitmap_Font()
; Desc: Release the allocated font resources
Destroy_Bitmap_Font     proc    uses esi Font_Struct:dword
                        mov     esi, Font_Struct
                        mov     edi, [esi + BITMAP_FONT.Textures_Ids]
                        mov     ecx, [esi + BITMAP_FONT.Nbr_Chars]
@@:                     push    ecx
                                invoke  Destroy_Texture, [edi]
                                add     edi, 4
                                pop     ecx
                        loop    @B
                        ret
Destroy_Bitmap_Font     endp

; ------------------------------------------------------
; Name: Get_Char_Ordinal_Pos()
; Desc: Return the ordinal position of a given ascii letter in a bitmap font
Get_Char_Ordinal_Pos    proc    uses ebx Ascii_Letters:dword, Max_Letters:dword, Letter:dword
                        mov     ebx, Ascii_Letters
                        dec     ebx
                        mov     ecx, Letter
                        or      eax, -1
_Search_Letter:         inc     eax
                        inc     ebx
                        cmp     eax, Max_Letters
                        jne     _Ascii_End_Chk
                        dec     ebx
                        dec     eax
                        jmp     _Done_AScii_Chk
_Ascii_End_Chk:         cmp     byte ptr [ebx], cl
                        jne     _Search_Letter
_Done_AScii_Chk:        ret
Get_Char_Ordinal_Pos    endp

; ------------------------------------------------------
; Name: Get_Char_Size()
; Desc: Return the size of a given ascii letter in a bitmap font
Get_Char_Size           proc    uses esi Font_Struct:dword, Letter:dword
                        mov     esi, Font_Struct
                        mov     eax, Letter
                        invoke  Get_Char_Ordinal_Pos, [esi + BITMAP_FONT.Ascii_Table], [esi + BITMAP_FONT.Nbr_Chars], eax
                        mov     ecx, [esi + BITMAP_FONT.Size_Table]
                        mov     eax, [ecx + eax * 4]
                        ret
Get_Char_Size           endp

; ------------------------------------------------------
; Name: Display_Bitmap_Text()
; Desc: Display a line of text with a bitmap font
Display_Bitmap_Text     proc    uses esi edi X:real4, Y:real4, Font_Struct:dword, Text:dword, TextLen:dword
                        mov     esi, Font_Struct
                        mov     ecx, TextLen
                        mov     edi, Text
_Draw_Letters:          push    ecx
                        movzx   eax, byte ptr [edi]
                        inc     edi
                        invoke  Get_Char_Ordinal_Pos, [esi + BITMAP_FONT.Ascii_Table], [esi + BITMAP_FONT.Nbr_Chars], eax
                        push    eax
                        mov     ecx, [esi + BITMAP_FONT.Textures_Ids]
                        invoke  Draw_2D_Quad, X, Y, INT2FLT([esi + BITMAP_FONT.Texture_Size]), [ecx + eax * 4]
                        pop     eax
                        ; Next Position
                        mov     ecx, [esi + BITMAP_FONT.Size_Table]
                        fild    dword ptr [ecx + eax * 4]
                        fadd    dword ptr [X]
                        fstp    dword ptr [X]
                        pop     ecx
                        loop    _Draw_Letters
                        ret
Display_Bitmap_Text     endp

endif