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

Last change on this file since 9851 was 9851, checked in by sandervl, 22 years ago

Convert win32 icon file to os2 format when creating a shell link

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