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
ConvertObjectType(WORD wType)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
alloc_gdi_handle(PVOID pvObject,WORD wType,const struct gdi_obj_funcs * funcs)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
free_gdi_handle(HGDIOBJ hobj)59 free_gdi_handle(HGDIOBJ hobj)
60 {
61 /* Should be a client object */
62 return GdiDeleteClientObj(hobj);
63 }
64
65 PVOID
GDI_GetObjPtr(HGDIOBJ hobj,WORD wType)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
GDI_ReleaseObj(HGDIOBJ hobj)100 GDI_ReleaseObj(HGDIOBJ hobj)
101 {
102 /* We don't do any reference-counting */
103 }
104
105 WINEDC*
alloc_dc_ptr(WORD magic)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*
get_dc_ptr(HDC hdc)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
GDI_hdc_using_object(HGDIOBJ hobj,HDC hdc)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
GDI_hdc_not_using_object(HGDIOBJ hobj,HDC hdc)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
bitmap_info_size(const BITMAPINFO * info,WORD coloruse)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
get_brush_bitmap_info(HBRUSH hbr,PBITMAPINFO pbmi,PVOID pvBits,PUINT puUsage)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
SetVirtualResolution(HDC hdc,DWORD cxVirtualDevicePixel,DWORD cyVirtualDevicePixel,DWORD cxVirtualDeviceMm,DWORD cyVirtualDeviceMm)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
DeleteColorSpace(HCOLORSPACE hcs)294 DeleteColorSpace(
295 HCOLORSPACE hcs)
296 {
297 return NtGdiDeleteColorSpace(hcs);
298 }
299 void
300 __cdecl
_assert(const char * exp,const char * file,unsigned line)301 _assert (
302 const char *exp,
303 const char *file,
304 unsigned line)
305 {
306 DbgRaiseAssertionFailure();
307 }
308
309 /******************************************************************************/
310 BOOL
311 WINAPI
METADC_SetD(_In_ HDC hdc,_In_ DWORD dwIn,_In_ USHORT usMF16Id)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
EMFDC_SetD(_In_ PLDC pldc,_In_ DWORD dwIn,_In_ ULONG ulMFId)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
METADC_RosGlueDeleteObject(HGDIOBJ hobj)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
METADC_RosGlueDeleteDC(_In_ HDC hdc)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