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