forked from KolibriOS/kolibrios
373 lines
12 KiB
NASM
373 lines
12 KiB
NASM
;;================================================================================================;;
|
|
;;//// ico.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009 ///////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
;; ;;
|
|
;; This file is part of Common development libraries (Libs-Dev). ;;
|
|
;; ;;
|
|
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
|
|
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
|
|
;; of the License, or (at your option) any later version. ;;
|
|
;; ;;
|
|
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
|
|
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
|
|
;; Lesser General Public License for more details. ;;
|
|
;; ;;
|
|
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
|
|
;; If not, see <http://www.gnu.org/licenses/>. ;;
|
|
;; ;;
|
|
;;================================================================================================;;
|
|
;; ;;
|
|
;; References: ;;
|
|
;; 1. "Icons in Win32" ;;
|
|
;; by John Hornick, Microsoft Corporation ;;
|
|
;; http://msdn2.microsoft.com/en-us/library/ms997538.aspx ;;
|
|
;; ;;
|
|
;;================================================================================================;;
|
|
|
|
include 'ico_cur.inc'
|
|
|
|
;;================================================================================================;;
|
|
;;proc img.is.ico _data, _length ;////////////////////////////////////////////////////////////////;;
|
|
img.is.ico:
|
|
mov edx, 0x00010000 ; icon type = 1
|
|
jmp @f
|
|
img.is.cur:
|
|
mov edx, 0x00020000 ; cursor type = 2
|
|
@@:
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? Determine if raw data could be decoded (is in ICO format) ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> _data = raw data as read from file/stream ;;
|
|
;> _length = data length ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< eax = false / true ;;
|
|
;;================================================================================================;;
|
|
; test 1 (length of data): data must contain FileHeader
|
|
mov ecx, [esp+8]
|
|
sub ecx, sizeof.ico.FileHeader
|
|
jb .nope
|
|
; test 2: signature
|
|
mov eax, [esp+4]
|
|
cmp dword [eax], edx ; Reserved & Type
|
|
jne .nope
|
|
; test 3: count must be non-zero
|
|
movzx eax, [eax + ico.FileHeader.Count]
|
|
test eax, eax
|
|
jz .nope
|
|
; test 4 (length of data): data must containt Count dir entries
|
|
shl eax, 4
|
|
sub ecx, eax
|
|
jae .yep
|
|
|
|
.nope:
|
|
xor eax, eax
|
|
ret 8
|
|
|
|
.yep:
|
|
xor eax, eax
|
|
inc eax
|
|
ret 8
|
|
;endp
|
|
|
|
;;================================================================================================;;
|
|
proc img.decode.ico_cur _data, _length, _options ;////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? Decode data into image if it contains correctly formed raw data in ICO/CUR format ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> _data = raw data as read from file/stream ;;
|
|
;> _length = data length ;;
|
|
;> _options = options for decoding (e.g. background color) ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< eax = 0 (error) or pointer to image ;;
|
|
;;================================================================================================;;
|
|
locals
|
|
count dd ?
|
|
img dd ?
|
|
main_img dd ?
|
|
endl
|
|
|
|
push ebx esi edi
|
|
|
|
; img.is.ico has been already called by img.decode
|
|
; stdcall img.is.ico, [_data], [_length]
|
|
; or eax, eax
|
|
; jz .error
|
|
|
|
mov ebx, [_data]
|
|
movzx eax, [ebx + ico.FileHeader.Count]
|
|
mov [count], eax
|
|
and [img], 0
|
|
and [main_img], 0
|
|
.loop:
|
|
mov ecx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ByteSize]
|
|
mov edx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ImageOffset]
|
|
mov eax, [_length]
|
|
sub eax, edx
|
|
jb .skip
|
|
cmp eax, ecx
|
|
jb .skip
|
|
cmp ecx, 12 ; length test, see img.is.bmp
|
|
jb .skip
|
|
add edx, [_data]
|
|
push [_options]
|
|
push ecx
|
|
push edx
|
|
call img.decode.ico._.decode_icon_data
|
|
test eax, eax
|
|
jz .skip
|
|
push 0xFFFFFF ; set bgr to white if no given
|
|
mov edx, [_options]
|
|
test edx, edx
|
|
jz @f
|
|
cmp [edx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4
|
|
jb @f
|
|
add esp, 4
|
|
push [edx + ImageDecodeOptions.BackgroundColor]
|
|
@@:
|
|
call img.decode.ico._.decode_icon_mask
|
|
test eax, eax
|
|
jz .skip
|
|
mov edx, [img]
|
|
test edx, edx
|
|
jz .first
|
|
mov [edx + Image.Next], eax
|
|
mov [eax + Image.Previous], edx
|
|
jmp @f
|
|
.first:
|
|
mov [main_img], eax
|
|
@@:
|
|
mov [img], eax
|
|
.skip:
|
|
add ebx, sizeof.ico.DirEntry
|
|
dec [count]
|
|
jnz .loop
|
|
|
|
mov eax, [main_img]
|
|
pop edi esi ebx
|
|
ret
|
|
endp
|
|
|
|
;;================================================================================================;;
|
|
img.encode.cur:
|
|
proc img.encode.ico _img, _p_length, _options ;///////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? Encode image into raw data in ICO format ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> _img = pointer to image ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< eax = 0 (error) or pointer to encoded data ;;
|
|
;< _p_length = encoded data length ;;
|
|
;;================================================================================================;;
|
|
xor eax, eax
|
|
ret
|
|
endp
|
|
|
|
|
|
;;================================================================================================;;
|
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
;! Below are private procs you should never call directly from your code ;;
|
|
;;================================================================================================;;
|
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
|
|
img.decode.ico._.decode_icon_data:
|
|
; create stack frame and jump to common BMP+ICO code
|
|
push ebp
|
|
mov ebp, esp
|
|
sub esp, 12
|
|
mov byte [ebp - 3], 1 ; bIsIco
|
|
jmp img.decode.bmp.common
|
|
|
|
img.decode.ico._.decode_icon_mask:
|
|
mov edx, [eax + Image.Width]
|
|
add edx, 31
|
|
shr edx, 3
|
|
and edx, not 3
|
|
push edx
|
|
imul edx, [eax + Image.Height]
|
|
cmp ecx, edx
|
|
pop edx
|
|
jb .error.free
|
|
mov edi, [eax + Image.Data]
|
|
push ebp ebx eax
|
|
xor ebp, ebp
|
|
mov ebx, [eax + Image.Extended]
|
|
cmp [ebx + bmp.Image.info.Height], 0
|
|
js @f
|
|
push edx
|
|
imul edx, [eax + Image.Height]
|
|
add esi, edx
|
|
pop edx
|
|
lea ebp, [edx+edx]
|
|
sub esi, edx
|
|
@@:
|
|
mov ebx, [eax + Image.Height]
|
|
mov ecx, [eax + Image.Width]
|
|
; for now, BMP code produces only 8 and 32 bpp images
|
|
cmp [eax + Image.Type], Image.bpp8
|
|
jz .bpp8
|
|
.bpp32:
|
|
mov edx, [esp+16] ; get background color
|
|
.bpp32.extloop:
|
|
push ecx
|
|
.bpp32.innloop:
|
|
lodsd
|
|
bswap eax
|
|
push 32
|
|
.bpp32.dwordloop:
|
|
add eax, eax
|
|
jnc @f
|
|
mov [edi], edx
|
|
@@:
|
|
add edi, 4
|
|
dec ecx
|
|
jz @f
|
|
dec dword [esp]
|
|
jnz .bpp32.dwordloop
|
|
@@:
|
|
pop eax
|
|
test ecx, ecx
|
|
jnz .bpp32.innloop
|
|
sub esi, ebp
|
|
pop ecx
|
|
dec ebx
|
|
jnz .bpp32.extloop
|
|
pop eax ebx ebp
|
|
ret 4
|
|
.bpp8:
|
|
push edi
|
|
mov edi, [eax + Image.Palette]
|
|
mov eax, [esp+20] ; get background color
|
|
; if palette already has index for bgr color, use it
|
|
push ecx
|
|
mov ecx, 256
|
|
repnz scasd
|
|
jnz .bpp8.notfound
|
|
not cl ; cl = index
|
|
pop edx
|
|
pop edi
|
|
.bpp8.extloop:
|
|
push edx
|
|
.bpp8.innloop:
|
|
lodsd
|
|
bswap eax
|
|
push 32
|
|
.bpp8.dwordloop:
|
|
add eax, eax
|
|
jnc @f
|
|
mov [edi], cl
|
|
@@:
|
|
inc edi
|
|
dec edx
|
|
jz @f
|
|
dec dword [esp]
|
|
jnz .bpp8.dwordloop
|
|
@@:
|
|
pop eax
|
|
test edx, edx
|
|
jnz .bpp8.innloop
|
|
sub esi, ebp
|
|
pop edx
|
|
dec ebx
|
|
jnz .bpp8.extloop
|
|
pop eax ebx ebp
|
|
ret 4
|
|
.bpp8.notfound:
|
|
; get maximum used color; if index < 255, then we can add one color to palette
|
|
pop ecx
|
|
pop edi
|
|
pop eax
|
|
mov edx, [eax + Image.Width]
|
|
imul edx, ebx
|
|
mov edi, [eax + Image.Data]
|
|
xor ecx, ecx
|
|
.bpp8.scanloop:
|
|
cmp [edi], cl
|
|
jb @f
|
|
mov cl, [edi]
|
|
@@:
|
|
inc edi
|
|
dec edx
|
|
jnz .bpp8.scanloop
|
|
inc cl
|
|
jz .bpp8.nospace
|
|
mov edx, [esp+8]
|
|
mov edi, [eax + Image.Palette]
|
|
mov [edi+ecx*4], edx ; set palette color
|
|
mov edi, [eax + Image.Data]
|
|
mov edx, [eax + Image.Width]
|
|
push eax
|
|
jmp .bpp8.extloop
|
|
.bpp8.nospace:
|
|
; convert to 24 bpp
|
|
mov edx, [eax + Image.Width]
|
|
imul edx, ebx
|
|
lea edx, [edx*3]
|
|
push eax
|
|
invoke mem.alloc, edx
|
|
mov edi, eax
|
|
pop eax
|
|
test edi, edi
|
|
jz .error.free2
|
|
push eax esi edi
|
|
mov esi, eax
|
|
call img._.do_rgb
|
|
pop edi esi eax
|
|
xchg edi, [eax + Image.Data]
|
|
mov byte [eax + Image.Type], Image.bpp24
|
|
push eax
|
|
invoke mem.free, edi
|
|
pop eax
|
|
push eax
|
|
mov ecx, [eax + Image.Width]
|
|
mov edi, [eax + Image.Data]
|
|
.bpp24:
|
|
mov edx, [esp+16] ; get background color
|
|
.bpp24.extloop:
|
|
push ecx
|
|
.bpp24.innloop:
|
|
lodsd
|
|
bswap eax
|
|
push 32
|
|
.bpp24.dwordloop:
|
|
add eax, eax
|
|
jnc @f
|
|
mov [edi], dx
|
|
ror edx, 16
|
|
mov [edi+2], dl
|
|
ror edx, 16
|
|
@@:
|
|
add edi, 3
|
|
dec ecx
|
|
jz @f
|
|
dec dword [esp]
|
|
jnz .bpp24.dwordloop
|
|
@@:
|
|
pop eax
|
|
test ecx, ecx
|
|
jnz .bpp24.innloop
|
|
sub esi, ebp
|
|
pop ecx
|
|
dec ebx
|
|
jnz .bpp24.extloop
|
|
pop eax ebx ebp
|
|
ret 4
|
|
.error.free2:
|
|
pop ebx ebp
|
|
.error.free:
|
|
stdcall img._.delete, eax
|
|
xor eax, eax
|
|
ret 4
|
|
|
|
;;================================================================================================;;
|
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
;! Below is private data you should never use directly from your code ;;
|
|
;;================================================================================================;;
|
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
|
|
|
|
;
|