2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
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.
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.
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
33 #include "gdi_private.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dc);
39 static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
41 static BOOL DC_DeleteObject( HGDIOBJ handle );
43 static const struct gdi_obj_funcs dc_funcs =
45 NULL, /* pSelectObject */
46 NULL, /* pGetObjectA */
47 NULL, /* pGetObjectW */
48 NULL, /* pUnrealizeObject */
49 DC_DeleteObject /* pDeleteObject */
53 static inline DC *get_dc_obj( HDC hdc )
55 DC *dc = GDI_GetObjPtr( hdc, 0 );
58 switch (GetObjectType( hdc ))
66 GDI_ReleaseObj( hdc );
67 SetLastError( ERROR_INVALID_HANDLE );
73 /***********************************************************************
76 DC *alloc_dc_ptr( WORD magic )
80 if (!(dc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dc) ))) return NULL;
82 dc->nulldrv.funcs = &null_driver;
83 dc->physDev = &dc->nulldrv;
84 dc->module = gdi32_module;
85 dc->thread = GetCurrentThreadId();
91 dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */
92 dc->hPen = GDI_inc_ref_count( GetStockObject( BLACK_PEN ));
93 dc->hBrush = GDI_inc_ref_count( GetStockObject( WHITE_BRUSH ));
94 dc->hFont = GDI_inc_ref_count( GetStockObject( SYSTEM_FONT ));
95 dc->hPalette = GetStockObject( DEFAULT_PALETTE );
96 dc->font_code_page = CP_ACP;
97 dc->ROPmode = R2_COPYPEN;
98 dc->polyFillMode = ALTERNATE;
99 dc->stretchBltMode = BLACKONWHITE;
100 dc->relAbsMode = ABSOLUTE;
101 dc->backgroundMode = OPAQUE;
102 dc->backgroundColor = RGB( 255, 255, 255 );
103 dc->dcBrushColor = RGB( 255, 255, 255 );
104 dc->dcPenColor = RGB( 0, 0, 0 );
105 dc->textColor = RGB( 0, 0, 0 );
106 dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP;
107 dc->MapMode = MM_TEXT;
108 dc->GraphicsMode = GM_COMPATIBLE;
109 dc->ArcDirection = AD_COUNTERCLOCKWISE;
110 dc->xformWorld2Wnd.eM11 = 1.0f;
111 dc->xformWorld2Wnd.eM12 = 0.0f;
112 dc->xformWorld2Wnd.eM21 = 0.0f;
113 dc->xformWorld2Wnd.eM22 = 1.0f;
114 dc->xformWorld2Wnd.eDx = 0.0f;
115 dc->xformWorld2Wnd.eDy = 0.0f;
116 dc->xformWorld2Vport = dc->xformWorld2Wnd;
117 dc->xformVport2World = dc->xformWorld2Wnd;
118 dc->vport2WorldValid = TRUE;
120 reset_bounds( &dc->bounds );
122 if (!(dc->hSelf = alloc_gdi_handle( dc, magic, &dc_funcs )))
124 HeapFree( GetProcessHeap(), 0, dc );
127 dc->nulldrv.hdc = dc->hSelf;
129 if (font_driver && !font_driver->pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL ))
139 /***********************************************************************
142 static void free_dc_state( DC *dc )
144 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
145 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
146 if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
147 if (dc->region) DeleteObject( dc->region );
148 if (dc->path) free_gdi_path( dc->path );
149 HeapFree( GetProcessHeap(), 0, dc );
153 /***********************************************************************
156 void free_dc_ptr( DC *dc )
158 assert( dc->refcount == 1 );
160 while (dc->physDev != &dc->nulldrv)
162 PHYSDEV physdev = dc->physDev;
163 dc->physDev = physdev->next;
164 physdev->funcs->pDeleteDC( physdev );
166 GDI_dec_ref_count( dc->hPen );
167 GDI_dec_ref_count( dc->hBrush );
168 GDI_dec_ref_count( dc->hFont );
169 if (dc->hBitmap) GDI_dec_ref_count( dc->hBitmap );
170 free_gdi_handle( dc->hSelf );
175 /***********************************************************************
178 * Retrieve a DC pointer but release the GDI lock.
180 DC *get_dc_ptr( HDC hdc )
182 DC *dc = get_dc_obj( hdc );
183 if (!dc) return NULL;
185 if (!InterlockedCompareExchange( &dc->refcount, 1, 0 ))
187 dc->thread = GetCurrentThreadId();
189 else if (dc->thread != GetCurrentThreadId())
191 WARN( "dc %p belongs to thread %04x\n", hdc, dc->thread );
192 GDI_ReleaseObj( hdc );
195 else InterlockedIncrement( &dc->refcount );
197 GDI_ReleaseObj( hdc );
202 /***********************************************************************
205 void release_dc_ptr( DC *dc )
210 ref = InterlockedDecrement( &dc->refcount );
212 if (ref) dc->thread = GetCurrentThreadId(); /* we still own it */
216 /***********************************************************************
219 * Make sure the DC vis region is up to date.
220 * This function may call up to USER so the GDI lock should _not_
221 * be held when calling it.
223 void update_dc( DC *dc )
225 if (InterlockedExchange( &dc->dirty, 0 ) && dc->hookProc)
226 dc->hookProc( dc->hSelf, DCHC_INVALIDVISRGN, dc->dwHookData, 0 );
230 /***********************************************************************
233 static BOOL DC_DeleteObject( HGDIOBJ handle )
235 return DeleteDC( handle );
239 /***********************************************************************
242 * Setup device-specific DC values for a newly created DC.
244 void DC_InitDC( DC* dc )
246 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRealizeDefaultPalette );
247 physdev->funcs->pRealizeDefaultPalette( physdev );
248 SetTextColor( dc->hSelf, dc->textColor );
249 SetBkColor( dc->hSelf, dc->backgroundColor );
250 SelectObject( dc->hSelf, dc->hPen );
251 SelectObject( dc->hSelf, dc->hBrush );
252 SelectObject( dc->hSelf, dc->hFont );
253 update_dc_clipping( dc );
254 SetVirtualResolution( dc->hSelf, 0, 0, 0, 0 );
255 physdev = GET_DC_PHYSDEV( dc, pSetBoundsRect );
256 physdev->funcs->pSetBoundsRect( physdev, &dc->bounds, dc->bounds_enabled ? DCB_ENABLE : DCB_DISABLE );
260 /***********************************************************************
263 * Computes the inverse of the transformation xformSrc and stores it to
264 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
267 static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
271 determinant = xformSrc->eM11*xformSrc->eM22 -
272 xformSrc->eM12*xformSrc->eM21;
273 if (determinant > -1e-12 && determinant < 1e-12)
276 xformDest->eM11 = xformSrc->eM22 / determinant;
277 xformDest->eM12 = -xformSrc->eM12 / determinant;
278 xformDest->eM21 = -xformSrc->eM21 / determinant;
279 xformDest->eM22 = xformSrc->eM11 / determinant;
280 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 -
281 xformSrc->eDy * xformDest->eM21;
282 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 -
283 xformSrc->eDy * xformDest->eM22;
288 /* Construct a transformation to do the window-to-viewport conversion */
289 static void construct_window_to_viewport(DC *dc, XFORM *xform)
291 double scaleX, scaleY;
292 scaleX = (double)dc->vportExtX / (double)dc->wndExtX;
293 scaleY = (double)dc->vportExtY / (double)dc->wndExtY;
295 if (dc->layout & LAYOUT_RTL) scaleX = -scaleX;
296 xform->eM11 = scaleX;
299 xform->eM22 = scaleY;
300 xform->eDx = (double)dc->vportOrgX - scaleX * (double)dc->wndOrgX;
301 xform->eDy = (double)dc->vportOrgY - scaleY * (double)dc->wndOrgY;
302 if (dc->layout & LAYOUT_RTL) xform->eDx = dc->vis_rect.right - dc->vis_rect.left - 1 - xform->eDx;
305 /***********************************************************************
308 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
309 * fields of the specified DC by creating a transformation that
310 * represents the current mapping mode and combining it with the DC's
311 * world transform. This function should be called whenever the
312 * parameters associated with the mapping mode (window and viewport
313 * extents and origins) or the world transform change.
315 void DC_UpdateXforms( DC *dc )
317 XFORM xformWnd2Vport, oldworld2vport;
319 construct_window_to_viewport(dc, &xformWnd2Vport);
321 oldworld2vport = dc->xformWorld2Vport;
322 /* Combine with the world transformation */
323 CombineTransform( &dc->xformWorld2Vport, &dc->xformWorld2Wnd,
326 /* Create inverse of world-to-viewport transformation */
327 dc->vport2WorldValid = DC_InvertXform( &dc->xformWorld2Vport,
328 &dc->xformVport2World );
330 /* Reselect the font and pen back into the dc so that the size
332 if (memcmp(&oldworld2vport, &dc->xformWorld2Vport, sizeof(oldworld2vport)) &&
333 !GdiIsMetaFileDC(dc->hSelf))
335 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_FONT));
336 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_PEN));
341 /***********************************************************************
344 INT nulldrv_SaveDC( PHYSDEV dev )
346 DC *newdc, *dc = get_nulldrv_dc( dev );
348 if (!(newdc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newdc )))) return 0;
349 newdc->layout = dc->layout;
350 newdc->hPen = dc->hPen;
351 newdc->hBrush = dc->hBrush;
352 newdc->hFont = dc->hFont;
353 newdc->hBitmap = dc->hBitmap;
354 newdc->hDevice = dc->hDevice;
355 newdc->hPalette = dc->hPalette;
356 newdc->ROPmode = dc->ROPmode;
357 newdc->polyFillMode = dc->polyFillMode;
358 newdc->stretchBltMode = dc->stretchBltMode;
359 newdc->relAbsMode = dc->relAbsMode;
360 newdc->backgroundMode = dc->backgroundMode;
361 newdc->backgroundColor = dc->backgroundColor;
362 newdc->textColor = dc->textColor;
363 newdc->dcBrushColor = dc->dcBrushColor;
364 newdc->dcPenColor = dc->dcPenColor;
365 newdc->brushOrgX = dc->brushOrgX;
366 newdc->brushOrgY = dc->brushOrgY;
367 newdc->mapperFlags = dc->mapperFlags;
368 newdc->textAlign = dc->textAlign;
369 newdc->charExtra = dc->charExtra;
370 newdc->breakExtra = dc->breakExtra;
371 newdc->breakRem = dc->breakRem;
372 newdc->MapMode = dc->MapMode;
373 newdc->GraphicsMode = dc->GraphicsMode;
374 newdc->CursPosX = dc->CursPosX;
375 newdc->CursPosY = dc->CursPosY;
376 newdc->ArcDirection = dc->ArcDirection;
377 newdc->xformWorld2Wnd = dc->xformWorld2Wnd;
378 newdc->xformWorld2Vport = dc->xformWorld2Vport;
379 newdc->xformVport2World = dc->xformVport2World;
380 newdc->vport2WorldValid = dc->vport2WorldValid;
381 newdc->wndOrgX = dc->wndOrgX;
382 newdc->wndOrgY = dc->wndOrgY;
383 newdc->wndExtX = dc->wndExtX;
384 newdc->wndExtY = dc->wndExtY;
385 newdc->vportOrgX = dc->vportOrgX;
386 newdc->vportOrgY = dc->vportOrgY;
387 newdc->vportExtX = dc->vportExtX;
388 newdc->vportExtY = dc->vportExtY;
389 newdc->virtual_res = dc->virtual_res;
390 newdc->virtual_size = dc->virtual_size;
391 newdc->gdiFont = dc->gdiFont;
393 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
397 newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
398 CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
402 newdc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
403 CombineRgn( newdc->hMetaRgn, dc->hMetaRgn, 0, RGN_COPY );
406 if (!PATH_SavePath( newdc, dc ))
408 release_dc_ptr( dc );
409 free_dc_state( newdc );
413 newdc->saved_dc = dc->saved_dc;
414 dc->saved_dc = newdc;
415 return ++dc->saveLevel;
419 /***********************************************************************
422 BOOL nulldrv_RestoreDC( PHYSDEV dev, INT level )
424 DC *dcs, *first_dcs, *dc = get_nulldrv_dc( dev );
427 /* find the state level to restore */
429 if (abs(level) > dc->saveLevel || level == 0) return FALSE;
430 if (level < 0) level = dc->saveLevel + level + 1;
431 first_dcs = dc->saved_dc;
432 for (dcs = first_dcs, save_level = dc->saveLevel; save_level > level; save_level--)
435 /* restore the state */
437 if (!PATH_RestorePath( dc, dcs )) return FALSE;
439 dc->layout = dcs->layout;
440 dc->hDevice = dcs->hDevice;
441 dc->ROPmode = dcs->ROPmode;
442 dc->polyFillMode = dcs->polyFillMode;
443 dc->stretchBltMode = dcs->stretchBltMode;
444 dc->relAbsMode = dcs->relAbsMode;
445 dc->backgroundMode = dcs->backgroundMode;
446 dc->backgroundColor = dcs->backgroundColor;
447 dc->textColor = dcs->textColor;
448 dc->dcBrushColor = dcs->dcBrushColor;
449 dc->dcPenColor = dcs->dcPenColor;
450 dc->brushOrgX = dcs->brushOrgX;
451 dc->brushOrgY = dcs->brushOrgY;
452 dc->mapperFlags = dcs->mapperFlags;
453 dc->textAlign = dcs->textAlign;
454 dc->charExtra = dcs->charExtra;
455 dc->breakExtra = dcs->breakExtra;
456 dc->breakRem = dcs->breakRem;
457 dc->MapMode = dcs->MapMode;
458 dc->GraphicsMode = dcs->GraphicsMode;
459 dc->CursPosX = dcs->CursPosX;
460 dc->CursPosY = dcs->CursPosY;
461 dc->ArcDirection = dcs->ArcDirection;
462 dc->xformWorld2Wnd = dcs->xformWorld2Wnd;
463 dc->xformWorld2Vport = dcs->xformWorld2Vport;
464 dc->xformVport2World = dcs->xformVport2World;
465 dc->vport2WorldValid = dcs->vport2WorldValid;
466 dc->wndOrgX = dcs->wndOrgX;
467 dc->wndOrgY = dcs->wndOrgY;
468 dc->wndExtX = dcs->wndExtX;
469 dc->wndExtY = dcs->wndExtY;
470 dc->vportOrgX = dcs->vportOrgX;
471 dc->vportOrgY = dcs->vportOrgY;
472 dc->vportExtX = dcs->vportExtX;
473 dc->vportExtY = dcs->vportExtY;
474 dc->virtual_res = dcs->virtual_res;
475 dc->virtual_size = dcs->virtual_size;
479 if (!dc->hClipRgn) dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
480 CombineRgn( dc->hClipRgn, dcs->hClipRgn, 0, RGN_COPY );
484 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
489 if (!dc->hMetaRgn) dc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
490 CombineRgn( dc->hMetaRgn, dcs->hMetaRgn, 0, RGN_COPY );
494 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
497 DC_UpdateXforms( dc );
498 update_dc_clipping( dc );
500 SelectObject( dev->hdc, dcs->hBitmap );
501 SelectObject( dev->hdc, dcs->hBrush );
502 SelectObject( dev->hdc, dcs->hFont );
503 SelectObject( dev->hdc, dcs->hPen );
504 SetBkColor( dev->hdc, dcs->backgroundColor);
505 SetTextColor( dev->hdc, dcs->textColor);
506 GDISelectPalette( dev->hdc, dcs->hPalette, FALSE );
508 dc->saved_dc = dcs->saved_dc;
510 dc->saveLevel = save_level - 1;
512 /* now destroy all the saved DCs */
516 DC *next = first_dcs->saved_dc;
517 free_dc_state( first_dcs );
524 /***********************************************************************
527 INT WINAPI SaveDC( HDC hdc )
532 if ((dc = get_dc_ptr( hdc )))
534 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSaveDC );
535 ret = physdev->funcs->pSaveDC( physdev );
536 release_dc_ptr( dc );
542 /***********************************************************************
543 * RestoreDC (GDI32.@)
545 BOOL WINAPI RestoreDC( HDC hdc, INT level )
549 BOOL success = FALSE;
551 TRACE("%p %d\n", hdc, level );
552 if ((dc = get_dc_ptr( hdc )))
555 physdev = GET_DC_PHYSDEV( dc, pRestoreDC );
556 success = physdev->funcs->pRestoreDC( physdev, level );
557 release_dc_ptr( dc );
563 /***********************************************************************
564 * CreateDCW (GDI32.@)
566 HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
567 const DEVMODEW *initData )
571 const struct gdi_dc_funcs *funcs;
577 if (!device || !DRIVER_GetDriverName( device, buf, 300 ))
581 ERR( "no device found for %s\n", debugstr_w(device) );
584 strcpyW(buf, driver);
587 if (!(funcs = DRIVER_load_driver( buf, &module )))
589 ERR( "no driver found for %s\n", debugstr_w(buf) );
592 if (!(dc = alloc_dc_ptr( OBJ_DC ))) return 0;
596 dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
598 TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
599 debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
601 if (funcs->pCreateDC)
603 if (!funcs->pCreateDC( &dc->physDev, buf, device, output, initData ))
605 WARN("creation aborted by device\n" );
611 dc->vis_rect.left = 0;
612 dc->vis_rect.top = 0;
613 dc->vis_rect.right = GetDeviceCaps( hdc, DESKTOPHORZRES );
614 dc->vis_rect.bottom = GetDeviceCaps( hdc, DESKTOPVERTRES );
617 release_dc_ptr( dc );
622 /***********************************************************************
623 * CreateDCA (GDI32.@)
625 HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
626 const DEVMODEA *initData )
628 UNICODE_STRING driverW, deviceW, outputW;
632 if (driver) RtlCreateUnicodeStringFromAsciiz(&driverW, driver);
633 else driverW.Buffer = NULL;
635 if (device) RtlCreateUnicodeStringFromAsciiz(&deviceW, device);
636 else deviceW.Buffer = NULL;
638 if (output) RtlCreateUnicodeStringFromAsciiz(&outputW, output);
639 else outputW.Buffer = NULL;
644 /* don't convert initData for DISPLAY driver, it's not used */
645 if (!driverW.Buffer || strcmpiW( driverW.Buffer, displayW ))
646 initDataW = GdiConvertToDevmodeW(initData);
649 ret = CreateDCW( driverW.Buffer, deviceW.Buffer, outputW.Buffer, initDataW );
651 RtlFreeUnicodeString(&driverW);
652 RtlFreeUnicodeString(&deviceW);
653 RtlFreeUnicodeString(&outputW);
654 HeapFree(GetProcessHeap(), 0, initDataW);
659 /***********************************************************************
660 * CreateICA (GDI32.@)
662 HDC WINAPI CreateICA( LPCSTR driver, LPCSTR device, LPCSTR output,
663 const DEVMODEA* initData )
665 /* Nothing special yet for ICs */
666 return CreateDCA( driver, device, output, initData );
670 /***********************************************************************
671 * CreateICW (GDI32.@)
673 HDC WINAPI CreateICW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
674 const DEVMODEW* initData )
676 /* Nothing special yet for ICs */
677 return CreateDCW( driver, device, output, initData );
681 /***********************************************************************
682 * CreateCompatibleDC (GDI32.@)
684 HDC WINAPI CreateCompatibleDC( HDC hdc )
688 const struct gdi_dc_funcs *funcs = &null_driver;
689 PHYSDEV physDev = NULL;
695 if (!(origDC = get_dc_ptr( hdc ))) return 0;
696 physDev = GET_DC_PHYSDEV( origDC, pCreateCompatibleDC );
697 funcs = physDev->funcs;
698 release_dc_ptr( origDC );
701 if (!(dc = alloc_dc_ptr( OBJ_MEMDC ))) return 0;
703 TRACE("(%p): returning %p\n", hdc, dc->hSelf );
705 dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
706 dc->vis_rect.left = 0;
707 dc->vis_rect.top = 0;
708 dc->vis_rect.right = 1;
709 dc->vis_rect.bottom = 1;
710 dc->device_rect = dc->vis_rect;
714 if (!funcs->pCreateCompatibleDC( physDev, &dc->physDev ))
716 WARN("creation aborted by device\n");
721 if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL ))
726 physDev = GET_DC_PHYSDEV( dc, pSelectBitmap );
727 physDev->funcs->pSelectBitmap( physDev, dc->hBitmap );
730 release_dc_ptr( dc );
735 /***********************************************************************
738 BOOL WINAPI DeleteDC( HDC hdc )
746 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
747 if (dc->refcount != 1)
749 FIXME( "not deleting busy DC %p refcount %u\n", dc->hSelf, dc->refcount );
750 release_dc_ptr( dc );
754 /* Call hook procedure to check whether is it OK to delete this DC */
755 if (dc->hookProc && !dc->hookProc( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ))
757 release_dc_ptr( dc );
761 while (dc->saveLevel)
763 DC *dcs = dc->saved_dc;
764 dc->saved_dc = dcs->saved_dc;
766 free_dc_state( dcs );
770 SelectObject( hdc, GetStockObject(BLACK_PEN) );
771 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
772 SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
773 SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
780 /***********************************************************************
783 HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
788 if ((dc = get_dc_ptr( hdc )))
790 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pResetDC );
791 ret = physdev->funcs->pResetDC( physdev, devmode );
792 if (ret) /* reset the visible region */
795 dc->vis_rect.left = 0;
796 dc->vis_rect.top = 0;
797 dc->vis_rect.right = GetDeviceCaps( hdc, DESKTOPHORZRES );
798 dc->vis_rect.bottom = GetDeviceCaps( hdc, DESKTOPVERTRES );
799 if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
801 update_dc_clipping( dc );
803 release_dc_ptr( dc );
809 /***********************************************************************
812 HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
817 if (devmode) devmodeW = GdiConvertToDevmodeW(devmode);
818 else devmodeW = NULL;
820 ret = ResetDCW(hdc, devmodeW);
822 HeapFree(GetProcessHeap(), 0, devmodeW);
827 /***********************************************************************
828 * GetDeviceCaps (GDI32.@)
830 INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
835 if ((dc = get_dc_ptr( hdc )))
837 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDeviceCaps );
838 ret = physdev->funcs->pGetDeviceCaps( physdev, cap );
839 release_dc_ptr( dc );
845 /***********************************************************************
846 * GetBkColor (GDI32.@)
848 COLORREF WINAPI GetBkColor( HDC hdc )
851 DC * dc = get_dc_ptr( hdc );
854 ret = dc->backgroundColor;
855 release_dc_ptr( dc );
861 /***********************************************************************
862 * SetBkColor (GDI32.@)
864 COLORREF WINAPI SetBkColor( HDC hdc, COLORREF color )
866 COLORREF ret = CLR_INVALID;
867 DC * dc = get_dc_ptr( hdc );
869 TRACE("hdc=%p color=0x%08x\n", hdc, color);
873 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetBkColor );
874 ret = dc->backgroundColor;
875 dc->backgroundColor = physdev->funcs->pSetBkColor( physdev, color );
876 release_dc_ptr( dc );
882 /***********************************************************************
883 * GetTextColor (GDI32.@)
885 COLORREF WINAPI GetTextColor( HDC hdc )
888 DC * dc = get_dc_ptr( hdc );
892 release_dc_ptr( dc );
898 /***********************************************************************
899 * SetTextColor (GDI32.@)
901 COLORREF WINAPI SetTextColor( HDC hdc, COLORREF color )
903 COLORREF ret = CLR_INVALID;
904 DC * dc = get_dc_ptr( hdc );
906 TRACE(" hdc=%p color=0x%08x\n", hdc, color);
910 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextColor );
912 dc->textColor = physdev->funcs->pSetTextColor( physdev, color );
913 release_dc_ptr( dc );
919 /***********************************************************************
920 * GetTextAlign (GDI32.@)
922 UINT WINAPI GetTextAlign( HDC hdc )
925 DC * dc = get_dc_ptr( hdc );
929 release_dc_ptr( dc );
935 /***********************************************************************
936 * SetTextAlign (GDI32.@)
938 UINT WINAPI SetTextAlign( HDC hdc, UINT align )
940 UINT ret = GDI_ERROR;
941 DC *dc = get_dc_ptr( hdc );
943 TRACE("hdc=%p align=%d\n", hdc, align);
947 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextAlign );
948 align = physdev->funcs->pSetTextAlign( physdev, align );
949 if (align != GDI_ERROR)
952 dc->textAlign = align;
954 release_dc_ptr( dc );
959 /***********************************************************************
960 * GetDCOrgEx (GDI32.@)
962 BOOL WINAPI GetDCOrgEx( HDC hDC, LPPOINT lpp )
966 if (!lpp) return FALSE;
967 if (!(dc = get_dc_ptr( hDC ))) return FALSE;
968 lpp->x = dc->vis_rect.left;
969 lpp->y = dc->vis_rect.top;
970 release_dc_ptr( dc );
975 /***********************************************************************
976 * GetGraphicsMode (GDI32.@)
978 INT WINAPI GetGraphicsMode( HDC hdc )
981 DC * dc = get_dc_ptr( hdc );
984 ret = dc->GraphicsMode;
985 release_dc_ptr( dc );
991 /***********************************************************************
992 * SetGraphicsMode (GDI32.@)
994 INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
997 DC *dc = get_dc_ptr( hdc );
999 /* One would think that setting the graphics mode to GM_COMPATIBLE
1000 * would also reset the world transformation matrix to the unity
1001 * matrix. However, in Windows, this is not the case. This doesn't
1002 * make a lot of sense to me, but that's the way it is.
1005 if ((mode > 0) && (mode <= GM_LAST))
1007 ret = dc->GraphicsMode;
1008 dc->GraphicsMode = mode;
1010 release_dc_ptr( dc );
1015 /***********************************************************************
1016 * GetArcDirection (GDI32.@)
1018 INT WINAPI GetArcDirection( HDC hdc )
1021 DC * dc = get_dc_ptr( hdc );
1024 ret = dc->ArcDirection;
1025 release_dc_ptr( dc );
1031 /***********************************************************************
1032 * SetArcDirection (GDI32.@)
1034 INT WINAPI SetArcDirection( HDC hdc, INT dir )
1039 if (dir != AD_COUNTERCLOCKWISE && dir != AD_CLOCKWISE)
1041 SetLastError(ERROR_INVALID_PARAMETER);
1045 if ((dc = get_dc_ptr( hdc )))
1047 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetArcDirection );
1048 dir = physdev->funcs->pSetArcDirection( physdev, dir );
1051 ret = dc->ArcDirection;
1052 dc->ArcDirection = dir;
1054 release_dc_ptr( dc );
1060 /***********************************************************************
1061 * GetWorldTransform (GDI32.@)
1063 BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
1066 if (!xform) return FALSE;
1067 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
1068 *xform = dc->xformWorld2Wnd;
1069 release_dc_ptr( dc );
1074 /***********************************************************************
1075 * GetTransform (GDI32.@)
1079 * Returns one of the co-ordinate space transforms
1082 * hdc [I] Device context.
1083 * which [I] Which xform to return:
1084 * 0x203 World -> Page transform (that set by SetWorldTransform).
1085 * 0x304 Page -> Device transform (the mapping mode transform).
1086 * 0x204 World -> Device transform (the combination of the above two).
1087 * 0x402 Device -> World transform (the inversion of the above).
1088 * xform [O] The xform.
1091 BOOL WINAPI GetTransform( HDC hdc, DWORD which, XFORM *xform )
1094 DC *dc = get_dc_ptr( hdc );
1095 if (!dc) return FALSE;
1100 *xform = dc->xformWorld2Wnd;
1104 construct_window_to_viewport(dc, xform);
1108 *xform = dc->xformWorld2Vport;
1112 *xform = dc->xformVport2World;
1116 FIXME("Unknown code %x\n", which);
1120 release_dc_ptr( dc );
1125 /****************************************************************************
1126 * CombineTransform [GDI32.@]
1127 * Combines two transformation matrices.
1130 * xformResult [O] Stores the result of combining the two matrices
1131 * xform1 [I] Specifies the first matrix to apply
1132 * xform2 [I] Specifies the second matrix to apply
1135 * The same matrix can be passed in for more than one of the parameters.
1139 * Failure: FALSE. Use GetLastError() to determine the cause.
1141 BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
1142 const XFORM *xform2 )
1146 /* Check for illegal parameters */
1147 if (!xformResult || !xform1 || !xform2)
1150 /* Create the result in a temporary XFORM, since xformResult may be
1151 * equal to xform1 or xform2 */
1152 xformTemp.eM11 = xform1->eM11 * xform2->eM11 +
1153 xform1->eM12 * xform2->eM21;
1154 xformTemp.eM12 = xform1->eM11 * xform2->eM12 +
1155 xform1->eM12 * xform2->eM22;
1156 xformTemp.eM21 = xform1->eM21 * xform2->eM11 +
1157 xform1->eM22 * xform2->eM21;
1158 xformTemp.eM22 = xform1->eM21 * xform2->eM12 +
1159 xform1->eM22 * xform2->eM22;
1160 xformTemp.eDx = xform1->eDx * xform2->eM11 +
1161 xform1->eDy * xform2->eM21 +
1163 xformTemp.eDy = xform1->eDx * xform2->eM12 +
1164 xform1->eDy * xform2->eM22 +
1167 /* Copy the result to xformResult */
1168 *xformResult = xformTemp;
1174 /***********************************************************************
1175 * SetDCHook (GDI32.@)
1177 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1179 BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD_PTR dwHookData )
1181 DC *dc = get_dc_ptr( hdc );
1183 if (!dc) return FALSE;
1185 dc->dwHookData = dwHookData;
1186 dc->hookProc = hookProc;
1187 release_dc_ptr( dc );
1192 /***********************************************************************
1193 * GetDCHook (GDI32.@)
1195 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1197 DWORD_PTR WINAPI GetDCHook( HDC hdc, DCHOOKPROC *proc )
1199 DC *dc = get_dc_ptr( hdc );
1203 if (proc) *proc = dc->hookProc;
1204 ret = dc->dwHookData;
1205 release_dc_ptr( dc );
1210 /***********************************************************************
1211 * SetHookFlags (GDI32.@)
1213 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1215 WORD WINAPI SetHookFlags( HDC hdc, WORD flags )
1217 DC *dc = get_dc_obj( hdc ); /* not get_dc_ptr, this needs to work from any thread */
1222 /* "Undocumented Windows" info is slightly confusing. */
1224 TRACE("hDC %p, flags %04x\n",hdc,flags);
1226 if (flags & DCHF_INVALIDATEVISRGN)
1227 ret = InterlockedExchange( &dc->dirty, 1 );
1228 else if (flags & DCHF_VALIDATEVISRGN || !flags)
1229 ret = InterlockedExchange( &dc->dirty, 0 );
1231 GDI_ReleaseObj( hdc );
1235 /***********************************************************************
1236 * SetICMMode (GDI32.@)
1238 INT WINAPI SetICMMode(HDC hdc, INT iEnableICM)
1240 /*FIXME: Assume that ICM is always off, and cannot be turned on */
1241 if (iEnableICM == ICM_OFF) return ICM_OFF;
1242 if (iEnableICM == ICM_ON) return 0;
1243 if (iEnableICM == ICM_QUERY) return ICM_OFF;
1247 /***********************************************************************
1248 * GetDeviceGammaRamp (GDI32.@)
1250 BOOL WINAPI GetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1253 DC *dc = get_dc_ptr( hDC );
1255 TRACE("%p, %p\n", hDC, ptr);
1258 if (GetObjectType( hDC ) != OBJ_MEMDC)
1260 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDeviceGammaRamp );
1261 ret = physdev->funcs->pGetDeviceGammaRamp( physdev, ptr );
1263 else SetLastError( ERROR_INVALID_PARAMETER );
1264 release_dc_ptr( dc );
1269 /***********************************************************************
1270 * SetDeviceGammaRamp (GDI32.@)
1272 BOOL WINAPI SetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1275 DC *dc = get_dc_ptr( hDC );
1277 TRACE("%p, %p\n", hDC, ptr);
1280 if (GetObjectType( hDC ) != OBJ_MEMDC)
1282 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDeviceGammaRamp );
1283 ret = physdev->funcs->pSetDeviceGammaRamp( physdev, ptr );
1285 else SetLastError( ERROR_INVALID_PARAMETER );
1286 release_dc_ptr( dc );
1291 /***********************************************************************
1292 * GetColorSpace (GDI32.@)
1294 HCOLORSPACE WINAPI GetColorSpace(HDC hdc)
1296 /*FIXME Need to do whatever GetColorSpace actually does */
1300 /***********************************************************************
1301 * CreateColorSpaceA (GDI32.@)
1303 HCOLORSPACE WINAPI CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace )
1309 /***********************************************************************
1310 * CreateColorSpaceW (GDI32.@)
1312 HCOLORSPACE WINAPI CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace )
1318 /***********************************************************************
1319 * DeleteColorSpace (GDI32.@)
1321 BOOL WINAPI DeleteColorSpace( HCOLORSPACE hColorSpace )
1328 /***********************************************************************
1329 * SetColorSpace (GDI32.@)
1331 HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
1338 /***********************************************************************
1339 * GetBoundsRect (GDI32.@)
1341 UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
1346 DC *dc = get_dc_ptr( hdc );
1348 if ( !dc ) return 0;
1350 physdev = GET_DC_PHYSDEV( dc, pGetBoundsRect );
1351 ret = physdev->funcs->pGetBoundsRect( physdev, &device_rect, DCB_RESET );
1354 release_dc_ptr( dc );
1357 if (dc->bounds_enabled && ret == DCB_SET) add_bounds_rect( &dc->bounds, &device_rect );
1361 if (is_rect_empty( &dc->bounds ))
1363 rect->left = rect->top = rect->right = rect->bottom = 0;
1369 rect->left = max( rect->left, 0 );
1370 rect->top = max( rect->top, 0 );
1371 rect->right = min( rect->right, dc->vis_rect.right - dc->vis_rect.left );
1372 rect->bottom = min( rect->bottom, dc->vis_rect.bottom - dc->vis_rect.top );
1375 DPtoLP( hdc, (POINT *)rect, 2 );
1379 if (flags & DCB_RESET) reset_bounds( &dc->bounds );
1380 release_dc_ptr( dc );
1385 /***********************************************************************
1386 * SetBoundsRect (GDI32.@)
1388 UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
1394 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
1395 if (!(dc = get_dc_ptr( hdc ))) return 0;
1397 physdev = GET_DC_PHYSDEV( dc, pSetBoundsRect );
1398 ret = physdev->funcs->pSetBoundsRect( physdev, &dc->bounds, flags );
1401 release_dc_ptr( dc );
1405 ret = (dc->bounds_enabled ? DCB_ENABLE : DCB_DISABLE) |
1406 (is_rect_empty( &dc->bounds ) ? ret & DCB_SET : DCB_SET);
1408 if (flags & DCB_RESET) reset_bounds( &dc->bounds );
1410 if ((flags & DCB_ACCUMULATE) && rect)
1414 LPtoDP( hdc, (POINT *)&rc, 2 );
1415 add_bounds_rect( &dc->bounds, &rc );
1418 if (flags & DCB_ENABLE) dc->bounds_enabled = TRUE;
1419 if (flags & DCB_DISABLE) dc->bounds_enabled = FALSE;
1421 release_dc_ptr( dc );
1426 /***********************************************************************
1427 * GetRelAbs (GDI32.@)
1429 INT WINAPI GetRelAbs( HDC hdc, DWORD dwIgnore )
1432 DC *dc = get_dc_ptr( hdc );
1435 ret = dc->relAbsMode;
1436 release_dc_ptr( dc );
1444 /***********************************************************************
1445 * GetBkMode (GDI32.@)
1447 INT WINAPI GetBkMode( HDC hdc )
1450 DC * dc = get_dc_ptr( hdc );
1453 ret = dc->backgroundMode;
1454 release_dc_ptr( dc );
1460 /***********************************************************************
1461 * SetBkMode (GDI32.@)
1463 INT WINAPI SetBkMode( HDC hdc, INT mode )
1468 if ((mode <= 0) || (mode > BKMODE_LAST))
1470 SetLastError(ERROR_INVALID_PARAMETER);
1473 if ((dc = get_dc_ptr( hdc )))
1475 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetBkMode );
1476 mode = physdev->funcs->pSetBkMode( physdev, mode );
1479 ret = dc->backgroundMode;
1480 dc->backgroundMode = mode;
1482 release_dc_ptr( dc );
1488 /***********************************************************************
1491 INT WINAPI GetROP2( HDC hdc )
1494 DC * dc = get_dc_ptr( hdc );
1498 release_dc_ptr( dc );
1504 /***********************************************************************
1507 INT WINAPI SetROP2( HDC hdc, INT mode )
1512 if ((mode < R2_BLACK) || (mode > R2_WHITE))
1514 SetLastError(ERROR_INVALID_PARAMETER);
1517 if ((dc = get_dc_ptr( hdc )))
1519 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetROP2 );
1520 mode = physdev->funcs->pSetROP2( physdev, mode );
1526 release_dc_ptr( dc );
1532 /***********************************************************************
1533 * SetRelAbs (GDI32.@)
1535 INT WINAPI SetRelAbs( HDC hdc, INT mode )
1540 if ((mode != ABSOLUTE) && (mode != RELATIVE))
1542 SetLastError(ERROR_INVALID_PARAMETER);
1545 if ((dc = get_dc_ptr( hdc )))
1547 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetRelAbs );
1548 mode = physdev->funcs->pSetRelAbs( physdev, mode );
1551 ret = dc->relAbsMode;
1552 dc->relAbsMode = mode;
1554 release_dc_ptr( dc );
1560 /***********************************************************************
1561 * GetPolyFillMode (GDI32.@)
1563 INT WINAPI GetPolyFillMode( HDC hdc )
1566 DC * dc = get_dc_ptr( hdc );
1569 ret = dc->polyFillMode;
1570 release_dc_ptr( dc );
1576 /***********************************************************************
1577 * SetPolyFillMode (GDI32.@)
1579 INT WINAPI SetPolyFillMode( HDC hdc, INT mode )
1584 if ((mode <= 0) || (mode > POLYFILL_LAST))
1586 SetLastError(ERROR_INVALID_PARAMETER);
1589 if ((dc = get_dc_ptr( hdc )))
1591 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetPolyFillMode );
1592 mode = physdev->funcs->pSetPolyFillMode( physdev, mode );
1595 ret = dc->polyFillMode;
1596 dc->polyFillMode = mode;
1598 release_dc_ptr( dc );
1604 /***********************************************************************
1605 * GetStretchBltMode (GDI32.@)
1607 INT WINAPI GetStretchBltMode( HDC hdc )
1610 DC * dc = get_dc_ptr( hdc );
1613 ret = dc->stretchBltMode;
1614 release_dc_ptr( dc );
1620 /***********************************************************************
1621 * SetStretchBltMode (GDI32.@)
1623 INT WINAPI SetStretchBltMode( HDC hdc, INT mode )
1628 if ((mode <= 0) || (mode > MAXSTRETCHBLTMODE))
1630 SetLastError(ERROR_INVALID_PARAMETER);
1633 if ((dc = get_dc_ptr( hdc )))
1635 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetStretchBltMode );
1636 mode = physdev->funcs->pSetStretchBltMode( physdev, mode );
1639 ret = dc->stretchBltMode;
1640 dc->stretchBltMode = mode;
1642 release_dc_ptr( dc );
1648 /***********************************************************************
1649 * GetMapMode (GDI32.@)
1651 INT WINAPI GetMapMode( HDC hdc )
1654 DC * dc = get_dc_ptr( hdc );
1658 release_dc_ptr( dc );
1664 /***********************************************************************
1665 * GetBrushOrgEx (GDI32.@)
1667 BOOL WINAPI GetBrushOrgEx( HDC hdc, LPPOINT pt )
1669 DC * dc = get_dc_ptr( hdc );
1670 if (!dc) return FALSE;
1671 pt->x = dc->brushOrgX;
1672 pt->y = dc->brushOrgY;
1673 release_dc_ptr( dc );
1678 /***********************************************************************
1679 * GetCurrentPositionEx (GDI32.@)
1681 BOOL WINAPI GetCurrentPositionEx( HDC hdc, LPPOINT pt )
1683 DC * dc = get_dc_ptr( hdc );
1684 if (!dc) return FALSE;
1685 pt->x = dc->CursPosX;
1686 pt->y = dc->CursPosY;
1687 release_dc_ptr( dc );
1692 /***********************************************************************
1693 * GetViewportExtEx (GDI32.@)
1695 BOOL WINAPI GetViewportExtEx( HDC hdc, LPSIZE size )
1697 DC * dc = get_dc_ptr( hdc );
1698 if (!dc) return FALSE;
1699 size->cx = dc->vportExtX;
1700 size->cy = dc->vportExtY;
1701 release_dc_ptr( dc );
1706 /***********************************************************************
1707 * GetViewportOrgEx (GDI32.@)
1709 BOOL WINAPI GetViewportOrgEx( HDC hdc, LPPOINT pt )
1711 DC * dc = get_dc_ptr( hdc );
1712 if (!dc) return FALSE;
1713 pt->x = dc->vportOrgX;
1714 pt->y = dc->vportOrgY;
1715 release_dc_ptr( dc );
1720 /***********************************************************************
1721 * GetWindowExtEx (GDI32.@)
1723 BOOL WINAPI GetWindowExtEx( HDC hdc, LPSIZE size )
1725 DC * dc = get_dc_ptr( hdc );
1726 if (!dc) return FALSE;
1727 size->cx = dc->wndExtX;
1728 size->cy = dc->wndExtY;
1729 release_dc_ptr( dc );
1734 /***********************************************************************
1735 * GetWindowOrgEx (GDI32.@)
1737 BOOL WINAPI GetWindowOrgEx( HDC hdc, LPPOINT pt )
1739 DC * dc = get_dc_ptr( hdc );
1740 if (!dc) return FALSE;
1741 pt->x = dc->wndOrgX;
1742 pt->y = dc->wndOrgY;
1743 release_dc_ptr( dc );
1748 /***********************************************************************
1749 * GetLayout (GDI32.@)
1751 * Gets left->right or right->left text layout flags of a dc.
1754 DWORD WINAPI GetLayout(HDC hdc)
1756 DWORD layout = GDI_ERROR;
1758 DC * dc = get_dc_ptr( hdc );
1761 layout = dc->layout;
1762 release_dc_ptr( dc );
1765 TRACE("hdc : %p, layout : %08x\n", hdc, layout);
1770 /***********************************************************************
1771 * SetLayout (GDI32.@)
1773 * Sets left->right or right->left text layout flags of a dc.
1776 DWORD WINAPI SetLayout(HDC hdc, DWORD layout)
1778 DWORD oldlayout = GDI_ERROR;
1780 DC * dc = get_dc_ptr( hdc );
1783 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetLayout );
1784 layout = physdev->funcs->pSetLayout( physdev, layout );
1785 if (layout != GDI_ERROR)
1787 oldlayout = dc->layout;
1788 dc->layout = layout;
1789 if (layout != oldlayout)
1791 if (layout & LAYOUT_RTL) dc->MapMode = MM_ANISOTROPIC;
1792 DC_UpdateXforms( dc );
1795 release_dc_ptr( dc );
1798 TRACE("hdc : %p, old layout : %08x, new layout : %08x\n", hdc, oldlayout, layout);
1803 /***********************************************************************
1804 * GetDCBrushColor (GDI32.@)
1806 COLORREF WINAPI GetDCBrushColor(HDC hdc)
1809 COLORREF dcBrushColor = CLR_INVALID;
1811 TRACE("hdc(%p)\n", hdc);
1813 dc = get_dc_ptr( hdc );
1816 dcBrushColor = dc->dcBrushColor;
1817 release_dc_ptr( dc );
1820 return dcBrushColor;
1823 /***********************************************************************
1824 * SetDCBrushColor (GDI32.@)
1826 COLORREF WINAPI SetDCBrushColor(HDC hdc, COLORREF crColor)
1829 COLORREF oldClr = CLR_INVALID;
1831 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
1833 dc = get_dc_ptr( hdc );
1836 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDCBrushColor );
1837 crColor = physdev->funcs->pSetDCBrushColor( physdev, crColor );
1838 if (crColor != CLR_INVALID)
1840 oldClr = dc->dcBrushColor;
1841 dc->dcBrushColor = crColor;
1843 release_dc_ptr( dc );
1849 /***********************************************************************
1850 * GetDCPenColor (GDI32.@)
1852 COLORREF WINAPI GetDCPenColor(HDC hdc)
1855 COLORREF dcPenColor = CLR_INVALID;
1857 TRACE("hdc(%p)\n", hdc);
1859 dc = get_dc_ptr( hdc );
1862 dcPenColor = dc->dcPenColor;
1863 release_dc_ptr( dc );
1869 /***********************************************************************
1870 * SetDCPenColor (GDI32.@)
1872 COLORREF WINAPI SetDCPenColor(HDC hdc, COLORREF crColor)
1875 COLORREF oldClr = CLR_INVALID;
1877 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
1879 dc = get_dc_ptr( hdc );
1882 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDCPenColor );
1883 crColor = physdev->funcs->pSetDCPenColor( physdev, crColor );
1884 if (crColor != CLR_INVALID)
1886 oldClr = dc->dcPenColor;
1887 dc->dcPenColor = crColor;
1889 release_dc_ptr( dc );
1895 /***********************************************************************
1896 * CancelDC (GDI32.@)
1898 BOOL WINAPI CancelDC(HDC hdc)
1904 /*******************************************************************
1905 * GetMiterLimit [GDI32.@]
1909 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1914 TRACE("(%p,%p)\n", hdc, peLimit);
1916 dc = get_dc_ptr( hdc );
1920 *peLimit = dc->miterLimit;
1922 release_dc_ptr( dc );
1928 /*******************************************************************
1929 * SetMiterLimit [GDI32.@]
1933 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1938 TRACE("(%p,%f,%p)\n", hdc, eNewLimit, peOldLimit);
1940 dc = get_dc_ptr( hdc );
1944 *peOldLimit = dc->miterLimit;
1945 dc->miterLimit = eNewLimit;
1946 release_dc_ptr( dc );
1952 /*******************************************************************
1953 * GdiIsMetaPrintDC [GDI32.@]
1955 BOOL WINAPI GdiIsMetaPrintDC(HDC hdc)
1961 /*******************************************************************
1962 * GdiIsMetaFileDC [GDI32.@]
1964 BOOL WINAPI GdiIsMetaFileDC(HDC hdc)
1968 switch( GetObjectType( hdc ) )
1977 /*******************************************************************
1978 * GdiIsPlayMetafileDC [GDI32.@]
1980 BOOL WINAPI GdiIsPlayMetafileDC(HDC hdc)