source: trunk/src/user32/icon.cpp@ 21916

Last change on this file since 21916 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 17.1 KB
Line 
1/* $Id: icon.cpp,v 1.15 2003-02-24 17:02:43 sandervl Exp $ */
2
3/*
4 * Win32 icon conversion functions for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_GPIBITMAPS
13#define INCL_BITMAPFILEFORMAT
14#define INCL_DOSFILEMGR /* File Manager values */
15#define INCL_DOSERRORS /* DOS Error values */
16#define INCL_DOSPROCESS /* DOS Process values */
17#define INCL_DOSMISC /* DOS Miscellanous values */
18#define INCL_WIN
19#include <os2wrap.h> //Odin32 OS/2 api wrappers
20#include <stdio.h>
21#include <string.h>
22#include <stdlib.h>
23#include <string.h>
24#ifndef __EMX__
25#include <iostream.h>
26#endif
27
28#include <win32api.h>
29#include <win32type.h>
30#include "dib.h"
31#include <winicon.h>
32#include <misc.h>
33
34#define DBG_LOCALLOG DBG_icon
35#include "dbglocal.h"
36
37#define DIB_RGB_COLORS_W 0
38#define DIB_PAL_COLORS_W 1
39#define CBM_INIT_W 4
40
41
42//******************************************************************************
43//******************************************************************************
44ULONG QueryConvertedIconSize(WINBITMAPINFOHEADER *bmpHdr, int size, BOOL fResizeTo40x40 = FALSE)
45{
46 int bwsize, colorsize, rgbsize, iconsize;
47
48 if(fResizeTo40x40) {
49 bwsize = DIB_GetDIBImageBytes(40, 40, 1);
50 colorsize = DIB_GetDIBImageBytes(40, 40, bmpHdr->biBitCount);
51 }
52 else {
53 bwsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), 1);
54 colorsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), bmpHdr->biBitCount);
55 }
56
57 if(bmpHdr->biBitCount <= 8)
58 rgbsize = (1<<bmpHdr->biBitCount)*sizeof(RGB2);
59 else rgbsize = 0;
60
61 if(bmpHdr->biSizeImage == 0 && bmpHdr->biCompression == 0) {
62 bmpHdr->biSizeImage = bwsize + colorsize;
63 }
64
65 //SvL: 28-09-'98: cllngenu.dll has an incorrect size in the header
66 if(bmpHdr->biSizeImage < colorsize) {
67 bmpHdr->biSizeImage = colorsize;
68 }
69 //bitmapfileheader for AndXor mask + 2 RGB structs + bitmapfileheader
70 //for color bitmap + RGB structs for all the colors
71 //SvL, 3-3-98: 2*bwsize
72 iconsize = 2*sizeof(BITMAPFILEHEADER2) + 2*sizeof(RGB2) +
73 rgbsize + 2*bwsize + colorsize;
74
75 return iconsize;
76}
77//******************************************************************************
78//NOTE: offsetBits is the value added to the offBits bitmap structure members
79// (handy for converting icon groups)
80//******************************************************************************
81void *ConvertIcon(WINBITMAPINFOHEADER *bmpHdr, int size, int *os2size, int offsetBits,
82 BOOL fResizeTo40x40 = FALSE)
83{
84 RGBQUAD *rgb;
85 RGB2 *os2rgb;
86 int bwsize, i, colorsize, rgbsize, iconsize, orgbwsize, orgcolorsize;
87 BITMAPFILEHEADER2 *iconhdr;
88 BITMAPFILEHEADER2 *iconhdr2;
89 char *pAnd, *pXor;
90
91 if(fResizeTo40x40) {
92 orgbwsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), 1);
93 orgcolorsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), bmpHdr->biBitCount);
94 bwsize = DIB_GetDIBImageBytes(40, 40, 1);
95 colorsize = DIB_GetDIBImageBytes(40, 40, bmpHdr->biBitCount);
96 }
97 else {
98 bwsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), 1);
99 colorsize = DIB_GetDIBImageBytes(bmpHdr->biWidth, (bmpHdr->biHeight/2), bmpHdr->biBitCount);
100 }
101 //SvL: 28-09-'98: only for <= 8
102 if(bmpHdr->biBitCount <= 8)
103 rgbsize = (1<<bmpHdr->biBitCount)*sizeof(RGB2);
104 else rgbsize = 0;
105
106 if(bmpHdr->biSizeImage == 0 && bmpHdr->biCompression == 0) {
107 bmpHdr->biSizeImage = bwsize + colorsize;
108 }
109 dprintf(("Icon size : %d", bmpHdr->biSizeImage));
110 dprintf(("Icon Width : %d", bmpHdr->biWidth));
111 //height for both the XOR and AND bitmap (color & BW)
112 dprintf(("Height : %d", bmpHdr->biHeight));
113 dprintf(("Icon Bitcount: %d", bmpHdr->biBitCount));
114 dprintf(("Icon Compress: %d", bmpHdr->biCompression));
115
116 //SvL: 28-09-'98: cllngenu.dll has an incorrect size in the header
117 if(bmpHdr->biSizeImage < colorsize) {
118 bmpHdr->biSizeImage = colorsize;
119 }
120 //bitmapfileheader for AndXor mask + 2 RGB structs + bitmapfileheader
121 //for color bitmap + RGB structs for all the colors
122 //SvL, 3-3-98: 2*bwsize
123 iconsize = 2*sizeof(BITMAPFILEHEADER2) + 2*sizeof(RGB2) +
124 rgbsize + 2*bwsize + colorsize;
125
126 iconhdr = (BITMAPFILEHEADER2 *)malloc(iconsize);
127 memset(iconhdr, 0, iconsize);
128 iconhdr->usType = BFT_COLORICON;
129 iconhdr->cbSize = sizeof(BITMAPFILEHEADER2);
130 iconhdr->xHotspot = 0;
131 iconhdr->yHotspot = 0;
132 iconhdr->offBits = 2*sizeof(BITMAPFILEHEADER2) +
133 2*sizeof(RGB2) + rgbsize + offsetBits;
134 iconhdr->bmp2.cbFix = sizeof(BITMAPINFOHEADER2);
135 if(fResizeTo40x40) {
136 iconhdr->bmp2.cx = (USHORT)40;
137 iconhdr->bmp2.cy = (USHORT)80;
138 }
139 else {
140 iconhdr->bmp2.cx = (USHORT)bmpHdr->biWidth;
141 iconhdr->bmp2.cy = (USHORT)bmpHdr->biHeight;
142 }
143 iconhdr->bmp2.cPlanes = 1;
144 iconhdr->bmp2.cBitCount= 1;
145 iconhdr->bmp2.cbImage = 2*bwsize;
146 iconhdr->bmp2.cclrUsed = 2;
147 iconhdr->bmp2.cclrImportant = 2;
148 iconhdr->bmp2.ulCompression = BCA_UNCOMP;
149 iconhdr->bmp2.ulColorEncoding = BCE_RGB;
150 os2rgb = (RGB2 *)(iconhdr+1);
151 memset(os2rgb, 0, sizeof(RGB2));
152 memset(os2rgb+1, 0xff, sizeof(RGB)); //not reserved byte!
153 iconhdr2 = (BITMAPFILEHEADER2 *)(os2rgb+2);
154 iconhdr2->usType = BFT_COLORICON;
155 iconhdr2->cbSize = sizeof(BITMAPFILEHEADER2);
156 iconhdr2->xHotspot = 0;
157 iconhdr2->yHotspot = 0;
158 iconhdr2->offBits = 2*sizeof(BITMAPFILEHEADER2) +
159 2*sizeof(RGB2) + rgbsize + 2*bwsize + offsetBits;
160 iconhdr2->bmp2.cbFix = sizeof(BITMAPINFOHEADER2);
161 if(fResizeTo40x40) {
162 iconhdr2->bmp2.cx = (USHORT)40;
163 iconhdr2->bmp2.cy = (USHORT)40;
164 }
165 else {
166 iconhdr2->bmp2.cx = (USHORT)bmpHdr->biWidth;
167 iconhdr2->bmp2.cy = (USHORT)(bmpHdr->biHeight/2);
168 }
169 iconhdr2->bmp2.cPlanes = bmpHdr->biPlanes;
170 iconhdr2->bmp2.cBitCount= bmpHdr->biBitCount;
171 iconhdr2->bmp2.cbImage = colorsize;
172 iconhdr2->bmp2.cclrUsed = bmpHdr->biClrUsed;
173 iconhdr2->bmp2.cclrImportant = bmpHdr->biClrImportant;
174 iconhdr2->bmp2.ulCompression = BCA_UNCOMP;
175 iconhdr2->bmp2.ulColorEncoding = BCE_RGB;
176 os2rgb = (RGB2 *)(iconhdr2+1);
177 rgb = (RGBQUAD *)(bmpHdr+1);
178 if(bmpHdr->biBitCount <= 8) {
179 for(i=0;i<(1<<bmpHdr->biBitCount);i++) {
180 os2rgb->bRed = rgb->red;
181 os2rgb->bBlue = rgb->blue;
182 os2rgb->bGreen = rgb->green;
183 os2rgb++;
184 rgb++;
185 }
186 }
187
188 if(fResizeTo40x40)
189 {
190 BYTE *src, *dest;
191 int linesizesrc, linesizedest;
192
193 pXor = (char *)os2rgb;
194 pAnd = (char *)os2rgb + bwsize;
195
196 if ((size - (bmpHdr->biSize + rgbsize + orgcolorsize + orgbwsize)) == orgbwsize)
197 {//this means an AND and XOR mask is present (interleaved; and/xor)
198 char *q;
199 int i, linesize;
200
201 //TODO:
202 dprintf(("TODO: icon conversion not correct"));
203 linesize = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
204 q = (char *)rgb + orgcolorsize;
205 for (i = 0; i < bmpHdr->biHeight/2; i++) {
206 memcpy (pAnd, q, linesize);
207 pAnd += linesize;
208 q += linesize;
209
210 memcpy (pXor, q, linesize);
211 pXor += linesize;
212 q += linesize;
213 }
214 }
215 else {
216 linesizesrc = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
217 linesizedest = DIB_GetDIBWidthBytes(40, 1);
218
219 src = (BYTE *)rgb + orgcolorsize;
220 dest = (BYTE *)pAnd + 4*linesizedest; //skip 4 lines
221 memset((char *)pAnd, 0xFF, bwsize);
222 for (i = 0; i < bmpHdr->biHeight/2; i++) {
223 for(int j=0;j<linesizesrc;j++) {
224 //must skip 4 pixels (4 bits)
225 dest[j] = (dest[j] & 0xF0) | ((src[j] >> 4));
226 dest[j+1] = (dest[j+1] & 0x0F) | ((src[j] & 0xF) << 4);
227 }
228 dest += linesizedest;
229 src += linesizesrc;
230 }
231 memset (pXor, 0, bwsize);
232 }
233 linesizesrc = DIB_GetDIBWidthBytes(32, bmpHdr->biBitCount);
234 linesizedest = DIB_GetDIBWidthBytes(40, bmpHdr->biBitCount);
235 int skipsize = (4*bmpHdr->biBitCount)/8; //must skip 4 pixels
236 src = (BYTE *)rgb;
237 dest = (BYTE *)os2rgb+2*bwsize + 4*linesizedest; //skip 4 rows
238
239 for (i = 0; i < 32; i++) {
240 memcpy(dest+skipsize, src, linesizesrc);
241 dest += linesizedest;
242 src += linesizesrc;
243 }
244 }
245 else {
246 pXor = (char *)os2rgb;
247 pAnd = (char *)os2rgb + bwsize;
248
249 if ((size - (bmpHdr->biSize + rgbsize + colorsize + bwsize)) == bwsize)
250 {//this means an AND and XOR mask is present (interleaved; and/xor)
251 char *q;
252 int i, linesize;
253
254 linesize = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
255 q = (char *)rgb + orgcolorsize;
256 for (i = 0; i < bmpHdr->biHeight/2; i++) {
257 memcpy (pAnd, q, linesize);
258 pAnd += linesize;
259 q += linesize;
260
261 memcpy (pXor, q, linesize);
262 pXor += linesize;
263 q += linesize;
264 }
265 }
266 else {
267 memcpy (pAnd, (char *)rgb + colorsize, bwsize);
268 memset (pXor, 0, bwsize);
269 }
270 memcpy((char *)os2rgb+2*bwsize, (char *)rgb, colorsize);
271 }
272 *os2size = iconsize;
273 return (void *)iconhdr;
274}
275
276extern "C" {
277
278//******************************************************************************
279//******************************************************************************
280void * WIN32API ConvertIconGroup(void *hdr, HINSTANCE hInstance, DWORD *ressize)
281{
282 IconHeader *ihdr = (IconHeader *)hdr;
283 ResourceDirectory *rdir = (ResourceDirectory *)(ihdr + 1);
284 int i, groupsize = 0, os2iconsize;
285 BITMAPARRAYFILEHEADER2 *bafh, *orgbafh;
286 WINBITMAPINFOHEADER *iconhdr;
287 void *os2icon;
288 HRSRC hRes;
289 int nricons = 0;
290
291 dprintf(("Icon Group type :%d", ihdr->wType));
292 dprintf(("Icon Group count:%d", ihdr->wCount));
293 for(i=0;i<ihdr->wCount;i++) {
294 dprintf2(("Icon : %d", rdir->wNameOrdinal));
295 dprintf2(("Width : %d", (int)rdir->bWidth));
296 dprintf2(("Height : %d", (int)rdir->bHeight));
297 dprintf2(("Colors : %d", (int)rdir->bColorCount));
298 dprintf2(("Bits : %d", rdir->wBitCount));
299 dprintf2(("ResBytes: %d", rdir->lBytesInRes));
300 hRes = FindResourceA(hInstance,
301 (LPCSTR)rdir->wNameOrdinal, (LPSTR)NTRT_ICON);
302
303 groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes)),
304 SizeofResource(hInstance, hRes));
305 //add centered icon if size is 32x32
306 if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4)
307 {
308 groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes)),
309 SizeofResource(hInstance, hRes), TRUE);
310 //extra pixels
311 groupsize += (40*8 + 8*32)*rdir->wBitCount/8;
312 nricons++;
313 }
314 nricons++;
315 rdir++;
316 }
317 groupsize = groupsize+nricons*(sizeof(BITMAPARRAYFILEHEADER2) - sizeof(BITMAPFILEHEADER2));
318 bafh = (BITMAPARRAYFILEHEADER2 *)malloc(groupsize);
319 memset(bafh, 0, groupsize);
320 orgbafh = bafh;
321
322 rdir = (ResourceDirectory *)(ihdr + 1);
323 for(i=0;i<ihdr->wCount;i++) {
324 bafh->usType = BFT_BITMAPARRAY;
325 bafh->cbSize = sizeof(BITMAPARRAYFILEHEADER2);
326 bafh->cxDisplay = 0;
327 bafh->cyDisplay = 0;
328 hRes = FindResourceA(hInstance,
329 (LPCSTR)rdir->wNameOrdinal, (LPSTR)NTRT_ICON);
330 if(hRes == NULL) {
331 dprintf(("Can't find icon!"));
332 rdir++;
333 continue;
334 }
335 iconhdr = (WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes));
336 os2icon = ConvertIcon(iconhdr, SizeofResource(hInstance, hRes), &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2));
337 if(os2icon == NULL) {
338 dprintf(("Can't convert icon!"));
339 rdir++;
340 continue;
341 }
342
343 if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4)
344 {
345 //add 40x40 icon by centering 32x32 icon in 40x40 grid
346 //(resize is really ugly)
347 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
348 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
349 free(os2icon);
350
351 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
352
353 os2icon = ConvertIcon(iconhdr, SizeofResource(hInstance, hRes), &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2), TRUE);
354 if(os2icon == NULL) {
355 dprintf(("Can't convert icon!"));
356 rdir++;
357 continue;
358 }
359 }
360
361 if(i != ihdr->wCount -1) {
362 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
363 }
364 else bafh->offNext = 0;
365
366 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
367 free(os2icon);
368
369 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
370
371 rdir++;
372 }
373 *ressize = groupsize;
374 return (void *)orgbafh;
375}
376//******************************************************************************
377//******************************************************************************
378void *WIN32API ConvertIconGroupIndirect(void *lpIconData, DWORD iconsize,
379 DWORD *ressize)
380{
381 ICONDIR *ihdr = (ICONDIR *)lpIconData;
382 ICONDIRENTRY *rdir = (ICONDIRENTRY *)(ihdr + 1);
383 int i, groupsize = 0, os2iconsize;
384 BITMAPARRAYFILEHEADER2 *bafh, *orgbafh;
385 WINBITMAPINFOHEADER *iconhdr;
386 void *os2icon;
387 int nricons = 0;
388 void *winicon;
389
390 dprintf(("Icon Group type :%d", ihdr->idType));
391 dprintf(("Icon Group count:%d", ihdr->idCount));
392 for(i=0;i<ihdr->idCount;i++) {
393 dprintf2(("Icon : %x", rdir->dwImageOffset));
394 dprintf2(("Width : %d", (int)rdir->bWidth));
395 dprintf2(("Height : %d", (int)rdir->bHeight));
396 dprintf2(("Colors : %d", (int)rdir->bColorCount));
397 dprintf2(("Bits : %d", rdir->wBitCount));
398 dprintf2(("ResBytes: %d", rdir->dwBytesInRes));
399
400 winicon = (char *)lpIconData + rdir->dwImageOffset;
401 groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)winicon,
402 rdir->dwBytesInRes);
403 //add centered icon if size is 32x32
404 if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4)
405 {
406 groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)winicon,
407 rdir->dwBytesInRes, TRUE);
408 //extra pixels
409 groupsize += (40*8 + 8*32)*rdir->wBitCount/8;
410 nricons++;
411 }
412 nricons++;
413 rdir++;
414 }
415 groupsize = groupsize+nricons*(sizeof(BITMAPARRAYFILEHEADER2) - sizeof(BITMAPFILEHEADER2));
416 bafh = (BITMAPARRAYFILEHEADER2 *)malloc(groupsize);
417 memset(bafh, 0, groupsize);
418 orgbafh = bafh;
419
420 rdir = (ICONDIRENTRY *)(ihdr + 1);
421 for(i=0;i<ihdr->idCount;i++) {
422 bafh->usType = BFT_BITMAPARRAY;
423 bafh->cbSize = sizeof(BITMAPARRAYFILEHEADER2);
424 bafh->cxDisplay = 0;
425 bafh->cyDisplay = 0;
426
427 winicon = (char *)lpIconData + rdir->dwImageOffset;
428 iconhdr = (WINBITMAPINFOHEADER *)winicon;
429
430 os2icon = ConvertIcon(iconhdr, rdir->dwBytesInRes, &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2));
431 if(os2icon == NULL) {
432 dprintf(("Can't convert icon!"));
433 rdir++;
434 continue;
435 }
436
437 if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4)
438 {
439 //add 40x40 icon by centering 32x32 icon in 40x40 grid
440 //(resize is really ugly)
441 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
442 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
443 free(os2icon);
444
445 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
446
447 os2icon = ConvertIcon(iconhdr, rdir->dwBytesInRes, &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2), TRUE);
448 if(os2icon == NULL) {
449 dprintf(("Can't convert icon!"));
450 rdir++;
451 continue;
452 }
453 }
454
455 if(i != ihdr->idCount -1) {
456 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
457 }
458 else bafh->offNext = 0;
459
460 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
461 free(os2icon);
462
463 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
464
465 rdir++;
466 }
467 *ressize = groupsize;
468 return (void *)orgbafh;
469}
470//******************************************************************************
471//******************************************************************************
472
473} // extern "C"
Note: See TracBrowser for help on using the repository browser.