1 /*
2 * GDI Device Context functions
3 *
4 * Copyright 1993 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winreg.h"
31 #include "winternl.h"
32 #include "winerror.h"
33 #include "wownt32.h"
34 #include "gdi_private.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(dc);
39
40 static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
41
42 static BOOL DC_DeleteObject( HGDIOBJ handle );
43
44 static const struct gdi_obj_funcs dc_funcs =
45 {
46 NULL, /* pSelectObject */
47 NULL, /* pGetObjectA */
48 NULL, /* pGetObjectW */
49 NULL, /* pUnrealizeObject */
50 DC_DeleteObject /* pDeleteObject */
51 };
52
53
54 static inline DC *get_dc_obj( HDC hdc )
55 {
56 DC *dc = GDI_GetObjPtr( hdc, 0 );
57 if (!dc) return NULL;
58
59 if ((dc->header.type != OBJ_DC) &&
60 (dc->header.type != OBJ_MEMDC) &&
61 (dc->header.type != OBJ_METADC) &&
62 (dc->header.type != OBJ_ENHMETADC))
63 {
64 GDI_ReleaseObj( hdc );
65 SetLastError( ERROR_INVALID_HANDLE );
66 dc = NULL;
67 }
68 return dc;
69 }
70
71
72 /***********************************************************************
73 * alloc_dc_ptr
74 */
75 DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic )
76 {
77 DC *dc;
78
79 if (!(dc = HeapAlloc( GetProcessHeap(), 0, sizeof(*dc) ))) return NULL;
80
81 dc->funcs = funcs;
82 dc->physDev = NULL;
83 dc->thread = GetCurrentThreadId();
84 dc->refcount = 1;
85 dc->dirty = 0;
86 dc->saveLevel = 0;
87 dc->saved_dc = 0;
88 dc->dwHookData = 0;
89 dc->hookProc = NULL;
90 dc->hookThunk = NULL;
91 dc->wndOrgX = 0;
92 dc->wndOrgY = 0;
93 dc->wndExtX = 1;
94 dc->wndExtY = 1;
95 dc->vportOrgX = 0;
96 dc->vportOrgY = 0;
97 dc->vportExtX = 1;
98 dc->vportExtY = 1;
99 dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */
100 dc->flags = 0;
101 dc->layout = 0;
102 dc->hClipRgn = 0;
103 dc->hMetaRgn = 0;
104 dc->hMetaClipRgn = 0;
105 dc->hVisRgn = 0;
106 dc->hPen = GDI_inc_ref_count( GetStockObject( BLACK_PEN ));
107 dc->hBrush = GDI_inc_ref_count( GetStockObject( WHITE_BRUSH ));
108 dc->hFont = GDI_inc_ref_count( GetStockObject( SYSTEM_FONT ));
109 dc->hBitmap = 0;
110 dc->hDevice = 0;
111 dc->hPalette = GetStockObject( DEFAULT_PALETTE );
112 dc->gdiFont = 0;
113 dc->ROPmode = R2_COPYPEN;
114 dc->polyFillMode = ALTERNATE;
115 dc->stretchBltMode = BLACKONWHITE;
116 dc->relAbsMode = ABSOLUTE;
117 dc->backgroundMode = OPAQUE;
118 dc->backgroundColor = RGB( 255, 255, 255 );
119 dc->dcBrushColor = RGB( 255, 255, 255 );
120 dc->dcPenColor = RGB( 0, 0, 0 );
121 dc->textColor = RGB( 0, 0, 0 );
122 dc->brushOrgX = 0;
123 dc->brushOrgY = 0;
124 dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP;
125 dc->charExtra = 0;
126 dc->breakExtra = 0;
127 dc->breakRem = 0;
128 dc->MapMode = MM_TEXT;
129 dc->GraphicsMode = GM_COMPATIBLE;
130 dc->pAbortProc = NULL;
131 dc->CursPosX = 0;
132 dc->CursPosY = 0;
133 dc->ArcDirection = AD_COUNTERCLOCKWISE;
134 dc->xformWorld2Wnd.eM11 = 1.0f;
135 dc->xformWorld2Wnd.eM12 = 0.0f;
136 dc->xformWorld2Wnd.eM21 = 0.0f;
137 dc->xformWorld2Wnd.eM22 = 1.0f;
138 dc->xformWorld2Wnd.eDx = 0.0f;
139 dc->xformWorld2Wnd.eDy = 0.0f;
140 dc->xformWorld2Vport = dc->xformWorld2Wnd;
141 dc->xformVport2World = dc->xformWorld2Wnd;
142 dc->vport2WorldValid = TRUE;
143 dc->BoundsRect.left = 0;
144 dc->BoundsRect.top = 0;
145 dc->BoundsRect.right = 0;
146 dc->BoundsRect.bottom = 0;
147 dc->saved_visrgn = NULL;
148 PATH_InitGdiPath(&dc->path);
149
150 if (!(dc->hSelf = alloc_gdi_handle( &dc->header, magic, &dc_funcs )))
151 {
152 HeapFree( GetProcessHeap(), 0, dc );
153 dc = NULL;
154 }
155 return dc;
156 }
157
158
159
160 /***********************************************************************
161 * free_dc_ptr
162 */
163 BOOL free_dc_ptr( DC *dc )
164 {
165 assert( dc->refcount == 1 );
166 if (free_gdi_handle( dc->hSelf ) != dc) return FALSE; /* shouldn't happen */
167 return HeapFree( GetProcessHeap(), 0, dc );
168 }
169
170
171 /***********************************************************************
172 * get_dc_ptr
173 *
174 * Retrieve a DC pointer but release the GDI lock.
175 */
176 DC *get_dc_ptr( HDC hdc )
177 {
178 DC *dc = get_dc_obj( hdc );
179 if (!dc) return NULL;
180
181 if (!InterlockedCompareExchange( &dc->refcount, 1, 0 ))
182 {
183 dc->thread = GetCurrentThreadId();
184 }
185 else if (dc->thread != GetCurrentThreadId())
186 {
187 WARN( "dc %p belongs to thread %04x\n", hdc, dc->thread );
188 GDI_ReleaseObj( hdc );
189 return NULL;
190 }
191 else InterlockedIncrement( &dc->refcount );
192
193 GDI_ReleaseObj( hdc );
194 return dc;
195 }
196
197
198 /***********************************************************************
199 * release_dc_ptr
200 */
201 void release_dc_ptr( DC *dc )
202 {
203 LONG ref;
204
205 dc->thread = 0;
206 ref = InterlockedDecrement( &dc->refcount );
207 assert( ref >= 0 );
208 if (ref) dc->thread = GetCurrentThreadId(); /* we still own it */
209 }
210
211
212 /***********************************************************************
213 * update_dc
214 *
215 * Make sure the DC vis region is up to date.
216 * This function may call up to USER so the GDI lock should _not_
217 * be held when calling it.
218 */
219 void update_dc( DC *dc )
220 {
221 if (InterlockedExchange( &dc->dirty, 0 ) && dc->hookThunk)
222 dc->hookThunk( dc->hSelf, DCHC_INVALIDVISRGN, dc->dwHookData, 0 );
223 }
224
225
226 /***********************************************************************
227 * DC_DeleteObject
228 */
229 static BOOL DC_DeleteObject( HGDIOBJ handle )
230 {
231 return DeleteDC( handle );
232 }
233
234
235 /***********************************************************************
236 * DC_InitDC
237 *
238 * Setup device-specific DC values for a newly created DC.
239 */
240 void DC_InitDC( DC* dc )
241 {
242 if (dc->funcs->pRealizeDefaultPalette) dc->funcs->pRealizeDefaultPalette( dc->physDev );
243 SetTextColor( dc->hSelf, dc->textColor );
244 SetBkColor( dc->hSelf, dc->backgroundColor );
245 SelectObject( dc->hSelf, dc->hPen );
246 SelectObject( dc->hSelf, dc->hBrush );
247 SelectObject( dc->hSelf, dc->hFont );
248 CLIPPING_UpdateGCRegion( dc );
249 }
250
251
252 /***********************************************************************
253 * DC_InvertXform
254 *
255 * Computes the inverse of the transformation xformSrc and stores it to
256 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
257 * is singular.
258 */
259 static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
260 {
261 double determinant;
262
263 determinant = xformSrc->eM11*xformSrc->eM22 -
264 xformSrc->eM12*xformSrc->eM21;
265 if (determinant > -1e-12 && determinant < 1e-12)
266 return FALSE;
267
268 xformDest->eM11 = xformSrc->eM22 / determinant;
269 xformDest->eM12 = -xformSrc->eM12 / determinant;
270 xformDest->eM21 = -xformSrc->eM21 / determinant;
271 xformDest->eM22 = xformSrc->eM11 / determinant;
272 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 -
273 xformSrc->eDy * xformDest->eM21;
274 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 -
275 xformSrc->eDy * xformDest->eM22;
276
277 return TRUE;
278 }
279
280
281 /***********************************************************************
282 * DC_UpdateXforms
283 *
284 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
285 * fields of the specified DC by creating a transformation that
286 * represents the current mapping mode and combining it with the DC's
287 * world transform. This function should be called whenever the
288 * parameters associated with the mapping mode (window and viewport
289 * extents and origins) or the world transform change.
290 */
291 void DC_UpdateXforms( DC *dc )
292 {
293 XFORM xformWnd2Vport, oldworld2vport;
294 double scaleX, scaleY;
295
296 /* Construct a transformation to do the window-to-viewport conversion */
297 scaleX = (double)dc->vportExtX / (double)dc->wndExtX;
298 scaleY = (double)dc->vportExtY / (double)dc->wndExtY;
299 xformWnd2Vport.eM11 = scaleX;
300 xformWnd2Vport.eM12 = 0.0;
301 xformWnd2Vport.eM21 = 0.0;
302 xformWnd2Vport.eM22 = scaleY;
303 xformWnd2Vport.eDx = (double)dc->vportOrgX -
304 scaleX * (double)dc->wndOrgX;
305 xformWnd2Vport.eDy = (double)dc->vportOrgY -
306 scaleY * (double)dc->wndOrgY;
307
308 oldworld2vport = dc->xformWorld2Vport;
309 /* Combine with the world transformation */
310 CombineTransform( &dc->xformWorld2Vport, &dc->xformWorld2Wnd,
311 &xformWnd2Vport );
312
313 /* Create inverse of world-to-viewport transformation */
314 dc->vport2WorldValid = DC_InvertXform( &dc->xformWorld2Vport,
315 &dc->xformVport2World );
316
317 /* Reselect the font and pen back into the dc so that the size
318 gets updated. */
319 if (memcmp(&oldworld2vport, &dc->xformWorld2Vport, sizeof(oldworld2vport)) &&
320 !GdiIsMetaFileDC(dc->hSelf))
321 {
322 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_FONT));
323 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_PEN));
324 }
325 }
326
327
328 /***********************************************************************
329 * get_dc_state (Not a Windows API)
330 */
331 HDC get_dc_state( HDC hdc )
332 {
333 DC * newdc, * dc;
334 HGDIOBJ handle;
335
336 if (!(dc = get_dc_ptr( hdc ))) return 0;
337 if (!(newdc = HeapAlloc( GetProcessHeap(), 0, sizeof(*newdc ))))
338 {
339 release_dc_ptr( dc );
340 return 0;
341 }
342
343 newdc->flags = dc->flags | DC_SAVED;
344 newdc->layout = dc->layout;
345 newdc->hPen = dc->hPen;
346 newdc->hBrush = dc->hBrush;
347 newdc->hFont = dc->hFont;
348 newdc->hBitmap = dc->hBitmap;
349 newdc->hDevice = dc->hDevice;
350 newdc->hPalette = dc->hPalette;
351 newdc->ROPmode = dc->ROPmode;
352 newdc->polyFillMode = dc->polyFillMode;
353 newdc->stretchBltMode = dc->stretchBltMode;
354 newdc->relAbsMode = dc->relAbsMode;
355 newdc->backgroundMode = dc->backgroundMode;
356 newdc->backgroundColor = dc->backgroundColor;
357 newdc->textColor = dc->textColor;
358 newdc->dcBrushColor = dc->dcBrushColor;
359 newdc->dcPenColor = dc->dcPenColor;
360 newdc->brushOrgX = dc->brushOrgX;
361 newdc->brushOrgY = dc->brushOrgY;
362 newdc->textAlign = dc->textAlign;
363 newdc->charExtra = dc->charExtra;
364 newdc->breakExtra = dc->breakExtra;
365 newdc->breakRem = dc->breakRem;
366 newdc->MapMode = dc->MapMode;
367 newdc->GraphicsMode = dc->GraphicsMode;
368 newdc->CursPosX = dc->CursPosX;
369 newdc->CursPosY = dc->CursPosY;
370 newdc->ArcDirection = dc->ArcDirection;
371 newdc->xformWorld2Wnd = dc->xformWorld2Wnd;
372 newdc->xformWorld2Vport = dc->xformWorld2Vport;
373 newdc->xformVport2World = dc->xformVport2World;
374 newdc->vport2WorldValid = dc->vport2WorldValid;
375 newdc->wndOrgX = dc->wndOrgX;
376 newdc->wndOrgY = dc->wndOrgY;
377 newdc->wndExtX = dc->wndExtX;
378 newdc->wndExtY = dc->wndExtY;
379 newdc->vportOrgX = dc->vportOrgX;
380 newdc->vportOrgY = dc->vportOrgY;
381 newdc->vportExtX = dc->vportExtX;
382 newdc->vportExtY = dc->vportExtY;
383 newdc->BoundsRect = dc->BoundsRect;
384 newdc->gdiFont = dc->gdiFont;
385
386 newdc->thread = GetCurrentThreadId();
387 newdc->refcount = 1;
388 newdc->saveLevel = 0;
389 newdc->saved_dc = 0;
390
391 PATH_InitGdiPath( &newdc->path );
392
393 newdc->pAbortProc = NULL;
394 newdc->hookThunk = NULL;
395 newdc->hookProc = 0;
396 newdc->saved_visrgn = NULL;
397
398 if (!(newdc->hSelf = alloc_gdi_handle( &newdc->header, dc->header.type, &dc_funcs )))
399 {
400 HeapFree( GetProcessHeap(), 0, newdc );
401 release_dc_ptr( dc );
402 return 0;
403 }
404 handle = newdc->hSelf;
405 TRACE("(%p): returning %p\n", hdc, handle );
406
407 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
408
409 newdc->hVisRgn = 0;
410 newdc->hClipRgn = 0;
411 newdc->hMetaRgn = 0;
412 newdc->hMetaClipRgn = 0;
413 if (dc->hClipRgn)
414 {
415 newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
416 CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
417 }
418 if (dc->hMetaRgn)
419 {
420 newdc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
421 CombineRgn( newdc->hMetaRgn, dc->hMetaRgn, 0, RGN_COPY );
422 }
423 /* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
424
425 release_dc_ptr( newdc );
426 release_dc_ptr( dc );
427 return handle;
428 }
429
430
431 /***********************************************************************
432 * set_dc_state (Not a Windows API)
433 */
434 void set_dc_state( HDC hdc, HDC hdcs )
435 {
436 DC *dc, *dcs;
437
438 if (!(dc = get_dc_ptr( hdc ))) return;
439 if (!(dcs = get_dc_ptr( hdcs )))
440 {
441 release_dc_ptr( dc );
442 return;
443 }
444 if (!(dcs->flags & DC_SAVED))
445 {
446 release_dc_ptr( dc );
447 release_dc_ptr( dcs );
448 return;
449 }
450 TRACE("%p %p\n", hdc, hdcs );
451
452 update_dc( dc );
453 dc->flags = dcs->flags & ~DC_SAVED;
454 dc->layout = dcs->layout;
455 dc->hDevice = dcs->hDevice;
456 dc->ROPmode = dcs->ROPmode;
457 dc->polyFillMode = dcs->polyFillMode;
458 dc->stretchBltMode = dcs->stretchBltMode;
459 dc->relAbsMode = dcs->relAbsMode;
460 dc->backgroundMode = dcs->backgroundMode;
461 dc->backgroundColor = dcs->backgroundColor;
462 dc->textColor = dcs->textColor;
463 dc->dcBrushColor = dcs->dcBrushColor;
464 dc->dcPenColor = dcs->dcPenColor;
465 dc->brushOrgX = dcs->brushOrgX;
466 dc->brushOrgY = dcs->brushOrgY;
467 dc->textAlign = dcs->textAlign;
468 dc->charExtra = dcs->charExtra;
469 dc->breakExtra = dcs->breakExtra;
470 dc->breakRem = dcs->breakRem;
471 dc->MapMode = dcs->MapMode;
472 dc->GraphicsMode = dcs->GraphicsMode;
473 dc->CursPosX = dcs->CursPosX;
474 dc->CursPosY = dcs->CursPosY;
475 dc->ArcDirection = dcs->ArcDirection;
476 dc->xformWorld2Wnd = dcs->xformWorld2Wnd;
477 dc->xformWorld2Vport = dcs->xformWorld2Vport;
478 dc->xformVport2World = dcs->xformVport2World;
479 dc->vport2WorldValid = dcs->vport2WorldValid;
480 dc->BoundsRect = dcs->BoundsRect;
481
482 dc->wndOrgX = dcs->wndOrgX;
483 dc->wndOrgY = dcs->wndOrgY;
484 dc->wndExtX = dcs->wndExtX;
485 dc->wndExtY = dcs->wndExtY;
486 dc->vportOrgX = dcs->vportOrgX;
487 dc->vportOrgY = dcs->vportOrgY;
488 dc->vportExtX = dcs->vportExtX;
489 dc->vportExtY = dcs->vportExtY;
490
491 if (dcs->hClipRgn)
492 {
493 if (!dc->hClipRgn) dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
494 CombineRgn( dc->hClipRgn, dcs->hClipRgn, 0, RGN_COPY );
495 }
496 else
497 {
498 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
499 dc->hClipRgn = 0;
500 }
501 if (dcs->hMetaRgn)
502 {
503 if (!dc->hMetaRgn) dc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
504 CombineRgn( dc->hMetaRgn, dcs->hMetaRgn, 0, RGN_COPY );
505 }
506 else
507 {
508 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
509 dc->hMetaRgn = 0;
510 }
511 CLIPPING_UpdateGCRegion( dc );
512
513 SelectObject( hdc, dcs->hBitmap );
514 SelectObject( hdc, dcs->hBrush );
515 SelectObject( hdc, dcs->hFont );
516 SelectObject( hdc, dcs->hPen );
517 SetBkColor( hdc, dcs->backgroundColor);
518 SetTextColor( hdc, dcs->textColor);
519 GDISelectPalette( hdc, dcs->hPalette, FALSE );
520 release_dc_ptr( dc );
521 release_dc_ptr( dcs );
522 }
523
524
525 /***********************************************************************
526 * SaveDC (GDI32.@)
527 */
528 INT WINAPI SaveDC( HDC hdc )
529 {
530 HDC hdcs;
531 DC * dc, * dcs;
532 INT ret;
533
534 dc = get_dc_ptr( hdc );
535 if (!dc) return 0;
536
537 if(dc->funcs->pSaveDC)
538 {
539 ret = dc->funcs->pSaveDC( dc->physDev );
540 if(ret)
541 ret = ++dc->saveLevel;
542 release_dc_ptr( dc );
543 return ret;
544 }
545
546 if (!(hdcs = get_dc_state( hdc )))
547 {
548 release_dc_ptr( dc );
549 return 0;
550 }
551 dcs = get_dc_ptr( hdcs );
552
553 /* Copy path. The reason why path saving / restoring is in SaveDC/
554 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
555 * functions are only in Win16 (which doesn't have paths) and that
556 * SetDCState doesn't allow us to signal an error (which can happen
557 * when copying paths).
558 */
559 if (!PATH_AssignGdiPath( &dcs->path, &dc->path ))
560 {
561 release_dc_ptr( dc );
562 release_dc_ptr( dcs );
563 DeleteDC( hdcs );
564 return 0;
565 }
566
567 dcs->saved_dc = dc->saved_dc;
568 dc->saved_dc = hdcs;
569 TRACE("(%p): returning %d\n", hdc, dc->saveLevel+1 );
570 ret = ++dc->saveLevel;
571 release_dc_ptr( dcs );
572 release_dc_ptr( dc );
573 return ret;
574 }
575
576
577 /***********************************************************************
578 * RestoreDC (GDI32.@)
579 */
580 BOOL WINAPI RestoreDC( HDC hdc, INT level )
581 {
582 DC * dc, * dcs;
583 BOOL success;
584
585 TRACE("%p %d\n", hdc, level );
586 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
587
588 if(abs(level) > dc->saveLevel || level == 0)
589 {
590 release_dc_ptr( dc );
591 return FALSE;
592 }
593
594 update_dc( dc );
595
596 if(dc->funcs->pRestoreDC)
597 {
598 success = dc->funcs->pRestoreDC( dc->physDev, level );
599 if(level < 0) level = dc->saveLevel + level + 1;
600 if(success)
601 dc->saveLevel = level - 1;
602 release_dc_ptr( dc );
603 return success;
604 }
605
606 if (level < 0) level = dc->saveLevel + level + 1;
607 success=TRUE;
608 while (dc->saveLevel >= level)
609 {
610 HDC hdcs = dc->saved_dc;
611 if (!(dcs = get_dc_ptr( hdcs )))
612 {
613 success = FALSE;
614 break;
615 }
616 dc->saved_dc = dcs->saved_dc;
617 dcs->saved_dc = 0;
618 if (--dc->saveLevel < level)
619 {
620 set_dc_state( hdc, hdcs );
621 if (!PATH_AssignGdiPath( &dc->path, &dcs->path ))
622 /* FIXME: This might not be quite right, since we're
623 * returning FALSE but still destroying the saved DC state */
624 success=FALSE;
625 }
626 release_dc_ptr( dcs );
627 DeleteDC( hdcs );
628 }
629 release_dc_ptr( dc );
630 return success;
631 }
632
633
634 /***********************************************************************
635 * CreateDCW (GDI32.@)
636 */
637 HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
638 const DEVMODEW *initData )
639 {
640 HDC hdc;
641 DC * dc;
642 const DC_FUNCTIONS *funcs;
643 WCHAR buf[300];
644
645 GDI_CheckNotLock();
646
647 if (!device || !DRIVER_GetDriverName( device, buf, 300 ))
648 {
649 if (!driver)
650 {
651 ERR( "no device found for %s\n", debugstr_w(device) );
652 return 0;
653 }
654 strcpyW(buf, driver);
655 }
656
657 if (!(funcs = DRIVER_load_driver( buf )))
658 {
659 ERR( "no driver found for %s\n", debugstr_w(buf) );
660 return 0;
661 }
662 if (!(dc = alloc_dc_ptr( funcs, OBJ_DC ))) goto error;
663 hdc = dc->hSelf;
664
665 dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
666 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;
667
668 TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
669 debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
670
671 if (dc->funcs->pCreateDC &&
672 !dc->funcs->pCreateDC( hdc, &dc->physDev, buf, device, output, initData ))
673 {
674 WARN("creation aborted by device\n" );
675 goto error;
676 }
677
678 SetRectRgn( dc->hVisRgn, 0, 0,
679 GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ) );
680
681 DC_InitDC( dc );
682 release_dc_ptr( dc );
683 return hdc;
684
685 error:
686 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
687 if (dc) free_dc_ptr( dc );
688 DRIVER_release_driver( funcs );
689 return 0;
690 }
691
692
693 /***********************************************************************
694 * CreateDCA (GDI32.@)
695 */
696 HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
697 const DEVMODEA *initData )
698 {
699 UNICODE_STRING driverW, deviceW, outputW;
700 DEVMODEW *initDataW;
701 HDC ret;
702
703 if (driver) RtlCreateUnicodeStringFromAsciiz(&driverW, driver);
704 else driverW.Buffer = NULL;
705
706 if (device) RtlCreateUnicodeStringFromAsciiz(&deviceW, device);
707 else deviceW.Buffer = NULL;
708
709 if (output) RtlCreateUnicodeStringFromAsciiz(&outputW, output);
710 else outputW.Buffer = NULL;
711
712 initDataW = NULL;
713 if (initData)
714 {
715 /* don't convert initData for DISPLAY driver, it's not used */
716 if (!driverW.Buffer || strcmpiW( driverW.Buffer, displayW ))
717 initDataW = GdiConvertToDevmodeW(initData);
718 }
719
720 ret = CreateDCW( driverW.Buffer, deviceW.Buffer, outputW.Buffer, initDataW );
721
722 RtlFreeUnicodeString(&driverW);
723 RtlFreeUnicodeString(&deviceW);
724 RtlFreeUnicodeString(&outputW);
725 HeapFree(GetProcessHeap(), 0, initDataW);
726 return ret;
727 }
728
729
730 /***********************************************************************
731 * CreateICA (GDI32.@)
732 */
733 HDC WINAPI CreateICA( LPCSTR driver, LPCSTR device, LPCSTR output,
734 const DEVMODEA* initData )
735 {
736 /* Nothing special yet for ICs */
737 return CreateDCA( driver, device, output, initData );
738 }
739
740
741 /***********************************************************************
742 * CreateICW (GDI32.@)
743 */
744 HDC WINAPI CreateICW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
745 const DEVMODEW* initData )
746 {
747 /* Nothing special yet for ICs */
748 return CreateDCW( driver, device, output, initData );
749 }
750
751
752 /***********************************************************************
753 * CreateCompatibleDC (GDI32.@)
754 */
755 HDC WINAPI CreateCompatibleDC( HDC hdc )
756 {
757 DC *dc, *origDC;
758 HDC ret;
759 const DC_FUNCTIONS *funcs = NULL;
760 PHYSDEV physDev = NULL;
761
762 GDI_CheckNotLock();
763
764 if ((origDC = get_dc_ptr( hdc )))
765 {
766 if (GetObjectType( hdc ) == OBJ_DC)
767 {
768 funcs = origDC->funcs;
769 physDev = origDC->physDev;
770 }
771 release_dc_ptr( origDC );
772 if (funcs) funcs = DRIVER_get_driver( funcs );
773 }
774 else if (hdc) return 0;
775
776 if (!funcs && !(funcs = DRIVER_load_driver( displayW ))) return 0;
777
778 if (!(dc = alloc_dc_ptr( funcs, OBJ_MEMDC ))) goto error;
779
780 TRACE("(%p): returning %p\n", hdc, dc->hSelf );
781
782 dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
783 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error; /* default bitmap is 1x1 */
784
785 /* Copy the driver-specific physical device info into
786 * the new DC. The driver may use this read-only info
787 * while creating the compatible DC below. */
788 dc->physDev = physDev;
789 ret = dc->hSelf;
790
791 if (dc->funcs->pCreateDC &&
792 !dc->funcs->pCreateDC( dc->hSelf, &dc->physDev, NULL, NULL, NULL, NULL ))
793 {
794 WARN("creation aborted by device\n");
795 goto error;
796 }
797
798 DC_InitDC( dc );
799 release_dc_ptr( dc );
800 return ret;
801
802 error:
803 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
804 if (dc) free_dc_ptr( dc );
805 DRIVER_release_driver( funcs );
806 return 0;
807 }
808
809
810 /***********************************************************************
811 * DeleteDC (GDI32.@)
812 */
813 BOOL WINAPI DeleteDC( HDC hdc )
814 {
815 const DC_FUNCTIONS *funcs = NULL;
816 DC * dc;
817
818 TRACE("%p\n", hdc );
819
820 GDI_CheckNotLock();
821
822 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
823 if (dc->refcount != 1)
824 {
825 FIXME( "not deleting busy DC %p refcount %u\n", dc->hSelf, dc->refcount );
826 release_dc_ptr( dc );
827 return FALSE;
828 }
829
830 /* Call hook procedure to check whether is it OK to delete this DC */
831 if (dc->hookThunk && !dc->hookThunk( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ))
832 {
833 release_dc_ptr( dc );
834 return FALSE;
835 }
836
837 while (dc->saveLevel)
838 {
839 DC * dcs;
840 HDC hdcs = dc->saved_dc;
841 if (!(dcs = get_dc_ptr( hdcs ))) break;
842 dc->saved_dc = dcs->saved_dc;
843 dc->saveLevel--;
844 if (dcs->hClipRgn) DeleteObject( dcs->hClipRgn );
845 if (dcs->hMetaRgn) DeleteObject( dcs->hMetaRgn );
846 if (dcs->hMetaClipRgn) DeleteObject( dcs->hMetaClipRgn );
847 if (dcs->hVisRgn) DeleteObject( dcs->hVisRgn );
848 PATH_DestroyGdiPath(&dcs->path);
849 free_dc_ptr( dcs );
850 }
851
852 if (!(dc->flags & DC_SAVED))
853 {
854 SelectObject( hdc, GetStockObject(BLACK_PEN) );
855 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
856 SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
857 SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
858 funcs = dc->funcs;
859 if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc->physDev);
860 dc->physDev = NULL;
861 }
862
863 while (dc->saved_visrgn)
864 {
865 struct saved_visrgn *next = dc->saved_visrgn->next;
866 DeleteObject( dc->saved_visrgn->hrgn );
867 HeapFree( GetProcessHeap(), 0, dc->saved_visrgn );
868 dc->saved_visrgn = next;
869 }
870 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
871 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
872 if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
873 if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
874 PATH_DestroyGdiPath(&dc->path);
875
876 free_dc_ptr( dc );
877 if (funcs) DRIVER_release_driver( funcs ); /* do that after releasing the GDI lock */
878 return TRUE;
879 }
880
881
882 /***********************************************************************
883 * ResetDCW (GDI32.@)
884 */
885 HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
886 {
887 DC *dc;
888 HDC ret = hdc;
889
890 if ((dc = get_dc_ptr( hdc )))
891 {
892 if (dc->funcs->pResetDC) ret = dc->funcs->pResetDC( dc->physDev, devmode );
893 release_dc_ptr( dc );
894 }
895 return ret;
896 }
897
898
899 /***********************************************************************
900 * ResetDCA (GDI32.@)
901 */
902 HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
903 {
904 DEVMODEW *devmodeW;
905 HDC ret;
906
907 if (devmode) devmodeW = GdiConvertToDevmodeW(devmode);
908 else devmodeW = NULL;
909
910 ret = ResetDCW(hdc, devmodeW);
911
912 HeapFree(GetProcessHeap(), 0, devmodeW);
913 return ret;
914 }
915
916
917 /***********************************************************************
918 * GetDeviceCaps (GDI32.@)
919 */
920 INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
921 {
922 DC *dc;
923 INT ret = 0;
924
925 if ((dc = get_dc_ptr( hdc )))
926 {
927 if (dc->funcs->pGetDeviceCaps) ret = dc->funcs->pGetDeviceCaps( dc->physDev, cap );
928 else switch(cap) /* return meaningful values for some entries */
929 {
930 case HORZRES: ret = 640; break;
931 case VERTRES: ret = 480; break;
932 case BITSPIXEL: ret = 1; break;
933 case PLANES: ret = 1; break;
934 case NUMCOLORS: ret = 2; break;
935 case ASPECTX: ret = 36; break;
936 case ASPECTY: ret = 36; break;
937 case ASPECTXY: ret = 51; break;
938 case LOGPIXELSX: ret = 72; break;
939 case LOGPIXELSY: ret = 72; break;
940 case SIZEPALETTE: ret = 2; break;
941 }
942 release_dc_ptr( dc );
943 }
944 return ret;
945 }
946
947
948 /***********************************************************************
949 * GetBkColor (GDI32.@)
950 */
951 COLORREF WINAPI GetBkColor( HDC hdc )
952 {
953 COLORREF ret = 0;
954 DC * dc = get_dc_ptr( hdc );
955 if (dc)
956 {
957 ret = dc->backgroundColor;
958 release_dc_ptr( dc );
959 }
960 return ret;
961 }
962
963
964 /***********************************************************************
965 * SetBkColor (GDI32.@)
966 */
967 COLORREF WINAPI SetBkColor( HDC hdc, COLORREF color )
968 {
969 COLORREF oldColor;
970 DC * dc = get_dc_ptr( hdc );
971
972 TRACE("hdc=%p color=0x%08x\n", hdc, color);
973
974 if (!dc) return CLR_INVALID;
975 oldColor = dc->backgroundColor;
976 if (dc->funcs->pSetBkColor)
977 {
978 color = dc->funcs->pSetBkColor(dc->physDev, color);
979 if (color == CLR_INVALID) /* don't change it */
980 {
981 color = oldColor;
982 oldColor = CLR_INVALID;
983 }
984 }
985 dc->backgroundColor = color;
986 release_dc_ptr( dc );
987 return oldColor;
988 }
989
990
991 /***********************************************************************
992 * GetTextColor (GDI32.@)
993 */
994 COLORREF WINAPI GetTextColor( HDC hdc )
995 {
996 COLORREF ret = 0;
997 DC * dc = get_dc_ptr( hdc );
998 if (dc)
999 {
1000 ret = dc->textColor;
1001 release_dc_ptr( dc );
1002 }
1003 return ret;
1004 }
1005
1006
1007 /***********************************************************************
1008 * SetTextColor (GDI32.@)
1009 */
1010 COLORREF WINAPI SetTextColor( HDC hdc, COLORREF color )
1011 {
1012 COLORREF oldColor;
1013 DC * dc = get_dc_ptr( hdc );
1014
1015 TRACE(" hdc=%p color=0x%08x\n", hdc, color);
1016
1017 if (!dc) return CLR_INVALID;
1018 oldColor = dc->textColor;
1019 if (dc->funcs->pSetTextColor)
1020 {
1021 color = dc->funcs->pSetTextColor(dc->physDev, color);
1022 if (color == CLR_INVALID) /* don't change it */
1023 {
1024 color = oldColor;
1025 oldColor = CLR_INVALID;
1026 }
1027 }
1028 dc->textColor = color;
1029 release_dc_ptr( dc );
1030 return oldColor;
1031 }
1032
1033
1034 /***********************************************************************
1035 * GetTextAlign (GDI32.@)
1036 */
1037 UINT WINAPI GetTextAlign( HDC hdc )
1038 {
1039 UINT ret = 0;
1040 DC * dc = get_dc_ptr( hdc );
1041 if (dc)
1042 {
1043 ret = dc->textAlign;
1044 release_dc_ptr( dc );
1045 }
1046 return ret;
1047 }
1048
1049
1050 /***********************************************************************
1051 * SetTextAlign (GDI32.@)
1052 */
1053 UINT WINAPI SetTextAlign( HDC hdc, UINT align )
1054 {
1055 UINT ret;
1056 DC *dc = get_dc_ptr( hdc );
1057
1058 TRACE("hdc=%p align=%d\n", hdc, align);
1059
1060 if (!dc) return 0x0;
1061 ret = dc->textAlign;
1062 if (dc->funcs->pSetTextAlign)
1063 if (!dc->funcs->pSetTextAlign(dc->physDev, align))
1064 ret = GDI_ERROR;
1065 if (ret != GDI_ERROR)
1066 dc->textAlign = align;
1067 release_dc_ptr( dc );
1068 return ret;
1069 }
1070
1071 /***********************************************************************
1072 * GetDCOrgEx (GDI32.@)
1073 */
1074 BOOL WINAPI GetDCOrgEx( HDC hDC, LPPOINT lpp )
1075 {
1076 DC * dc;
1077
1078 if (!lpp) return FALSE;
1079 if (!(dc = get_dc_ptr( hDC ))) return FALSE;
1080
1081 lpp->x = lpp->y = 0;
1082 if (dc->funcs->pGetDCOrgEx) dc->funcs->pGetDCOrgEx( dc->physDev, lpp );
1083 release_dc_ptr( dc );
1084 return TRUE;
1085 }
1086
1087
1088 /***********************************************************************
1089 * GetGraphicsMode (GDI32.@)
1090 */
1091 INT WINAPI GetGraphicsMode( HDC hdc )
1092 {
1093 INT ret = 0;
1094 DC * dc = get_dc_ptr( hdc );
1095 if (dc)
1096 {
1097 ret = dc->GraphicsMode;
1098 release_dc_ptr( dc );
1099 }
1100 return ret;
1101 }
1102
1103
1104 /***********************************************************************
1105 * SetGraphicsMode (GDI32.@)
1106 */
1107 INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
1108 {
1109 INT ret = 0;
1110 DC *dc = get_dc_ptr( hdc );
1111
1112 /* One would think that setting the graphics mode to GM_COMPATIBLE
1113 * would also reset the world transformation matrix to the unity
1114 * matrix. However, in Windows, this is not the case. This doesn't
1115 * make a lot of sense to me, but that's the way it is.
1116 */
1117 if (!dc) return 0;
1118 if ((mode > 0) && (mode <= GM_LAST))
1119 {
1120 ret = dc->GraphicsMode;
1121 dc->GraphicsMode = mode;
1122 }
1123 release_dc_ptr( dc );
1124 return ret;
1125 }
1126
1127
1128 /***********************************************************************
1129 * GetArcDirection (GDI32.@)
1130 */
1131 INT WINAPI GetArcDirection( HDC hdc )
1132 {
1133 INT ret = 0;
1134 DC * dc = get_dc_ptr( hdc );
1135 if (dc)
1136 {
1137 ret = dc->ArcDirection;
1138 release_dc_ptr( dc );
1139 }
1140 return ret;
1141 }
1142
1143
1144 /***********************************************************************
1145 * SetArcDirection (GDI32.@)
1146 */
1147 INT WINAPI SetArcDirection( HDC hdc, INT nDirection )
1148 {
1149 DC * dc;
1150 INT nOldDirection = 0;
1151
1152 if (nDirection!=AD_COUNTERCLOCKWISE && nDirection!=AD_CLOCKWISE)
1153 {
1154 SetLastError(ERROR_INVALID_PARAMETER);
1155 return 0;
1156 }
1157
1158 if ((dc = get_dc_ptr( hdc )))
1159 {
1160 if (dc->funcs->pSetArcDirection)
1161 {
1162 dc->funcs->pSetArcDirection(dc->physDev, nDirection);
1163 }
1164 nOldDirection = dc->ArcDirection;
1165 dc->ArcDirection = nDirection;
1166 release_dc_ptr( dc );
1167 }
1168 return nOldDirection;
1169 }
1170
1171
1172 /***********************************************************************
1173 * GetWorldTransform (GDI32.@)
1174 */
1175 BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
1176 {
1177 DC * dc;
1178 if (!xform) return FALSE;
1179 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
1180 *xform = dc->xformWorld2Wnd;
1181 release_dc_ptr( dc );
1182 return TRUE;
1183 }
1184
1185
1186 /***********************************************************************
1187 * GetTransform (GDI32.@)
1188 */
1189 BOOL WINAPI GetTransform( HDC hdc, DWORD unknown, LPXFORM xform )
1190 {
1191 if (unknown == 0x0203) return GetWorldTransform( hdc, xform );
1192 FIXME("stub: don't know what to do for code %x\n", unknown );
1193 return FALSE;
1194 }
1195
1196
1197 /***********************************************************************
1198 * SetWorldTransform (GDI32.@)
1199 */
1200 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
1201 {
1202 BOOL ret = FALSE;
1203 DC *dc = get_dc_ptr( hdc );
1204
1205 if (!dc) return FALSE;
1206 if (!xform) goto done;
1207
1208 /* Check that graphics mode is GM_ADVANCED */
1209 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1210
1211 TRACE("eM11 %f eM12 %f eM21 %f eM22 %f eDx %f eDy %f\n",
1212 xform->eM11, xform->eM12, xform->eM21, xform->eM22, xform->eDx, xform->eDy);
1213
1214 if (dc->funcs->pSetWorldTransform)
1215 {
1216 ret = dc->funcs->pSetWorldTransform(dc->physDev, xform);
1217 if (!ret) goto done;
1218 }
1219
1220 dc->xformWorld2Wnd = *xform;
1221 DC_UpdateXforms( dc );
1222 ret = TRUE;
1223 done:
1224 release_dc_ptr( dc );
1225 return ret;
1226 }
1227
1228
1229 /****************************************************************************
1230 * ModifyWorldTransform [GDI32.@]
1231 * Modifies the world transformation for a device context.
1232 *
1233 * PARAMS
1234 * hdc [I] Handle to device context
1235 * xform [I] XFORM structure that will be used to modify the world
1236 * transformation
1237 * iMode [I] Specifies in what way to modify the world transformation
1238 * Possible values:
1239 * MWT_IDENTITY
1240 * Resets the world transformation to the identity matrix.
1241 * The parameter xform is ignored.
1242 * MWT_LEFTMULTIPLY
1243 * Multiplies xform into the world transformation matrix from
1244 * the left.
1245 * MWT_RIGHTMULTIPLY
1246 * Multiplies xform into the world transformation matrix from
1247 * the right.
1248 *
1249 * RETURNS
1250 * Success: TRUE.
1251 * Failure: FALSE. Use GetLastError() to determine the cause.
1252 */
1253 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform,
1254 DWORD iMode )
1255 {
1256 BOOL ret = FALSE;
1257 DC *dc = get_dc_ptr( hdc );
1258
1259 /* Check for illegal parameters */
1260 if (!dc) return FALSE;
1261 if (!xform && iMode != MWT_IDENTITY) goto done;
1262
1263 /* Check that graphics mode is GM_ADVANCED */
1264 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1265
1266 if (dc->funcs->pModifyWorldTransform)
1267 {
1268 ret = dc->funcs->pModifyWorldTransform(dc->physDev, xform, iMode);
1269 if (!ret) goto done;
1270 }
1271
1272 switch (iMode)
1273 {
1274 case MWT_IDENTITY:
1275 dc->xformWorld2Wnd.eM11 = 1.0f;
1276 dc->xformWorld2Wnd.eM12 = 0.0f;
1277 dc->xformWorld2Wnd.eM21 = 0.0f;
1278 dc->xformWorld2Wnd.eM22 = 1.0f;
1279 dc->xformWorld2Wnd.eDx = 0.0f;
1280 dc->xformWorld2Wnd.eDy = 0.0f;
1281 break;
1282 case MWT_LEFTMULTIPLY:
1283 CombineTransform( &dc->xformWorld2Wnd, xform,
1284 &dc->xformWorld2Wnd );
1285 break;
1286 case MWT_RIGHTMULTIPLY:
1287 CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd,
1288 xform );
1289 break;
1290 default:
1291 goto done;
1292 }
1293
1294 DC_UpdateXforms( dc );
1295 ret = TRUE;
1296 done:
1297 release_dc_ptr( dc );
1298 return ret;
1299 }
1300
1301
1302 /****************************************************************************
1303 * CombineTransform [GDI32.@]
1304 * Combines two transformation matrices.
1305 *
1306 * PARAMS
1307 * xformResult [O] Stores the result of combining the two matrices
1308 * xform1 [I] Specifies the first matrix to apply
1309 * xform2 [I] Specifies the second matrix to apply
1310 *
1311 * REMARKS
1312 * The same matrix can be passed in for more than one of the parameters.
1313 *
1314 * RETURNS
1315 * Success: TRUE.
1316 * Failure: FALSE. Use GetLastError() to determine the cause.
1317 */
1318 BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
1319 const XFORM *xform2 )
1320 {
1321 XFORM xformTemp;
1322
1323 /* Check for illegal parameters */
1324 if (!xformResult || !xform1 || !xform2)
1325 return FALSE;
1326
1327 /* Create the result in a temporary XFORM, since xformResult may be
1328 * equal to xform1 or xform2 */
1329 xformTemp.eM11 = xform1->eM11 * xform2->eM11 +
1330 xform1->eM12 * xform2->eM21;
1331 xformTemp.eM12 = xform1->eM11 * xform2->eM12 +
1332 xform1->eM12 * xform2->eM22;
1333 xformTemp.eM21 = xform1->eM21 * xform2->eM11 +
1334 xform1->eM22 * xform2->eM21;
1335 xformTemp.eM22 = xform1->eM21 * xform2->eM12 +
1336 xform1->eM22 * xform2->eM22;
1337 xformTemp.eDx = xform1->eDx * xform2->eM11 +
1338 xform1->eDy * xform2->eM21 +
1339 xform2->eDx;
1340 xformTemp.eDy = xform1->eDx * xform2->eM12 +
1341 xform1->eDy * xform2->eM22 +
1342 xform2->eDy;
1343
1344 /* Copy the result to xformResult */
1345 *xformResult = xformTemp;
1346
1347 return TRUE;
1348 }
1349
1350
1351 /***********************************************************************
1352 * SetDCHook (GDI32.@)
1353 *
1354 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1355 */
1356 BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD_PTR dwHookData )
1357 {
1358 DC *dc = get_dc_ptr( hdc );
1359
1360 if (!dc) return FALSE;
1361
1362 if (!(dc->flags & DC_SAVED))
1363 {
1364 dc->dwHookData = dwHookData;
1365 dc->hookThunk = hookProc;
1366 }
1367 release_dc_ptr( dc );
1368 return TRUE;
1369 }
1370
1371
1372 /***********************************************************************
1373 * GetDCHook (GDI32.@)
1374 *
1375 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1376 */
1377 DWORD_PTR WINAPI GetDCHook( HDC hdc, DCHOOKPROC *proc )
1378 {
1379 DC *dc = get_dc_ptr( hdc );
1380 DWORD_PTR ret;
1381
1382 if (!dc) return 0;
1383 if (proc) *proc = dc->hookThunk;
1384 ret = dc->dwHookData;
1385 release_dc_ptr( dc );
1386 return ret;
1387 }
1388
1389
1390 /* relay function to call the 16-bit DC hook proc */
1391 static BOOL WINAPI call_dc_hook16( HDC hdc, WORD code, DWORD_PTR data, LPARAM lParam )
1392 {
1393 WORD args[6];
1394 DWORD ret = 0;
1395 DC *dc = get_dc_ptr( hdc );
1396
1397 if (!dc) return FALSE;
1398 if (dc->hookProc)
1399 {
1400 args[5] = HDC_16(hdc);
1401 args[4] = code;
1402 args[3] = HIWORD(data);
1403 args[2] = LOWORD(data);
1404 args[1] = HIWORD(lParam);
1405 args[0] = LOWORD(lParam);
1406 WOWCallback16Ex( (DWORD)dc->hookProc, WCB16_PASCAL, sizeof(args), args, &ret );
1407 }
1408 release_dc_ptr( dc );
1409 return LOWORD(ret);
1410 }
1411
1412 /***********************************************************************
1413 * SetDCHook (GDI.190)
1414 */
1415 BOOL16 WINAPI SetDCHook16( HDC16 hdc16, FARPROC16 hookProc, DWORD dwHookData )
1416 {
1417 DC *dc = get_dc_ptr( HDC_32(hdc16) );
1418
1419 if (!dc) return FALSE;
1420 if (!(dc->flags & DC_SAVED))
1421 {
1422 dc->dwHookData = dwHookData;
1423 dc->hookThunk = call_dc_hook16;
1424 dc->hookProc = hookProc;
1425 }
1426 release_dc_ptr( dc );
1427 return TRUE;
1428 }
1429
1430
1431 /***********************************************************************
1432 * GetDCHook (GDI.191)
1433 */
1434 DWORD WINAPI GetDCHook16( HDC16 hdc16, FARPROC16 *phookProc )
1435 {
1436 HDC hdc = HDC_32( hdc16 );
1437 DC *dc = get_dc_ptr( hdc );
1438 DWORD ret;
1439
1440 if (!dc) return 0;
1441 *phookProc = dc->hookProc;
1442 ret = dc->dwHookData;
1443 release_dc_ptr( dc );
1444 return ret;
1445 }
1446
1447
1448 /***********************************************************************
1449 * SetHookFlags (GDI32.@)
1450 *
1451 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1452 */
1453 WORD WINAPI SetHookFlags( HDC hdc, WORD flags )
1454 {
1455 DC *dc = get_dc_obj( hdc ); /* not get_dc_ptr, this needs to work from any thread */
1456 LONG ret = 0;
1457
1458 if (!dc) return 0;
1459
1460 /* "Undocumented Windows" info is slightly confusing. */
1461
1462 TRACE("hDC %p, flags %04x\n",hdc,flags);
1463
1464 if (flags & DCHF_INVALIDATEVISRGN)
1465 ret = InterlockedExchange( &dc->dirty, 1 );
1466 else if (flags & DCHF_VALIDATEVISRGN || !flags)
1467 ret = InterlockedExchange( &dc->dirty, 0 );
1468
1469 GDI_ReleaseObj( dc );
1470 return ret;
1471 }
1472
1473 /***********************************************************************
1474 * SetICMMode (GDI32.@)
1475 */
1476 INT WINAPI SetICMMode(HDC hdc, INT iEnableICM)
1477 {
1478 /*FIXME: Assume that ICM is always off, and cannot be turned on */
1479 if (iEnableICM == ICM_OFF) return ICM_OFF;
1480 if (iEnableICM == ICM_ON) return 0;
1481 if (iEnableICM == ICM_QUERY) return ICM_OFF;
1482 return 0;
1483 }
1484
1485 /***********************************************************************
1486 * GetDeviceGammaRamp (GDI32.@)
1487 */
1488 BOOL WINAPI GetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1489 {
1490 BOOL ret = FALSE;
1491 DC *dc = get_dc_ptr( hDC );
1492
1493 if( dc )
1494 {
1495 if (dc->funcs->pGetDeviceGammaRamp)
1496 ret = dc->funcs->pGetDeviceGammaRamp(dc->physDev, ptr);
1497 release_dc_ptr( dc );
1498 }
1499 return ret;
1500 }
1501
1502 /***********************************************************************
1503 * SetDeviceGammaRamp (GDI32.@)
1504 */
1505 BOOL WINAPI SetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1506 {
1507 BOOL ret = FALSE;
1508 DC *dc = get_dc_ptr( hDC );
1509
1510 if( dc )
1511 {
1512 if (dc->funcs->pSetDeviceGammaRamp)
1513 ret = dc->funcs->pSetDeviceGammaRamp(dc->physDev, ptr);
1514 release_dc_ptr( dc );
1515 }
1516 return ret;
1517 }
1518
1519 /***********************************************************************
1520 * GetColorSpace (GDI32.@)
1521 */
1522 HCOLORSPACE WINAPI GetColorSpace(HDC hdc)
1523 {
1524 /*FIXME Need to to whatever GetColorSpace actually does */
1525 return 0;
1526 }
1527
1528 /***********************************************************************
1529 * CreateColorSpaceA (GDI32.@)
1530 */
1531 HCOLORSPACE WINAPI CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace )
1532 {
1533 FIXME( "stub\n" );
1534 return 0;
1535 }
1536
1537 /***********************************************************************
1538 * CreateColorSpaceW (GDI32.@)
1539 */
1540 HCOLORSPACE WINAPI CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace )
1541 {
1542 FIXME( "stub\n" );
1543 return 0;
1544 }
1545
1546 /***********************************************************************
1547 * DeleteColorSpace (GDI32.@)
1548 */
1549 BOOL WINAPI DeleteColorSpace( HCOLORSPACE hColorSpace )
1550 {
1551 FIXME( "stub\n" );
1552
1553 return TRUE;
1554 }
1555
1556 /***********************************************************************
1557 * SetColorSpace (GDI32.@)
1558 */
1559 HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
1560 {
1561 FIXME( "stub\n" );
1562
1563 return hColorSpace;
1564 }
1565
1566 /***********************************************************************
1567 * GetBoundsRect (GDI32.@)
1568 */
1569 UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
1570 {
1571 UINT ret;
1572 DC *dc = get_dc_ptr( hdc );
1573
1574 if ( !dc ) return 0;
1575
1576 if (rect) *rect = dc->BoundsRect;
1577
1578 ret = ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1579
1580 if (flags & DCB_RESET)
1581 {
1582 dc->BoundsRect.left = 0;
1583 dc->BoundsRect.top = 0;
1584 dc->BoundsRect.right = 0;
1585 dc->BoundsRect.bottom = 0;
1586 dc->flags &= ~DC_BOUNDS_SET;
1587 }
1588 release_dc_ptr( dc );
1589 return ret;
1590 }
1591
1592
1593 /***********************************************************************
1594 * SetBoundsRect (GDI32.@)
1595 */
1596 UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
1597 {
1598 UINT ret;
1599 DC *dc;
1600
1601 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
1602 if (!(dc = get_dc_ptr( hdc ))) return 0;
1603
1604 ret = ((dc->flags & DC_BOUNDS_ENABLE) ? DCB_ENABLE : DCB_DISABLE) |
1605 ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1606
1607 if (flags & DCB_RESET)
1608 {
1609 dc->BoundsRect.left = 0;
1610 dc->BoundsRect.top = 0;
1611 dc->BoundsRect.right = 0;
1612 dc->BoundsRect.bottom = 0;
1613 dc->flags &= ~DC_BOUNDS_SET;
1614 }
1615
1616 if ((flags & DCB_ACCUMULATE) && rect && rect->left < rect->right && rect->top < rect->bottom)
1617 {
1618 if (dc->flags & DC_BOUNDS_SET)
1619 {
1620 dc->BoundsRect.left = min( dc->BoundsRect.left, rect->left );
1621 dc->BoundsRect.top = min( dc->BoundsRect.top, rect->top );
1622 dc->BoundsRect.right = max( dc->BoundsRect.right, rect->right );
1623 dc->BoundsRect.bottom = max( dc->BoundsRect.bottom, rect->bottom );
1624 }
1625 else
1626 {
1627 dc->BoundsRect = *rect;
1628 dc->flags |= DC_BOUNDS_SET;
1629 }
1630 }
1631
1632 if (flags & DCB_ENABLE) dc->flags |= DC_BOUNDS_ENABLE;
1633 if (flags & DCB_DISABLE) dc->flags &= ~DC_BOUNDS_ENABLE;
1634
1635 release_dc_ptr( dc );
1636 return ret;
1637 }
1638
1639
1640 /***********************************************************************
1641 * GetRelAbs (GDI32.@)
1642 */
1643 INT WINAPI GetRelAbs( HDC hdc, DWORD dwIgnore )
1644 {
1645 INT ret = 0;
1646 DC *dc = get_dc_ptr( hdc );
1647 if (dc)
1648 {
1649 ret = dc->relAbsMode;
1650 release_dc_ptr( dc );
1651 }
1652 return ret;
1653 }
1654
1655
1656
1657
1658 /***********************************************************************
1659 * GetBkMode (GDI32.@)
1660 */
1661 INT WINAPI GetBkMode( HDC hdc )
1662 {
1663 INT ret = 0;
1664 DC * dc = get_dc_ptr( hdc );
1665 if (dc)
1666 {
1667 ret = dc->backgroundMode;
1668 release_dc_ptr( dc );
1669 }
1670 return ret;
1671 }
1672
1673
1674 /***********************************************************************
1675 * SetBkMode (GDI32.@)
1676 */
1677 INT WINAPI SetBkMode( HDC hdc, INT mode )
1678 {
1679 INT ret;
1680 DC *dc;
1681 if ((mode <= 0) || (mode > BKMODE_LAST))
1682 {
1683 SetLastError(ERROR_INVALID_PARAMETER);
1684 return 0;
1685 }
1686 if (!(dc = get_dc_ptr( hdc ))) return 0;
1687
1688 ret = dc->backgroundMode;
1689 if (dc->funcs->pSetBkMode)
1690 if (!dc->funcs->pSetBkMode( dc->physDev, mode ))
1691 ret = 0;
1692 if (ret)
1693 dc->backgroundMode = mode;
1694 release_dc_ptr( dc );
1695 return ret;
1696 }
1697
1698
1699 /***********************************************************************
1700 * GetROP2 (GDI32.@)
1701 */
1702 INT WINAPI GetROP2( HDC hdc )
1703 {
1704 INT ret = 0;
1705 DC * dc = get_dc_ptr( hdc );
1706 if (dc)
1707 {
1708 ret = dc->ROPmode;
1709 release_dc_ptr( dc );
1710 }
1711 return ret;
1712 }
1713
1714
1715 /***********************************************************************
1716 * SetROP2 (GDI32.@)
1717 */
1718 INT WINAPI SetROP2( HDC hdc, INT mode )
1719 {
1720 INT ret;
1721 DC *dc;
1722 if ((mode < R2_BLACK) || (mode > R2_WHITE))
1723 {
1724 SetLastError(ERROR_INVALID_PARAMETER);
1725 return 0;
1726 }
1727 if (!(dc = get_dc_ptr( hdc ))) return 0;
1728 ret = dc->ROPmode;
1729 if (dc->funcs->pSetROP2)
1730 if (!dc->funcs->pSetROP2( dc->physDev, mode ))
1731 ret = 0;
1732 if (ret)
1733 dc->ROPmode = mode;
1734 release_dc_ptr( dc );
1735 return ret;
1736 }
1737
1738
1739 /***********************************************************************
1740 * SetRelAbs (GDI32.@)
1741 */
1742 INT WINAPI SetRelAbs( HDC hdc, INT mode )
1743 {
1744 INT ret;
1745 DC *dc;
1746 if ((mode != ABSOLUTE) && (mode != RELATIVE))
1747 {
1748 SetLastError(ERROR_INVALID_PARAMETER);
1749 return 0;
1750 }
1751 if (!(dc = get_dc_ptr( hdc ))) return 0;
1752 if (dc->funcs->pSetRelAbs)
1753 ret = dc->funcs->pSetRelAbs( dc->physDev, mode );
1754 else
1755 {
1756 ret = dc->relAbsMode;
1757 dc->relAbsMode = mode;
1758 }
1759 release_dc_ptr( dc );
1760 return ret;
1761 }
1762
1763
1764 /***********************************************************************
1765 * GetPolyFillMode (GDI32.@)
1766 */
1767 INT WINAPI GetPolyFillMode( HDC hdc )
1768 {
1769 INT ret = 0;
1770 DC * dc = get_dc_ptr( hdc );
1771 if (dc)
1772 {
1773 ret = dc->polyFillMode;
1774 release_dc_ptr( dc );
1775 }
1776 return ret;
1777 }
1778
1779
1780 /***********************************************************************
1781 * SetPolyFillMode (GDI32.@)
1782 */
1783 INT WINAPI SetPolyFillMode( HDC hdc, INT mode )
1784 {
1785 INT ret;
1786 DC *dc;
1787 if ((mode <= 0) || (mode > POLYFILL_LAST))
1788 {
1789 SetLastError(ERROR_INVALID_PARAMETER);
1790 return 0;
1791 }
1792 if (!(dc = get_dc_ptr( hdc ))) return 0;
1793 ret = dc->polyFillMode;
1794 if (dc->funcs->pSetPolyFillMode)
1795 if (!dc->funcs->pSetPolyFillMode( dc->physDev, mode ))
1796 ret = 0;
1797 if (ret)
1798 dc->polyFillMode = mode;
1799 release_dc_ptr( dc );
1800 return ret;
1801 }
1802
1803
1804 /***********************************************************************
1805 * GetStretchBltMode (GDI32.@)
1806 */
1807 INT WINAPI GetStretchBltMode( HDC hdc )
1808 {
1809 INT ret = 0;
1810 DC * dc = get_dc_ptr( hdc );
1811 if (dc)
1812 {
1813 ret = dc->stretchBltMode;
1814 release_dc_ptr( dc );
1815 }
1816 return ret;
1817 }
1818
1819
1820 /***********************************************************************
1821 * SetStretchBltMode (GDI32.@)
1822 */
1823 INT WINAPI SetStretchBltMode( HDC hdc, INT mode )
1824 {
1825 INT ret;
1826 DC *dc;
1827 if ((mode <= 0) || (mode > MAXSTRETCHBLTMODE))
1828 {
1829 SetLastError(ERROR_INVALID_PARAMETER);
1830 return 0;
1831 }
1832 if (!(dc = get_dc_ptr( hdc ))) return 0;
1833 ret = dc->stretchBltMode;
1834 if (dc->funcs->pSetStretchBltMode)
1835 if (!dc->funcs->pSetStretchBltMode( dc->physDev, mode ))
1836 ret = 0;
1837 if (ret)
1838 dc->stretchBltMode = mode;
1839 release_dc_ptr( dc );
1840 return ret;
1841 }
1842
1843
1844 /***********************************************************************
1845 * GetMapMode (GDI32.@)
1846 */
1847 INT WINAPI GetMapMode( HDC hdc )
1848 {
1849 INT ret = 0;
1850 DC * dc = get_dc_ptr( hdc );
1851 if (dc)
1852 {
1853 ret = dc->MapMode;
1854 release_dc_ptr( dc );
1855 }
1856 return ret;
1857 }
1858
1859
1860 /***********************************************************************
1861 * GetBrushOrgEx (GDI32.@)
1862 */
1863 BOOL WINAPI GetBrushOrgEx( HDC hdc, LPPOINT pt )
1864 {
1865 DC * dc = get_dc_ptr( hdc );
1866 if (!dc) return FALSE;
1867 pt->x = dc->brushOrgX;
1868 pt->y = dc->brushOrgY;
1869 release_dc_ptr( dc );
1870 return TRUE;
1871 }
1872
1873
1874 /***********************************************************************
1875 * GetCurrentPositionEx (GDI32.@)
1876 */
1877 BOOL WINAPI GetCurrentPositionEx( HDC hdc, LPPOINT pt )
1878 {
1879 DC * dc = get_dc_ptr( hdc );
1880 if (!dc) return FALSE;
1881 pt->x = dc->CursPosX;
1882 pt->y = dc->CursPosY;
1883 release_dc_ptr( dc );
1884 return TRUE;
1885 }
1886
1887
1888 /***********************************************************************
1889 * GetViewportExtEx (GDI32.@)
1890 */
1891 BOOL WINAPI GetViewportExtEx( HDC hdc, LPSIZE size )
1892 {
1893 DC * dc = get_dc_ptr( hdc );
1894 if (!dc) return FALSE;
1895 size->cx = dc->vportExtX;
1896 size->cy = dc->vportExtY;
1897 release_dc_ptr( dc );
1898 return TRUE;
1899 }
1900
1901
1902 /***********************************************************************
1903 * GetViewportOrgEx (GDI32.@)
1904 */
1905 BOOL WINAPI GetViewportOrgEx( HDC hdc, LPPOINT pt )
1906 {
1907 DC * dc = get_dc_ptr( hdc );
1908 if (!dc) return FALSE;
1909 pt->x = dc->vportOrgX;
1910 pt->y = dc->vportOrgY;
1911 release_dc_ptr( dc );
1912 return TRUE;
1913 }
1914
1915
1916 /***********************************************************************
1917 * GetWindowExtEx (GDI32.@)
1918 */
1919 BOOL WINAPI GetWindowExtEx( HDC hdc, LPSIZE size )
1920 {
1921 DC * dc = get_dc_ptr( hdc );
1922 if (!dc) return FALSE;
1923 size->cx = dc->wndExtX;
1924 size->cy = dc->wndExtY;
1925 release_dc_ptr( dc );
1926 return TRUE;
1927 }
1928
1929
1930 /***********************************************************************
1931 * GetWindowOrgEx (GDI32.@)
1932 */
1933 BOOL WINAPI GetWindowOrgEx( HDC hdc, LPPOINT pt )
1934 {
1935 DC * dc = get_dc_ptr( hdc );
1936 if (!dc) return FALSE;
1937 pt->x = dc->wndOrgX;
1938 pt->y = dc->wndOrgY;
1939 release_dc_ptr( dc );
1940 return TRUE;
1941 }
1942
1943
1944 /***********************************************************************
1945 * GetLayout (GDI32.@)
1946 *
1947 * Gets left->right or right->left text layout flags of a dc.
1948 *
1949 */
1950 DWORD WINAPI GetLayout(HDC hdc)
1951 {
1952 DWORD layout = GDI_ERROR;
1953
1954 DC * dc = get_dc_ptr( hdc );
1955 if (dc)
1956 {
1957 layout = dc->layout;
1958 release_dc_ptr( dc );
1959 }
1960
1961 TRACE("hdc : %p, layout : %08x\n", hdc, layout);
1962
1963 return layout;
1964 }
1965
1966 /***********************************************************************
1967 * SetLayout (GDI32.@)
1968 *
1969 * Sets left->right or right->left text layout flags of a dc.
1970 *
1971 */
1972 DWORD WINAPI SetLayout(HDC hdc, DWORD layout)
1973 {
1974 DWORD oldlayout = GDI_ERROR;
1975
1976 DC * dc = get_dc_ptr( hdc );
1977 if (dc)
1978 {
1979 oldlayout = dc->layout;
1980 dc->layout = layout;
1981 release_dc_ptr( dc );
1982 }
1983
1984 TRACE("hdc : %p, old layout : %08x, new layout : %08x\n", hdc, oldlayout, layout);
1985
1986 return oldlayout;
1987 }
1988
1989 /***********************************************************************
1990 * GetDCBrushColor (GDI32.@)
1991 *
1992 * Retrieves the current brush color for the specified device
1993 * context (DC).
1994 *
1995 */
1996 COLORREF WINAPI GetDCBrushColor(HDC hdc)
1997 {
1998 DC *dc;
1999 COLORREF dcBrushColor = CLR_INVALID;
2000
2001 TRACE("hdc(%p)\n", hdc);
2002
2003 dc = get_dc_ptr( hdc );
2004 if (dc)
2005 {
2006 dcBrushColor = dc->dcBrushColor;
2007 release_dc_ptr( dc );
2008 }
2009
2010 return dcBrushColor;
2011 }
2012
2013 /***********************************************************************
2014 * SetDCBrushColor (GDI32.@)
2015 *
2016 * Sets the current device context (DC) brush color to the specified
2017 * color value. If the device cannot represent the specified color
2018 * value, the color is set to the nearest physical color.
2019 *
2020 */
2021 COLORREF WINAPI SetDCBrushColor(HDC hdc, COLORREF crColor)
2022 {
2023 DC *dc;
2024 COLORREF oldClr = CLR_INVALID;
2025
2026 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2027
2028 dc = get_dc_ptr( hdc );
2029 if (dc)
2030 {
2031 if (dc->funcs->pSetDCBrushColor)
2032 crColor = dc->funcs->pSetDCBrushColor( dc->physDev, crColor );
2033 else if (dc->hBrush == GetStockObject( DC_BRUSH ))
2034 {
2035 /* If DC_BRUSH is selected, update driver pen color */
2036 HBRUSH hBrush = CreateSolidBrush( crColor );
2037 dc->funcs->pSelectBrush( dc->physDev, hBrush );
2038 DeleteObject( hBrush );
2039 }
2040
2041 if (crColor != CLR_INVALID)
2042 {
2043 oldClr = dc->dcBrushColor;
2044 dc->dcBrushColor = crColor;
2045 }
2046
2047 release_dc_ptr( dc );
2048 }
2049
2050 return oldClr;
2051 }
2052
2053 /***********************************************************************
2054 * GetDCPenColor (GDI32.@)
2055 *
2056 * Retrieves the current pen color for the specified device
2057 * context (DC).
2058 *
2059 */
2060 COLORREF WINAPI GetDCPenColor(HDC hdc)
2061 {
2062 DC *dc;
2063 COLORREF dcPenColor = CLR_INVALID;
2064
2065 TRACE("hdc(%p)\n", hdc);
2066
2067 dc = get_dc_ptr( hdc );
2068 if (dc)
2069 {
2070 dcPenColor = dc->dcPenColor;
2071 release_dc_ptr( dc );
2072 }
2073
2074 return dcPenColor;
2075 }
2076
2077 /***********************************************************************
2078 * SetDCPenColor (GDI32.@)
2079 *
2080 * Sets the current device context (DC) pen color to the specified
2081 * color value. If the device cannot represent the specified color
2082 * value, the color is set to the nearest physical color.
2083 *
2084 */
2085 COLORREF WINAPI SetDCPenColor(HDC hdc, COLORREF crColor)
2086 {
2087 DC *dc;
2088 COLORREF oldClr = CLR_INVALID;
2089
2090 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2091
2092 dc = get_dc_ptr( hdc );
2093 if (dc)
2094 {
2095 if (dc->funcs->pSetDCPenColor)
2096 crColor = dc->funcs->pSetDCPenColor( dc->physDev, crColor );
2097 else if (dc->hPen == GetStockObject( DC_PEN ))
2098 {
2099 /* If DC_PEN is selected, update the driver pen color */
2100 LOGPEN logpen = { PS_SOLID, { 0, 0 }, crColor };
2101 HPEN hPen = CreatePenIndirect( &logpen );
2102 dc->funcs->pSelectPen( dc->physDev, hPen );
2103 DeleteObject( hPen );
2104 }
2105
2106 if (crColor != CLR_INVALID)
2107 {
2108 oldClr = dc->dcPenColor;
2109 dc->dcPenColor = crColor;
2110 }
2111
2112 release_dc_ptr( dc );
2113 }
2114
2115 return oldClr;
2116 }
2117
2118 /***********************************************************************
2119 * CancelDC (GDI32.@)
2120 */
2121 BOOL WINAPI CancelDC(HDC hdc)
2122 {
2123 FIXME("stub\n");
2124 return TRUE;
2125 }
2126
2127 /***********************************************************************
2128 * SetVirtualResolution (GDI32.@)
2129 *
2130 * Undocumented on msdn. Called when PowerPoint XP saves a file.
2131 */
2132 DWORD WINAPI SetVirtualResolution(HDC hdc, DWORD dw2, DWORD dw3, DWORD dw4, DWORD dw5)
2133 {
2134 FIXME("(%p %08x %08x %08x %08x): stub!\n", hdc, dw2, dw3, dw4, dw5);
2135 return FALSE;
2136 }
2137
2138 /*******************************************************************
2139 * GetMiterLimit [GDI32.@]
2140 *
2141 *
2142 */
2143 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
2144 {
2145 BOOL bRet = FALSE;
2146 DC *dc;
2147
2148 TRACE("(%p,%p)\n", hdc, peLimit);
2149
2150 dc = get_dc_ptr( hdc );
2151 if (dc)
2152 {
2153 if (peLimit)
2154 *peLimit = dc->miterLimit;
2155
2156 release_dc_ptr( dc );
2157 bRet = TRUE;
2158 }
2159 return bRet;
2160 }
2161
2162 /*******************************************************************
2163 * SetMiterLimit [GDI32.@]
2164 *
2165 *
2166 */
2167 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
2168 {
2169 BOOL bRet = FALSE;
2170 DC *dc;
2171
2172 TRACE("(%p,%f,%p)\n", hdc, eNewLimit, peOldLimit);
2173
2174 dc = get_dc_ptr( hdc );
2175 if (dc)
2176 {
2177 if (peOldLimit)
2178 *peOldLimit = dc->miterLimit;
2179 dc->miterLimit = eNewLimit;
2180 release_dc_ptr( dc );
2181 bRet = TRUE;
2182 }
2183 return bRet;
2184 }
2185
2186 /*******************************************************************
2187 * GdiIsMetaPrintDC [GDI32.@]
2188 */
2189 BOOL WINAPI GdiIsMetaPrintDC(HDC hdc)
2190 {
2191 FIXME("%p\n", hdc);
2192 return FALSE;
2193 }
2194
2195 /*******************************************************************
2196 * GdiIsMetaFileDC [GDI32.@]
2197 */
2198 BOOL WINAPI GdiIsMetaFileDC(HDC hdc)
2199 {
2200 TRACE("%p\n", hdc);
2201
2202 switch( GetObjectType( hdc ) )
2203 {
2204 case OBJ_METADC:
2205 case OBJ_ENHMETADC:
2206 return TRUE;
2207 }
2208 return FALSE;
2209 }
2210
2211 /*******************************************************************
2212 * GdiIsPlayMetafileDC [GDI32.@]
2213 */
2214 BOOL WINAPI GdiIsPlayMetafileDC(HDC hdc)
2215 {
2216 FIXME("%p\n", hdc);
2217 return FALSE;
2218 }
2219
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.