; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "Fresh artistic license."         |
;|_______________________________________________________________________________________|
;
;  Description: Text drawing library.
;
;  Target OS: Win32
;
;  Dependencies: memory.asm
;
;  Notes:
;_________________________________________________________________________________________



proc DrawString, .context, .ptrString, .len, .x, .y, .font, .color
.pwc dd ?
.pwl dd ?
.buffer  rb 256
.charlen dd ?
begin
        push    eax ebx ecx edx

; first convert the string:
        lea     eax, [.buffer]
        mov     ecx, [.len]
        shl     ecx, 3
        cmp     ecx, $100
        jbe     @f

        stdcall GetMem, ecx

@@:
        mov     [.pwl], ecx
        mov     [.pwc], eax

        invoke  MultiByteToWideChar, CP_UTF8, 0, [.ptrString], [.len], [.pwc], ecx
        mov     [.charlen], eax

        mov     ebx, [.context]

        cmp     [.font], 0
        jne     @f

        invoke  GetStockObject, DEFAULT_GUI_FONT
        mov     [.font], eax

@@:
        invoke  SelectObject, [ebx+TContext.handle], [.font]
        push    eax

        invoke  SetBkMode, [ebx+TContext.handle], TRANSPARENT
        invoke  SetTextAlign, [ebx+TContext.handle], TA_NOUPDATECP or TA_LEFT or TA_BASELINE

        mov     eax, [.color]
        bswap   eax
        ror     eax, 8
        invoke  SetTextColor, [ebx+TContext.handle], eax
        invoke  TextOutW, [ebx+TContext.handle], [.x], [.y], [.pwc], [.charlen]

        invoke  SelectObject, [ebx+TContext.handle] ; old font from the stack.

        cmp     [.pwl], $100
        jbe     @f
        stdcall FreeMem, [.pwc]
@@:
        pop     edx ecx ebx eax
        return
endp



proc DrawStringOpaque, .context, .ptrString, .len, .x, .y, .font, .color, .background
.pwc dd ?
.pwl dd ?
.buffer  rb 256
.charlen dd ?
begin
        push    eax ebx ecx edx

; first convert the string:
        lea     eax, [.buffer]
        mov     ecx, [.len]
        shl     ecx, 2
        cmp     ecx, $100
        jbe     @f

        stdcall GetMem, ecx

@@:
        mov     [.pwl], ecx
        mov     [.pwc], eax

        invoke  MultiByteToWideChar, CP_UTF8, 0, [.ptrString], [.len], [.pwc], ecx
        mov     [.charlen], eax

        mov     ebx, [.context]

        cmp     [.font], 0
        jne     @f

        invoke  GetStockObject, DEFAULT_GUI_FONT
        mov     [.font], eax

@@:
        invoke  SelectObject, [ebx+TContext.handle], [.font]
        push    eax

        invoke  SetBkMode, [ebx+TContext.handle], OPAQUE
        mov     eax, [.background]
        bswap   eax
        ror     eax, 8
        invoke  SetBkColor, [ebx+TContext.handle], eax
        invoke  SetTextAlign, [ebx+TContext.handle], TA_NOUPDATECP or TA_LEFT or TA_BASELINE

        mov     eax, [.color]
        bswap   eax
        ror     eax, 8
        invoke  SetTextColor, [ebx+TContext.handle], eax
        invoke  TextOut, [ebx+TContext.handle], [.x], [.y], [.pwc], [.charlen]

        invoke  SelectObject, [ebx+TContext.handle] ; old font from the stack.

        cmp     [.pwl], $100
        jbe     @f
        stdcall FreeMem, [.pwc]
@@:
        pop     edx ecx ebx eax
        return
endp




proc DrawColoredString, .context, .ptrString, .pCharAttr, .str_len_bytes, .x, .y, .char_offs, .fontwidth, .fontheight
.xbeg    dd ?
;.wbeg    dd ?
.pwc     dd ?
.charlen dd ?
.point   POINT
begin
        push    eax ebx ecx edx esi edi

        mov     eax, [.x]
;        mov     ecx, [.width]
        mov     [.xbeg], eax
;        mov     [.wbeg], ecx

; first convert the string:
        mov     ecx, [.str_len_bytes]
        shl     ecx, 2
        stdcall GetMem, ecx
        mov     esi, eax
        mov     [.pwc], eax

        invoke  MultiByteToWideChar, CP_UTF8, 0, [.ptrString], [.str_len_bytes], esi, ecx
        mov     [.charlen], eax

        mov     ebx, [.context]
        mov     edi, [.pCharAttr]

        invoke  SaveDC, [ebx+TContext.handle]

        invoke  SetBkMode,    [ebx+TContext.handle], TRANSPARENT
        invoke  SetTextAlign, [ebx+TContext.handle], TA_LEFT or TA_BASELINE

.skip_offset:
        mov     ecx, [.char_offs]

.offsloop:
        jecxz   .loop

        lodsw
        add     edi, sizeof.TCharAttr
        dec     [.charlen]
        jz      .endline

        dec     ecx
        cmp     eax, $01
        jne     .offsloop

        mov     eax, [.fontheight]
        add     [.y], eax
        jmp     .skip_offset

.loop:
        cmp     word [esi], $01
        je      .wrapline

        mov     eax, [edi+TCharAttr.font]
        test    eax, eax
        jnz     @f

        invoke  GetStockObject, DEFAULT_GUI_FONT
@@:
        invoke  SelectObject, [ebx+TContext.handle], eax
        mov     eax, [edi+TCharAttr.background]
        bswap   eax
        ror     eax, 8
        invoke  SetBkColor, [ebx+TContext.handle], $ff0000

        mov     eax, [edi+TCharAttr.color]
        bswap   eax
        ror     eax, 8
        invoke  SetTextColor, [ebx+TContext.handle], eax

        invoke  TextOutW, [ebx+TContext.handle], [.x], [.y], esi, 1

        mov     eax, [.fontwidth]
        add     [.x], eax
;        sub     [.width], eax
;        jl      .endline

.nextchar:
        add     esi, 2
        add     edi, sizeof.TCharAttr
        dec     [.charlen]
        jnz     .loop

.endline:
        invoke  RestoreDC, [ebx+TContext.handle], -1
        stdcall FreeMem, [.pwc]
        pop     edi esi edx ecx ebx eax
        return

.wrapline:
        mov     eax, [.fontheight]
        add     [.y], eax
        mov     eax, [.xbeg]
;        mov     ecx, [.wbeg]
        mov     [.x], eax
;        mov     [.width], ecx

        add     esi, 2
        add     edi, sizeof.TCharAttr
        dec     [.charlen]
        jnz     .skip_offset
        jmp     .endline
endp






proc GetTextBounds, .context, .ptrString, .len, .font
.size SIZE
.pwc dd ?
.charlen dd ?
begin
        push    ebx ecx

; first convert the string:
        mov     ecx, [.len]
        shl     ecx, 3
        stdcall GetMem, ecx
        mov     [.pwc], eax
        invoke  MultiByteToWideChar, CP_UTF8, 0, [.ptrString], [.len], [.pwc], ecx
        mov     [.charlen], eax

        mov     ebx, [.context]

        cmp     [.font], 0
        jne     @f
        invoke  GetStockObject, DEFAULT_GUI_FONT
        mov     [.font], eax

@@:
        invoke  SelectObject, [ebx+TContext.handle], [.font]
        push    eax

        lea     eax, [.size]
        invoke  GetTextExtentPoint32W, [ebx+TContext.handle], [.pwc], [.charlen], eax
        invoke  SelectObject, [ebx+TContext.handle] ; from the stack.

        mov     eax, [.size.cx]
        mov     edx, [.size.cy]

        stdcall FreeMem, [.pwc]
        pop     ecx ebx
        return
endp


; returns:
;       eax - x offset of the baseline of the string.
;       edx - y offset of the baseline of the string.

proc GetTextOffset, .context, .ptrString, .len, .font
.metrics TEXTMETRIC
.pwc dd ?
.charlen dd ?
begin
        push    ebx ecx

; first convert the string:
        mov     ecx, [.len]
        shl     ecx, 3
        stdcall GetMem, ecx
        mov     [.pwc], eax
        invoke  MultiByteToWideChar, CP_UTF8, 0, [.ptrString], [.len], [.pwc], ecx
        mov     [.charlen], eax

        mov     ebx, [.context]

        cmp     [.font], 0
        jne     @f
        invoke  GetStockObject, DEFAULT_GUI_FONT
        mov     [.font], eax

@@:
        invoke  SelectObject, [ebx+TContext.handle], [.font]
        push    eax

        lea     eax, [.metrics]
        invoke  GetTextMetricsW, [ebx+TContext.handle], eax
        invoke  SelectObject, [ebx+TContext.handle] ; from the stack.

        xor     eax, eax
        mov     edx, [.metrics.tmAscent]
        sub     edx, [.metrics.tmInternalLeading]

        stdcall FreeMem, [.pwc]
        pop     ecx ebx
        return
endp