forked from KolibriOS/kolibrios
4ff2c74504
git-svn-id: svn://kolibrios.org@6128 a494cfbc-eb01-0410-851d-a64ba20cac60
656 lines
9.6 KiB
NASM
656 lines
9.6 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; ;;
|
||
;; Copyright (C) KolibriOS team 2016. All rights reserved. ;;
|
||
;; Distributed under terms of the GNU General Public License ;;
|
||
;; ;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
format MS COFF
|
||
|
||
public @EXPORT as 'EXPORTS'
|
||
|
||
include '../../../macros.inc'
|
||
include '../../../proc32.inc'
|
||
|
||
|
||
; calculate string width in pixels
|
||
proc stringWidth, charQuantity, charHeight
|
||
mov eax,[charHeight]
|
||
shr eax,1
|
||
mul [charQuantity]
|
||
ret
|
||
endp
|
||
|
||
|
||
; calculate amount of chars that fits given width
|
||
proc charsFit, areaWidth, charHeight
|
||
shr [charHeight],1
|
||
mov eax,[areaWidth]
|
||
xor edx,edx
|
||
div [charHeight]
|
||
ret
|
||
endp
|
||
|
||
|
||
; calculate amount of valid chars in UTF-8 string
|
||
; supports zero terminated string (set byteQuantity = -1)
|
||
proc countUTF8, string, byteQuantity
|
||
push esi
|
||
mov edx,[byteQuantity]
|
||
inc edx
|
||
xor ecx,ecx
|
||
dec ecx
|
||
mov esi,[string]
|
||
@@:
|
||
inc ecx
|
||
dec edx
|
||
jz .done
|
||
lodsb
|
||
test al,al
|
||
jz .done
|
||
jns @b
|
||
dec ecx
|
||
shl al,1
|
||
jns @b
|
||
.next:
|
||
mov ah,[esi]
|
||
test ah,ah
|
||
jns @b
|
||
shl ah,1
|
||
js @b
|
||
inc esi
|
||
dec edx
|
||
jz @f
|
||
shl al,1
|
||
js .next
|
||
inc ecx
|
||
jmp @b
|
||
@@:
|
||
inc ecx
|
||
.done:
|
||
mov eax,ecx
|
||
pop esi
|
||
ret
|
||
endp
|
||
|
||
|
||
; draw text on 24bpp or 32bpp image
|
||
; autofits text between 'x' and 'xSize'
|
||
proc drawText, canvas, x, y, string, charQuantity, fontColor, params
|
||
; [canvas]:
|
||
; xSize dd ?
|
||
; ySize dd ?
|
||
; picture rb xSize * ySize * bpp
|
||
|
||
; fontColor dd AARRGGBB
|
||
; AA = alpha channel ; 0 = transparent, FF = non transparent
|
||
|
||
; params dd ffeewwhh
|
||
; hh = char height
|
||
; ww = char width ; 0 = auto (proportional)
|
||
; ee = encoding ; 1 = cp866, 2 = UTF-16LE, 3 = UTF-8
|
||
; ff = flags ; 0001 = bold, 0010 = italic
|
||
; 0100 = underline, 1000 = strike-through
|
||
; 00010000 = align right, 00100000 = align center
|
||
; 01000000 = set text area between higher and lower halfs of 'x'
|
||
; 10000000 = 32bpp canvas insted of 24bpp
|
||
; all flags combinable, except align right + align center
|
||
|
||
; returns: eax = char width (0 = error), ecx = text start X
|
||
pusha
|
||
movzx eax,byte[params+1]
|
||
test eax,eax
|
||
jnz @f
|
||
mov al ,byte[params]
|
||
shr al ,1
|
||
mov byte[params+1],al
|
||
@@:
|
||
cmp al, 22
|
||
jc @f
|
||
mov al, 21
|
||
mov byte[params+1],21
|
||
@@:
|
||
inc [charQuantity]
|
||
mul [charQuantity]
|
||
mov ebx,eax
|
||
mov esi,[canvas]
|
||
mov esi,[esi]
|
||
test byte[params+3],64
|
||
jz .fit
|
||
movzx eax,word[x]
|
||
movzx ecx,word[x+2]
|
||
cmp eax,ecx
|
||
jnc @f
|
||
xchg eax,ecx
|
||
@@:
|
||
mov [x],ecx
|
||
cmp esi,eax
|
||
jc .fit
|
||
mov esi,eax
|
||
.fit:
|
||
mov eax,esi
|
||
sub eax,[x]
|
||
jnc @f
|
||
popa
|
||
xor eax,eax
|
||
jmp .exit
|
||
@@:
|
||
cmp eax,ebx
|
||
jnc @f
|
||
mov ebx,eax
|
||
div [charQuantity]
|
||
mov byte[params+1],al
|
||
sub ebx,edx
|
||
@@:
|
||
mov eax,esi
|
||
sub eax,ebx
|
||
test byte[params+3],32
|
||
jz @f
|
||
sub eax,[x]
|
||
shr eax,1
|
||
add [x],eax
|
||
jmp .ok
|
||
@@:
|
||
test byte[params+3],16
|
||
jz .ok
|
||
mov [x],eax
|
||
.ok:
|
||
movzx eax,byte[params+1]
|
||
lea eax,[eax*2+eax]
|
||
shr eax,3
|
||
test byte[params+1],7
|
||
jz @f
|
||
inc eax
|
||
@@:
|
||
mov ecx,eax
|
||
push eax
|
||
shl eax,3
|
||
mul [charQuantity]
|
||
shl ecx,4
|
||
push ecx
|
||
push eax
|
||
mul ecx
|
||
push eax
|
||
lea ecx,[eax*4+8]
|
||
mcall 68,12
|
||
|
||
pop ecx
|
||
popd [eax]
|
||
popd [eax+4]
|
||
push eax
|
||
lea edi,[eax+8]
|
||
xor eax,eax
|
||
rep stosd
|
||
pop edi
|
||
pop ecx
|
||
shl ecx,4
|
||
mov ch, byte[params+2]
|
||
shl ecx,22
|
||
shr ecx,2
|
||
dec ecx
|
||
bts ecx,27
|
||
mov esi,[charQuantity]
|
||
dec esi
|
||
xor ebx,ebx
|
||
mcall 4,,,[string]
|
||
|
||
xor eax,eax
|
||
mov ebx,[edi]
|
||
mov ecx,[edi+4]
|
||
push edi
|
||
add edi,8
|
||
test byte[params+3],1
|
||
jnz .bold
|
||
movzx esi,byte[params]
|
||
@@:
|
||
pusha
|
||
call verSub
|
||
popa
|
||
sub esi,16
|
||
jg @b
|
||
jmp @f
|
||
.bold:
|
||
imul ecx,ebx
|
||
dec eax
|
||
movzx ebx,byte[params+1]
|
||
.loop:
|
||
push edi
|
||
push ecx
|
||
call horAdd
|
||
pop ecx
|
||
pop edi
|
||
sub ebx,8
|
||
jg .loop
|
||
@@:
|
||
|
||
test byte[params+3],2
|
||
jz @f
|
||
mov edi,[esp]
|
||
mov ecx,[edi]
|
||
mov ebx,[edi+4]
|
||
add edi,8
|
||
mov esi,edi
|
||
call italic
|
||
@@:
|
||
|
||
mov edi,[esp]
|
||
mov eax,[edi]
|
||
mov ebx,[edi+4]
|
||
add edi,8
|
||
mov esi,edi
|
||
movzx edx,byte[params]
|
||
call verScale
|
||
|
||
mov eax,[charQuantity]
|
||
mul byte[params+1]
|
||
mov esi,[esp]
|
||
mov edx,[esi]
|
||
add esi,8
|
||
mov edi,esi
|
||
mov ebx,eax
|
||
push eax
|
||
movzx eax,byte[params]
|
||
call ClearType
|
||
|
||
test byte[params+3],4
|
||
jz @f
|
||
movzx eax,byte[params]
|
||
movzx esi,byte[params+1]
|
||
mov ebx,eax
|
||
dec eax
|
||
call drawLine
|
||
@@:
|
||
|
||
test byte[params+3],8
|
||
jz @f
|
||
movzx eax,byte[params]
|
||
movzx esi,byte[params+1]
|
||
mov ebx,eax
|
||
shr eax,1
|
||
call drawLine
|
||
@@:
|
||
|
||
mov esi,[canvas]
|
||
mov eax,[esi]
|
||
mul [y]
|
||
add eax,[x]
|
||
mov edi,eax
|
||
mov eax,[esi]
|
||
pop ecx
|
||
sub eax,ecx
|
||
mov ebx,[fontColor]
|
||
movzx edx,byte[params]
|
||
test byte[params+3],128
|
||
mov ebp,3
|
||
jnz @f
|
||
lea edi,[edi*2+edi+8]
|
||
lea eax,[eax*2+eax]
|
||
jmp .go
|
||
@@:
|
||
lea edi,[edi*4+8]
|
||
shl eax,2
|
||
inc ebp
|
||
.go:
|
||
add edi,esi
|
||
mov esi,[esp]
|
||
add esi,8
|
||
call putOnPicture
|
||
|
||
pop ecx
|
||
mcall 68,13
|
||
popa
|
||
movzx eax,byte[params+1]
|
||
mov ecx,[x]
|
||
.exit:
|
||
ret
|
||
endp
|
||
|
||
|
||
drawLine:
|
||
mov ecx,[esp+4]
|
||
lea ecx,[ecx*2+ecx]
|
||
mul ecx
|
||
lea esi,[esi*2+esi]
|
||
sub ecx,esi
|
||
add esi,ecx
|
||
add esi,ecx
|
||
shr ecx,2
|
||
add eax,[esp+8]
|
||
lea edi,[eax+8]
|
||
mov eax,-1
|
||
@@:
|
||
push ecx
|
||
rep stosd
|
||
sub edi,esi
|
||
pop ecx
|
||
sub ebx,16
|
||
jg @b
|
||
ret
|
||
|
||
|
||
; make horizontal lines thinner
|
||
; one color background only
|
||
verSub:
|
||
; edi -> buffer (32bpp)
|
||
; eax = background color
|
||
; ebx = width
|
||
; ecx = height
|
||
push ebp
|
||
mov edx,ebx
|
||
mov esi,edi
|
||
mov ebp,ecx
|
||
shl ebx,2
|
||
.start:
|
||
cmp [edi],eax
|
||
jnz @f
|
||
.loop:
|
||
add edi,ebx
|
||
dec ecx
|
||
jnz .start
|
||
jmp .next
|
||
@@:
|
||
mov [edi],eax
|
||
@@:
|
||
add edi,ebx
|
||
dec ecx
|
||
jz .next
|
||
cmp [edi],eax
|
||
jnz @b
|
||
jmp .loop
|
||
.next:
|
||
add esi,4
|
||
mov edi,esi
|
||
mov ecx,ebp
|
||
dec edx
|
||
jnz .start
|
||
pop ebp
|
||
ret
|
||
|
||
|
||
; make vertical lines thicker
|
||
horAdd:
|
||
; edi -> buffer (32bpp)
|
||
; eax = font color
|
||
; ecx = total number of pixels
|
||
repnz scasd
|
||
jcxz .end
|
||
repz scasd
|
||
mov [edi-4],eax
|
||
jmp horAdd
|
||
.end:
|
||
ret
|
||
|
||
|
||
; esi=edi supported (32bpp)
|
||
italic:
|
||
; esi -> source buffer
|
||
; edi -> result buffer
|
||
; ebx = height
|
||
; ecx = width
|
||
shl ecx,2
|
||
shr ebx,2
|
||
mov eax,ecx
|
||
mul ebx
|
||
shl eax,2
|
||
add esi,eax
|
||
add edi,eax
|
||
dec ecx
|
||
sub esi,8
|
||
sub edi,4
|
||
push ebx
|
||
std
|
||
@@:
|
||
push ecx
|
||
rep movsd
|
||
pop ecx
|
||
sub esi,4
|
||
dec ebx
|
||
jnz @b
|
||
pop ecx
|
||
mov eax,[edi+4]
|
||
rep stosd
|
||
cld
|
||
ret
|
||
|
||
|
||
; vertical downscale
|
||
; white-black-gray only
|
||
; esi=edi supported (32bpp)
|
||
verScale:
|
||
; esi -> source buffer
|
||
; edi -> result buffer
|
||
; eax = width
|
||
; ebx = source height
|
||
; edx = result height
|
||
push ebp
|
||
dec eax
|
||
shl eax,2
|
||
push eax
|
||
add eax,4
|
||
push edx
|
||
push esi
|
||
push edi
|
||
push eax
|
||
mov ecx,edx
|
||
.scale:
|
||
mov al, [esi]
|
||
add esi,[esp]
|
||
mul cl
|
||
neg ecx
|
||
add ecx,ebx
|
||
mov ebp,eax
|
||
mov al, [esi]
|
||
@@:
|
||
cmp edx,ecx
|
||
jnc @f
|
||
add esi,[esp]
|
||
mul dl
|
||
sub ecx,edx
|
||
add ebp,eax
|
||
mov al, [esi]
|
||
jmp @b
|
||
@@:
|
||
mul cl
|
||
add eax,ebp
|
||
div bl
|
||
mov [edi],al
|
||
mov [edi+1],al
|
||
mov [edi+2],al
|
||
add edi,[esp]
|
||
neg ecx
|
||
add ecx,edx
|
||
jnz @f
|
||
add ecx,edx
|
||
add esi,[esp]
|
||
@@:
|
||
dec dword[esp+12]
|
||
jnz .scale
|
||
mov edi,[esp+4]
|
||
mov esi,[esp+8]
|
||
mov [esp+12],edx
|
||
add edi,[esp+16]
|
||
add esi,[esp+16]
|
||
sub dword[esp+16],4
|
||
jnc .scale
|
||
add esp,20
|
||
pop ebp
|
||
ret
|
||
|
||
|
||
; horizontal downscale
|
||
; minimum <20> x3, maximum <20> x6
|
||
; white-black-gray only
|
||
; esi=edi supported
|
||
ClearType:
|
||
; esi -> source buffer (32bpp)
|
||
; edi -> result buffer (24bpp)
|
||
; eax = height
|
||
; edx = source width
|
||
; ebx = result width
|
||
push ebp
|
||
lea ebx,[ebx*2+ebx]
|
||
imul eax,ebx
|
||
push eax
|
||
push edi
|
||
push eax
|
||
push edx
|
||
mov ecx,ebx
|
||
.scale:
|
||
movzx eax,byte[esi]
|
||
add esi,4
|
||
mul ecx
|
||
neg ecx
|
||
add ecx,[esp]
|
||
mov ebp,eax
|
||
movzx eax,byte[esi]
|
||
cmp ebx,ecx
|
||
jnc @f
|
||
add esi,4
|
||
mul ebx
|
||
sub ecx,ebx
|
||
add ebp,eax
|
||
movzx eax,byte[esi]
|
||
@@:
|
||
mul ecx
|
||
add eax,ebp
|
||
div dword[esp]
|
||
stosb
|
||
neg ecx
|
||
add ecx,ebx
|
||
jnz @f
|
||
add ecx,ebx
|
||
add esi,4
|
||
@@:
|
||
dec dword[esp+4]
|
||
jnz .scale
|
||
pop edi
|
||
pop edi
|
||
mov edi,[esp]
|
||
mov ecx,[esp+4]
|
||
movzx ebx,byte[edi]
|
||
xor eax,eax
|
||
dec ecx
|
||
.degradation:
|
||
mov al, [edi]
|
||
shl eax,1
|
||
lea eax,[eax*2+eax]
|
||
lea edx,[ebx*4+ebx]
|
||
mov bl, [edi+1]
|
||
add eax,edx
|
||
lea edx,[ebx*4+ebx]
|
||
mov bl, [edi]
|
||
add eax,edx
|
||
shr eax,4
|
||
stosb
|
||
dec ecx
|
||
jnz .degradation
|
||
pop edi
|
||
pop ecx
|
||
.colRev:
|
||
mov al,[edi]
|
||
xchg al,[edi+2]
|
||
mov [edi],al
|
||
add edi,3
|
||
sub ecx,3
|
||
jnz .colRev
|
||
pop ebp
|
||
ret
|
||
|
||
|
||
; apply color on font, put font on picture
|
||
; white font on black background only, smoothing allowed
|
||
putOnPicture:
|
||
; esi -> font buffer (24bpp)
|
||
; edi -> picture buffer
|
||
; ebx = font color
|
||
; ecx = width
|
||
; edx = height
|
||
; eax = picture buffer line gap in bytes
|
||
; ebp = picture buffer bytes per pixel
|
||
push edx
|
||
push eax
|
||
push ecx
|
||
push ebp
|
||
xor eax,eax
|
||
rol ebx,8
|
||
mov ebp,ecx
|
||
.start:
|
||
cmp byte[esi], 0
|
||
jz @f
|
||
mov al, [esi]
|
||
mul bl
|
||
mov al, ah
|
||
shr ah, 7
|
||
add al, ah
|
||
mov cl, 255
|
||
sub cl, al
|
||
mul bh
|
||
mov edx,eax
|
||
mov al, [edi]
|
||
mul cl
|
||
add eax,edx
|
||
mov al, ah
|
||
shr ah, 7
|
||
add al, ah
|
||
mov [edi],al
|
||
@@:
|
||
cmp byte[esi+1], 0
|
||
jz @f
|
||
mov al, [esi+1]
|
||
mul bl
|
||
mov al, ah
|
||
shr ah, 7
|
||
add al, ah
|
||
mov cl, 255
|
||
sub cl, al
|
||
rol ebx,16
|
||
mul bl
|
||
rol ebx,16
|
||
mov edx,eax
|
||
mov al, [edi+1]
|
||
mul cl
|
||
add eax,edx
|
||
mov al, ah
|
||
shr ah, 7
|
||
add al, ah
|
||
mov [edi+1],al
|
||
@@:
|
||
cmp byte[esi+2], 0
|
||
jz @f
|
||
mov al, [esi+2]
|
||
mul bl
|
||
mov al, ah
|
||
shr ah, 7
|
||
add al, ah
|
||
mov cl, 255
|
||
sub cl, al
|
||
rol ebx,16
|
||
mul bh
|
||
rol ebx,16
|
||
mov edx,eax
|
||
mov al, [edi+2]
|
||
mul cl
|
||
add eax,edx
|
||
mov al, ah
|
||
shr ah, 7
|
||
add al, ah
|
||
mov [edi+2],al
|
||
@@:
|
||
add esi,3
|
||
add edi,[esp]
|
||
dec ebp
|
||
jnz .start
|
||
mov ebp,[esp+4]
|
||
add edi,[esp+8]
|
||
dec dword[esp+12]
|
||
jnz .start
|
||
add esp,16
|
||
ret
|
||
|
||
align 4
|
||
@EXPORT:
|
||
export drawText, 'drawText', \
|
||
countUTF8, 'cntUTF-8', \
|
||
charsFit, 'charsFit', \
|
||
stringWidth, 'strWidth'
|