1 2 #include <precomp.h> 3 #include "gdi_private.h" 4 #undef SetWorldTransform 5 6 #define NDEBUG 7 #include <debug.h> 8 9 static 10 GDILOOBJTYPE 11 ConvertObjectType( 12 WORD wType) 13 { 14 /* Get the GDI object type */ 15 switch (wType) 16 { 17 case OBJ_PEN: return GDILoObjType_LO_PEN_TYPE; 18 case OBJ_BRUSH: return GDILoObjType_LO_BRUSH_TYPE; 19 case OBJ_DC: return GDILoObjType_LO_DC_TYPE; 20 case OBJ_METADC: return GDILoObjType_LO_METADC16_TYPE; 21 case OBJ_PAL: return GDILoObjType_LO_PALETTE_TYPE; 22 case OBJ_FONT: return GDILoObjType_LO_FONT_TYPE; 23 case OBJ_BITMAP: return GDILoObjType_LO_BITMAP_TYPE; 24 case OBJ_REGION: return GDILoObjType_LO_REGION_TYPE; 25 case OBJ_METAFILE: return GDILoObjType_LO_METAFILE16_TYPE; 26 case OBJ_MEMDC: return GDILoObjType_LO_DC_TYPE; 27 case OBJ_EXTPEN: return GDILoObjType_LO_EXTPEN_TYPE; 28 case OBJ_ENHMETADC: return GDILoObjType_LO_ALTDC_TYPE; 29 case OBJ_ENHMETAFILE: return GDILoObjType_LO_METAFILE_TYPE; 30 case OBJ_COLORSPACE: return GDILoObjType_LO_ICMLCS_TYPE; 31 default: return 0; 32 } 33 } 34 35 HGDIOBJ 36 alloc_gdi_handle( 37 PVOID pvObject, 38 WORD wType, 39 const struct gdi_obj_funcs *funcs) 40 { 41 GDILOOBJTYPE eObjType; 42 43 /* Get the GDI object type */ 44 eObjType = ConvertObjectType(wType); 45 if ((eObjType != GDILoObjType_LO_METAFILE_TYPE) && 46 (eObjType != GDILoObjType_LO_METAFILE16_TYPE) && 47 (eObjType != GDILoObjType_LO_METADC16_TYPE)) 48 { 49 /* This is not supported! */ 50 ASSERT(FALSE); 51 return NULL; 52 } 53 54 /* Insert the client object */ 55 return GdiCreateClientObj(pvObject, eObjType); 56 } 57 58 PVOID 59 free_gdi_handle(HGDIOBJ hobj) 60 { 61 /* Should be a client object */ 62 return GdiDeleteClientObj(hobj); 63 } 64 65 PVOID 66 GDI_GetObjPtr( 67 HGDIOBJ hobj, 68 WORD wType) 69 { 70 GDILOOBJTYPE eObjType; 71 72 /* Check if the object type matches */ 73 eObjType = ConvertObjectType(wType); 74 if ((eObjType == 0) || (GDI_HANDLE_GET_TYPE(hobj) != eObjType)) 75 { 76 return NULL; 77 } 78 79 /* Check if we have an ALTDC */ 80 if (eObjType == GDILoObjType_LO_ALTDC_TYPE) 81 { 82 /* Object is stored as LDC */ 83 return GdiGetLDC(hobj); 84 } 85 86 /* Check for client objects */ 87 if ((eObjType == GDILoObjType_LO_METAFILE_TYPE) || 88 (eObjType == GDILoObjType_LO_METAFILE16_TYPE) || 89 (eObjType == GDILoObjType_LO_METADC16_TYPE)) 90 { 91 return GdiGetClientObjLink(hobj); 92 } 93 94 /* This should never happen! */ 95 ASSERT(FALSE); 96 return NULL; 97 } 98 99 VOID 100 GDI_ReleaseObj(HGDIOBJ hobj) 101 { 102 /* We don't do any reference-counting */ 103 } 104 105 WINEDC* 106 alloc_dc_ptr(WORD magic) 107 { 108 WINEDC* pWineDc; 109 110 /* Allocate the Wine DC */ 111 pWineDc = HeapAlloc(GetProcessHeap(), 0, sizeof(*pWineDc)); 112 if (pWineDc == NULL) 113 { 114 return NULL; 115 } 116 117 ZeroMemory(pWineDc, sizeof(*pWineDc)); 118 pWineDc->hBrush = GetStockObject(WHITE_BRUSH); 119 pWineDc->hPen = GetStockObject(BLACK_PEN); 120 121 if (magic == OBJ_ENHMETADC) 122 { 123 /* We create a metafile DC, but we ignore the reference DC, this is 124 handled by the wine code */ 125 pWineDc->hdc = NtGdiCreateMetafileDC(NULL); 126 if (pWineDc->hdc == NULL) 127 { 128 HeapFree(GetProcessHeap(), 0, pWineDc); 129 return NULL; 130 } 131 132 pWineDc->iType = LDC_EMFLDC; 133 134 /* Set the Wine DC as LDC */ 135 GdiSetLDC(pWineDc->hdc, pWineDc); 136 } 137 else 138 { 139 // nothing else supported! 140 ASSERT(FALSE); 141 } 142 143 return pWineDc; 144 } 145 146 WINEDC* 147 get_dc_ptr(HDC hdc) 148 { 149 /* Check for EMF DC */ 150 if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE) 151 { 152 /* The Wine DC is stored as the LDC */ 153 return (WINEDC*)GdiGetLDC(hdc); 154 } 155 156 /* Check for METADC16 */ 157 if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) 158 { 159 return GdiGetClientObjLink(hdc); 160 } 161 162 return NULL; 163 } 164 165 VOID 166 GDI_hdc_using_object( 167 HGDIOBJ hobj, 168 HDC hdc) 169 { 170 /* Record that we have an object in use by a METADC. We simply link the 171 object to the HDC that we use. Wine API does not give us a way to 172 respond to failure, so we silently ignore it */ 173 if (!GdiCreateClientObjLink(hobj, hdc)) 174 { 175 /* Ignore failure, and return */ 176 DPRINT1("Failed to create link for selected METADC object.\n"); 177 return; 178 } 179 } 180 181 VOID 182 GDI_hdc_not_using_object( 183 HGDIOBJ hobj, 184 HDC hdc) 185 { 186 HDC hdcLink; 187 188 /* Remove the HDC link for the object */ 189 hdcLink = GdiRemoveClientObjLink(hobj); 190 ASSERT(hdcLink == hdc); 191 } 192 193 /*********************************************************************** 194 * bitmap_info_size 195 * 196 * Return the size of the bitmap info structure including color table. 197 */ 198 int 199 bitmap_info_size( 200 const BITMAPINFO * info, 201 WORD coloruse) 202 { 203 unsigned int colors, size, masks = 0; 204 205 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) 206 { 207 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info; 208 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0; 209 return sizeof(BITMAPCOREHEADER) + colors * 210 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD)); 211 } 212 else /* assume BITMAPINFOHEADER */ 213 { 214 if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 ); 215 else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount; 216 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3; 217 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ); 218 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); 219 } 220 } 221 222 BOOL 223 get_brush_bitmap_info( 224 HBRUSH hbr, 225 PBITMAPINFO pbmi, 226 PVOID pvBits, 227 PUINT puUsage) 228 { 229 HBITMAP hbmp; 230 HDC hdc; 231 PVOID Bits; 232 233 /* Call win32k to get the bitmap handle and color usage */ 234 hbmp = NtGdiGetObjectBitmapHandle(hbr, puUsage); 235 if (hbmp == NULL) 236 return FALSE; 237 238 hdc = GetDC(NULL); 239 if (hdc == NULL) 240 return FALSE; 241 242 /* Initialize the BITMAPINFO */ 243 ZeroMemory(pbmi, sizeof(*pbmi)); 244 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 245 246 /* Retrieve information about the bitmap */ 247 if (!GetDIBits(hdc, hbmp, 0, 0, NULL, pbmi, *puUsage)) 248 return FALSE; 249 250 if (pvBits) 251 { 252 /* Now allocate a buffer for the bits */ 253 Bits = HeapAlloc(GetProcessHeap(), 0, pbmi->bmiHeader.biSizeImage); 254 if (Bits == NULL) 255 return FALSE; 256 257 /* Retrieve the bitmap bits */ 258 if (!GetDIBits(hdc, hbmp, 0, pbmi->bmiHeader.biHeight, Bits, pbmi, *puUsage)) 259 { 260 HeapFree(GetProcessHeap(), 0, Bits); 261 return FALSE; 262 } 263 264 CopyMemory( pvBits, Bits, pbmi->bmiHeader.biSizeImage ); 265 266 } 267 268 /* GetDIBits doesn't set biClrUsed, but wine code needs it, so we set it */ 269 if (pbmi->bmiHeader.biBitCount <= 8) 270 { 271 pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount; 272 } 273 return TRUE; 274 } 275 276 BOOL 277 WINAPI 278 SetVirtualResolution( 279 HDC hdc, 280 DWORD cxVirtualDevicePixel, 281 DWORD cyVirtualDevicePixel, 282 DWORD cxVirtualDeviceMm, 283 DWORD cyVirtualDeviceMm) 284 { 285 return NtGdiSetVirtualResolution(hdc, 286 cxVirtualDevicePixel, 287 cyVirtualDevicePixel, 288 cxVirtualDeviceMm, 289 cyVirtualDeviceMm); 290 } 291 292 BOOL 293 WINAPI 294 DeleteColorSpace( 295 HCOLORSPACE hcs) 296 { 297 return NtGdiDeleteColorSpace(hcs); 298 } 299 void 300 __cdecl 301 _assert ( 302 const char *exp, 303 const char *file, 304 unsigned line) 305 { 306 DbgRaiseAssertionFailure(); 307 } 308 309 /******************************************************************************/ 310 BOOL 311 WINAPI 312 METADC_SetD( 313 _In_ HDC hdc, 314 _In_ DWORD dwIn, 315 _In_ USHORT usMF16Id 316 ) 317 { 318 switch(usMF16Id) 319 { 320 case META_SETMAPMODE: 321 return METADC_SetMapMode(hdc, dwIn); 322 case META_SETRELABS: 323 return METADC_SetRelAbs(hdc, dwIn); 324 default: 325 return FALSE; 326 } 327 } 328 329 BOOL 330 WINAPI 331 EMFDC_SetD( 332 _In_ PLDC pldc, 333 _In_ DWORD dwIn, 334 _In_ ULONG ulMFId) 335 { 336 switch(ulMFId) 337 { 338 case EMR_SETMAPMODE: 339 return EMFDC_SetMapMode( pldc, dwIn); 340 case EMR_SETARCDIRECTION: 341 return EMFDC_SetArcDirection( pldc, dwIn); 342 default: 343 return FALSE; 344 } 345 } 346 347 extern void METADC_DeleteObject( HDC hdc, HGDIOBJ obj ); 348 extern void emfdc_delete_object( HDC hdc, HGDIOBJ obj ); 349 350 VOID 351 WINAPI 352 METADC_RosGlueDeleteObject(HGDIOBJ hobj) 353 { 354 GDILOOBJTYPE eObjectType; 355 HDC hdc; 356 357 /* Check for one of the types we actually handle here */ 358 eObjectType = GDI_HANDLE_GET_TYPE(hobj); 359 if ((eObjectType != GDILoObjType_LO_BRUSH_TYPE) && 360 (eObjectType != GDILoObjType_LO_PEN_TYPE) && 361 (eObjectType != GDILoObjType_LO_EXTPEN_TYPE) && 362 (eObjectType != GDILoObjType_LO_PALETTE_TYPE) && 363 (eObjectType != GDILoObjType_LO_FONT_TYPE)) 364 { 365 return; 366 } 367 368 /* Check if we have a client object link and remove it if it was found. 369 The link is the HDC that the object was selected into. */ 370 hdc = GdiRemoveClientObjLink(hobj); 371 if (hdc == NULL) 372 { 373 DPRINT1("the link was not found\n"); 374 /* The link was not found, so we are not handling this object here */ 375 return; 376 } 377 378 if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE ) METADC_DeleteObject( hdc, hobj ); 379 380 if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE ) 381 { 382 LDC* pWineDc = GdiGetLDC(hdc); 383 if ( pWineDc ) 384 { 385 emfdc_delete_object( hdc, hobj ); 386 } 387 } 388 } 389 390 BOOL 391 WINAPI 392 METADC_RosGlueDeleteDC( 393 _In_ HDC hdc) 394 { 395 LDC* pWineDc = NULL; 396 397 if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE ) 398 { 399 return METADC_DeleteDC(hdc); 400 } 401 402 if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE ) 403 { 404 pWineDc = GdiGetLDC(hdc); 405 406 if ( pWineDc ) 407 { 408 // Handle Printer LDC 409 if (pWineDc->iType != LDC_EMFLDC) 410 { 411 //return IntDeleteDC(hdc); 412 } 413 414 EMFDC_DeleteDC( pWineDc ); 415 416 /* Get rid of the LDC */ 417 ASSERT(GdiGetLDC(pWineDc->hDC) == pWineDc); 418 GdiSetLDC(pWineDc->hDC, NULL); 419 420 /* Free the Wine DC */ 421 HeapFree(GetProcessHeap(), 0, pWineDc); 422 } 423 } 424 425 return NtGdiDeleteObjectApp(hdc); 426 } 427 428