734d5df54c6bd89d5027f772792fe6ad13b0592c
[reactos.git] / reactos / dll / win32 / gdi32 / objects / utils.c
1 #include "precomp.h"
2
3 /**
4 * @name CalculateColorTableSize
5 *
6 * Internal routine to calculate the number of color table entries.
7 *
8 * @param BitmapInfoHeader
9 * Input bitmap information header, can be any version of
10 * BITMAPINFOHEADER or BITMAPCOREHEADER.
11 *
12 * @param ColorSpec
13 * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
14 * or DIB_RGB_COLORS). On successful return this value is normalized
15 * according to the bitmap info.
16 *
17 * @param ColorTableSize
18 * On successful return this variable is filled with number of
19 * entries in color table for the image with specified parameters.
20 *
21 * @return
22 * TRUE if the input values together form a valid image, FALSE otherwise.
23 */
24
25 BOOL WINAPI
26 CalculateColorTableSize(
27 CONST BITMAPINFOHEADER *BitmapInfoHeader,
28 UINT *ColorSpec,
29 UINT *ColorTableSize)
30 {
31 WORD BitCount;
32 DWORD ClrUsed;
33 DWORD Compression;
34
35 /*
36 * At first get some basic parameters from the passed BitmapInfoHeader
37 * structure. It can have one of the following formats:
38 * - BITMAPCOREHEADER (the oldest one with totally different layout
39 * from the others)
40 * - BITMAPINFOHEADER (the standard and most common header)
41 * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
42 * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
43 */
44
45 if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
46 {
47 BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
48 ClrUsed = 0;
49 Compression = BI_RGB;
50 }
51 else
52 {
53 BitCount = BitmapInfoHeader->biBitCount;
54 ClrUsed = BitmapInfoHeader->biClrUsed;
55 Compression = BitmapInfoHeader->biCompression;
56 }
57
58 switch (Compression)
59 {
60 case BI_BITFIELDS:
61 if (*ColorSpec == DIB_PAL_COLORS)
62 *ColorSpec = DIB_RGB_COLORS;
63
64 if (BitCount != 16 && BitCount != 32)
65 return FALSE;
66
67 /*
68 * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
69 * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
70 * For BITMAPINFOHEADER the color masks are stored in the palette.
71 */
72
73 if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
74 *ColorTableSize = 0;
75 else
76 *ColorTableSize = 3;
77
78 return TRUE;
79
80 case BI_RGB:
81 switch (BitCount)
82 {
83 case 1:
84 *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
85 return TRUE;
86
87 case 4:
88 *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
89 return TRUE;
90
91 case 8:
92 *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
93 return TRUE;
94
95 default:
96 if (*ColorSpec == DIB_PAL_COLORS)
97 *ColorSpec = DIB_RGB_COLORS;
98 if (BitCount != 16 && BitCount != 24 && BitCount != 32)
99 return FALSE;
100 *ColorTableSize = ClrUsed;
101 return TRUE;
102 }
103
104 case BI_RLE4:
105 if (BitCount == 4)
106 {
107 *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
108 return TRUE;
109 }
110 return FALSE;
111
112 case BI_RLE8:
113 if (BitCount == 8)
114 {
115 *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
116 return TRUE;
117 }
118 return FALSE;
119
120 case BI_JPEG:
121 case BI_PNG:
122 *ColorTableSize = ClrUsed;
123 return TRUE;
124
125 default:
126 return FALSE;
127 }
128 }
129
130 /**
131 * @name ConvertBitmapInfo
132 *
133 * Internal routine to convert a user-passed BITMAPINFO structure into
134 * unified BITMAPINFO structure.
135 *
136 * @param BitmapInfo
137 * Input bitmap info, can be any version of BITMAPINFO or
138 * BITMAPCOREINFO.
139 * @param ColorSpec
140 * Specifies whether the bmiColors member of the BITMAPINFO structure
141 * contains a valid color table and, if so, whether the entries in
142 * this color table contain explicit red, green, blue (DIB_RGB_COLORS)
143 * values or palette indexes (DIB_PAL_COLORS).
144 * @param BitmapInfoSize
145 * On successful return contains the size of the returned BITMAPINFO
146 * structure. If FollowedByData is TRUE the size includes the number
147 * of bytes occupied by the image data.
148 * @param FollowedByData
149 * Specifies if the BITMAPINFO header is immediately followed
150 * by the actual bitmap data (eg. as passed to CreateDIBPatternBrush).
151 *
152 * @return
153 * Either the original BitmapInfo or newly allocated structure is
154 * returned. For the later case the caller is responsible for freeing the
155 * memory using RtlFreeHeap with the current process heap.
156 *
157 * @example
158 * PBITMAPINFO NewBitmapInfo;
159 * UINT NewBitmapInfoSize;
160 *
161 * NewBitmapInfo = ConvertBitmapInfo(OldBitmapInfo, DIB_RGB_COLORS,
162 * &NewBitmapInfoSize, FALSE);
163 * if (NewBitmapInfo)
164 * {
165 * <do something with the bitmap info>
166 * if (NewBitmapInfo != OldBitmapInfo)
167 * RtlFreeHeap(RtlGetProcessHeap(), 0, NewBitmapInfo);
168 * }
169 */
170
171 LPBITMAPINFO WINAPI
172 ConvertBitmapInfo(
173 CONST BITMAPINFO *BitmapInfo,
174 UINT ColorSpec,
175 UINT *BitmapInfoSize,
176 BOOL FollowedByData)
177 {
178 LPBITMAPINFO NewBitmapInfo = (LPBITMAPINFO)BitmapInfo;
179 LPBITMAPCOREINFO CoreBitmapInfo = (LPBITMAPCOREINFO)BitmapInfo;
180 DWORD Size = 0;
181 ULONG DataSize = 0;
182 UINT PaletteEntryCount = 0;
183
184 /*
185 * At first check if the passed BitmapInfo structure has valid size. It
186 * can have one of these headers: BITMAPCOREHEADER, BITMAPINFOHEADER,
187 * BITMAPV4HEADER or BITMAPV5HEADER (see CalculateColorTableSize for
188 * description).
189 */
190
191 if ( !BitmapInfo ||
192 (BitmapInfo->bmiHeader.biSize != sizeof(BITMAPCOREHEADER) &&
193 (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER) ||
194 BitmapInfo->bmiHeader.biSize > sizeof(BITMAPV5HEADER))))
195 {
196 return NULL;
197 }
198
199 /*
200 * Now calculate the color table size. Also if the bitmap info contains
201 * invalid color information it's rejected here.
202 */
203
204 if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, &ColorSpec,
205 &PaletteEntryCount))
206 {
207 return NULL;
208 }
209
210 /*
211 * Calculate the size of image data if applicable. We must be careful
212 * to do proper aligning on line ends.
213 */
214
215 if (FollowedByData)
216 {
217 DataSize = DIB_BitmapBitsSize((PBITMAPINFO)BitmapInfo );
218 }
219
220 /*
221 * If BitmapInfo was originally BITMAPCOREINFO then we need to convert
222 * it to the standard BITMAPINFO layout.
223 */
224
225 if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
226 {
227 Size = sizeof(BITMAPINFOHEADER);
228 if (ColorSpec == DIB_RGB_COLORS)
229 Size += PaletteEntryCount * sizeof(RGBQUAD);
230 else
231 Size += PaletteEntryCount * sizeof(USHORT);
232 Size += DataSize;
233
234 NewBitmapInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
235 if (NewBitmapInfo == NULL)
236 {
237 return NULL;
238 }
239
240 NewBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
241 NewBitmapInfo->bmiHeader.biWidth = CoreBitmapInfo->bmciHeader.bcWidth;
242 NewBitmapInfo->bmiHeader.biHeight = CoreBitmapInfo->bmciHeader.bcHeight;
243 NewBitmapInfo->bmiHeader.biPlanes = CoreBitmapInfo->bmciHeader.bcPlanes;
244 NewBitmapInfo->bmiHeader.biBitCount = CoreBitmapInfo->bmciHeader.bcBitCount;
245 NewBitmapInfo->bmiHeader.biCompression = BI_RGB;
246 NewBitmapInfo->bmiHeader.biSizeImage = 0;
247 NewBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
248 NewBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
249 NewBitmapInfo->bmiHeader.biClrUsed = 0;
250 NewBitmapInfo->bmiHeader.biClrImportant = 0;
251
252 if (PaletteEntryCount != 0)
253 {
254 if (ColorSpec == DIB_RGB_COLORS)
255 {
256 ULONG Index;
257
258 for (Index = 0; Index < PaletteEntryCount; Index++)
259 {
260 NewBitmapInfo->bmiColors[Index].rgbRed =
261 CoreBitmapInfo->bmciColors[Index].rgbtRed;
262 NewBitmapInfo->bmiColors[Index].rgbGreen =
263 CoreBitmapInfo->bmciColors[Index].rgbtGreen;
264 NewBitmapInfo->bmiColors[Index].rgbBlue =
265 CoreBitmapInfo->bmciColors[Index].rgbtBlue;
266 NewBitmapInfo->bmiColors[Index].rgbReserved = 0;
267 }
268 }
269 else
270 {
271 RtlCopyMemory(NewBitmapInfo->bmiColors,
272 CoreBitmapInfo->bmciColors,
273 PaletteEntryCount * sizeof(USHORT));
274 }
275 }
276
277 if (FollowedByData)
278 {
279 ULONG_PTR NewDataPtr, OldDataPtr;
280
281 if (ColorSpec == DIB_RGB_COLORS)
282 {
283 NewDataPtr = (ULONG_PTR)(NewBitmapInfo->bmiColors +
284 PaletteEntryCount);
285 OldDataPtr = (ULONG_PTR)(CoreBitmapInfo->bmciColors +
286 PaletteEntryCount);
287 }
288 else
289 {
290 NewDataPtr = (ULONG_PTR)(NewBitmapInfo->bmiColors) +
291 PaletteEntryCount * sizeof(USHORT);
292 OldDataPtr = (ULONG_PTR)(CoreBitmapInfo->bmciColors) +
293 PaletteEntryCount * sizeof(USHORT);
294 }
295
296 RtlCopyMemory((PVOID)NewDataPtr, (PVOID)OldDataPtr, DataSize);
297 }
298 }
299
300 Size = NewBitmapInfo->bmiHeader.biSize;
301 if (ColorSpec == DIB_RGB_COLORS)
302 Size += PaletteEntryCount * sizeof(RGBQUAD);
303 else
304 Size += PaletteEntryCount * sizeof(USHORT);
305 Size += DataSize;
306 *BitmapInfoSize = Size;
307
308 return NewBitmapInfo;
309 }
310
311 VOID
312 WINAPI
313 LogFontA2W(LPLOGFONTW pW, CONST LOGFONTA *pA)
314 {
315 #define COPYS(f,len) MultiByteToWideChar ( CP_THREAD_ACP, 0, pA->f, len, pW->f, len )
316 #define COPYN(f) pW->f = pA->f
317
318 COPYN(lfHeight);
319 COPYN(lfWidth);
320 COPYN(lfEscapement);
321 COPYN(lfOrientation);
322 COPYN(lfWeight);
323 COPYN(lfItalic);
324 COPYN(lfUnderline);
325 COPYN(lfStrikeOut);
326 COPYN(lfCharSet);
327 COPYN(lfOutPrecision);
328 COPYN(lfClipPrecision);
329 COPYN(lfQuality);
330 COPYN(lfPitchAndFamily);
331 COPYS(lfFaceName,LF_FACESIZE);
332 pW->lfFaceName[LF_FACESIZE - 1] = '\0';
333
334 #undef COPYN
335 #undef COPYS
336 }
337
338 VOID
339 WINAPI
340 LogFontW2A(LPLOGFONTA pA, CONST LOGFONTW *pW)
341 {
342 #define COPYS(f,len) WideCharToMultiByte ( CP_THREAD_ACP, 0, pW->f, len, pA->f, len, NULL, NULL )
343 #define COPYN(f) pA->f = pW->f
344
345 COPYN(lfHeight);
346 COPYN(lfWidth);
347 COPYN(lfEscapement);
348 COPYN(lfOrientation);
349 COPYN(lfWeight);
350 COPYN(lfItalic);
351 COPYN(lfUnderline);
352 COPYN(lfStrikeOut);
353 COPYN(lfCharSet);
354 COPYN(lfOutPrecision);
355 COPYN(lfClipPrecision);
356 COPYN(lfQuality);
357 COPYN(lfPitchAndFamily);
358 COPYS(lfFaceName,LF_FACESIZE);
359 pA->lfFaceName[LF_FACESIZE - 1] = '\0';
360
361 #undef COPYN
362 #undef COPYS
363 }
364
365 VOID
366 WINAPI
367 EnumLogFontExW2A( LPENUMLOGFONTEXA fontA, CONST ENUMLOGFONTEXW *fontW )
368 {
369 LogFontW2A( (LPLOGFONTA)fontA, (CONST LOGFONTW *)fontW );
370
371 WideCharToMultiByte( CP_THREAD_ACP, 0, fontW->elfFullName, -1,
372 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
373 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
374 WideCharToMultiByte( CP_THREAD_ACP, 0, fontW->elfStyle, -1,
375 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
376 fontA->elfStyle[LF_FACESIZE-1] = '\0';
377 WideCharToMultiByte( CP_THREAD_ACP, 0, fontW->elfScript, -1,
378 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
379 fontA->elfScript[LF_FACESIZE-1] = '\0';
380 }
381