push 0f15bbd80d260bbd8adf052e820484a405c49375
[wine/hacks.git] / dlls / gdi32 / dc.c
blob161e0df0bc6f22bace8e72565a2065f825e4a927
1 /*
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
21 #include "config.h"
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"
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, void *obj );
44 static const struct gdi_obj_funcs dc_funcs =
46 NULL, /* pSelectObject */
47 NULL, /* pGetObject16 */
48 NULL, /* pGetObjectA */
49 NULL, /* pGetObjectW */
50 NULL, /* pUnrealizeObject */
51 DC_DeleteObject /* pDeleteObject */
55 static inline DC *get_dc_obj( HDC hdc )
57 DC *dc = GDI_GetObjPtr( hdc, MAGIC_DONTCARE );
58 if (!dc) return NULL;
60 if ((GDIMAGIC(dc->header.wMagic) != DC_MAGIC) &&
61 (GDIMAGIC(dc->header.wMagic) != MEMORY_DC_MAGIC) &&
62 (GDIMAGIC(dc->header.wMagic) != METAFILE_DC_MAGIC) &&
63 (GDIMAGIC(dc->header.wMagic) != ENHMETAFILE_DC_MAGIC))
65 GDI_ReleaseObj( hdc );
66 SetLastError( ERROR_INVALID_HANDLE );
67 dc = NULL;
69 return dc;
73 /***********************************************************************
74 * alloc_dc_ptr
76 DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic )
78 HDC hdc;
79 DC *dc;
81 if (!(dc = GDI_AllocObject( sizeof(*dc), magic, (HGDIOBJ*)&hdc, &dc_funcs ))) return NULL;
83 dc->hSelf = hdc;
84 dc->funcs = funcs;
85 dc->physDev = NULL;
86 dc->thread = GetCurrentThreadId();
87 dc->refcount = 1;
88 dc->dirty = 0;
89 dc->saveLevel = 0;
90 dc->saved_dc = 0;
91 dc->dwHookData = 0;
92 dc->hookProc = NULL;
93 dc->hookThunk = NULL;
94 dc->wndOrgX = 0;
95 dc->wndOrgY = 0;
96 dc->wndExtX = 1;
97 dc->wndExtY = 1;
98 dc->vportOrgX = 0;
99 dc->vportOrgY = 0;
100 dc->vportExtX = 1;
101 dc->vportExtY = 1;
102 dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */
103 dc->flags = 0;
104 dc->layout = 0;
105 dc->hClipRgn = 0;
106 dc->hMetaRgn = 0;
107 dc->hMetaClipRgn = 0;
108 dc->hVisRgn = 0;
109 dc->hPen = GetStockObject( BLACK_PEN );
110 dc->hBrush = GetStockObject( WHITE_BRUSH );
111 dc->hFont = GetStockObject( SYSTEM_FONT );
112 dc->hBitmap = 0;
113 dc->hDevice = 0;
114 dc->hPalette = GetStockObject( DEFAULT_PALETTE );
115 dc->gdiFont = 0;
116 dc->ROPmode = R2_COPYPEN;
117 dc->polyFillMode = ALTERNATE;
118 dc->stretchBltMode = BLACKONWHITE;
119 dc->relAbsMode = ABSOLUTE;
120 dc->backgroundMode = OPAQUE;
121 dc->backgroundColor = RGB( 255, 255, 255 );
122 dc->dcBrushColor = RGB( 255, 255, 255 );
123 dc->dcPenColor = RGB( 0, 0, 0 );
124 dc->textColor = RGB( 0, 0, 0 );
125 dc->brushOrgX = 0;
126 dc->brushOrgY = 0;
127 dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP;
128 dc->charExtra = 0;
129 dc->breakExtra = 0;
130 dc->breakRem = 0;
131 dc->MapMode = MM_TEXT;
132 dc->GraphicsMode = GM_COMPATIBLE;
133 dc->pAbortProc = NULL;
134 dc->CursPosX = 0;
135 dc->CursPosY = 0;
136 dc->ArcDirection = AD_COUNTERCLOCKWISE;
137 dc->xformWorld2Wnd.eM11 = 1.0f;
138 dc->xformWorld2Wnd.eM12 = 0.0f;
139 dc->xformWorld2Wnd.eM21 = 0.0f;
140 dc->xformWorld2Wnd.eM22 = 1.0f;
141 dc->xformWorld2Wnd.eDx = 0.0f;
142 dc->xformWorld2Wnd.eDy = 0.0f;
143 dc->xformWorld2Vport = dc->xformWorld2Wnd;
144 dc->xformVport2World = dc->xformWorld2Wnd;
145 dc->vport2WorldValid = TRUE;
146 dc->BoundsRect.left = 0;
147 dc->BoundsRect.top = 0;
148 dc->BoundsRect.right = 0;
149 dc->BoundsRect.bottom = 0;
150 dc->saved_visrgn = NULL;
151 PATH_InitGdiPath(&dc->path);
152 GDI_ReleaseObj( dc->hSelf );
153 return dc;
158 /***********************************************************************
159 * DC_GetDCPtr
161 DC *DC_GetDCPtr( HDC hdc )
163 DC *dc = get_dc_obj( hdc );
164 if (!dc) return NULL;
166 if (!InterlockedCompareExchange( &dc->refcount, 1, 0 ))
168 dc->thread = GetCurrentThreadId();
170 else if (dc->thread != GetCurrentThreadId())
172 GDI_ReleaseObj( hdc );
173 SetLastError( ERROR_ACCESS_DENIED );
174 return NULL;
176 else InterlockedIncrement( &dc->refcount );
178 return dc;
182 /***********************************************************************
183 * DC_ReleaseDCPtr
185 void DC_ReleaseDCPtr( DC *dc )
187 release_dc_ptr( dc );
188 GDI_ReleaseObj( dc->hSelf );
192 /***********************************************************************
193 * free_dc_ptr
195 BOOL free_dc_ptr( DC *dc )
197 assert( dc->refcount == 1 );
198 /* grab the gdi lock again */
199 if (!GDI_GetObjPtr( dc->hSelf, MAGIC_DONTCARE )) return FALSE; /* shouldn't happen */
200 return GDI_FreeObject( dc->hSelf, dc );
204 /***********************************************************************
205 * get_dc_ptr
207 * Retrieve a DC pointer but release the GDI lock.
209 DC *get_dc_ptr( HDC hdc )
211 DC *dc = get_dc_obj( hdc );
212 if (!dc) return NULL;
214 if (!InterlockedCompareExchange( &dc->refcount, 1, 0 ))
216 dc->thread = GetCurrentThreadId();
218 else if (dc->thread != GetCurrentThreadId())
220 WARN( "dc %p belongs to thread %04x\n", hdc, dc->thread );
221 GDI_ReleaseObj( hdc );
222 return NULL;
224 else InterlockedIncrement( &dc->refcount );
226 GDI_ReleaseObj( hdc );
227 return dc;
231 /***********************************************************************
232 * release_dc_ptr
234 void release_dc_ptr( DC *dc )
236 LONG ref;
238 dc->thread = 0;
239 ref = InterlockedDecrement( &dc->refcount );
240 assert( ref >= 0 );
241 if (ref) dc->thread = GetCurrentThreadId(); /* we still own it */
245 /***********************************************************************
246 * update_dc
248 * Make sure the DC vis region is up to date.
249 * This function may call up to USER so the GDI lock should _not_
250 * be held when calling it.
252 void update_dc( DC *dc )
254 if (InterlockedExchange( &dc->dirty, 0 ) && dc->hookThunk)
255 dc->hookThunk( dc->hSelf, DCHC_INVALIDVISRGN, dc->dwHookData, 0 );
259 /***********************************************************************
260 * DC_DeleteObject
262 static BOOL DC_DeleteObject( HGDIOBJ handle, void *obj )
264 GDI_ReleaseObj( handle );
265 return DeleteDC( handle );
269 /***********************************************************************
270 * DC_InitDC
272 * Setup device-specific DC values for a newly created DC.
274 void DC_InitDC( DC* dc )
276 if (dc->funcs->pRealizeDefaultPalette) dc->funcs->pRealizeDefaultPalette( dc->physDev );
277 SetTextColor( dc->hSelf, dc->textColor );
278 SetBkColor( dc->hSelf, dc->backgroundColor );
279 SelectObject( dc->hSelf, dc->hPen );
280 SelectObject( dc->hSelf, dc->hBrush );
281 SelectObject( dc->hSelf, dc->hFont );
282 CLIPPING_UpdateGCRegion( dc );
286 /***********************************************************************
287 * DC_InvertXform
289 * Computes the inverse of the transformation xformSrc and stores it to
290 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
291 * is singular.
293 static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
295 FLOAT determinant;
297 determinant = xformSrc->eM11*xformSrc->eM22 -
298 xformSrc->eM12*xformSrc->eM21;
299 if (determinant > -1e-12 && determinant < 1e-12)
300 return FALSE;
302 xformDest->eM11 = xformSrc->eM22 / determinant;
303 xformDest->eM12 = -xformSrc->eM12 / determinant;
304 xformDest->eM21 = -xformSrc->eM21 / determinant;
305 xformDest->eM22 = xformSrc->eM11 / determinant;
306 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 -
307 xformSrc->eDy * xformDest->eM21;
308 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 -
309 xformSrc->eDy * xformDest->eM22;
311 return TRUE;
315 /***********************************************************************
316 * DC_UpdateXforms
318 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
319 * fields of the specified DC by creating a transformation that
320 * represents the current mapping mode and combining it with the DC's
321 * world transform. This function should be called whenever the
322 * parameters associated with the mapping mode (window and viewport
323 * extents and origins) or the world transform change.
325 void DC_UpdateXforms( DC *dc )
327 XFORM xformWnd2Vport, oldworld2vport;
328 FLOAT scaleX, scaleY;
330 /* Construct a transformation to do the window-to-viewport conversion */
331 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
332 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
333 xformWnd2Vport.eM11 = scaleX;
334 xformWnd2Vport.eM12 = 0.0;
335 xformWnd2Vport.eM21 = 0.0;
336 xformWnd2Vport.eM22 = scaleY;
337 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX -
338 scaleX * (FLOAT)dc->wndOrgX;
339 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY -
340 scaleY * (FLOAT)dc->wndOrgY;
342 oldworld2vport = dc->xformWorld2Vport;
343 /* Combine with the world transformation */
344 CombineTransform( &dc->xformWorld2Vport, &dc->xformWorld2Wnd,
345 &xformWnd2Vport );
347 /* Create inverse of world-to-viewport transformation */
348 dc->vport2WorldValid = DC_InvertXform( &dc->xformWorld2Vport,
349 &dc->xformVport2World );
351 /* Reselect the font and pen back into the dc so that the size
352 gets updated. */
353 if(memcmp(&oldworld2vport, &dc->xformWorld2Vport, sizeof(oldworld2vport)))
355 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_FONT));
356 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_PEN));
361 /***********************************************************************
362 * GetDCState (Not a Windows API)
364 HDC WINAPI GetDCState( HDC hdc )
366 DC * newdc, * dc;
367 HGDIOBJ handle;
369 if (!(dc = get_dc_ptr( hdc ))) return 0;
370 if (!(newdc = GDI_AllocObject( sizeof(DC), GDIMAGIC(dc->header.wMagic), &handle, &dc_funcs )))
372 release_dc_ptr( dc );
373 return 0;
375 TRACE("(%p): returning %p\n", hdc, handle );
377 newdc->flags = dc->flags | DC_SAVED;
378 newdc->layout = dc->layout;
379 newdc->hPen = dc->hPen;
380 newdc->hBrush = dc->hBrush;
381 newdc->hFont = dc->hFont;
382 newdc->hBitmap = dc->hBitmap;
383 newdc->hDevice = dc->hDevice;
384 newdc->hPalette = dc->hPalette;
385 newdc->ROPmode = dc->ROPmode;
386 newdc->polyFillMode = dc->polyFillMode;
387 newdc->stretchBltMode = dc->stretchBltMode;
388 newdc->relAbsMode = dc->relAbsMode;
389 newdc->backgroundMode = dc->backgroundMode;
390 newdc->backgroundColor = dc->backgroundColor;
391 newdc->textColor = dc->textColor;
392 newdc->dcBrushColor = dc->dcBrushColor;
393 newdc->dcPenColor = dc->dcPenColor;
394 newdc->brushOrgX = dc->brushOrgX;
395 newdc->brushOrgY = dc->brushOrgY;
396 newdc->textAlign = dc->textAlign;
397 newdc->charExtra = dc->charExtra;
398 newdc->breakExtra = dc->breakExtra;
399 newdc->breakRem = dc->breakRem;
400 newdc->MapMode = dc->MapMode;
401 newdc->GraphicsMode = dc->GraphicsMode;
402 newdc->CursPosX = dc->CursPosX;
403 newdc->CursPosY = dc->CursPosY;
404 newdc->ArcDirection = dc->ArcDirection;
405 newdc->xformWorld2Wnd = dc->xformWorld2Wnd;
406 newdc->xformWorld2Vport = dc->xformWorld2Vport;
407 newdc->xformVport2World = dc->xformVport2World;
408 newdc->vport2WorldValid = dc->vport2WorldValid;
409 newdc->wndOrgX = dc->wndOrgX;
410 newdc->wndOrgY = dc->wndOrgY;
411 newdc->wndExtX = dc->wndExtX;
412 newdc->wndExtY = dc->wndExtY;
413 newdc->vportOrgX = dc->vportOrgX;
414 newdc->vportOrgY = dc->vportOrgY;
415 newdc->vportExtX = dc->vportExtX;
416 newdc->vportExtY = dc->vportExtY;
417 newdc->BoundsRect = dc->BoundsRect;
419 newdc->hSelf = (HDC)handle;
420 newdc->thread = GetCurrentThreadId();
421 newdc->refcount = 1;
422 newdc->saveLevel = 0;
423 newdc->saved_dc = 0;
424 GDI_ReleaseObj( handle );
426 PATH_InitGdiPath( &newdc->path );
428 newdc->pAbortProc = NULL;
429 newdc->hookThunk = NULL;
430 newdc->hookProc = 0;
431 newdc->saved_visrgn = NULL;
433 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
435 newdc->hVisRgn = 0;
436 newdc->hClipRgn = 0;
437 newdc->hMetaRgn = 0;
438 newdc->hMetaClipRgn = 0;
439 if (dc->hClipRgn)
441 newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
442 CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
444 if (dc->hMetaRgn)
446 newdc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
447 CombineRgn( newdc->hMetaRgn, dc->hMetaRgn, 0, RGN_COPY );
449 /* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
451 if(dc->gdiFont) {
452 newdc->gdiFont = dc->gdiFont;
453 } else
454 newdc->gdiFont = 0;
456 release_dc_ptr( newdc );
457 release_dc_ptr( dc );
458 return handle;
462 /***********************************************************************
463 * SetDCState (Not a Windows API)
465 void WINAPI SetDCState( HDC hdc, HDC hdcs )
467 DC *dc, *dcs;
469 if (!(dc = get_dc_ptr( hdc ))) return;
470 if (!(dcs = get_dc_ptr( hdcs )))
472 release_dc_ptr( dc );
473 return;
475 if (!(dcs->flags & DC_SAVED))
477 release_dc_ptr( dc );
478 release_dc_ptr( dcs );
479 return;
481 TRACE("%p %p\n", hdc, hdcs );
483 update_dc( dc );
484 dc->flags = dcs->flags & ~DC_SAVED;
485 dc->layout = dcs->layout;
486 dc->hDevice = dcs->hDevice;
487 dc->ROPmode = dcs->ROPmode;
488 dc->polyFillMode = dcs->polyFillMode;
489 dc->stretchBltMode = dcs->stretchBltMode;
490 dc->relAbsMode = dcs->relAbsMode;
491 dc->backgroundMode = dcs->backgroundMode;
492 dc->backgroundColor = dcs->backgroundColor;
493 dc->textColor = dcs->textColor;
494 dc->dcBrushColor = dcs->dcBrushColor;
495 dc->dcPenColor = dcs->dcPenColor;
496 dc->brushOrgX = dcs->brushOrgX;
497 dc->brushOrgY = dcs->brushOrgY;
498 dc->textAlign = dcs->textAlign;
499 dc->charExtra = dcs->charExtra;
500 dc->breakExtra = dcs->breakExtra;
501 dc->breakRem = dcs->breakRem;
502 dc->MapMode = dcs->MapMode;
503 dc->GraphicsMode = dcs->GraphicsMode;
504 dc->CursPosX = dcs->CursPosX;
505 dc->CursPosY = dcs->CursPosY;
506 dc->ArcDirection = dcs->ArcDirection;
507 dc->xformWorld2Wnd = dcs->xformWorld2Wnd;
508 dc->xformWorld2Vport = dcs->xformWorld2Vport;
509 dc->xformVport2World = dcs->xformVport2World;
510 dc->vport2WorldValid = dcs->vport2WorldValid;
511 dc->BoundsRect = dcs->BoundsRect;
513 dc->wndOrgX = dcs->wndOrgX;
514 dc->wndOrgY = dcs->wndOrgY;
515 dc->wndExtX = dcs->wndExtX;
516 dc->wndExtY = dcs->wndExtY;
517 dc->vportOrgX = dcs->vportOrgX;
518 dc->vportOrgY = dcs->vportOrgY;
519 dc->vportExtX = dcs->vportExtX;
520 dc->vportExtY = dcs->vportExtY;
522 if (dcs->hClipRgn)
524 if (!dc->hClipRgn) dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
525 CombineRgn( dc->hClipRgn, dcs->hClipRgn, 0, RGN_COPY );
527 else
529 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
530 dc->hClipRgn = 0;
532 if (dcs->hMetaRgn)
534 if (!dc->hMetaRgn) dc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
535 CombineRgn( dc->hMetaRgn, dcs->hMetaRgn, 0, RGN_COPY );
537 else
539 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
540 dc->hMetaRgn = 0;
542 CLIPPING_UpdateGCRegion( dc );
544 SelectObject( hdc, dcs->hBitmap );
545 SelectObject( hdc, dcs->hBrush );
546 SelectObject( hdc, dcs->hFont );
547 SelectObject( hdc, dcs->hPen );
548 SetBkColor( hdc, dcs->backgroundColor);
549 SetTextColor( hdc, dcs->textColor);
550 GDISelectPalette( hdc, dcs->hPalette, FALSE );
551 release_dc_ptr( dc );
552 release_dc_ptr( dcs );
556 /***********************************************************************
557 * GetDCState (GDI.179)
559 HDC16 WINAPI GetDCState16( HDC16 hdc )
561 return HDC_16( GetDCState( HDC_32(hdc) ));
565 /***********************************************************************
566 * SetDCState (GDI.180)
568 void WINAPI SetDCState16( HDC16 hdc, HDC16 hdcs )
570 SetDCState( HDC_32(hdc), HDC_32(hdcs) );
574 /***********************************************************************
575 * SaveDC (GDI32.@)
577 INT WINAPI SaveDC( HDC hdc )
579 HDC hdcs;
580 DC * dc, * dcs;
581 INT ret;
583 dc = get_dc_ptr( hdc );
584 if (!dc) return 0;
586 if(dc->funcs->pSaveDC)
588 ret = dc->funcs->pSaveDC( dc->physDev );
589 if(ret)
590 ret = ++dc->saveLevel;
591 release_dc_ptr( dc );
592 return ret;
595 if (!(hdcs = GetDCState( hdc )))
597 release_dc_ptr( dc );
598 return 0;
600 dcs = get_dc_ptr( hdcs );
602 /* Copy path. The reason why path saving / restoring is in SaveDC/
603 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
604 * functions are only in Win16 (which doesn't have paths) and that
605 * SetDCState doesn't allow us to signal an error (which can happen
606 * when copying paths).
608 if (!PATH_AssignGdiPath( &dcs->path, &dc->path ))
610 release_dc_ptr( dc );
611 release_dc_ptr( dcs );
612 DeleteDC( hdcs );
613 return 0;
616 dcs->saved_dc = dc->saved_dc;
617 dc->saved_dc = hdcs;
618 TRACE("(%p): returning %d\n", hdc, dc->saveLevel+1 );
619 ret = ++dc->saveLevel;
620 release_dc_ptr( dcs );
621 release_dc_ptr( dc );
622 return ret;
626 /***********************************************************************
627 * RestoreDC (GDI32.@)
629 BOOL WINAPI RestoreDC( HDC hdc, INT level )
631 DC * dc, * dcs;
632 BOOL success;
634 TRACE("%p %d\n", hdc, level );
635 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
637 if(abs(level) > dc->saveLevel || level == 0)
639 release_dc_ptr( dc );
640 return FALSE;
643 update_dc( dc );
645 if(dc->funcs->pRestoreDC)
647 success = dc->funcs->pRestoreDC( dc->physDev, level );
648 if(level < 0) level = dc->saveLevel + level + 1;
649 if(success)
650 dc->saveLevel = level - 1;
651 release_dc_ptr( dc );
652 return success;
655 if (level < 0) level = dc->saveLevel + level + 1;
656 success=TRUE;
657 while (dc->saveLevel >= level)
659 HDC hdcs = dc->saved_dc;
660 if (!(dcs = get_dc_ptr( hdcs )))
662 success = FALSE;
663 break;
665 dc->saved_dc = dcs->saved_dc;
666 dcs->saved_dc = 0;
667 if (--dc->saveLevel < level)
669 SetDCState( hdc, hdcs );
670 if (!PATH_AssignGdiPath( &dc->path, &dcs->path ))
671 /* FIXME: This might not be quite right, since we're
672 * returning FALSE but still destroying the saved DC state */
673 success=FALSE;
675 release_dc_ptr( dcs );
676 DeleteDC( hdcs );
678 release_dc_ptr( dc );
679 return success;
683 /***********************************************************************
684 * CreateDCW (GDI32.@)
686 HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
687 const DEVMODEW *initData )
689 HDC hdc;
690 DC * dc;
691 const DC_FUNCTIONS *funcs;
692 WCHAR buf[300];
694 GDI_CheckNotLock();
696 if (!device || !DRIVER_GetDriverName( device, buf, 300 ))
698 if (!driver)
700 ERR( "no device found for %s\n", debugstr_w(device) );
701 return 0;
703 strcpyW(buf, driver);
706 if (!(funcs = DRIVER_load_driver( buf )))
708 ERR( "no driver found for %s\n", debugstr_w(buf) );
709 return 0;
711 if (!(dc = alloc_dc_ptr( funcs, DC_MAGIC ))) goto error;
712 hdc = dc->hSelf;
714 dc->hBitmap = GetStockObject( DEFAULT_BITMAP );
715 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;
717 TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
718 debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
720 if (dc->funcs->pCreateDC &&
721 !dc->funcs->pCreateDC( hdc, &dc->physDev, buf, device, output, initData ))
723 WARN("creation aborted by device\n" );
724 goto error;
727 SetRectRgn( dc->hVisRgn, 0, 0,
728 GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ) );
730 DC_InitDC( dc );
731 release_dc_ptr( dc );
732 return hdc;
734 error:
735 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
736 if (dc) free_dc_ptr( dc );
737 DRIVER_release_driver( funcs );
738 return 0;
742 /***********************************************************************
743 * CreateDCA (GDI32.@)
745 HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
746 const DEVMODEA *initData )
748 UNICODE_STRING driverW, deviceW, outputW;
749 DEVMODEW *initDataW;
750 HDC ret;
752 if (driver) RtlCreateUnicodeStringFromAsciiz(&driverW, driver);
753 else driverW.Buffer = NULL;
755 if (device) RtlCreateUnicodeStringFromAsciiz(&deviceW, device);
756 else deviceW.Buffer = NULL;
758 if (output) RtlCreateUnicodeStringFromAsciiz(&outputW, output);
759 else outputW.Buffer = NULL;
761 initDataW = NULL;
762 if (initData)
764 /* don't convert initData for DISPLAY driver, it's not used */
765 if (!driverW.Buffer || strcmpiW( driverW.Buffer, displayW ))
766 initDataW = GdiConvertToDevmodeW(initData);
769 ret = CreateDCW( driverW.Buffer, deviceW.Buffer, outputW.Buffer, initDataW );
771 RtlFreeUnicodeString(&driverW);
772 RtlFreeUnicodeString(&deviceW);
773 RtlFreeUnicodeString(&outputW);
774 HeapFree(GetProcessHeap(), 0, initDataW);
775 return ret;
779 /***********************************************************************
780 * CreateICA (GDI32.@)
782 HDC WINAPI CreateICA( LPCSTR driver, LPCSTR device, LPCSTR output,
783 const DEVMODEA* initData )
785 /* Nothing special yet for ICs */
786 return CreateDCA( driver, device, output, initData );
790 /***********************************************************************
791 * CreateICW (GDI32.@)
793 HDC WINAPI CreateICW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
794 const DEVMODEW* initData )
796 /* Nothing special yet for ICs */
797 return CreateDCW( driver, device, output, initData );
801 /***********************************************************************
802 * CreateCompatibleDC (GDI32.@)
804 HDC WINAPI CreateCompatibleDC( HDC hdc )
806 DC *dc, *origDC;
807 HDC ret;
808 const DC_FUNCTIONS *funcs = NULL;
809 PHYSDEV physDev = NULL;
811 GDI_CheckNotLock();
813 if ((origDC = get_dc_ptr( hdc )))
815 if (GetObjectType( hdc ) == OBJ_DC)
817 funcs = origDC->funcs;
818 physDev = origDC->physDev;
820 release_dc_ptr( origDC );
821 if (funcs) funcs = DRIVER_get_driver( funcs );
824 if (!funcs && !(funcs = DRIVER_load_driver( displayW ))) return 0;
826 if (!(dc = alloc_dc_ptr( funcs, MEMORY_DC_MAGIC ))) goto error;
828 TRACE("(%p): returning %p\n", hdc, dc->hSelf );
830 dc->hBitmap = GetStockObject( DEFAULT_BITMAP );
831 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error; /* default bitmap is 1x1 */
833 /* Copy the driver-specific physical device info into
834 * the new DC. The driver may use this read-only info
835 * while creating the compatible DC below. */
836 dc->physDev = physDev;
837 ret = dc->hSelf;
839 if (dc->funcs->pCreateDC &&
840 !dc->funcs->pCreateDC( dc->hSelf, &dc->physDev, NULL, NULL, NULL, NULL ))
842 WARN("creation aborted by device\n");
843 goto error;
846 DC_InitDC( dc );
847 release_dc_ptr( dc );
848 return ret;
850 error:
851 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
852 if (dc) free_dc_ptr( dc );
853 DRIVER_release_driver( funcs );
854 return 0;
858 /***********************************************************************
859 * DeleteDC (GDI32.@)
861 BOOL WINAPI DeleteDC( HDC hdc )
863 const DC_FUNCTIONS *funcs = NULL;
864 DC * dc;
866 TRACE("%p\n", hdc );
868 GDI_CheckNotLock();
870 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
871 if (dc->refcount != 1)
873 FIXME( "not deleting busy DC %p refcount %u\n", dc->hSelf, dc->refcount );
874 release_dc_ptr( dc );
875 return FALSE;
878 /* Call hook procedure to check whether is it OK to delete this DC */
879 if (dc->hookThunk && !dc->hookThunk( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ))
881 release_dc_ptr( dc );
882 return FALSE;
885 while (dc->saveLevel)
887 DC * dcs;
888 HDC hdcs = dc->saved_dc;
889 if (!(dcs = get_dc_ptr( hdcs ))) break;
890 dc->saved_dc = dcs->saved_dc;
891 dc->saveLevel--;
892 if (dcs->hClipRgn) DeleteObject( dcs->hClipRgn );
893 if (dcs->hMetaRgn) DeleteObject( dcs->hMetaRgn );
894 if (dcs->hMetaClipRgn) DeleteObject( dcs->hMetaClipRgn );
895 if (dcs->hVisRgn) DeleteObject( dcs->hVisRgn );
896 PATH_DestroyGdiPath(&dcs->path);
897 free_dc_ptr( dcs );
900 if (!(dc->flags & DC_SAVED))
902 SelectObject( hdc, GetStockObject(BLACK_PEN) );
903 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
904 SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
905 SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
906 funcs = dc->funcs;
907 if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc->physDev);
908 dc->physDev = NULL;
911 while (dc->saved_visrgn)
913 struct saved_visrgn *next = dc->saved_visrgn->next;
914 DeleteObject( dc->saved_visrgn->hrgn );
915 HeapFree( GetProcessHeap(), 0, dc->saved_visrgn );
916 dc->saved_visrgn = next;
918 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
919 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
920 if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
921 if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
922 PATH_DestroyGdiPath(&dc->path);
924 free_dc_ptr( dc );
925 if (funcs) DRIVER_release_driver( funcs ); /* do that after releasing the GDI lock */
926 return TRUE;
930 /***********************************************************************
931 * ResetDCW (GDI32.@)
933 HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
935 DC *dc;
936 HDC ret = hdc;
938 if ((dc = get_dc_ptr( hdc )))
940 if (dc->funcs->pResetDC) ret = dc->funcs->pResetDC( dc->physDev, devmode );
941 release_dc_ptr( dc );
943 return ret;
947 /***********************************************************************
948 * ResetDCA (GDI32.@)
950 HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
952 DEVMODEW *devmodeW;
953 HDC ret;
955 if (devmode) devmodeW = GdiConvertToDevmodeW(devmode);
956 else devmodeW = NULL;
958 ret = ResetDCW(hdc, devmodeW);
960 HeapFree(GetProcessHeap(), 0, devmodeW);
961 return ret;
965 /***********************************************************************
966 * GetDeviceCaps (GDI32.@)
968 INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
970 DC *dc;
971 INT ret = 0;
973 if ((dc = get_dc_ptr( hdc )))
975 if (dc->funcs->pGetDeviceCaps) ret = dc->funcs->pGetDeviceCaps( dc->physDev, cap );
976 else switch(cap) /* return meaningful values for some entries */
978 case HORZRES: ret = 640; break;
979 case VERTRES: ret = 480; break;
980 case BITSPIXEL: ret = 1; break;
981 case PLANES: ret = 1; break;
982 case NUMCOLORS: ret = 2; break;
983 case ASPECTX: ret = 36; break;
984 case ASPECTY: ret = 36; break;
985 case ASPECTXY: ret = 51; break;
986 case LOGPIXELSX: ret = 72; break;
987 case LOGPIXELSY: ret = 72; break;
988 case SIZEPALETTE: ret = 2; break;
990 release_dc_ptr( dc );
992 return ret;
996 /***********************************************************************
997 * GetBkColor (GDI32.@)
999 COLORREF WINAPI GetBkColor( HDC hdc )
1001 COLORREF ret = 0;
1002 DC * dc = get_dc_ptr( hdc );
1003 if (dc)
1005 ret = dc->backgroundColor;
1006 release_dc_ptr( dc );
1008 return ret;
1012 /***********************************************************************
1013 * SetBkColor (GDI32.@)
1015 COLORREF WINAPI SetBkColor( HDC hdc, COLORREF color )
1017 COLORREF oldColor;
1018 DC * dc = get_dc_ptr( hdc );
1020 TRACE("hdc=%p color=0x%08x\n", hdc, color);
1022 if (!dc) return CLR_INVALID;
1023 oldColor = dc->backgroundColor;
1024 if (dc->funcs->pSetBkColor)
1026 color = dc->funcs->pSetBkColor(dc->physDev, color);
1027 if (color == CLR_INVALID) /* don't change it */
1029 color = oldColor;
1030 oldColor = CLR_INVALID;
1033 dc->backgroundColor = color;
1034 release_dc_ptr( dc );
1035 return oldColor;
1039 /***********************************************************************
1040 * GetTextColor (GDI32.@)
1042 COLORREF WINAPI GetTextColor( HDC hdc )
1044 COLORREF ret = 0;
1045 DC * dc = get_dc_ptr( hdc );
1046 if (dc)
1048 ret = dc->textColor;
1049 release_dc_ptr( dc );
1051 return ret;
1055 /***********************************************************************
1056 * SetTextColor (GDI32.@)
1058 COLORREF WINAPI SetTextColor( HDC hdc, COLORREF color )
1060 COLORREF oldColor;
1061 DC * dc = get_dc_ptr( hdc );
1063 TRACE(" hdc=%p color=0x%08x\n", hdc, color);
1065 if (!dc) return CLR_INVALID;
1066 oldColor = dc->textColor;
1067 if (dc->funcs->pSetTextColor)
1069 color = dc->funcs->pSetTextColor(dc->physDev, color);
1070 if (color == CLR_INVALID) /* don't change it */
1072 color = oldColor;
1073 oldColor = CLR_INVALID;
1076 dc->textColor = color;
1077 release_dc_ptr( dc );
1078 return oldColor;
1082 /***********************************************************************
1083 * GetTextAlign (GDI32.@)
1085 UINT WINAPI GetTextAlign( HDC hdc )
1087 UINT ret = 0;
1088 DC * dc = get_dc_ptr( hdc );
1089 if (dc)
1091 ret = dc->textAlign;
1092 release_dc_ptr( dc );
1094 return ret;
1098 /***********************************************************************
1099 * SetTextAlign (GDI32.@)
1101 UINT WINAPI SetTextAlign( HDC hdc, UINT align )
1103 UINT ret;
1104 DC *dc = get_dc_ptr( hdc );
1106 TRACE("hdc=%p align=%d\n", hdc, align);
1108 if (!dc) return 0x0;
1109 ret = dc->textAlign;
1110 if (dc->funcs->pSetTextAlign)
1111 if (!dc->funcs->pSetTextAlign(dc->physDev, align))
1112 ret = GDI_ERROR;
1113 if (ret != GDI_ERROR)
1114 dc->textAlign = align;
1115 release_dc_ptr( dc );
1116 return ret;
1119 /***********************************************************************
1120 * GetDCOrgEx (GDI32.@)
1122 BOOL WINAPI GetDCOrgEx( HDC hDC, LPPOINT lpp )
1124 DC * dc;
1126 if (!lpp) return FALSE;
1127 if (!(dc = get_dc_ptr( hDC ))) return FALSE;
1129 lpp->x = lpp->y = 0;
1130 if (dc->funcs->pGetDCOrgEx) dc->funcs->pGetDCOrgEx( dc->physDev, lpp );
1131 release_dc_ptr( dc );
1132 return TRUE;
1136 /***********************************************************************
1137 * SetDCOrg (GDI.117)
1139 DWORD WINAPI SetDCOrg16( HDC16 hdc16, INT16 x, INT16 y )
1141 DWORD prevOrg = 0;
1142 HDC hdc = HDC_32( hdc16 );
1143 DC *dc = get_dc_ptr( hdc );
1144 if (!dc) return 0;
1145 if (dc->funcs->pSetDCOrg) prevOrg = dc->funcs->pSetDCOrg( dc->physDev, x, y );
1146 release_dc_ptr( dc );
1147 return prevOrg;
1151 /***********************************************************************
1152 * GetGraphicsMode (GDI32.@)
1154 INT WINAPI GetGraphicsMode( HDC hdc )
1156 INT ret = 0;
1157 DC * dc = get_dc_ptr( hdc );
1158 if (dc)
1160 ret = dc->GraphicsMode;
1161 release_dc_ptr( dc );
1163 return ret;
1167 /***********************************************************************
1168 * SetGraphicsMode (GDI32.@)
1170 INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
1172 INT ret = 0;
1173 DC *dc = get_dc_ptr( hdc );
1175 /* One would think that setting the graphics mode to GM_COMPATIBLE
1176 * would also reset the world transformation matrix to the unity
1177 * matrix. However, in Windows, this is not the case. This doesn't
1178 * make a lot of sense to me, but that's the way it is.
1180 if (!dc) return 0;
1181 if ((mode > 0) && (mode <= GM_LAST))
1183 ret = dc->GraphicsMode;
1184 dc->GraphicsMode = mode;
1186 release_dc_ptr( dc );
1187 return ret;
1191 /***********************************************************************
1192 * GetArcDirection (GDI32.@)
1194 INT WINAPI GetArcDirection( HDC hdc )
1196 INT ret = 0;
1197 DC * dc = get_dc_ptr( hdc );
1198 if (dc)
1200 ret = dc->ArcDirection;
1201 release_dc_ptr( dc );
1203 return ret;
1207 /***********************************************************************
1208 * SetArcDirection (GDI32.@)
1210 INT WINAPI SetArcDirection( HDC hdc, INT nDirection )
1212 DC * dc;
1213 INT nOldDirection = 0;
1215 if (nDirection!=AD_COUNTERCLOCKWISE && nDirection!=AD_CLOCKWISE)
1217 SetLastError(ERROR_INVALID_PARAMETER);
1218 return 0;
1221 if ((dc = get_dc_ptr( hdc )))
1223 if (dc->funcs->pSetArcDirection)
1225 dc->funcs->pSetArcDirection(dc->physDev, nDirection);
1227 nOldDirection = dc->ArcDirection;
1228 dc->ArcDirection = nDirection;
1229 release_dc_ptr( dc );
1231 return nOldDirection;
1235 /***********************************************************************
1236 * GetWorldTransform (GDI32.@)
1238 BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
1240 DC * dc;
1241 if (!xform) return FALSE;
1242 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
1243 *xform = dc->xformWorld2Wnd;
1244 release_dc_ptr( dc );
1245 return TRUE;
1249 /***********************************************************************
1250 * GetTransform (GDI32.@)
1252 BOOL WINAPI GetTransform( HDC hdc, DWORD unknown, LPXFORM xform )
1254 if (unknown == 0x0203) return GetWorldTransform( hdc, xform );
1255 FIXME("stub: don't know what to do for code %x\n", unknown );
1256 return FALSE;
1260 /***********************************************************************
1261 * SetWorldTransform (GDI32.@)
1263 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
1265 BOOL ret = FALSE;
1266 DC *dc = get_dc_ptr( hdc );
1268 if (!dc) return FALSE;
1269 if (!xform) goto done;
1271 /* Check that graphics mode is GM_ADVANCED */
1272 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1274 if (dc->funcs->pSetWorldTransform)
1276 ret = dc->funcs->pSetWorldTransform(dc->physDev, xform);
1277 if (!ret) goto done;
1280 dc->xformWorld2Wnd = *xform;
1281 DC_UpdateXforms( dc );
1282 ret = TRUE;
1283 done:
1284 release_dc_ptr( dc );
1285 return ret;
1289 /****************************************************************************
1290 * ModifyWorldTransform [GDI32.@]
1291 * Modifies the world transformation for a device context.
1293 * PARAMS
1294 * hdc [I] Handle to device context
1295 * xform [I] XFORM structure that will be used to modify the world
1296 * transformation
1297 * iMode [I] Specifies in what way to modify the world transformation
1298 * Possible values:
1299 * MWT_IDENTITY
1300 * Resets the world transformation to the identity matrix.
1301 * The parameter xform is ignored.
1302 * MWT_LEFTMULTIPLY
1303 * Multiplies xform into the world transformation matrix from
1304 * the left.
1305 * MWT_RIGHTMULTIPLY
1306 * Multiplies xform into the world transformation matrix from
1307 * the right.
1309 * RETURNS
1310 * Success: TRUE.
1311 * Failure: FALSE. Use GetLastError() to determine the cause.
1313 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform,
1314 DWORD iMode )
1316 BOOL ret = FALSE;
1317 DC *dc = get_dc_ptr( hdc );
1319 /* Check for illegal parameters */
1320 if (!dc) return FALSE;
1321 if (!xform && iMode != MWT_IDENTITY) goto done;
1323 /* Check that graphics mode is GM_ADVANCED */
1324 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1326 if (dc->funcs->pModifyWorldTransform)
1328 ret = dc->funcs->pModifyWorldTransform(dc->physDev, xform, iMode);
1329 if (!ret) goto done;
1332 switch (iMode)
1334 case MWT_IDENTITY:
1335 dc->xformWorld2Wnd.eM11 = 1.0f;
1336 dc->xformWorld2Wnd.eM12 = 0.0f;
1337 dc->xformWorld2Wnd.eM21 = 0.0f;
1338 dc->xformWorld2Wnd.eM22 = 1.0f;
1339 dc->xformWorld2Wnd.eDx = 0.0f;
1340 dc->xformWorld2Wnd.eDy = 0.0f;
1341 break;
1342 case MWT_LEFTMULTIPLY:
1343 CombineTransform( &dc->xformWorld2Wnd, xform,
1344 &dc->xformWorld2Wnd );
1345 break;
1346 case MWT_RIGHTMULTIPLY:
1347 CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd,
1348 xform );
1349 break;
1350 default:
1351 goto done;
1354 DC_UpdateXforms( dc );
1355 ret = TRUE;
1356 done:
1357 release_dc_ptr( dc );
1358 return ret;
1362 /****************************************************************************
1363 * CombineTransform [GDI32.@]
1364 * Combines two transformation matrices.
1366 * PARAMS
1367 * xformResult [O] Stores the result of combining the two matrices
1368 * xform1 [I] Specifies the first matrix to apply
1369 * xform2 [I] Specifies the second matrix to apply
1371 * REMARKS
1372 * The same matrix can be passed in for more than one of the parameters.
1374 * RETURNS
1375 * Success: TRUE.
1376 * Failure: FALSE. Use GetLastError() to determine the cause.
1378 BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
1379 const XFORM *xform2 )
1381 XFORM xformTemp;
1383 /* Check for illegal parameters */
1384 if (!xformResult || !xform1 || !xform2)
1385 return FALSE;
1387 /* Create the result in a temporary XFORM, since xformResult may be
1388 * equal to xform1 or xform2 */
1389 xformTemp.eM11 = xform1->eM11 * xform2->eM11 +
1390 xform1->eM12 * xform2->eM21;
1391 xformTemp.eM12 = xform1->eM11 * xform2->eM12 +
1392 xform1->eM12 * xform2->eM22;
1393 xformTemp.eM21 = xform1->eM21 * xform2->eM11 +
1394 xform1->eM22 * xform2->eM21;
1395 xformTemp.eM22 = xform1->eM21 * xform2->eM12 +
1396 xform1->eM22 * xform2->eM22;
1397 xformTemp.eDx = xform1->eDx * xform2->eM11 +
1398 xform1->eDy * xform2->eM21 +
1399 xform2->eDx;
1400 xformTemp.eDy = xform1->eDx * xform2->eM12 +
1401 xform1->eDy * xform2->eM22 +
1402 xform2->eDy;
1404 /* Copy the result to xformResult */
1405 *xformResult = xformTemp;
1407 return TRUE;
1411 /***********************************************************************
1412 * SetDCHook (GDI32.@)
1414 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1416 BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD_PTR dwHookData )
1418 DC *dc = get_dc_ptr( hdc );
1420 if (!dc) return FALSE;
1422 if (!(dc->flags & DC_SAVED))
1424 dc->dwHookData = dwHookData;
1425 dc->hookThunk = hookProc;
1427 release_dc_ptr( dc );
1428 return TRUE;
1432 /* relay function to call the 16-bit DC hook proc */
1433 static BOOL WINAPI call_dc_hook16( HDC hdc, WORD code, DWORD_PTR data, LPARAM lParam )
1435 WORD args[6];
1436 DWORD ret = 0;
1437 DC *dc = get_dc_ptr( hdc );
1439 if (!dc) return FALSE;
1440 if (dc->hookProc)
1442 args[5] = HDC_16(hdc);
1443 args[4] = code;
1444 args[3] = HIWORD(data);
1445 args[2] = LOWORD(data);
1446 args[1] = HIWORD(lParam);
1447 args[0] = LOWORD(lParam);
1448 WOWCallback16Ex( (DWORD)dc->hookProc, WCB16_PASCAL, sizeof(args), args, &ret );
1450 release_dc_ptr( dc );
1451 return LOWORD(ret);
1454 /***********************************************************************
1455 * SetDCHook (GDI.190)
1457 BOOL16 WINAPI SetDCHook16( HDC16 hdc16, FARPROC16 hookProc, DWORD dwHookData )
1459 DC *dc = get_dc_ptr( HDC_32(hdc16) );
1461 if (!dc) return FALSE;
1462 if (!(dc->flags & DC_SAVED))
1464 dc->dwHookData = dwHookData;
1465 dc->hookThunk = call_dc_hook16;
1466 dc->hookProc = hookProc;
1468 release_dc_ptr( dc );
1469 return TRUE;
1473 /***********************************************************************
1474 * GetDCHook (GDI.191)
1476 DWORD WINAPI GetDCHook16( HDC16 hdc16, FARPROC16 *phookProc )
1478 HDC hdc = HDC_32( hdc16 );
1479 DC *dc = get_dc_ptr( hdc );
1480 DWORD ret;
1482 if (!dc) return 0;
1483 *phookProc = dc->hookProc;
1484 ret = dc->dwHookData;
1485 release_dc_ptr( dc );
1486 return ret;
1490 /***********************************************************************
1491 * SetHookFlags (GDI.192)
1493 WORD WINAPI SetHookFlags16(HDC16 hdc16, WORD flags)
1495 HDC hdc = HDC_32( hdc16 );
1496 DC *dc = get_dc_obj( hdc ); /* not get_dc_ptr, this needs to work from any thread */
1497 LONG ret = 0;
1499 if (!dc) return 0;
1501 /* "Undocumented Windows" info is slightly confusing. */
1503 TRACE("hDC %p, flags %04x\n",hdc,flags);
1505 if (flags & DCHF_INVALIDATEVISRGN)
1506 ret = InterlockedExchange( &dc->dirty, 1 );
1507 else if (flags & DCHF_VALIDATEVISRGN || !flags)
1508 ret = InterlockedExchange( &dc->dirty, 0 );
1510 GDI_ReleaseObj( dc );
1511 return ret;
1514 /***********************************************************************
1515 * SetICMMode (GDI32.@)
1517 INT WINAPI SetICMMode(HDC hdc, INT iEnableICM)
1519 /*FIXME Asuming that ICM is always off, and cannot be turned on */
1520 if (iEnableICM == ICM_OFF) return ICM_OFF;
1521 if (iEnableICM == ICM_ON) return 0;
1522 if (iEnableICM == ICM_QUERY) return ICM_OFF;
1523 return 0;
1526 /***********************************************************************
1527 * GetDeviceGammaRamp (GDI32.@)
1529 BOOL WINAPI GetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1531 BOOL ret = FALSE;
1532 DC *dc = get_dc_ptr( hDC );
1534 if( dc )
1536 if (dc->funcs->pGetDeviceGammaRamp)
1537 ret = dc->funcs->pGetDeviceGammaRamp(dc->physDev, ptr);
1538 release_dc_ptr( dc );
1540 return ret;
1543 /***********************************************************************
1544 * SetDeviceGammaRamp (GDI32.@)
1546 BOOL WINAPI SetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1548 BOOL ret = FALSE;
1549 DC *dc = get_dc_ptr( hDC );
1551 if( dc )
1553 if (dc->funcs->pSetDeviceGammaRamp)
1554 ret = dc->funcs->pSetDeviceGammaRamp(dc->physDev, ptr);
1555 release_dc_ptr( dc );
1557 return ret;
1560 /***********************************************************************
1561 * GetColorSpace (GDI32.@)
1563 HCOLORSPACE WINAPI GetColorSpace(HDC hdc)
1565 /*FIXME Need to to whatever GetColorSpace actually does */
1566 return 0;
1569 /***********************************************************************
1570 * CreateColorSpaceA (GDI32.@)
1572 HCOLORSPACE WINAPI CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace )
1574 FIXME( "stub\n" );
1575 return 0;
1578 /***********************************************************************
1579 * CreateColorSpaceW (GDI32.@)
1581 HCOLORSPACE WINAPI CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace )
1583 FIXME( "stub\n" );
1584 return 0;
1587 /***********************************************************************
1588 * DeleteColorSpace (GDI32.@)
1590 BOOL WINAPI DeleteColorSpace( HCOLORSPACE hColorSpace )
1592 FIXME( "stub\n" );
1594 return TRUE;
1597 /***********************************************************************
1598 * SetColorSpace (GDI32.@)
1600 HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
1602 FIXME( "stub\n" );
1604 return hColorSpace;
1607 /***********************************************************************
1608 * GetBoundsRect (GDI32.@)
1610 UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
1612 UINT ret;
1613 DC *dc = get_dc_ptr( hdc );
1615 if ( !dc ) return 0;
1617 if (rect) *rect = dc->BoundsRect;
1619 ret = ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1621 if (flags & DCB_RESET)
1623 dc->BoundsRect.left = 0;
1624 dc->BoundsRect.top = 0;
1625 dc->BoundsRect.right = 0;
1626 dc->BoundsRect.bottom = 0;
1627 dc->flags &= ~DC_BOUNDS_SET;
1629 release_dc_ptr( dc );
1630 return ret;
1634 /***********************************************************************
1635 * SetBoundsRect (GDI32.@)
1637 UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
1639 UINT ret;
1640 DC *dc;
1642 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
1643 if (!(dc = get_dc_ptr( hdc ))) return 0;
1645 ret = ((dc->flags & DC_BOUNDS_ENABLE) ? DCB_ENABLE : DCB_DISABLE) |
1646 ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1648 if (flags & DCB_RESET)
1650 dc->BoundsRect.left = 0;
1651 dc->BoundsRect.top = 0;
1652 dc->BoundsRect.right = 0;
1653 dc->BoundsRect.bottom = 0;
1654 dc->flags &= ~DC_BOUNDS_SET;
1657 if ((flags & DCB_ACCUMULATE) && rect && rect->left < rect->right && rect->top < rect->bottom)
1659 if (dc->flags & DC_BOUNDS_SET)
1661 dc->BoundsRect.left = min( dc->BoundsRect.left, rect->left );
1662 dc->BoundsRect.top = min( dc->BoundsRect.top, rect->top );
1663 dc->BoundsRect.right = max( dc->BoundsRect.right, rect->right );
1664 dc->BoundsRect.bottom = max( dc->BoundsRect.bottom, rect->bottom );
1666 else
1668 dc->BoundsRect = *rect;
1669 dc->flags |= DC_BOUNDS_SET;
1673 if (flags & DCB_ENABLE) dc->flags |= DC_BOUNDS_ENABLE;
1674 if (flags & DCB_DISABLE) dc->flags &= ~DC_BOUNDS_ENABLE;
1676 release_dc_ptr( dc );
1677 return ret;
1681 /***********************************************************************
1682 * GetRelAbs (GDI32.@)
1684 INT WINAPI GetRelAbs( HDC hdc, DWORD dwIgnore )
1686 INT ret = 0;
1687 DC *dc = get_dc_ptr( hdc );
1688 if (dc)
1690 ret = dc->relAbsMode;
1691 release_dc_ptr( dc );
1693 return ret;
1699 /***********************************************************************
1700 * GetBkMode (GDI32.@)
1702 INT WINAPI GetBkMode( HDC hdc )
1704 INT ret = 0;
1705 DC * dc = get_dc_ptr( hdc );
1706 if (dc)
1708 ret = dc->backgroundMode;
1709 release_dc_ptr( dc );
1711 return ret;
1715 /***********************************************************************
1716 * SetBkMode (GDI32.@)
1718 INT WINAPI SetBkMode( HDC hdc, INT mode )
1720 INT ret;
1721 DC *dc;
1722 if ((mode <= 0) || (mode > BKMODE_LAST))
1724 SetLastError(ERROR_INVALID_PARAMETER);
1725 return 0;
1727 if (!(dc = get_dc_ptr( hdc ))) return 0;
1729 ret = dc->backgroundMode;
1730 if (dc->funcs->pSetBkMode)
1731 if (!dc->funcs->pSetBkMode( dc->physDev, mode ))
1732 ret = 0;
1733 if (ret)
1734 dc->backgroundMode = mode;
1735 release_dc_ptr( dc );
1736 return ret;
1740 /***********************************************************************
1741 * GetROP2 (GDI32.@)
1743 INT WINAPI GetROP2( HDC hdc )
1745 INT ret = 0;
1746 DC * dc = get_dc_ptr( hdc );
1747 if (dc)
1749 ret = dc->ROPmode;
1750 release_dc_ptr( dc );
1752 return ret;
1756 /***********************************************************************
1757 * SetROP2 (GDI32.@)
1759 INT WINAPI SetROP2( HDC hdc, INT mode )
1761 INT ret;
1762 DC *dc;
1763 if ((mode < R2_BLACK) || (mode > R2_WHITE))
1765 SetLastError(ERROR_INVALID_PARAMETER);
1766 return 0;
1768 if (!(dc = get_dc_ptr( hdc ))) return 0;
1769 ret = dc->ROPmode;
1770 if (dc->funcs->pSetROP2)
1771 if (!dc->funcs->pSetROP2( dc->physDev, mode ))
1772 ret = 0;
1773 if (ret)
1774 dc->ROPmode = mode;
1775 release_dc_ptr( dc );
1776 return ret;
1780 /***********************************************************************
1781 * SetRelAbs (GDI32.@)
1783 INT WINAPI SetRelAbs( HDC hdc, INT mode )
1785 INT ret;
1786 DC *dc;
1787 if ((mode != ABSOLUTE) && (mode != RELATIVE))
1789 SetLastError(ERROR_INVALID_PARAMETER);
1790 return 0;
1792 if (!(dc = get_dc_ptr( hdc ))) return 0;
1793 if (dc->funcs->pSetRelAbs)
1794 ret = dc->funcs->pSetRelAbs( dc->physDev, mode );
1795 else
1797 ret = dc->relAbsMode;
1798 dc->relAbsMode = mode;
1800 release_dc_ptr( dc );
1801 return ret;
1805 /***********************************************************************
1806 * GetPolyFillMode (GDI32.@)
1808 INT WINAPI GetPolyFillMode( HDC hdc )
1810 INT ret = 0;
1811 DC * dc = get_dc_ptr( hdc );
1812 if (dc)
1814 ret = dc->polyFillMode;
1815 release_dc_ptr( dc );
1817 return ret;
1821 /***********************************************************************
1822 * SetPolyFillMode (GDI32.@)
1824 INT WINAPI SetPolyFillMode( HDC hdc, INT mode )
1826 INT ret;
1827 DC *dc;
1828 if ((mode <= 0) || (mode > POLYFILL_LAST))
1830 SetLastError(ERROR_INVALID_PARAMETER);
1831 return 0;
1833 if (!(dc = get_dc_ptr( hdc ))) return 0;
1834 ret = dc->polyFillMode;
1835 if (dc->funcs->pSetPolyFillMode)
1836 if (!dc->funcs->pSetPolyFillMode( dc->physDev, mode ))
1837 ret = 0;
1838 if (ret)
1839 dc->polyFillMode = mode;
1840 release_dc_ptr( dc );
1841 return ret;
1845 /***********************************************************************
1846 * GetStretchBltMode (GDI32.@)
1848 INT WINAPI GetStretchBltMode( HDC hdc )
1850 INT ret = 0;
1851 DC * dc = get_dc_ptr( hdc );
1852 if (dc)
1854 ret = dc->stretchBltMode;
1855 release_dc_ptr( dc );
1857 return ret;
1861 /***********************************************************************
1862 * SetStretchBltMode (GDI32.@)
1864 INT WINAPI SetStretchBltMode( HDC hdc, INT mode )
1866 INT ret;
1867 DC *dc;
1868 if ((mode <= 0) || (mode > MAXSTRETCHBLTMODE))
1870 SetLastError(ERROR_INVALID_PARAMETER);
1871 return 0;
1873 if (!(dc = get_dc_ptr( hdc ))) return 0;
1874 ret = dc->stretchBltMode;
1875 if (dc->funcs->pSetStretchBltMode)
1876 if (!dc->funcs->pSetStretchBltMode( dc->physDev, mode ))
1877 ret = 0;
1878 if (ret)
1879 dc->stretchBltMode = mode;
1880 release_dc_ptr( dc );
1881 return ret;
1885 /***********************************************************************
1886 * GetMapMode (GDI32.@)
1888 INT WINAPI GetMapMode( HDC hdc )
1890 INT ret = 0;
1891 DC * dc = get_dc_ptr( hdc );
1892 if (dc)
1894 ret = dc->MapMode;
1895 release_dc_ptr( dc );
1897 return ret;
1901 /***********************************************************************
1902 * GetBrushOrgEx (GDI32.@)
1904 BOOL WINAPI GetBrushOrgEx( HDC hdc, LPPOINT pt )
1906 DC * dc = get_dc_ptr( hdc );
1907 if (!dc) return FALSE;
1908 pt->x = dc->brushOrgX;
1909 pt->y = dc->brushOrgY;
1910 release_dc_ptr( dc );
1911 return TRUE;
1915 /***********************************************************************
1916 * GetCurrentPositionEx (GDI32.@)
1918 BOOL WINAPI GetCurrentPositionEx( HDC hdc, LPPOINT pt )
1920 DC * dc = get_dc_ptr( hdc );
1921 if (!dc) return FALSE;
1922 pt->x = dc->CursPosX;
1923 pt->y = dc->CursPosY;
1924 release_dc_ptr( dc );
1925 return TRUE;
1929 /***********************************************************************
1930 * GetViewportExtEx (GDI32.@)
1932 BOOL WINAPI GetViewportExtEx( HDC hdc, LPSIZE size )
1934 DC * dc = get_dc_ptr( hdc );
1935 if (!dc) return FALSE;
1936 size->cx = dc->vportExtX;
1937 size->cy = dc->vportExtY;
1938 release_dc_ptr( dc );
1939 return TRUE;
1943 /***********************************************************************
1944 * GetViewportOrgEx (GDI32.@)
1946 BOOL WINAPI GetViewportOrgEx( HDC hdc, LPPOINT pt )
1948 DC * dc = get_dc_ptr( hdc );
1949 if (!dc) return FALSE;
1950 pt->x = dc->vportOrgX;
1951 pt->y = dc->vportOrgY;
1952 release_dc_ptr( dc );
1953 return TRUE;
1957 /***********************************************************************
1958 * GetWindowExtEx (GDI32.@)
1960 BOOL WINAPI GetWindowExtEx( HDC hdc, LPSIZE size )
1962 DC * dc = get_dc_ptr( hdc );
1963 if (!dc) return FALSE;
1964 size->cx = dc->wndExtX;
1965 size->cy = dc->wndExtY;
1966 release_dc_ptr( dc );
1967 return TRUE;
1971 /***********************************************************************
1972 * GetWindowOrgEx (GDI32.@)
1974 BOOL WINAPI GetWindowOrgEx( HDC hdc, LPPOINT pt )
1976 DC * dc = get_dc_ptr( hdc );
1977 if (!dc) return FALSE;
1978 pt->x = dc->wndOrgX;
1979 pt->y = dc->wndOrgY;
1980 release_dc_ptr( dc );
1981 return TRUE;
1985 /***********************************************************************
1986 * InquireVisRgn (GDI.131)
1988 HRGN16 WINAPI InquireVisRgn16( HDC16 hdc )
1990 HRGN16 ret = 0;
1991 DC * dc = get_dc_ptr( HDC_32(hdc) );
1992 if (dc)
1994 ret = HRGN_16(dc->hVisRgn);
1995 release_dc_ptr( dc );
1997 return ret;
2001 /***********************************************************************
2002 * GetClipRgn (GDI.173)
2004 HRGN16 WINAPI GetClipRgn16( HDC16 hdc )
2006 HRGN16 ret = 0;
2007 DC * dc = get_dc_ptr( HDC_32(hdc) );
2008 if (dc)
2010 ret = HRGN_16(dc->hClipRgn);
2011 release_dc_ptr( dc );
2013 return ret;
2017 /***********************************************************************
2018 * GetLayout (GDI32.@)
2020 * Gets left->right or right->left text layout flags of a dc.
2023 DWORD WINAPI GetLayout(HDC hdc)
2025 DWORD layout = GDI_ERROR;
2027 DC * dc = get_dc_ptr( hdc );
2028 if (dc)
2030 layout = dc->layout;
2031 release_dc_ptr( dc );
2034 TRACE("hdc : %p, layout : %08x\n", hdc, layout);
2036 return layout;
2039 /***********************************************************************
2040 * SetLayout (GDI32.@)
2042 * Sets left->right or right->left text layout flags of a dc.
2045 DWORD WINAPI SetLayout(HDC hdc, DWORD layout)
2047 DWORD oldlayout = GDI_ERROR;
2049 DC * dc = get_dc_ptr( hdc );
2050 if (dc)
2052 oldlayout = dc->layout;
2053 dc->layout = layout;
2054 release_dc_ptr( dc );
2057 TRACE("hdc : %p, old layout : %08x, new layout : %08x\n", hdc, oldlayout, layout);
2059 return oldlayout;
2062 /***********************************************************************
2063 * GetDCBrushColor (GDI32.@)
2065 * Retrieves the current brush color for the specified device
2066 * context (DC).
2069 COLORREF WINAPI GetDCBrushColor(HDC hdc)
2071 DC *dc;
2072 COLORREF dcBrushColor = CLR_INVALID;
2074 TRACE("hdc(%p)\n", hdc);
2076 dc = get_dc_ptr( hdc );
2077 if (dc)
2079 dcBrushColor = dc->dcBrushColor;
2080 release_dc_ptr( dc );
2083 return dcBrushColor;
2086 /***********************************************************************
2087 * SetDCBrushColor (GDI32.@)
2089 * Sets the current device context (DC) brush color to the specified
2090 * color value. If the device cannot represent the specified color
2091 * value, the color is set to the nearest physical color.
2094 COLORREF WINAPI SetDCBrushColor(HDC hdc, COLORREF crColor)
2096 DC *dc;
2097 COLORREF oldClr = CLR_INVALID;
2099 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2101 dc = get_dc_ptr( hdc );
2102 if (dc)
2104 if (dc->funcs->pSetDCBrushColor)
2105 crColor = dc->funcs->pSetDCBrushColor( dc->physDev, crColor );
2106 else if (dc->hBrush == GetStockObject( DC_BRUSH ))
2108 /* If DC_BRUSH is selected, update driver pen color */
2109 HBRUSH hBrush = CreateSolidBrush( crColor );
2110 dc->funcs->pSelectBrush( dc->physDev, hBrush );
2111 DeleteObject( hBrush );
2114 if (crColor != CLR_INVALID)
2116 oldClr = dc->dcBrushColor;
2117 dc->dcBrushColor = crColor;
2120 release_dc_ptr( dc );
2123 return oldClr;
2126 /***********************************************************************
2127 * GetDCPenColor (GDI32.@)
2129 * Retrieves the current pen color for the specified device
2130 * context (DC).
2133 COLORREF WINAPI GetDCPenColor(HDC hdc)
2135 DC *dc;
2136 COLORREF dcPenColor = CLR_INVALID;
2138 TRACE("hdc(%p)\n", hdc);
2140 dc = get_dc_ptr( hdc );
2141 if (dc)
2143 dcPenColor = dc->dcPenColor;
2144 release_dc_ptr( dc );
2147 return dcPenColor;
2150 /***********************************************************************
2151 * SetDCPenColor (GDI32.@)
2153 * Sets the current device context (DC) pen color to the specified
2154 * color value. If the device cannot represent the specified color
2155 * value, the color is set to the nearest physical color.
2158 COLORREF WINAPI SetDCPenColor(HDC hdc, COLORREF crColor)
2160 DC *dc;
2161 COLORREF oldClr = CLR_INVALID;
2163 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2165 dc = get_dc_ptr( hdc );
2166 if (dc)
2168 if (dc->funcs->pSetDCPenColor)
2169 crColor = dc->funcs->pSetDCPenColor( dc->physDev, crColor );
2170 else if (dc->hPen == GetStockObject( DC_PEN ))
2172 /* If DC_PEN is selected, update the driver pen color */
2173 LOGPEN logpen = { PS_SOLID, { 0, 0 }, crColor };
2174 HPEN hPen = CreatePenIndirect( &logpen );
2175 dc->funcs->pSelectPen( dc->physDev, hPen );
2176 DeleteObject( hPen );
2179 if (crColor != CLR_INVALID)
2181 oldClr = dc->dcPenColor;
2182 dc->dcPenColor = crColor;
2185 release_dc_ptr( dc );
2188 return oldClr;
2191 /***********************************************************************
2192 * CancelDC (GDI32.@)
2194 BOOL WINAPI CancelDC(HDC hdc)
2196 FIXME("stub\n");
2197 return TRUE;
2200 /***********************************************************************
2201 * SetVirtualResolution (GDI32.@)
2203 * Undocumented on msdn. Called when PowerPoint XP saves a file.
2205 DWORD WINAPI SetVirtualResolution(HDC hdc, DWORD dw2, DWORD dw3, DWORD dw4, DWORD dw5)
2207 FIXME("(%p %08x %08x %08x %08x): stub!\n", hdc, dw2, dw3, dw4, dw5);
2208 return FALSE;
2211 /*******************************************************************
2212 * GetMiterLimit [GDI32.@]
2216 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
2218 BOOL bRet = FALSE;
2219 DC *dc;
2221 TRACE("(%p,%p)\n", hdc, peLimit);
2223 dc = get_dc_ptr( hdc );
2224 if (dc)
2226 if (peLimit)
2227 *peLimit = dc->miterLimit;
2229 release_dc_ptr( dc );
2230 bRet = TRUE;
2232 return bRet;
2235 /*******************************************************************
2236 * SetMiterLimit [GDI32.@]
2240 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
2242 BOOL bRet = FALSE;
2243 DC *dc;
2245 TRACE("(%p,%f,%p)\n", hdc, eNewLimit, peOldLimit);
2247 dc = get_dc_ptr( hdc );
2248 if (dc)
2250 if (peOldLimit)
2251 *peOldLimit = dc->miterLimit;
2252 dc->miterLimit = eNewLimit;
2253 release_dc_ptr( dc );
2254 bRet = TRUE;
2256 return bRet;
2259 /*******************************************************************
2260 * GdiIsMetaPrintDC [GDI32.@]
2262 BOOL WINAPI GdiIsMetaPrintDC(HDC hdc)
2264 FIXME("%p\n", hdc);
2265 return FALSE;
2268 /*******************************************************************
2269 * GdiIsMetaFileDC [GDI32.@]
2271 BOOL WINAPI GdiIsMetaFileDC(HDC hdc)
2273 TRACE("%p\n", hdc);
2275 switch( GetObjectType( hdc ) )
2277 case OBJ_METADC:
2278 case OBJ_ENHMETADC:
2279 return TRUE;
2281 return FALSE;
2284 /*******************************************************************
2285 * GdiIsPlayMetafileDC [GDI32.@]
2287 BOOL WINAPI GdiIsPlayMetafileDC(HDC hdc)
2289 FIXME("%p\n", hdc);
2290 return FALSE;