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

Last change on this file since 6503 was 6503, checked in by sandervl, 24 years ago

add 40x40 icon when converting windows icons

File size: 13.2 KB
Line 
1/* $Id: icon.cpp,v 1.13 2001-08-09 15:02:11 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 linesize = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
200 q = (char *)rgb + orgcolorsize;
201 for (i = 0; i < bmpHdr->biHeight/2; i++) {
202 memcpy (pAnd, q, linesize);
203 pAnd += linesize;
204 q += linesize;
205
206 memcpy (pXor, q, linesize);
207 pXor += linesize;
208 q += linesize;
209 }
210 }
211 else {
212 linesizesrc = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
213 linesizedest = DIB_GetDIBWidthBytes(40, 1);
214
215 src = (BYTE *)rgb + orgcolorsize;
216 dest = (BYTE *)pAnd + 4*linesizedest; //skip 4 lines
217 memset((char *)pAnd, 0xFF, bwsize);
218 for (i = 0; i < bmpHdr->biHeight/2; i++) {
219 for(int j=0;j<linesizesrc;j++) {
220 //must skip 4 pixels (4 bits)
221 dest[j] = (dest[j] & 0xF0) | ((src[j] >> 4));
222 dest[j+1] = (dest[j+1] & 0x0F) | ((src[j] & 0xF) << 4);
223 }
224 dest += linesizedest;
225 src += linesizesrc;
226 }
227 memset (pXor, 0, bwsize);
228 }
229 linesizesrc = DIB_GetDIBWidthBytes(32, bmpHdr->biBitCount);
230 linesizedest = DIB_GetDIBWidthBytes(40, bmpHdr->biBitCount);
231 int skipsize = (4*bmpHdr->biBitCount)/8; //must skip 4 pixels
232 src = (BYTE *)rgb;
233 dest = (BYTE *)os2rgb+2*bwsize + 4*linesizedest; //skip 4 rows
234
235 for (i = 0; i < 32; i++) {
236 memcpy(dest+skipsize, src, linesizesrc);
237 dest += linesizedest;
238 src += linesizesrc;
239 }
240 }
241 else {
242 pXor = (char *)os2rgb;
243 pAnd = (char *)os2rgb + bwsize;
244
245 if ((size - (bmpHdr->biSize + rgbsize + colorsize + bwsize)) == bwsize)
246 {//this means an AND and XOR mask is present (interleaved; and/xor)
247 char *q;
248 int i, linesize;
249
250 linesize = DIB_GetDIBWidthBytes(bmpHdr->biWidth, 1);
251 q = (char *)rgb + orgcolorsize;
252 for (i = 0; i < bmpHdr->biHeight/2; i++) {
253 memcpy (pAnd, q, linesize);
254 pAnd += linesize;
255 q += linesize;
256
257 memcpy (pXor, q, linesize);
258 pXor += linesize;
259 q += linesize;
260 }
261 }
262 else {
263 memcpy (pAnd, (char *)rgb + colorsize, bwsize);
264 memset (pXor, 0, bwsize);
265 }
266 memcpy((char *)os2rgb+2*bwsize, (char *)rgb, colorsize);
267 }
268 *os2size = iconsize;
269 return (void *)iconhdr;
270}
271//******************************************************************************
272//******************************************************************************
273void * WIN32API ConvertIconGroup(void *hdr, HINSTANCE hInstance, DWORD *ressize)
274{
275 IconHeader *ihdr = (IconHeader *)hdr;
276 ResourceDirectory *rdir = (ResourceDirectory *)(ihdr + 1);
277 int i, groupsize = 0, os2iconsize;
278 BITMAPARRAYFILEHEADER2 *bafh, *orgbafh;
279 WINBITMAPINFOHEADER *iconhdr;
280 void *os2icon;
281 HRSRC hRes;
282 int nricons = 0;
283
284 dprintf(("Icon Group type :%d", ihdr->wType));
285 dprintf(("Icon Group count:%d", ihdr->wCount));
286 for(i=0;i<ihdr->wCount;i++) {
287 dprintf2(("Icon : %d", rdir->wNameOrdinal));
288 dprintf2(("Width : %d", (int)rdir->bWidth));
289 dprintf2(("Height : %d", (int)rdir->bHeight));
290 dprintf2(("Colors : %d", (int)rdir->bColorCount));
291 dprintf2(("Bits : %d", rdir->wBitCount));
292 dprintf2(("ResBytes: %d", rdir->lBytesInRes));
293 hRes = FindResourceA(hInstance,
294 (LPCSTR)rdir->wNameOrdinal, (LPSTR)NTRT_ICON);
295
296 groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes)),
297 SizeofResource(hInstance, hRes));
298 if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4) {
299 groupsize += QueryConvertedIconSize((WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes)),
300 SizeofResource(hInstance, hRes), TRUE);
301 nricons++;
302 }
303 nricons++;
304 rdir++;
305 }
306 groupsize = groupsize+nricons*(sizeof(BITMAPARRAYFILEHEADER2) - sizeof(BITMAPFILEHEADER2));
307 bafh = (BITMAPARRAYFILEHEADER2 *)malloc(groupsize);
308 memset(bafh, 0, groupsize);
309 orgbafh = bafh;
310
311 rdir = (ResourceDirectory *)(ihdr + 1);
312 for(i=0;i<ihdr->wCount;i++) {
313 bafh->usType = BFT_BITMAPARRAY;
314 bafh->cbSize = sizeof(BITMAPARRAYFILEHEADER2);
315 bafh->cxDisplay = 0;
316 bafh->cyDisplay = 0;
317 hRes = FindResourceA(hInstance,
318 (LPCSTR)rdir->wNameOrdinal, (LPSTR)NTRT_ICON);
319 if(hRes == NULL) {
320 dprintf(("Can't find icon!"));
321 rdir++;
322 continue;
323 }
324 iconhdr = (WINBITMAPINFOHEADER *)LockResource(LoadResource(hInstance, hRes));
325 os2icon = ConvertIcon(iconhdr, SizeofResource(hInstance, hRes), &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2));
326 if(os2icon == NULL) {
327 dprintf(("Can't convert icon!"));
328 rdir++;
329 continue;
330 }
331
332 if(rdir->bWidth == 32 && rdir->bHeight == 32 && rdir->wBitCount >= 4)
333 {
334 //add 40x40 icon by centering 32x32 icon in 40x40 grid
335 //(resize is really ugly)
336 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
337 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
338 free(os2icon);
339
340 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
341
342 os2icon = ConvertIcon(iconhdr, SizeofResource(hInstance, hRes), &os2iconsize, (ULONG)bafh - (ULONG)orgbafh + sizeof(BITMAPARRAYFILEHEADER2)-sizeof(BITMAPFILEHEADER2), TRUE);
343 if(os2icon == NULL) {
344 dprintf(("Can't convert icon!"));
345 rdir++;
346 continue;
347 }
348 }
349
350 if(i != ihdr->wCount -1) {
351 bafh->offNext = (ULONG)&bafh->bfh2 - (ULONG)orgbafh + os2iconsize;
352 }
353 else bafh->offNext = 0;
354
355 memcpy((char *)&bafh->bfh2, os2icon, os2iconsize);
356 free(os2icon);
357
358 bafh = (BITMAPARRAYFILEHEADER2 *)((ULONG)&bafh->bfh2 + os2iconsize);
359
360 rdir++;
361 }
362 *ressize = groupsize;
363 return (void *)orgbafh;
364}
365//******************************************************************************
366//******************************************************************************
Note: See TracBrowser for help on using the repository browser.