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 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 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 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 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 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 */ 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