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
34 #include "gdi_private.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(dc);
40 static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
42 static BOOL DC_DeleteObject( HGDIOBJ handle );
44 static const struct gdi_obj_funcs dc_funcs =
46 NULL, /* pSelectObject */
47 NULL, /* pGetObjectA */
48 NULL, /* pGetObjectW */
49 NULL, /* pUnrealizeObject */
50 DC_DeleteObject /* pDeleteObject */
54 static inline DC *get_dc_obj( HDC hdc )
56 DC *dc = GDI_GetObjPtr( hdc, 0 );
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))
64 GDI_ReleaseObj( hdc );
65 SetLastError( ERROR_INVALID_HANDLE );
72 /***********************************************************************
75 DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic )
79 if (!(dc = HeapAlloc( GetProcessHeap(), 0, sizeof(*dc) ))) return NULL;
83 dc->thread = GetCurrentThreadId();
99 dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */
104 dc->hMetaClipRgn = 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 ));
111 dc->hPalette = GetStockObject( DEFAULT_PALETTE );
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 );
124 dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP;
128 dc->MapMode = MM_TEXT;
129 dc->GraphicsMode = GM_COMPATIBLE;
130 dc->pAbortProc = NULL;
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);
150 if (!(dc->hSelf = alloc_gdi_handle( &dc->header, magic, &dc_funcs )))
152 HeapFree( GetProcessHeap(), 0, dc );
160 /***********************************************************************
163 BOOL free_dc_ptr( DC *dc )
165 assert( dc->refcount == 1 );
166 if (free_gdi_handle( dc->hSelf ) != dc) return FALSE; /* shouldn't happen */
167 return HeapFree( GetProcessHeap(), 0, dc );
171 /***********************************************************************
174 * Retrieve a DC pointer but release the GDI lock.
176 DC *get_dc_ptr( HDC hdc )
178 DC *dc = get_dc_obj( hdc );
179 if (!dc) return NULL;
181 if (!InterlockedCompareExchange( &dc->refcount, 1, 0 ))
183 dc->thread = GetCurrentThreadId();
185 else if (dc->thread != GetCurrentThreadId())
187 WARN( "dc %p belongs to thread %04x\n", hdc, dc->thread );
188 GDI_ReleaseObj( hdc );
191 else InterlockedIncrement( &dc->refcount );
193 GDI_ReleaseObj( hdc );
198 /***********************************************************************
201 void release_dc_ptr( DC *dc )
206 ref = InterlockedDecrement( &dc->refcount );
208 if (ref) dc->thread = GetCurrentThreadId(); /* we still own it */
212 /***********************************************************************
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.
219 void update_dc( DC *dc )
221 if (InterlockedExchange( &dc->dirty, 0 ) && dc->hookThunk)
222 dc->hookThunk( dc->hSelf, DCHC_INVALIDVISRGN, dc->dwHookData, 0 );
226 /***********************************************************************
229 static BOOL DC_DeleteObject( HGDIOBJ handle )
231 return DeleteDC( handle );
235 /***********************************************************************
238 * Setup device-specific DC values for a newly created DC.
240 void DC_InitDC( DC* dc )
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 );
252 /***********************************************************************
255 * Computes the inverse of the transformation xformSrc and stores it to
256 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
259 static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
263 determinant = xformSrc->eM11*xformSrc->eM22 -
264 xformSrc->eM12*xformSrc->eM21;
265 if (determinant > -1e-12 && determinant < 1e-12)
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;
281 /***********************************************************************
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.
291 void DC_UpdateXforms( DC *dc )
293 XFORM xformWnd2Vport, oldworld2vport;
294 double scaleX, scaleY;
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;
308 oldworld2vport = dc->xformWorld2Vport;
309 /* Combine with the world transformation */
310 CombineTransform( &dc->xformWorld2Vport, &dc->xformWorld2Wnd,
313 /* Create inverse of world-to-viewport transformation */
314 dc->vport2WorldValid = DC_InvertXform( &dc->xformWorld2Vport,
315 &dc->xformVport2World );
317 /* Reselect the font and pen back into the dc so that the size
319 if (memcmp(&oldworld2vport, &dc->xformWorld2Vport, sizeof(oldworld2vport)) &&
320 !GdiIsMetaFileDC(dc->hSelf))
322 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_FONT));
323 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_PEN));
328 /***********************************************************************
329 * get_dc_state (Not a Windows API)
331 HDC get_dc_state( HDC hdc )
336 if (!(dc = get_dc_ptr( hdc ))) return 0;
337 if (!(newdc = HeapAlloc( GetProcessHeap(), 0, sizeof(*newdc ))))
339 release_dc_ptr( dc );
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;
386 newdc->thread = GetCurrentThreadId();
388 newdc->saveLevel = 0;
391 PATH_InitGdiPath( &newdc->path );
393 newdc->pAbortProc = NULL;
394 newdc->hookThunk = NULL;
396 newdc->saved_visrgn = NULL;
398 if (!(newdc->hSelf = alloc_gdi_handle( &newdc->header, dc->header.type, &dc_funcs )))
400 HeapFree( GetProcessHeap(), 0, newdc );
401 release_dc_ptr( dc );
404 handle = newdc->hSelf;
405 TRACE("(%p): returning %p\n", hdc, handle );
407 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
412 newdc->hMetaClipRgn = 0;
415 newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
416 CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
420 newdc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
421 CombineRgn( newdc->hMetaRgn, dc->hMetaRgn, 0, RGN_COPY );
423 /* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
425 release_dc_ptr( newdc );
426 release_dc_ptr( dc );
431 /***********************************************************************
432 * set_dc_state (Not a Windows API)
434 void set_dc_state( HDC hdc, HDC hdcs )
438 if (!(dc = get_dc_ptr( hdc ))) return;
439 if (!(dcs = get_dc_ptr( hdcs )))
441 release_dc_ptr( dc );
444 if (!(dcs->flags & DC_SAVED))
446 release_dc_ptr( dc );
447 release_dc_ptr( dcs );
450 TRACE("%p %p\n", hdc, hdcs );
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;
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;
493 if (!dc->hClipRgn) dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
494 CombineRgn( dc->hClipRgn, dcs->hClipRgn, 0, RGN_COPY );
498 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
503 if (!dc->hMetaRgn) dc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
504 CombineRgn( dc->hMetaRgn, dcs->hMetaRgn, 0, RGN_COPY );
508 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
511 CLIPPING_UpdateGCRegion( dc );
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 );
525 /***********************************************************************
528 INT WINAPI SaveDC( HDC hdc )
534 dc = get_dc_ptr( hdc );
537 if(dc->funcs->pSaveDC)
539 ret = dc->funcs->pSaveDC( dc->physDev );
541 ret = ++dc->saveLevel;
542 release_dc_ptr( dc );
546 if (!(hdcs = get_dc_state( hdc )))
548 release_dc_ptr( dc );
551 dcs = get_dc_ptr( hdcs );
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).
559 if (!PATH_AssignGdiPath( &dcs->path, &dc->path ))
561 release_dc_ptr( dc );
562 release_dc_ptr( dcs );
567 dcs->saved_dc = dc->saved_dc;
569 TRACE("(%p): returning %d\n", hdc, dc->saveLevel+1 );
570 ret = ++dc->saveLevel;
571 release_dc_ptr( dcs );
572 release_dc_ptr( dc );
577 /***********************************************************************
578 * RestoreDC (GDI32.@)
580 BOOL WINAPI RestoreDC( HDC hdc, INT level )
585 TRACE("%p %d\n", hdc, level );
586 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
588 if(abs(level) > dc->saveLevel || level == 0)
590 release_dc_ptr( dc );
596 if(dc->funcs->pRestoreDC)
598 success = dc->funcs->pRestoreDC( dc->physDev, level );
599 if(level < 0) level = dc->saveLevel + level + 1;
601 dc->saveLevel = level - 1;
602 release_dc_ptr( dc );
606 if (level < 0) level = dc->saveLevel + level + 1;
608 while (dc->saveLevel >= level)
610 HDC hdcs = dc->saved_dc;
611 if (!(dcs = get_dc_ptr( hdcs )))
616 dc->saved_dc = dcs->saved_dc;
618 if (--dc->saveLevel < level)
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 */
626 release_dc_ptr( dcs );
629 release_dc_ptr( dc );
634 /***********************************************************************
635 * CreateDCW (GDI32.@)
637 HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
638 const DEVMODEW *initData )
642 const DC_FUNCTIONS *funcs;
647 if (!device || !DRIVER_GetDriverName( device, buf, 300 ))
651 ERR( "no device found for %s\n", debugstr_w(device) );
654 strcpyW(buf, driver);
657 if (!(funcs = DRIVER_load_driver( buf )))
659 ERR( "no driver found for %s\n", debugstr_w(buf) );
662 if (!(dc = alloc_dc_ptr( funcs, OBJ_DC ))) goto error;
665 dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
666 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;
668 TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
669 debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
671 if (dc->funcs->pCreateDC &&
672 !dc->funcs->pCreateDC( hdc, &dc->physDev, buf, device, output, initData ))
674 WARN("creation aborted by device\n" );
678 SetRectRgn( dc->hVisRgn, 0, 0,
679 GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ) );
682 release_dc_ptr( dc );
686 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
687 if (dc) free_dc_ptr( dc );
688 DRIVER_release_driver( funcs );
693 /***********************************************************************
694 * CreateDCA (GDI32.@)
696 HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
697 const DEVMODEA *initData )
699 UNICODE_STRING driverW, deviceW, outputW;
703 if (driver) RtlCreateUnicodeStringFromAsciiz(&driverW, driver);
704 else driverW.Buffer = NULL;
706 if (device) RtlCreateUnicodeStringFromAsciiz(&deviceW, device);
707 else deviceW.Buffer = NULL;
709 if (output) RtlCreateUnicodeStringFromAsciiz(&outputW, output);
710 else outputW.Buffer = NULL;
715 /* don't convert initData for DISPLAY driver, it's not used */
716 if (!driverW.Buffer || strcmpiW( driverW.Buffer, displayW ))
717 initDataW = GdiConvertToDevmodeW(initData);
720 ret = CreateDCW( driverW.Buffer, deviceW.Buffer, outputW.Buffer, initDataW );
722 RtlFreeUnicodeString(&driverW);
723 RtlFreeUnicodeString(&deviceW);
724 RtlFreeUnicodeString(&outputW);
725 HeapFree(GetProcessHeap(), 0, initDataW);
730 /***********************************************************************
731 * CreateICA (GDI32.@)
733 HDC WINAPI CreateICA( LPCSTR driver, LPCSTR device, LPCSTR output,
734 const DEVMODEA* initData )
736 /* Nothing special yet for ICs */
737 return CreateDCA( driver, device, output, initData );
741 /***********************************************************************
742 * CreateICW (GDI32.@)
744 HDC WINAPI CreateICW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
745 const DEVMODEW* initData )
747 /* Nothing special yet for ICs */
748 return CreateDCW( driver, device, output, initData );
752 /***********************************************************************
753 * CreateCompatibleDC (GDI32.@)
755 HDC WINAPI CreateCompatibleDC( HDC hdc )
759 const DC_FUNCTIONS *funcs = NULL;
760 PHYSDEV physDev = NULL;
764 if ((origDC = get_dc_ptr( hdc )))
766 if (GetObjectType( hdc ) == OBJ_DC)
768 funcs = origDC->funcs;
769 physDev = origDC->physDev;
771 release_dc_ptr( origDC );
772 if (funcs) funcs = DRIVER_get_driver( funcs );
774 else if (hdc) return 0;
776 if (!funcs && !(funcs = DRIVER_load_driver( displayW ))) return 0;
778 if (!(dc = alloc_dc_ptr( funcs, OBJ_MEMDC ))) goto error;
780 TRACE("(%p): returning %p\n", hdc, dc->hSelf );
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 */
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;
791 if (dc->funcs->pCreateDC &&
792 !dc->funcs->pCreateDC( dc->hSelf, &dc->physDev, NULL, NULL, NULL, NULL ))
794 WARN("creation aborted by device\n");
799 release_dc_ptr( dc );
803 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
804 if (dc) free_dc_ptr( dc );
805 DRIVER_release_driver( funcs );
810 /***********************************************************************
813 BOOL WINAPI DeleteDC( HDC hdc )
815 const DC_FUNCTIONS *funcs = NULL;
822 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
823 if (dc->refcount != 1)
825 FIXME( "not deleting busy DC %p refcount %u\n", dc->hSelf, dc->refcount );
826 release_dc_ptr( dc );
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 ))
833 release_dc_ptr( dc );
837 while (dc->saveLevel)
840 HDC hdcs = dc->saved_dc;
841 if (!(dcs = get_dc_ptr( hdcs ))) break;
842 dc->saved_dc = dcs->saved_dc;
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);
852 if (!(dc->flags & DC_SAVED))
854 SelectObject( hdc, GetStockObject(BLACK_PEN) );
855 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
856 SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
857 SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
859 if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc->physDev);
863 while (dc->saved_visrgn)
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;
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);
877 if (funcs) DRIVER_release_driver( funcs ); /* do that after releasing the GDI lock */
882 /***********************************************************************
885 HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
890 if ((dc = get_dc_ptr( hdc )))
892 if (dc->funcs->pResetDC) ret = dc->funcs->pResetDC( dc->physDev, devmode );
893 release_dc_ptr( dc );
899 /***********************************************************************
902 HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
907 if (devmode) devmodeW = GdiConvertToDevmodeW(devmode);
908 else devmodeW = NULL;
910 ret = ResetDCW(hdc, devmodeW);
912 HeapFree(GetProcessHeap(), 0, devmodeW);
917 /***********************************************************************
918 * GetDeviceCaps (GDI32.@)
920 INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
925 if ((dc = get_dc_ptr( hdc )))
927 if (dc->funcs->pGetDeviceCaps) ret = dc->funcs->pGetDeviceCaps( dc->physDev, cap );
928 else switch(cap) /* return meaningful values for some entries */
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;
942 release_dc_ptr( dc );
948 /***********************************************************************
949 * GetBkColor (GDI32.@)
951 COLORREF WINAPI GetBkColor( HDC hdc )
954 DC * dc = get_dc_ptr( hdc );
957 ret = dc->backgroundColor;
958 release_dc_ptr( dc );
964 /***********************************************************************
965 * SetBkColor (GDI32.@)
967 COLORREF WINAPI SetBkColor( HDC hdc, COLORREF color )
970 DC * dc = get_dc_ptr( hdc );
972 TRACE("hdc=%p color=0x%08x\n", hdc, color);
974 if (!dc) return CLR_INVALID;
975 oldColor = dc->backgroundColor;
976 if (dc->funcs->pSetBkColor)
978 color = dc->funcs->pSetBkColor(dc->physDev, color);
979 if (color == CLR_INVALID) /* don't change it */
982 oldColor = CLR_INVALID;
985 dc->backgroundColor = color;
986 release_dc_ptr( dc );
991 /***********************************************************************
992 * GetTextColor (GDI32.@)
994 COLORREF WINAPI GetTextColor( HDC hdc )
997 DC * dc = get_dc_ptr( hdc );
1000 ret = dc->textColor;
1001 release_dc_ptr( dc );
1007 /***********************************************************************
1008 * SetTextColor (GDI32.@)
1010 COLORREF WINAPI SetTextColor( HDC hdc, COLORREF color )
1013 DC * dc = get_dc_ptr( hdc );
1015 TRACE(" hdc=%p color=0x%08x\n", hdc, color);
1017 if (!dc) return CLR_INVALID;
1018 oldColor = dc->textColor;
1019 if (dc->funcs->pSetTextColor)
1021 color = dc->funcs->pSetTextColor(dc->physDev, color);
1022 if (color == CLR_INVALID) /* don't change it */
1025 oldColor = CLR_INVALID;
1028 dc->textColor = color;
1029 release_dc_ptr( dc );
1034 /***********************************************************************
1035 * GetTextAlign (GDI32.@)
1037 UINT WINAPI GetTextAlign( HDC hdc )
1040 DC * dc = get_dc_ptr( hdc );
1043 ret = dc->textAlign;
1044 release_dc_ptr( dc );
1050 /***********************************************************************
1051 * SetTextAlign (GDI32.@)
1053 UINT WINAPI SetTextAlign( HDC hdc, UINT align )
1056 DC *dc = get_dc_ptr( hdc );
1058 TRACE("hdc=%p align=%d\n", hdc, align);
1060 if (!dc) return 0x0;
1061 ret = dc->textAlign;
1062 if (dc->funcs->pSetTextAlign)
1063 if (!dc->funcs->pSetTextAlign(dc->physDev, align))
1065 if (ret != GDI_ERROR)
1066 dc->textAlign = align;
1067 release_dc_ptr( dc );
1071 /***********************************************************************
1072 * GetDCOrgEx (GDI32.@)
1074 BOOL WINAPI GetDCOrgEx( HDC hDC, LPPOINT lpp )
1078 if (!lpp) return FALSE;
1079 if (!(dc = get_dc_ptr( hDC ))) return FALSE;
1081 lpp->x = lpp->y = 0;
1082 if (dc->funcs->pGetDCOrgEx) dc->funcs->pGetDCOrgEx( dc->physDev, lpp );
1083 release_dc_ptr( dc );
1088 /***********************************************************************
1089 * GetGraphicsMode (GDI32.@)
1091 INT WINAPI GetGraphicsMode( HDC hdc )
1094 DC * dc = get_dc_ptr( hdc );
1097 ret = dc->GraphicsMode;
1098 release_dc_ptr( dc );
1104 /***********************************************************************
1105 * SetGraphicsMode (GDI32.@)
1107 INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
1110 DC *dc = get_dc_ptr( hdc );
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.
1118 if ((mode > 0) && (mode <= GM_LAST))
1120 ret = dc->GraphicsMode;
1121 dc->GraphicsMode = mode;
1123 release_dc_ptr( dc );
1128 /***********************************************************************
1129 * GetArcDirection (GDI32.@)
1131 INT WINAPI GetArcDirection( HDC hdc )
1134 DC * dc = get_dc_ptr( hdc );
1137 ret = dc->ArcDirection;
1138 release_dc_ptr( dc );
1144 /***********************************************************************
1145 * SetArcDirection (GDI32.@)
1147 INT WINAPI SetArcDirection( HDC hdc, INT nDirection )
1150 INT nOldDirection = 0;
1152 if (nDirection!=AD_COUNTERCLOCKWISE && nDirection!=AD_CLOCKWISE)
1154 SetLastError(ERROR_INVALID_PARAMETER);
1158 if ((dc = get_dc_ptr( hdc )))
1160 if (dc->funcs->pSetArcDirection)
1162 dc->funcs->pSetArcDirection(dc->physDev, nDirection);
1164 nOldDirection = dc->ArcDirection;
1165 dc->ArcDirection = nDirection;
1166 release_dc_ptr( dc );
1168 return nOldDirection;
1172 /***********************************************************************
1173 * GetWorldTransform (GDI32.@)
1175 BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
1178 if (!xform) return FALSE;
1179 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
1180 *xform = dc->xformWorld2Wnd;
1181 release_dc_ptr( dc );
1186 /***********************************************************************
1187 * GetTransform (GDI32.@)
1189 BOOL WINAPI GetTransform( HDC hdc, DWORD unknown, LPXFORM xform )
1191 if (unknown == 0x0203) return GetWorldTransform( hdc, xform );
1192 FIXME("stub: don't know what to do for code %x\n", unknown );
1197 /***********************************************************************
1198 * SetWorldTransform (GDI32.@)
1200 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
1203 DC *dc = get_dc_ptr( hdc );
1205 if (!dc) return FALSE;
1206 if (!xform) goto done;
1208 /* Check that graphics mode is GM_ADVANCED */
1209 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
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);
1214 if (dc->funcs->pSetWorldTransform)
1216 ret = dc->funcs->pSetWorldTransform(dc->physDev, xform);
1217 if (!ret) goto done;
1220 dc->xformWorld2Wnd = *xform;
1221 DC_UpdateXforms( dc );
1224 release_dc_ptr( dc );
1229 /****************************************************************************
1230 * ModifyWorldTransform [GDI32.@]
1231 * Modifies the world transformation for a device context.
1234 * hdc [I] Handle to device context
1235 * xform [I] XFORM structure that will be used to modify the world
1237 * iMode [I] Specifies in what way to modify the world transformation
1240 * Resets the world transformation to the identity matrix.
1241 * The parameter xform is ignored.
1243 * Multiplies xform into the world transformation matrix from
1246 * Multiplies xform into the world transformation matrix from
1251 * Failure: FALSE. Use GetLastError() to determine the cause.
1253 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform,
1257 DC *dc = get_dc_ptr( hdc );
1259 /* Check for illegal parameters */
1260 if (!dc) return FALSE;
1261 if (!xform && iMode != MWT_IDENTITY) goto done;
1263 /* Check that graphics mode is GM_ADVANCED */
1264 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1266 if (dc->funcs->pModifyWorldTransform)
1268 ret = dc->funcs->pModifyWorldTransform(dc->physDev, xform, iMode);
1269 if (!ret) goto done;
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;
1282 case MWT_LEFTMULTIPLY:
1283 CombineTransform( &dc->xformWorld2Wnd, xform,
1284 &dc->xformWorld2Wnd );
1286 case MWT_RIGHTMULTIPLY:
1287 CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd,
1294 DC_UpdateXforms( dc );
1297 release_dc_ptr( dc );
1302 /****************************************************************************
1303 * CombineTransform [GDI32.@]
1304 * Combines two transformation matrices.
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
1312 * The same matrix can be passed in for more than one of the parameters.
1316 * Failure: FALSE. Use GetLastError() to determine the cause.
1318 BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
1319 const XFORM *xform2 )
1323 /* Check for illegal parameters */
1324 if (!xformResult || !xform1 || !xform2)
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 +
1340 xformTemp.eDy = xform1->eDx * xform2->eM12 +
1341 xform1->eDy * xform2->eM22 +
1344 /* Copy the result to xformResult */
1345 *xformResult = xformTemp;
1351 /***********************************************************************
1352 * SetDCHook (GDI32.@)
1354 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1356 BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD_PTR dwHookData )
1358 DC *dc = get_dc_ptr( hdc );
1360 if (!dc) return FALSE;
1362 if (!(dc->flags & DC_SAVED))
1364 dc->dwHookData = dwHookData;
1365 dc->hookThunk = hookProc;
1367 release_dc_ptr( dc );
1372 /***********************************************************************
1373 * GetDCHook (GDI32.@)
1375 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1377 DWORD_PTR WINAPI GetDCHook( HDC hdc, DCHOOKPROC *proc )
1379 DC *dc = get_dc_ptr( hdc );
1383 if (proc) *proc = dc->hookThunk;
1384 ret = dc->dwHookData;
1385 release_dc_ptr( dc );
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 )
1395 DC *dc = get_dc_ptr( hdc );
1397 if (!dc) return FALSE;
1400 args[5] = HDC_16(hdc);
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 );
1408 release_dc_ptr( dc );
1412 /***********************************************************************
1413 * SetDCHook (GDI.190)
1415 BOOL16 WINAPI SetDCHook16( HDC16 hdc16, FARPROC16 hookProc, DWORD dwHookData )
1417 DC *dc = get_dc_ptr( HDC_32(hdc16) );
1419 if (!dc) return FALSE;
1420 if (!(dc->flags & DC_SAVED))
1422 dc->dwHookData = dwHookData;
1423 dc->hookThunk = call_dc_hook16;
1424 dc->hookProc = hookProc;
1426 release_dc_ptr( dc );
1431 /***********************************************************************
1432 * GetDCHook (GDI.191)
1434 DWORD WINAPI GetDCHook16( HDC16 hdc16, FARPROC16 *phookProc )
1436 HDC hdc = HDC_32( hdc16 );
1437 DC *dc = get_dc_ptr( hdc );
1441 *phookProc = dc->hookProc;
1442 ret = dc->dwHookData;
1443 release_dc_ptr( dc );
1448 /***********************************************************************
1449 * SetHookFlags (GDI32.@)
1451 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1453 WORD WINAPI SetHookFlags( HDC hdc, WORD flags )
1455 DC *dc = get_dc_obj( hdc ); /* not get_dc_ptr, this needs to work from any thread */
1460 /* "Undocumented Windows" info is slightly confusing. */
1462 TRACE("hDC %p, flags %04x\n",hdc,flags);
1464 if (flags & DCHF_INVALIDATEVISRGN)
1465 ret = InterlockedExchange( &dc->dirty, 1 );
1466 else if (flags & DCHF_VALIDATEVISRGN || !flags)
1467 ret = InterlockedExchange( &dc->dirty, 0 );
1469 GDI_ReleaseObj( dc );
1473 /***********************************************************************
1474 * SetICMMode (GDI32.@)
1476 INT WINAPI SetICMMode(HDC hdc, INT iEnableICM)
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;
1485 /***********************************************************************
1486 * GetDeviceGammaRamp (GDI32.@)
1488 BOOL WINAPI GetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1491 DC *dc = get_dc_ptr( hDC );
1495 if (dc->funcs->pGetDeviceGammaRamp)
1496 ret = dc->funcs->pGetDeviceGammaRamp(dc->physDev, ptr);
1497 release_dc_ptr( dc );
1502 /***********************************************************************
1503 * SetDeviceGammaRamp (GDI32.@)
1505 BOOL WINAPI SetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1508 DC *dc = get_dc_ptr( hDC );
1512 if (dc->funcs->pSetDeviceGammaRamp)
1513 ret = dc->funcs->pSetDeviceGammaRamp(dc->physDev, ptr);
1514 release_dc_ptr( dc );
1519 /***********************************************************************
1520 * GetColorSpace (GDI32.@)
1522 HCOLORSPACE WINAPI GetColorSpace(HDC hdc)
1524 /*FIXME Need to to whatever GetColorSpace actually does */
1528 /***********************************************************************
1529 * CreateColorSpaceA (GDI32.@)
1531 HCOLORSPACE WINAPI CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace )
1537 /***********************************************************************
1538 * CreateColorSpaceW (GDI32.@)
1540 HCOLORSPACE WINAPI CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace )
1546 /***********************************************************************
1547 * DeleteColorSpace (GDI32.@)
1549 BOOL WINAPI DeleteColorSpace( HCOLORSPACE hColorSpace )
1556 /***********************************************************************
1557 * SetColorSpace (GDI32.@)
1559 HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
1566 /***********************************************************************
1567 * GetBoundsRect (GDI32.@)
1569 UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
1572 DC *dc = get_dc_ptr( hdc );
1574 if ( !dc ) return 0;
1576 if (rect) *rect = dc->BoundsRect;
1578 ret = ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1580 if (flags & DCB_RESET)
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;
1588 release_dc_ptr( dc );
1593 /***********************************************************************
1594 * SetBoundsRect (GDI32.@)
1596 UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
1601 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
1602 if (!(dc = get_dc_ptr( hdc ))) return 0;
1604 ret = ((dc->flags & DC_BOUNDS_ENABLE) ? DCB_ENABLE : DCB_DISABLE) |
1605 ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1607 if (flags & DCB_RESET)
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;
1616 if ((flags & DCB_ACCUMULATE) && rect && rect->left < rect->right && rect->top < rect->bottom)
1618 if (dc->flags & DC_BOUNDS_SET)
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 );
1627 dc->BoundsRect = *rect;
1628 dc->flags |= DC_BOUNDS_SET;
1632 if (flags & DCB_ENABLE) dc->flags |= DC_BOUNDS_ENABLE;
1633 if (flags & DCB_DISABLE) dc->flags &= ~DC_BOUNDS_ENABLE;
1635 release_dc_ptr( dc );
1640 /***********************************************************************
1641 * GetRelAbs (GDI32.@)
1643 INT WINAPI GetRelAbs( HDC hdc, DWORD dwIgnore )
1646 DC *dc = get_dc_ptr( hdc );
1649 ret = dc->relAbsMode;
1650 release_dc_ptr( dc );
1658 /***********************************************************************
1659 * GetBkMode (GDI32.@)
1661 INT WINAPI GetBkMode( HDC hdc )
1664 DC * dc = get_dc_ptr( hdc );
1667 ret = dc->backgroundMode;
1668 release_dc_ptr( dc );
1674 /***********************************************************************
1675 * SetBkMode (GDI32.@)
1677 INT WINAPI SetBkMode( HDC hdc, INT mode )
1681 if ((mode <= 0) || (mode > BKMODE_LAST))
1683 SetLastError(ERROR_INVALID_PARAMETER);
1686 if (!(dc = get_dc_ptr( hdc ))) return 0;
1688 ret = dc->backgroundMode;
1689 if (dc->funcs->pSetBkMode)
1690 if (!dc->funcs->pSetBkMode( dc->physDev, mode ))
1693 dc->backgroundMode = mode;
1694 release_dc_ptr( dc );
1699 /***********************************************************************
1702 INT WINAPI GetROP2( HDC hdc )
1705 DC * dc = get_dc_ptr( hdc );
1709 release_dc_ptr( dc );
1715 /***********************************************************************
1718 INT WINAPI SetROP2( HDC hdc, INT mode )
1722 if ((mode < R2_BLACK) || (mode > R2_WHITE))
1724 SetLastError(ERROR_INVALID_PARAMETER);
1727 if (!(dc = get_dc_ptr( hdc ))) return 0;
1729 if (dc->funcs->pSetROP2)
1730 if (!dc->funcs->pSetROP2( dc->physDev, mode ))
1734 release_dc_ptr( dc );
1739 /***********************************************************************
1740 * SetRelAbs (GDI32.@)
1742 INT WINAPI SetRelAbs( HDC hdc, INT mode )
1746 if ((mode != ABSOLUTE) && (mode != RELATIVE))
1748 SetLastError(ERROR_INVALID_PARAMETER);
1751 if (!(dc = get_dc_ptr( hdc ))) return 0;
1752 if (dc->funcs->pSetRelAbs)
1753 ret = dc->funcs->pSetRelAbs( dc->physDev, mode );
1756 ret = dc->relAbsMode;
1757 dc->relAbsMode = mode;
1759 release_dc_ptr( dc );
1764 /***********************************************************************
1765 * GetPolyFillMode (GDI32.@)
1767 INT WINAPI GetPolyFillMode( HDC hdc )
1770 DC * dc = get_dc_ptr( hdc );
1773 ret = dc->polyFillMode;
1774 release_dc_ptr( dc );
1780 /***********************************************************************
1781 * SetPolyFillMode (GDI32.@)
1783 INT WINAPI SetPolyFillMode( HDC hdc, INT mode )
1787 if ((mode <= 0) || (mode > POLYFILL_LAST))
1789 SetLastError(ERROR_INVALID_PARAMETER);
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 ))
1798 dc->polyFillMode = mode;
1799 release_dc_ptr( dc );
1804 /***********************************************************************
1805 * GetStretchBltMode (GDI32.@)
1807 INT WINAPI GetStretchBltMode( HDC hdc )
1810 DC * dc = get_dc_ptr( hdc );
1813 ret = dc->stretchBltMode;
1814 release_dc_ptr( dc );
1820 /***********************************************************************
1821 * SetStretchBltMode (GDI32.@)
1823 INT WINAPI SetStretchBltMode( HDC hdc, INT mode )
1827 if ((mode <= 0) || (mode > MAXSTRETCHBLTMODE))
1829 SetLastError(ERROR_INVALID_PARAMETER);
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 ))
1838 dc->stretchBltMode = mode;
1839 release_dc_ptr( dc );
1844 /***********************************************************************
1845 * GetMapMode (GDI32.@)
1847 INT WINAPI GetMapMode( HDC hdc )
1850 DC * dc = get_dc_ptr( hdc );
1854 release_dc_ptr( dc );
1860 /***********************************************************************
1861 * GetBrushOrgEx (GDI32.@)
1863 BOOL WINAPI GetBrushOrgEx( HDC hdc, LPPOINT pt )
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 );
1874 /***********************************************************************
1875 * GetCurrentPositionEx (GDI32.@)
1877 BOOL WINAPI GetCurrentPositionEx( HDC hdc, LPPOINT pt )
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 );
1888 /***********************************************************************
1889 * GetViewportExtEx (GDI32.@)
1891 BOOL WINAPI GetViewportExtEx( HDC hdc, LPSIZE size )
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 );
1902 /***********************************************************************
1903 * GetViewportOrgEx (GDI32.@)
1905 BOOL WINAPI GetViewportOrgEx( HDC hdc, LPPOINT pt )
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 );
1916 /***********************************************************************
1917 * GetWindowExtEx (GDI32.@)
1919 BOOL WINAPI GetWindowExtEx( HDC hdc, LPSIZE size )
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 );
1930 /***********************************************************************
1931 * GetWindowOrgEx (GDI32.@)
1933 BOOL WINAPI GetWindowOrgEx( HDC hdc, LPPOINT pt )
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 );
1944 /***********************************************************************
1945 * GetLayout (GDI32.@)
1947 * Gets left->right or right->left text layout flags of a dc.
1950 DWORD WINAPI GetLayout(HDC hdc)
1952 DWORD layout = GDI_ERROR;
1954 DC * dc = get_dc_ptr( hdc );
1957 layout = dc->layout;
1958 release_dc_ptr( dc );
1961 TRACE("hdc : %p, layout : %08x\n", hdc, layout);
1966 /***********************************************************************
1967 * SetLayout (GDI32.@)
1969 * Sets left->right or right->left text layout flags of a dc.
1972 DWORD WINAPI SetLayout(HDC hdc, DWORD layout)
1974 DWORD oldlayout = GDI_ERROR;
1976 DC * dc = get_dc_ptr( hdc );
1979 oldlayout = dc->layout;
1980 dc->layout = layout;
1981 release_dc_ptr( dc );
1984 TRACE("hdc : %p, old layout : %08x, new layout : %08x\n", hdc, oldlayout, layout);
1989 /***********************************************************************
1990 * GetDCBrushColor (GDI32.@)
1992 * Retrieves the current brush color for the specified device
1996 COLORREF WINAPI GetDCBrushColor(HDC hdc)
1999 COLORREF dcBrushColor = CLR_INVALID;
2001 TRACE("hdc(%p)\n", hdc);
2003 dc = get_dc_ptr( hdc );
2006 dcBrushColor = dc->dcBrushColor;
2007 release_dc_ptr( dc );
2010 return dcBrushColor;
2013 /***********************************************************************
2014 * SetDCBrushColor (GDI32.@)
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.
2021 COLORREF WINAPI SetDCBrushColor(HDC hdc, COLORREF crColor)
2024 COLORREF oldClr = CLR_INVALID;
2026 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2028 dc = get_dc_ptr( hdc );
2031 if (dc->funcs->pSetDCBrushColor)
2032 crColor = dc->funcs->pSetDCBrushColor( dc->physDev, crColor );
2033 else if (dc->hBrush == GetStockObject( DC_BRUSH ))
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 );
2041 if (crColor != CLR_INVALID)
2043 oldClr = dc->dcBrushColor;
2044 dc->dcBrushColor = crColor;
2047 release_dc_ptr( dc );
2053 /***********************************************************************
2054 * GetDCPenColor (GDI32.@)
2056 * Retrieves the current pen color for the specified device
2060 COLORREF WINAPI GetDCPenColor(HDC hdc)
2063 COLORREF dcPenColor = CLR_INVALID;
2065 TRACE("hdc(%p)\n", hdc);
2067 dc = get_dc_ptr( hdc );
2070 dcPenColor = dc->dcPenColor;
2071 release_dc_ptr( dc );
2077 /***********************************************************************
2078 * SetDCPenColor (GDI32.@)
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.
2085 COLORREF WINAPI SetDCPenColor(HDC hdc, COLORREF crColor)
2088 COLORREF oldClr = CLR_INVALID;
2090 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2092 dc = get_dc_ptr( hdc );
2095 if (dc->funcs->pSetDCPenColor)
2096 crColor = dc->funcs->pSetDCPenColor( dc->physDev, crColor );
2097 else if (dc->hPen == GetStockObject( DC_PEN ))
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 );
2106 if (crColor != CLR_INVALID)
2108 oldClr = dc->dcPenColor;
2109 dc->dcPenColor = crColor;
2112 release_dc_ptr( dc );
2118 /***********************************************************************
2119 * CancelDC (GDI32.@)
2121 BOOL WINAPI CancelDC(HDC hdc)
2127 /***********************************************************************
2128 * SetVirtualResolution (GDI32.@)
2130 * Undocumented on msdn. Called when PowerPoint XP saves a file.
2132 DWORD WINAPI SetVirtualResolution(HDC hdc, DWORD dw2, DWORD dw3, DWORD dw4, DWORD dw5)
2134 FIXME("(%p %08x %08x %08x %08x): stub!\n", hdc, dw2, dw3, dw4, dw5);
2138 /*******************************************************************
2139 * GetMiterLimit [GDI32.@]
2143 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
2148 TRACE("(%p,%p)\n", hdc, peLimit);
2150 dc = get_dc_ptr( hdc );
2154 *peLimit = dc->miterLimit;
2156 release_dc_ptr( dc );
2162 /*******************************************************************
2163 * SetMiterLimit [GDI32.@]
2167 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
2172 TRACE("(%p,%f,%p)\n", hdc, eNewLimit, peOldLimit);
2174 dc = get_dc_ptr( hdc );
2178 *peOldLimit = dc->miterLimit;
2179 dc->miterLimit = eNewLimit;
2180 release_dc_ptr( dc );
2186 /*******************************************************************
2187 * GdiIsMetaPrintDC [GDI32.@]
2189 BOOL WINAPI GdiIsMetaPrintDC(HDC hdc)
2195 /*******************************************************************
2196 * GdiIsMetaFileDC [GDI32.@]
2198 BOOL WINAPI GdiIsMetaFileDC(HDC hdc)
2202 switch( GetObjectType( hdc ) )
2211 /*******************************************************************
2212 * GdiIsPlayMetafileDC [GDI32.@]
2214 BOOL WINAPI GdiIsPlayMetafileDC(HDC hdc)