font.inc
kolibrios-nextgen_kolibrios-kernel/kernel/gui/font.inc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License    ;;
;;                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dtext:
; edx -> string
; esi = number of characters
; ebx = output coordinates XXXXYYYY h
; ecx = char color and flags flRRGGBB h
; fl = ZBFFRSSS b
; Z=1: edx -> zero terminated string, esi = ?
; B=1: fill background with color eax
; R=1: edi -> user area for redirect
; FF=3: UTF-8 8x16, FF=2: UTF-16LE 8x16
; FF=1: cp866 8x16, FF=0: cp866 6x9
; SSS = (font multiplier)-1
; edi=1: force output    
; flag CF=1 means that we deal with asciiz but need to draw no more than esi symbols
        clc
._:        
        push    ecx edx
        setc    dl        
        and     eax, 0xFFFFFF
        and     ecx, 1 shl 31
        shl     edx, 29
        or      eax, ecx    
        or      eax, edx
        pop     edx ecx        
        bt      ecx, 30
        jc      @f
        or      eax, 1 shl 30
@@:
        pushd   0 0 0 eax
        movsx   eax, bx
        sar     ebx, 16
        push    eax ebx edi
        bt      ecx, 27
        jc      .redirect
        mov     ebp, [_display.width]
        xor     edi, edi
        jmp     @f

.ret:
        add     esp, 28
        ret

.redirect:
        mov     ebp, [edi]
        add     edi, 8
@@:
        shl     ebp, 2
        imul    eax, ebp
        shl     ebx, 2
        add     eax, ebx
        js      .ret
        add     edi, eax
        mov     eax, ecx
        mov     ebx, ecx
        test    ecx, ecx
        jns     @f
        mov     esi, 256
@@:
        shr     ecx, 24
        and     cl, 7
        inc     ecx
        push    ebp ecx esi
        mov     esi, edx
        or      eax, 0xFF000000
        bt      ebx, 27
        jc      .bufferReady
        mov     eax, 9
        test    ebx, 0x30000000
        jz      @f
        add     eax, 7
@@:
        imul    eax, ecx
        mov     [esp+32], eax
        imul    ebp, eax
        stdcall kernel_alloc, ebp
        mov     ecx, ebp
        shr     ecx, 2
        mov     [esp+36], eax
        sub     edi, eax
        mov     edx, eax
        mov     eax, [esp+24]
        test    eax, 1 shl 30
        jz      @f
        or      eax, -1
        mov     [esp+28], edi
        jmp     .1
@@:     
        and     eax, 0x00ffffff          
.1:
        mov     edi, edx
        rep stosd
        mov     edi, edx
        mov     eax, ebx
        and     eax, 0xFFFFFF
.bufferReady:
        mov     ebp, eax
        mov     eax, [esp+8]
        shr     eax, 2
        sub     eax, [esp+16]
        shr     eax, 3
        xor     edx, edx
        div     dword[esp+4]
        mov     ecx, [esp]
        cmp     eax, ecx
        jnc     @f
        mov     [esp], eax
@@:
        xor     edx, edx
        bt      ebx, 29
        jc      @f
        bt      ebx, 28
        jc      .draw866toUni
        shl     eax, 3
        mov     bx, 6
        div     bx
        xor     edx, edx
        inc     eax
        mov     [esp], ecx
        cmp     eax, ecx
        jnc     .draw866
        mov     [esp], eax
        jmp     .draw866

@@:
        bt      ebx, 28
        jc      .drawUTF8

; ebp = font color
; esi -> string
; edi -> buffer

; Stack map:
; char counter +0
fontMultiplier = 4
widthX = 8
; edi +12
; X +16
; Y +20
; internal flags & background +24
deltaToScreen = 28
; temp buffer height +32
; temp buffer pointer +36

.drawUTF16:
        dec     dword [esp]
        js      .done
        movzx   ebx, word [esi]
        test    dword [esp + 24], 1 shl 31
        jnz     @f                
        test    dword [esp + 24], 1 shl 29
        jz      .u16Still
@@:        
        test    ebx, ebx
        jz      .done
.u16Still:        
        inc     esi
        inc     esi
        cmp     bx, 1419
        jc      @f
        xor     ebx, ebx
@@:
        pushd   esi edi 16
        shl     ebx, 4
        add     ebx, fontUni
        mov     esi, [esp+12+fontMultiplier]
        call    drawChar
        imul    esi, 8*4
        pop     edi
        pop     edi
        add     edi, esi
        pop     esi
        jmp     .drawUTF16

.drawUTF8:
        dec     dword [esp]
        js      .done
        xor     eax, eax
        call    utf8to16
        test    dword [esp + 24], 1 shl 31
        jnz     @f                
        test    dword [esp + 24], 1 shl 29
        jz      .u8Still
@@:        
        test    eax, eax
        jz      .done
.u8Still:        
        cmp     eax, 1419
        jc      @f
        xor     eax, eax
@@:
        shl     eax, 4
        lea     ebx, [eax+fontUni]
        pushd   esi edi 16
        mov     esi, [esp+12+fontMultiplier]
        call    drawChar
        imul    esi, 8*4
        pop     edi
        pop     edi
        add     edi, esi
        pop     esi
        jmp     .drawUTF8

.draw866:
        dec     dword [esp]
        js      .done
        movzx   ebx, byte [esi]
        test    dword [esp + 24], 1 shl 31
        jnz     @f                
        test    dword [esp + 24], 1 shl 29
        jz      .866Still
@@:        
        test    ebx, ebx
        jz      .done
.866Still:        
        inc     esi
        pushd   esi edi 9
        lea     ebx, [ebx*8+ebx+font1]
        mov     esi, [esp+12+fontMultiplier]
        call    drawChar
        imul    esi, 6*4
        pop     edi
        pop     edi
        add     edi, esi
        pop     esi
        jmp     .draw866

.draw866toUni:
        dec     dword [esp]
        js      .done
        movzx   eax, byte [esi]
        test    dword [esp + 24], 1 shl 31
        jnz     @f                
        test    dword [esp + 24], 1 shl 29
        jz      .8662uStill         
@@:        
        test    eax, eax
        jz      .done
.8662uStill:        
        call    ansi2uni_char
        shl     eax, 4
        lea     ebx, [eax+fontUni]
        inc     esi
        pushd   esi edi 16
        mov     esi, [esp+12+fontMultiplier]
        call    drawChar
        imul    esi, 8*4
        pop     edi
        pop     edi
        add     edi, esi
        pop     esi
        jmp     .draw866toUni

.done:
        mov     ecx, edi
        pop     eax eax eax esi edx ebx ebp ebp ebp
        mov     edi, [esp]
        test    edi, edi
        jnz     @f
        pop     eax
        ret

@@: ; redraw from buffer to screen
        push    eax
        sub     ecx, edi
        shr     ecx, 2
        add     edx, ecx
        inc     ecx
        push    ecx
        push    edi
.drawPicture:
        mov     eax, -1
        repz scasd
        jecxz   @f
        mov     eax, edx
        sub     eax, ecx
        push    ecx
        mov     ecx, [edi-4]
        xchg    esi, edi
        call    __sys_putpixel
        xchg    esi, edi
        pop     ecx
        jmp     .drawPicture

@@:
        pop     edi
        mov     ecx, [esp]
        add     edi, [esp+4]
        inc     ebx
        push    edi
        dec     ebp
        jnz     .drawPicture
        add     esp, 12
        call    kernel_free
        ret

; scaling/smoothing algorithm
drawChar:
; ebp = font color
; esi = font multiplier
; edi -> buffer
; ebx -> char data
        mov     dl, [ebx]
.raw:
        bsf     eax, edx
        jz      .nextRaw
        imul    eax, esi
        shl     eax, 2
        push    edi
        add     edi, eax
        mov     ecx, esi
        dec     esi
        jnz     .square
        mov     [edi], ebp
        inc     esi
        cmp     [fontSmoothing], 0
        jz      .nextPixel
.checkLeftSM:     ; smoothing
        bsf     eax, edx
        dec     eax
        js      .checkRightSM
        bt      [ebx], eax
        jc      .checkRightSM
        dec     eax
        js      .checkLeftDownSM
        bt      [ebx], eax
        jc      .checkRightSM
.checkLeftDownSM:
        inc     eax
        bt      [ebx+1], eax
        jnc     .checkLeftUpSM
        inc     eax
        bt      [ebx+1], eax
        jnc     @f
        bt      [ebx-1], eax
        jc      .checkRightSM
        dec     eax
        dec     eax
        js      @f
        bt      [ebx+1], eax
        jnc     @f
        inc     eax
.checkLeftUpSM:
        bt      [ebx-1], eax
        jnc     .checkRightSM
        inc     eax
        bt      [ebx-1], eax
        jnc     @f
        bt      [ebx+1], eax
        jc      .checkRightSM
        dec     eax
        dec     eax
        js      @f
        bt      [ebx-1], eax
        jc      .checkRightSM
@@:
        mov     ecx, [esp+20+deltaToScreen]
        mov     eax, [edi-4]
        test    ecx, ecx
        jz      @f
        pusha
        lea     ebx, [edi+ecx-4]
        shr     ebx, 2
        call    syscall_getpixel
        popa
@@:
        push    ebx edx
        mov     ebx, ebp
        xor     ecx, ecx
        cmp     [fontSmoothing], 1
        jnz     .subpixelLeft
        call    antiAliasing
        jmp     @f

.subpixelLeft:
        mov     cl, bl
        lea     edx, [ecx*8+ecx]
        lea     edx, [ecx*2+edx]
        mov     cl, al
        lea     ecx, [ecx*4+ecx]
        add     edx, ecx
        shr     edx, 4
        mov     al, dl

        xor     ecx, ecx
        mov     cl, ah
        lea     edx, [ecx*8+ecx]
        lea     edx, [ecx*2+edx]
        mov     cl, bh
        lea     ecx, [ecx*4+ecx]
        add     edx, ecx
        shr     edx, 4
        mov     ah, dl

        rol     eax, 16
        rol     ebx, 16
        xor     ecx, ecx
        mov     cl, al
        mov     edx, ecx
        shl     ecx, 3
        sub     ecx, edx
        mov     dl, bl
        add     ecx, edx
        shr     ecx, 3
        mov     al, cl
        rol     eax, 16
@@:
        mov     [edi-4], eax
        pop     edx ebx
.checkRightSM:
        bsf     eax, edx
        inc     eax
        bt      [ebx], eax
        jc      .nextPixel
        inc     eax
        bt      [ebx], eax
        jc      .nextPixel
        dec     eax
.checkRightDownSM:
        bt      [ebx+1], eax
        jnc     .checkRightUpSM
        dec     eax
        bt      [ebx+1], eax
        jnc     @f
        bt      [ebx-1], eax
        jc      .nextPixel
        inc     eax
        inc     eax
        bt      [ebx+1], eax
        jnc     @f
        dec     eax
.checkRightUpSM:
        bt      [ebx-1], eax
        jnc     .nextPixel
        dec     eax
        bt      [ebx-1], eax
        jnc     @f
        bt      [ebx+1], eax
        jc      .nextPixel
        inc     eax
        inc     eax
        bt      [ebx-1], eax
        jc      .nextPixel
@@:
        mov     ecx, [esp+20+deltaToScreen]
        mov     eax, [edi+4]
        test    ecx, ecx
        jz      @f
        pusha
        lea     ebx, [edi+ecx+4]
        shr     ebx, 2
        call    syscall_getpixel
        popa
@@:
        push    ebx edx
        mov     ebx, ebp
        xor     ecx, ecx
        cmp     [fontSmoothing], 1
        jnz     .subpixelRight
        call    antiAliasing
        jmp     @f

.subpixelRight:
        mov     cl, al
        mov     edx, ecx
        shl     ecx, 3
        sub     ecx, edx
        mov     dl, bl
        add     ecx, edx
        shr     ecx, 3
        mov     al, cl

        xor     ecx, ecx
        mov     cl, ah
        lea     edx, [ecx*8+ecx]
        lea     edx, [ecx*2+edx]
        mov     cl, bh
        lea     ecx, [ecx*4+ecx]
        add     edx, ecx
        shr     edx, 4
        mov     ah, dl

        rol     ebx, 16
        rol     eax, 16
        xor     ecx, ecx
        mov     cl, bl
        lea     edx, [ecx*8+ecx]
        lea     edx, [ecx*2+edx]
        mov     cl, al
        lea     ecx, [ecx*4+ecx]
        add     edx, ecx
        shr     edx, 4
        mov     al, dl
        rol     eax, 16
@@:
        mov     [edi+4], eax
        pop     edx ebx
        jmp     .nextPixel

.square:    ; scaling
        mov     eax, esi
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        dec     ecx
        jnz     .square
        inc     esi
        mov     edi, [esp]
.checkLeft:
        bsf     eax, edx
        dec     eax
        js      .checkRight
        bt      [ebx], eax
        jc      .checkRight
.checkLeftDown:
        bt      [ebx+1], eax
        jnc     .checkLeftUp
        mov     ecx, eax
        inc     eax
        bt      [ebx+1], eax
        jc      @f
        bt      [ebx-1], eax
        jnc     .downRightLow
        bt      [ebx-2], eax
        jc      .downRightLow
        dec     eax
        bt      [ebx-1], eax
        jc      .downRightLow
        dec     eax
        js      .downRightHigh
        bt      [ebx-2], eax
        jc      .downRightLow
        jmp     .downRightHigh

@@:
        bt      [ebx-1], eax
        jc      .checkLeftUp
        dec     eax
        dec     eax
        js      .downRightLow
        bt      [ebx+1], eax
        jc      .checkLeftUp
.downRightLow:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        dec     esi
        mov     eax, [esp+20+widthX]
        imul    eax, esi
        add     edi, eax
        add     edi, 4
        mov     ecx, esi
        dec     ecx
.drawDownRight:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        sub     edi, [esp+20+widthX]
        add     edi, 4
        dec     ecx
        jns     .drawDownRight
        inc     esi
        mov     edi, [esp]
        jmp     .checkLeftUp

.downRightHigh:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        dec     esi
        mov     eax, [esp+20+widthX]
        imul    eax, esi
        add     edi, eax
        add     edi, 4
        mov     ecx, esi
        dec     ecx
.drawDownRightHigh:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        sub     edi, [esp+20+widthX]
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        sub     edi, [esp+20+widthX]
        add     edi, 4
        dec     ecx
        jns     .drawDownRightHigh
        inc     esi
        mov     edi, [esp]
.checkLeftUp:
        bsf     eax, edx
        dec     eax
        bt      [ebx-1], eax
        jnc     .checkRight
        mov     ecx, eax
        inc     eax
        bt      [ebx-1], eax
        jc      @f
        bt      [ebx+1], eax
        jnc     .upRightLow
        bt      [ebx+2], eax
        jc      .upRightLow
        dec     eax
        bt      [ebx+1], eax
        jc      .upRightLow
        dec     eax
        js      .upRightHigh
        bt      [ebx+2], eax
        jc      .upRightLow
        jmp     .upRightHigh

@@:
        bt      [ebx+1], eax
        jc      .checkRight
        dec     eax
        dec     eax
        js      .upRightLow
        bt      [ebx-1], eax
        jc      .checkRight
.upRightLow:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        add     edi, 4
        mov     ecx, esi
        dec     ecx
        dec     ecx
.drawUpRight:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        add     edi, 4
        dec     ecx
        jns     .drawUpRight
        mov     edi, [esp]
        jmp     .checkRight

.upRightHigh:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        add     edi, 4
        mov     ecx, esi
        dec     ecx
        dec     ecx
.drawUpRightHigh:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        add     edi, 4
        dec     ecx
        jns     .drawUpRightHigh
        mov     edi, [esp]
.checkRight:
        bsf     eax, edx
        inc     eax
        bt      [ebx], eax
        jc      .nextPixel
.checkRightDown:
        bt      [ebx+1], eax
        jnc     .checkRightUp
        mov     ecx, eax
        dec     eax
        bt      [ebx+1], eax
        jc      @f
        bt      [ebx-1], eax
        jnc     .downLeftLow
        bt      [ebx-2], eax
        jc      .downLeftLow
        inc     eax
        bt      [ebx-1], eax
        jc      .downLeftLow
        inc     eax
        bt      [ebx-2], eax
        jc      .downLeftLow
        jmp     .downLeftHigh

@@:
        bt      [ebx-1], eax
        jc      .checkRightUp
        inc     eax
        inc     eax
        bt      [ebx+1], eax
        jc      .checkRightUp
.downLeftLow:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        dec     esi
        mov     eax, [esp+20+widthX]
        imul    eax, esi
        add     edi, eax
        mov     ecx, esi
        dec     ecx
.drawDownLeft:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        sub     edi, [esp+20+widthX]
        dec     ecx
        jns     .drawDownLeft
        inc     esi
        mov     edi, [esp]
        jmp     .checkRightUp

.downLeftHigh:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        dec     esi
        mov     eax, [esp+20+widthX]
        imul    eax, esi
        add     edi, eax
        mov     ecx, esi
        dec     ecx
.drawDownLeftHigh:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        sub     edi, [esp+20+widthX]
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        sub     edi, [esp+20+widthX]
        dec     ecx
        jns     .drawDownLeftHigh
        inc     esi
        mov     edi, [esp]
.checkRightUp:
        bsf     eax, edx
        inc     eax
        bt      [ebx-1], eax
        jnc     .nextPixel
        mov     ecx, eax
        dec     eax
        bt      [ebx-1], eax
        jc      @f
        bt      [ebx+1], eax
        jnc     .upLeftLow
        bt      [ebx+2], eax
        jc      .upLeftLow
        inc     eax
        bt      [ebx+1], eax
        jc      .upLeftLow
        inc     eax
        bt      [ebx+2], eax
        jc      .upLeftLow
        jmp     .upLeftHigh

@@:
        bt      [ebx+1], eax
        jc      .nextPixel
        inc     eax
        inc     eax
        bt      [ebx-1], eax
        jc      .nextPixel
.upLeftLow:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        mov     ecx, esi
        dec     ecx
        dec     ecx
.drawUpLeft:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        dec     ecx
        jns     .drawUpLeft
        jmp     .nextPixel

.upLeftHigh:
        imul    ecx, esi
        shl     ecx, 2
        add     edi, ecx
        mov     ecx, esi
        dec     ecx
        dec     ecx
.drawUpLeftHigh:
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        mov     eax, ecx
@@:
        mov     [edi+eax*4], ebp
        dec     eax
        jns     @b
        add     edi, [esp+20+widthX]
        dec     ecx
        jns     .drawUpLeftHigh
.nextPixel:
        bsf     eax, edx
        btr     edx, eax
        pop     edi
        jmp     .raw

.nextRaw:
        inc     ebx
        mov     eax, [esp+16+widthX]
        imul    eax, esi
        add     edi, eax
        dec     dword [esp+4]
        jnz     drawChar
        ret

antiAliasing:
        mov     bp, 3
@@:
        mov     cl, al
        mov     dl, bl
        lea     ecx, [ecx*2+ecx]
        add     ecx, edx
        shr     ecx, 2
        mov     al, cl
        ror     eax, 8
        ror     ebx, 8
        dec     bp
        jnz     @b
        ror     eax, 8
        ror     ebx, 8
        mov     ebp, ebx
        ret

iglobal
fontSmoothing   db  2   ; = 0, 1 or 2
fontSize        db  0   ; user mode setting
font1:
  if lang eq sp
  file 'gui/char_sp.mt'
  else if lang eq et
  file 'gui/char_et.mt'
  else
  file 'gui/char.mt'
  end if
fontUni:
file 'gui/charUni.mt'
endg
