push 83f6eeab4f78cf34cba36fe6c2150f9c23ec0aba
[wine/hacks.git] / dlls / gdi32 / dc.c
blob222da2da26cced773a76287b9b9402978469d472
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 <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "winerror.h"
32 #include "wownt32.h"
33 #include "gdi_private.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dc);
39 static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
41 static BOOL DC_DeleteObject( HGDIOBJ handle, void *obj );
43 static const struct gdi_obj_funcs dc_funcs =
45 NULL, /* pSelectObject */
46 NULL, /* pGetObject16 */
47 NULL, /* pGetObjectA */
48 NULL, /* pGetObjectW */
49 NULL, /* pUnrealizeObject */
50 DC_DeleteObject /* pDeleteObject */
53 /***********************************************************************
54 * DC_AllocDC
56 DC *DC_AllocDC( const DC_FUNCTIONS *funcs, WORD magic )
58 HDC hdc;
59 DC *dc;
61 if (!(dc = GDI_AllocObject( sizeof(*dc), magic, (HGDIOBJ*)&hdc, &dc_funcs ))) return NULL;
63 dc->hSelf = hdc;
64 dc->funcs = funcs;
65 dc->physDev = NULL;
66 dc->saveLevel = 0;
67 dc->saved_dc = 0;
68 dc->dwHookData = 0;
69 dc->hookProc = NULL;
70 dc->hookThunk = NULL;
71 dc->wndOrgX = 0;
72 dc->wndOrgY = 0;
73 dc->wndExtX = 1;
74 dc->wndExtY = 1;
75 dc->vportOrgX = 0;
76 dc->vportOrgY = 0;
77 dc->vportExtX = 1;
78 dc->vportExtY = 1;
79 dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */
80 dc->flags = 0;
81 dc->layout = 0;
82 dc->hClipRgn = 0;
83 dc->hMetaRgn = 0;
84 dc->hMetaClipRgn = 0;
85 dc->hVisRgn = 0;
86 dc->hPen = GetStockObject( BLACK_PEN );
87 dc->hBrush = GetStockObject( WHITE_BRUSH );
88 dc->hFont = GetStockObject( SYSTEM_FONT );
89 dc->hBitmap = 0;
90 dc->hDevice = 0;
91 dc->hPalette = GetStockObject( DEFAULT_PALETTE );
92 dc->gdiFont = 0;
93 dc->ROPmode = R2_COPYPEN;
94 dc->polyFillMode = ALTERNATE;
95 dc->stretchBltMode = BLACKONWHITE;
96 dc->relAbsMode = ABSOLUTE;
97 dc->backgroundMode = OPAQUE;
98 dc->backgroundColor = RGB( 255, 255, 255 );
99 dc->dcBrushColor = RGB( 255, 255, 255 );
100 dc->dcPenColor = RGB( 0, 0, 0 );
101 dc->textColor = RGB( 0, 0, 0 );
102 dc->brushOrgX = 0;
103 dc->brushOrgY = 0;
104 dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP;
105 dc->charExtra = 0;
106 dc->breakExtra = 0;
107 dc->breakRem = 0;
108 dc->MapMode = MM_TEXT;
109 dc->GraphicsMode = GM_COMPATIBLE;
110 dc->pAbortProc = NULL;
111 dc->CursPosX = 0;
112 dc->CursPosY = 0;
113 dc->ArcDirection = AD_COUNTERCLOCKWISE;
114 dc->xformWorld2Wnd.eM11 = 1.0f;
115 dc->xformWorld2Wnd.eM12 = 0.0f;
116 dc->xformWorld2Wnd.eM21 = 0.0f;
117 dc->xformWorld2Wnd.eM22 = 1.0f;
118 dc->xformWorld2Wnd.eDx = 0.0f;
119 dc->xformWorld2Wnd.eDy = 0.0f;
120 dc->xformWorld2Vport = dc->xformWorld2Wnd;
121 dc->xformVport2World = dc->xformWorld2Wnd;
122 dc->vport2WorldValid = TRUE;
123 dc->BoundsRect.left = 0;
124 dc->BoundsRect.top = 0;
125 dc->BoundsRect.right = 0;
126 dc->BoundsRect.bottom = 0;
127 dc->saved_visrgn = NULL;
128 PATH_InitGdiPath(&dc->path);
129 return dc;
134 /***********************************************************************
135 * DC_GetDCPtr
137 DC *DC_GetDCPtr( HDC hdc )
139 GDIOBJHDR *ptr = GDI_GetObjPtr( hdc, MAGIC_DONTCARE );
140 if (!ptr) return NULL;
141 if ((GDIMAGIC(ptr->wMagic) == DC_MAGIC) ||
142 (GDIMAGIC(ptr->wMagic) == MEMORY_DC_MAGIC) ||
143 (GDIMAGIC(ptr->wMagic) == METAFILE_DC_MAGIC) ||
144 (GDIMAGIC(ptr->wMagic) == ENHMETAFILE_DC_MAGIC))
145 return (DC *)ptr;
146 GDI_ReleaseObj( hdc );
147 SetLastError( ERROR_INVALID_HANDLE );
148 return NULL;
151 /***********************************************************************
152 * DC_GetDCUpdate
154 * Retrieve a DC ptr while making sure the visRgn is updated.
155 * This function may call up to USER so the GDI lock should _not_
156 * be held when calling it.
158 DC *DC_GetDCUpdate( HDC hdc )
160 DC *dc = DC_GetDCPtr( hdc );
161 if (!dc) return NULL;
162 while (dc->flags & DC_DIRTY)
164 DCHOOKPROC proc = dc->hookThunk;
165 dc->flags &= ~DC_DIRTY;
166 if (proc)
168 DWORD_PTR data = dc->dwHookData;
169 DC_ReleaseDCPtr( dc );
170 proc( hdc, DCHC_INVALIDVISRGN, data, 0 );
171 if (!(dc = DC_GetDCPtr( hdc ))) break;
172 /* otherwise restart the loop in case it became dirty again in the meantime */
175 return dc;
179 /***********************************************************************
180 * DC_ReleaseDCPtr
182 void DC_ReleaseDCPtr( DC *dc )
184 GDI_ReleaseObj( dc->hSelf );
188 /***********************************************************************
189 * DC_FreeDCPtr
191 BOOL DC_FreeDCPtr( DC *dc )
193 return GDI_FreeObject( dc->hSelf, dc );
197 /***********************************************************************
198 * DC_DeleteObject
200 static BOOL DC_DeleteObject( HGDIOBJ handle, void *obj )
202 GDI_ReleaseObj( handle );
203 return DeleteDC( handle );
207 /***********************************************************************
208 * DC_InitDC
210 * Setup device-specific DC values for a newly created DC.
212 void DC_InitDC( DC* dc )
214 if (dc->funcs->pRealizeDefaultPalette) dc->funcs->pRealizeDefaultPalette( dc->physDev );
215 SetTextColor( dc->hSelf, dc->textColor );
216 SetBkColor( dc->hSelf, dc->backgroundColor );
217 SelectObject( dc->hSelf, dc->hPen );
218 SelectObject( dc->hSelf, dc->hBrush );
219 SelectObject( dc->hSelf, dc->hFont );
220 CLIPPING_UpdateGCRegion( dc );
224 /***********************************************************************
225 * DC_InvertXform
227 * Computes the inverse of the transformation xformSrc and stores it to
228 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
229 * is singular.
231 static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
233 FLOAT determinant;
235 determinant = xformSrc->eM11*xformSrc->eM22 -
236 xformSrc->eM12*xformSrc->eM21;
237 if (determinant > -1e-12 && determinant < 1e-12)
238 return FALSE;
240 xformDest->eM11 = xformSrc->eM22 / determinant;
241 xformDest->eM12 = -xformSrc->eM12 / determinant;
242 xformDest->eM21 = -xformSrc->eM21 / determinant;
243 xformDest->eM22 = xformSrc->eM11 / determinant;
244 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 -
245 xformSrc->eDy * xformDest->eM21;
246 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 -
247 xformSrc->eDy * xformDest->eM22;
249 return TRUE;
253 /***********************************************************************
254 * DC_UpdateXforms
256 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
257 * fields of the specified DC by creating a transformation that
258 * represents the current mapping mode and combining it with the DC's
259 * world transform. This function should be called whenever the
260 * parameters associated with the mapping mode (window and viewport
261 * extents and origins) or the world transform change.
263 void DC_UpdateXforms( DC *dc )
265 XFORM xformWnd2Vport, oldworld2vport;
266 FLOAT scaleX, scaleY;
268 /* Construct a transformation to do the window-to-viewport conversion */
269 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
270 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
271 xformWnd2Vport.eM11 = scaleX;
272 xformWnd2Vport.eM12 = 0.0;
273 xformWnd2Vport.eM21 = 0.0;
274 xformWnd2Vport.eM22 = scaleY;
275 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX -
276 scaleX * (FLOAT)dc->wndOrgX;
277 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY -
278 scaleY * (FLOAT)dc->wndOrgY;
280 oldworld2vport = dc->xformWorld2Vport;
281 /* Combine with the world transformation */
282 CombineTransform( &dc->xformWorld2Vport, &dc->xformWorld2Wnd,
283 &xformWnd2Vport );
285 /* Create inverse of world-to-viewport transformation */
286 dc->vport2WorldValid = DC_InvertXform( &dc->xformWorld2Vport,
287 &dc->xformVport2World );
289 /* Reselect the font and pen back into the dc so that the size
290 gets updated. */
291 if(memcmp(&oldworld2vport, &dc->xformWorld2Vport, sizeof(oldworld2vport)))
293 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_FONT));
294 SelectObject(dc->hSelf, GetCurrentObject(dc->hSelf, OBJ_PEN));
299 /***********************************************************************
300 * GetDCState (Not a Windows API)
302 HDC WINAPI GetDCState( HDC hdc )
304 DC * newdc, * dc;
305 HGDIOBJ handle;
307 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
308 if (!(newdc = GDI_AllocObject( sizeof(DC), GDIMAGIC(dc->header.wMagic), &handle, &dc_funcs )))
310 DC_ReleaseDCPtr( dc );
311 return 0;
313 TRACE("(%p): returning %p\n", hdc, handle );
315 newdc->flags = dc->flags | DC_SAVED;
316 newdc->layout = dc->layout;
317 newdc->hPen = dc->hPen;
318 newdc->hBrush = dc->hBrush;
319 newdc->hFont = dc->hFont;
320 newdc->hBitmap = dc->hBitmap;
321 newdc->hDevice = dc->hDevice;
322 newdc->hPalette = dc->hPalette;
323 newdc->ROPmode = dc->ROPmode;
324 newdc->polyFillMode = dc->polyFillMode;
325 newdc->stretchBltMode = dc->stretchBltMode;
326 newdc->relAbsMode = dc->relAbsMode;
327 newdc->backgroundMode = dc->backgroundMode;
328 newdc->backgroundColor = dc->backgroundColor;
329 newdc->textColor = dc->textColor;
330 newdc->dcBrushColor = dc->dcBrushColor;
331 newdc->dcPenColor = dc->dcPenColor;
332 newdc->brushOrgX = dc->brushOrgX;
333 newdc->brushOrgY = dc->brushOrgY;
334 newdc->textAlign = dc->textAlign;
335 newdc->charExtra = dc->charExtra;
336 newdc->breakExtra = dc->breakExtra;
337 newdc->breakRem = dc->breakRem;
338 newdc->MapMode = dc->MapMode;
339 newdc->GraphicsMode = dc->GraphicsMode;
340 newdc->CursPosX = dc->CursPosX;
341 newdc->CursPosY = dc->CursPosY;
342 newdc->ArcDirection = dc->ArcDirection;
343 newdc->xformWorld2Wnd = dc->xformWorld2Wnd;
344 newdc->xformWorld2Vport = dc->xformWorld2Vport;
345 newdc->xformVport2World = dc->xformVport2World;
346 newdc->vport2WorldValid = dc->vport2WorldValid;
347 newdc->wndOrgX = dc->wndOrgX;
348 newdc->wndOrgY = dc->wndOrgY;
349 newdc->wndExtX = dc->wndExtX;
350 newdc->wndExtY = dc->wndExtY;
351 newdc->vportOrgX = dc->vportOrgX;
352 newdc->vportOrgY = dc->vportOrgY;
353 newdc->vportExtX = dc->vportExtX;
354 newdc->vportExtY = dc->vportExtY;
355 newdc->BoundsRect = dc->BoundsRect;
357 newdc->hSelf = (HDC)handle;
358 newdc->saveLevel = 0;
359 newdc->saved_dc = 0;
361 PATH_InitGdiPath( &newdc->path );
363 newdc->pAbortProc = NULL;
364 newdc->hookThunk = NULL;
365 newdc->hookProc = 0;
366 newdc->saved_visrgn = NULL;
368 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
370 newdc->hVisRgn = 0;
371 newdc->hClipRgn = 0;
372 newdc->hMetaRgn = 0;
373 newdc->hMetaClipRgn = 0;
374 if (dc->hClipRgn)
376 newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
377 CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
379 if (dc->hMetaRgn)
381 newdc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
382 CombineRgn( newdc->hMetaRgn, dc->hMetaRgn, 0, RGN_COPY );
384 /* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
386 if(dc->gdiFont) {
387 newdc->gdiFont = dc->gdiFont;
388 } else
389 newdc->gdiFont = 0;
391 DC_ReleaseDCPtr( newdc );
392 DC_ReleaseDCPtr( dc );
393 return handle;
397 /***********************************************************************
398 * SetDCState (Not a Windows API)
400 void WINAPI SetDCState( HDC hdc, HDC hdcs )
402 DC *dc, *dcs;
404 if (!(dc = DC_GetDCUpdate( hdc ))) return;
405 if (!(dcs = DC_GetDCPtr( hdcs )))
407 DC_ReleaseDCPtr( dc );
408 return;
410 if (!dcs->flags & DC_SAVED)
412 DC_ReleaseDCPtr( dc );
413 DC_ReleaseDCPtr( dcs );
414 return;
416 TRACE("%p %p\n", hdc, hdcs );
418 dc->flags = dcs->flags & ~(DC_SAVED | DC_DIRTY);
419 dc->layout = dcs->layout;
420 dc->hDevice = dcs->hDevice;
421 dc->ROPmode = dcs->ROPmode;
422 dc->polyFillMode = dcs->polyFillMode;
423 dc->stretchBltMode = dcs->stretchBltMode;
424 dc->relAbsMode = dcs->relAbsMode;
425 dc->backgroundMode = dcs->backgroundMode;
426 dc->backgroundColor = dcs->backgroundColor;
427 dc->textColor = dcs->textColor;
428 dc->dcBrushColor = dcs->dcBrushColor;
429 dc->dcPenColor = dcs->dcPenColor;
430 dc->brushOrgX = dcs->brushOrgX;
431 dc->brushOrgY = dcs->brushOrgY;
432 dc->textAlign = dcs->textAlign;
433 dc->charExtra = dcs->charExtra;
434 dc->breakExtra = dcs->breakExtra;
435 dc->breakRem = dcs->breakRem;
436 dc->MapMode = dcs->MapMode;
437 dc->GraphicsMode = dcs->GraphicsMode;
438 dc->CursPosX = dcs->CursPosX;
439 dc->CursPosY = dcs->CursPosY;
440 dc->ArcDirection = dcs->ArcDirection;
441 dc->xformWorld2Wnd = dcs->xformWorld2Wnd;
442 dc->xformWorld2Vport = dcs->xformWorld2Vport;
443 dc->xformVport2World = dcs->xformVport2World;
444 dc->vport2WorldValid = dcs->vport2WorldValid;
445 dc->BoundsRect = dcs->BoundsRect;
447 dc->wndOrgX = dcs->wndOrgX;
448 dc->wndOrgY = dcs->wndOrgY;
449 dc->wndExtX = dcs->wndExtX;
450 dc->wndExtY = dcs->wndExtY;
451 dc->vportOrgX = dcs->vportOrgX;
452 dc->vportOrgY = dcs->vportOrgY;
453 dc->vportExtX = dcs->vportExtX;
454 dc->vportExtY = dcs->vportExtY;
456 if (dcs->hClipRgn)
458 if (!dc->hClipRgn) dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
459 CombineRgn( dc->hClipRgn, dcs->hClipRgn, 0, RGN_COPY );
461 else
463 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
464 dc->hClipRgn = 0;
466 if (dcs->hMetaRgn)
468 if (!dc->hMetaRgn) dc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
469 CombineRgn( dc->hMetaRgn, dcs->hMetaRgn, 0, RGN_COPY );
471 else
473 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
474 dc->hMetaRgn = 0;
476 CLIPPING_UpdateGCRegion( dc );
478 SelectObject( hdc, dcs->hBitmap );
479 SelectObject( hdc, dcs->hBrush );
480 SelectObject( hdc, dcs->hFont );
481 SelectObject( hdc, dcs->hPen );
482 SetBkColor( hdc, dcs->backgroundColor);
483 SetTextColor( hdc, dcs->textColor);
484 GDISelectPalette( hdc, dcs->hPalette, FALSE );
485 DC_ReleaseDCPtr( dcs );
486 DC_ReleaseDCPtr( dc );
490 /***********************************************************************
491 * GetDCState (GDI.179)
493 HDC16 WINAPI GetDCState16( HDC16 hdc )
495 return HDC_16( GetDCState( HDC_32(hdc) ));
499 /***********************************************************************
500 * SetDCState (GDI.180)
502 void WINAPI SetDCState16( HDC16 hdc, HDC16 hdcs )
504 SetDCState( HDC_32(hdc), HDC_32(hdcs) );
508 /***********************************************************************
509 * SaveDC (GDI32.@)
511 INT WINAPI SaveDC( HDC hdc )
513 HDC hdcs;
514 DC * dc, * dcs;
515 INT ret;
517 dc = DC_GetDCPtr( hdc );
518 if (!dc) return 0;
520 if(dc->funcs->pSaveDC)
522 ret = dc->funcs->pSaveDC( dc->physDev );
523 if(ret)
524 ret = ++dc->saveLevel;
525 DC_ReleaseDCPtr( dc );
526 return ret;
529 if (!(hdcs = GetDCState( hdc )))
531 DC_ReleaseDCPtr( dc );
532 return 0;
534 dcs = DC_GetDCPtr( hdcs );
536 /* Copy path. The reason why path saving / restoring is in SaveDC/
537 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
538 * functions are only in Win16 (which doesn't have paths) and that
539 * SetDCState doesn't allow us to signal an error (which can happen
540 * when copying paths).
542 if (!PATH_AssignGdiPath( &dcs->path, &dc->path ))
544 DC_ReleaseDCPtr( dc );
545 DC_ReleaseDCPtr( dcs );
546 DeleteDC( hdcs );
547 return 0;
550 dcs->saved_dc = dc->saved_dc;
551 dc->saved_dc = hdcs;
552 TRACE("(%p): returning %d\n", hdc, dc->saveLevel+1 );
553 ret = ++dc->saveLevel;
554 DC_ReleaseDCPtr( dcs );
555 DC_ReleaseDCPtr( dc );
556 return ret;
560 /***********************************************************************
561 * RestoreDC (GDI32.@)
563 BOOL WINAPI RestoreDC( HDC hdc, INT level )
565 DC * dc, * dcs;
566 BOOL success;
568 TRACE("%p %d\n", hdc, level );
569 dc = DC_GetDCUpdate( hdc );
570 if(!dc) return FALSE;
572 if(abs(level) > dc->saveLevel || level == 0)
574 DC_ReleaseDCPtr( dc );
575 return FALSE;
578 if(dc->funcs->pRestoreDC)
580 success = dc->funcs->pRestoreDC( dc->physDev, level );
581 if(level < 0) level = dc->saveLevel + level + 1;
582 if(success)
583 dc->saveLevel = level - 1;
584 DC_ReleaseDCPtr( dc );
585 return success;
588 if (level < 0) level = dc->saveLevel + level + 1;
589 success=TRUE;
590 while (dc->saveLevel >= level)
592 HDC hdcs = dc->saved_dc;
593 if (!(dcs = DC_GetDCPtr( hdcs )))
595 DC_ReleaseDCPtr( dc );
596 return FALSE;
598 dc->saved_dc = dcs->saved_dc;
599 dcs->saved_dc = 0;
600 if (--dc->saveLevel < level)
602 SetDCState( hdc, hdcs );
603 if (!PATH_AssignGdiPath( &dc->path, &dcs->path ))
604 /* FIXME: This might not be quite right, since we're
605 * returning FALSE but still destroying the saved DC state */
606 success=FALSE;
608 DC_ReleaseDCPtr( dcs );
609 DC_ReleaseDCPtr( dc );
610 DeleteDC( hdcs );
611 if (!(dc = DC_GetDCPtr( hdc ))) return FALSE;
613 DC_ReleaseDCPtr( dc );
614 return success;
618 /***********************************************************************
619 * CreateDCW (GDI32.@)
621 HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
622 const DEVMODEW *initData )
624 HDC hdc;
625 DC * dc;
626 const DC_FUNCTIONS *funcs;
627 WCHAR buf[300];
629 GDI_CheckNotLock();
631 if (!device || !DRIVER_GetDriverName( device, buf, 300 ))
633 if (!driver)
635 ERR( "no device found for %s\n", debugstr_w(device) );
636 return 0;
638 strcpyW(buf, driver);
641 if (!(funcs = DRIVER_load_driver( buf )))
643 ERR( "no driver found for %s\n", debugstr_w(buf) );
644 return 0;
646 if (!(dc = DC_AllocDC( funcs, DC_MAGIC ))) goto error;
647 hdc = dc->hSelf;
649 dc->hBitmap = GetStockObject( DEFAULT_BITMAP );
650 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;
652 TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
653 debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
655 if (dc->funcs->pCreateDC &&
656 !dc->funcs->pCreateDC( hdc, &dc->physDev, buf, device, output, initData ))
658 WARN("creation aborted by device\n" );
659 goto error;
662 SetRectRgn( dc->hVisRgn, 0, 0,
663 GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ) );
665 DC_InitDC( dc );
666 DC_ReleaseDCPtr( dc );
667 return hdc;
669 error:
670 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
671 if (dc) DC_FreeDCPtr( dc );
672 DRIVER_release_driver( funcs );
673 return 0;
677 /***********************************************************************
678 * CreateDCA (GDI32.@)
680 HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
681 const DEVMODEA *initData )
683 UNICODE_STRING driverW, deviceW, outputW;
684 DEVMODEW *initDataW;
685 HDC ret;
687 if (driver) RtlCreateUnicodeStringFromAsciiz(&driverW, driver);
688 else driverW.Buffer = NULL;
690 if (device) RtlCreateUnicodeStringFromAsciiz(&deviceW, device);
691 else deviceW.Buffer = NULL;
693 if (output) RtlCreateUnicodeStringFromAsciiz(&outputW, output);
694 else outputW.Buffer = NULL;
696 initDataW = NULL;
697 if (initData)
699 /* don't convert initData for DISPLAY driver, it's not used */
700 if (!driverW.Buffer || strcmpiW( driverW.Buffer, displayW ))
701 initDataW = GdiConvertToDevmodeW(initData);
704 ret = CreateDCW( driverW.Buffer, deviceW.Buffer, outputW.Buffer, initDataW );
706 RtlFreeUnicodeString(&driverW);
707 RtlFreeUnicodeString(&deviceW);
708 RtlFreeUnicodeString(&outputW);
709 HeapFree(GetProcessHeap(), 0, initDataW);
710 return ret;
714 /***********************************************************************
715 * CreateICA (GDI32.@)
717 HDC WINAPI CreateICA( LPCSTR driver, LPCSTR device, LPCSTR output,
718 const DEVMODEA* initData )
720 /* Nothing special yet for ICs */
721 return CreateDCA( driver, device, output, initData );
725 /***********************************************************************
726 * CreateICW (GDI32.@)
728 HDC WINAPI CreateICW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
729 const DEVMODEW* initData )
731 /* Nothing special yet for ICs */
732 return CreateDCW( driver, device, output, initData );
736 /***********************************************************************
737 * CreateCompatibleDC (GDI32.@)
739 HDC WINAPI CreateCompatibleDC( HDC hdc )
741 DC *dc, *origDC;
742 const DC_FUNCTIONS *funcs = NULL;
743 PHYSDEV physDev = NULL;
745 GDI_CheckNotLock();
747 if ((origDC = DC_GetDCPtr( hdc )))
749 if (GetObjectType( hdc ) == OBJ_DC)
751 funcs = origDC->funcs;
752 physDev = origDC->physDev;
754 DC_ReleaseDCPtr( origDC ); /* can't hold the lock while loading the driver */
755 if (funcs) funcs = DRIVER_get_driver( funcs );
758 if (!funcs && !(funcs = DRIVER_load_driver( displayW ))) return 0;
760 if (!(dc = DC_AllocDC( funcs, MEMORY_DC_MAGIC ))) goto error;
762 TRACE("(%p): returning %p\n", hdc, dc->hSelf );
764 dc->hBitmap = GetStockObject( DEFAULT_BITMAP );
765 if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error; /* default bitmap is 1x1 */
767 /* Copy the driver-specific physical device info into
768 * the new DC. The driver may use this read-only info
769 * while creating the compatible DC below. */
770 dc->physDev = physDev;
772 if (dc->funcs->pCreateDC &&
773 !dc->funcs->pCreateDC( dc->hSelf, &dc->physDev, NULL, NULL, NULL, NULL ))
775 WARN("creation aborted by device\n");
776 goto error;
779 DC_InitDC( dc );
780 DC_ReleaseDCPtr( dc );
781 return dc->hSelf;
783 error:
784 if (dc && dc->hVisRgn) DeleteObject( dc->hVisRgn );
785 if (dc) DC_FreeDCPtr( dc );
786 DRIVER_release_driver( funcs );
787 return 0;
791 /***********************************************************************
792 * DeleteDC (GDI32.@)
794 BOOL WINAPI DeleteDC( HDC hdc )
796 const DC_FUNCTIONS *funcs = NULL;
797 DC * dc;
799 TRACE("%p\n", hdc );
801 GDI_CheckNotLock();
803 if (!(dc = DC_GetDCPtr( hdc ))) return FALSE;
805 /* Call hook procedure to check whether is it OK to delete this DC */
806 if (dc->hookThunk)
808 DCHOOKPROC proc = dc->hookThunk;
809 DWORD_PTR data = dc->dwHookData;
810 DC_ReleaseDCPtr( dc );
811 if (!proc( hdc, DCHC_DELETEDC, data, 0 )) return FALSE;
812 if (!(dc = DC_GetDCPtr( hdc ))) return TRUE; /* deleted by the hook */
815 while (dc->saveLevel)
817 DC * dcs;
818 HDC hdcs = dc->saved_dc;
819 if (!(dcs = DC_GetDCPtr( hdcs ))) break;
820 dc->saved_dc = dcs->saved_dc;
821 dc->saveLevel--;
822 if (dcs->hClipRgn) DeleteObject( dcs->hClipRgn );
823 if (dcs->hMetaRgn) DeleteObject( dcs->hMetaRgn );
824 if (dcs->hMetaClipRgn) DeleteObject( dcs->hMetaClipRgn );
825 if (dcs->hVisRgn) DeleteObject( dcs->hVisRgn );
826 PATH_DestroyGdiPath(&dcs->path);
827 DC_FreeDCPtr( dcs );
830 if (!(dc->flags & DC_SAVED))
832 SelectObject( hdc, GetStockObject(BLACK_PEN) );
833 SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
834 SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
835 SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
836 funcs = dc->funcs;
837 if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc->physDev);
838 dc->physDev = NULL;
841 while (dc->saved_visrgn)
843 struct saved_visrgn *next = dc->saved_visrgn->next;
844 DeleteObject( dc->saved_visrgn->hrgn );
845 HeapFree( GetProcessHeap(), 0, dc->saved_visrgn );
846 dc->saved_visrgn = next;
848 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
849 if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
850 if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
851 if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
852 PATH_DestroyGdiPath(&dc->path);
854 DC_FreeDCPtr( dc );
855 if (funcs) DRIVER_release_driver( funcs ); /* do that after releasing the GDI lock */
856 return TRUE;
860 /***********************************************************************
861 * ResetDCW (GDI32.@)
863 HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
865 DC *dc;
866 HDC ret = hdc;
868 if ((dc = DC_GetDCPtr( hdc )))
870 if (dc->funcs->pResetDC) ret = dc->funcs->pResetDC( dc->physDev, devmode );
871 DC_ReleaseDCPtr( dc );
873 return ret;
877 /***********************************************************************
878 * ResetDCA (GDI32.@)
880 HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
882 DEVMODEW *devmodeW;
883 HDC ret;
885 if (devmode) devmodeW = GdiConvertToDevmodeW(devmode);
886 else devmodeW = NULL;
888 ret = ResetDCW(hdc, devmodeW);
890 HeapFree(GetProcessHeap(), 0, devmodeW);
891 return ret;
895 /***********************************************************************
896 * GetDeviceCaps (GDI32.@)
898 INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
900 DC *dc;
901 INT ret = 0;
903 if ((dc = DC_GetDCPtr( hdc )))
905 if (dc->funcs->pGetDeviceCaps) ret = dc->funcs->pGetDeviceCaps( dc->physDev, cap );
906 else switch(cap) /* return meaningful values for some entries */
908 case HORZRES: ret = 640; break;
909 case VERTRES: ret = 480; break;
910 case BITSPIXEL: ret = 1; break;
911 case PLANES: ret = 1; break;
912 case NUMCOLORS: ret = 2; break;
913 case ASPECTX: ret = 36; break;
914 case ASPECTY: ret = 36; break;
915 case ASPECTXY: ret = 51; break;
916 case LOGPIXELSX: ret = 72; break;
917 case LOGPIXELSY: ret = 72; break;
918 case SIZEPALETTE: ret = 2; break;
920 DC_ReleaseDCPtr( dc );
922 return ret;
926 /***********************************************************************
927 * GetBkColor (GDI32.@)
929 COLORREF WINAPI GetBkColor( HDC hdc )
931 COLORREF ret = 0;
932 DC * dc = DC_GetDCPtr( hdc );
933 if (dc)
935 ret = dc->backgroundColor;
936 DC_ReleaseDCPtr( dc );
938 return ret;
942 /***********************************************************************
943 * SetBkColor (GDI32.@)
945 COLORREF WINAPI SetBkColor( HDC hdc, COLORREF color )
947 COLORREF oldColor;
948 DC * dc = DC_GetDCPtr( hdc );
950 TRACE("hdc=%p color=0x%08x\n", hdc, color);
952 if (!dc) return CLR_INVALID;
953 oldColor = dc->backgroundColor;
954 if (dc->funcs->pSetBkColor)
956 color = dc->funcs->pSetBkColor(dc->physDev, color);
957 if (color == CLR_INVALID) /* don't change it */
959 color = oldColor;
960 oldColor = CLR_INVALID;
963 dc->backgroundColor = color;
964 DC_ReleaseDCPtr( dc );
965 return oldColor;
969 /***********************************************************************
970 * GetTextColor (GDI32.@)
972 COLORREF WINAPI GetTextColor( HDC hdc )
974 COLORREF ret = 0;
975 DC * dc = DC_GetDCPtr( hdc );
976 if (dc)
978 ret = dc->textColor;
979 DC_ReleaseDCPtr( dc );
981 return ret;
985 /***********************************************************************
986 * SetTextColor (GDI32.@)
988 COLORREF WINAPI SetTextColor( HDC hdc, COLORREF color )
990 COLORREF oldColor;
991 DC * dc = DC_GetDCPtr( hdc );
993 TRACE(" hdc=%p color=0x%08x\n", hdc, color);
995 if (!dc) return CLR_INVALID;
996 oldColor = dc->textColor;
997 if (dc->funcs->pSetTextColor)
999 color = dc->funcs->pSetTextColor(dc->physDev, color);
1000 if (color == CLR_INVALID) /* don't change it */
1002 color = oldColor;
1003 oldColor = CLR_INVALID;
1006 dc->textColor = color;
1007 DC_ReleaseDCPtr( dc );
1008 return oldColor;
1012 /***********************************************************************
1013 * GetTextAlign (GDI32.@)
1015 UINT WINAPI GetTextAlign( HDC hdc )
1017 UINT ret = 0;
1018 DC * dc = DC_GetDCPtr( hdc );
1019 if (dc)
1021 ret = dc->textAlign;
1022 DC_ReleaseDCPtr( dc );
1024 return ret;
1028 /***********************************************************************
1029 * SetTextAlign (GDI32.@)
1031 UINT WINAPI SetTextAlign( HDC hdc, UINT align )
1033 UINT ret;
1034 DC *dc = DC_GetDCPtr( hdc );
1036 TRACE("hdc=%p align=%d\n", hdc, align);
1038 if (!dc) return 0x0;
1039 ret = dc->textAlign;
1040 if (dc->funcs->pSetTextAlign)
1041 if (!dc->funcs->pSetTextAlign(dc->physDev, align))
1042 ret = GDI_ERROR;
1043 if (ret != GDI_ERROR)
1044 dc->textAlign = align;
1045 DC_ReleaseDCPtr( dc );
1046 return ret;
1049 /***********************************************************************
1050 * GetDCOrgEx (GDI32.@)
1052 BOOL WINAPI GetDCOrgEx( HDC hDC, LPPOINT lpp )
1054 DC * dc;
1056 if (!lpp) return FALSE;
1057 if (!(dc = DC_GetDCPtr( hDC ))) return FALSE;
1059 lpp->x = lpp->y = 0;
1060 if (dc->funcs->pGetDCOrgEx) dc->funcs->pGetDCOrgEx( dc->physDev, lpp );
1061 DC_ReleaseDCPtr( dc );
1062 return TRUE;
1066 /***********************************************************************
1067 * SetDCOrg (GDI.117)
1069 DWORD WINAPI SetDCOrg16( HDC16 hdc16, INT16 x, INT16 y )
1071 DWORD prevOrg = 0;
1072 HDC hdc = HDC_32( hdc16 );
1073 DC *dc = DC_GetDCPtr( hdc );
1074 if (!dc) return 0;
1075 if (dc->funcs->pSetDCOrg) prevOrg = dc->funcs->pSetDCOrg( dc->physDev, x, y );
1076 DC_ReleaseDCPtr( dc );
1077 return prevOrg;
1081 /***********************************************************************
1082 * GetGraphicsMode (GDI32.@)
1084 INT WINAPI GetGraphicsMode( HDC hdc )
1086 INT ret = 0;
1087 DC * dc = DC_GetDCPtr( hdc );
1088 if (dc)
1090 ret = dc->GraphicsMode;
1091 DC_ReleaseDCPtr( dc );
1093 return ret;
1097 /***********************************************************************
1098 * SetGraphicsMode (GDI32.@)
1100 INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
1102 INT ret = 0;
1103 DC *dc = DC_GetDCPtr( hdc );
1105 /* One would think that setting the graphics mode to GM_COMPATIBLE
1106 * would also reset the world transformation matrix to the unity
1107 * matrix. However, in Windows, this is not the case. This doesn't
1108 * make a lot of sense to me, but that's the way it is.
1110 if (!dc) return 0;
1111 if ((mode > 0) && (mode <= GM_LAST))
1113 ret = dc->GraphicsMode;
1114 dc->GraphicsMode = mode;
1116 DC_ReleaseDCPtr( dc );
1117 return ret;
1121 /***********************************************************************
1122 * GetArcDirection (GDI32.@)
1124 INT WINAPI GetArcDirection( HDC hdc )
1126 INT ret = 0;
1127 DC * dc = DC_GetDCPtr( hdc );
1128 if (dc)
1130 ret = dc->ArcDirection;
1131 DC_ReleaseDCPtr( dc );
1133 return ret;
1137 /***********************************************************************
1138 * SetArcDirection (GDI32.@)
1140 INT WINAPI SetArcDirection( HDC hdc, INT nDirection )
1142 DC * dc;
1143 INT nOldDirection = 0;
1145 if (nDirection!=AD_COUNTERCLOCKWISE && nDirection!=AD_CLOCKWISE)
1147 SetLastError(ERROR_INVALID_PARAMETER);
1148 return 0;
1151 if ((dc = DC_GetDCPtr( hdc )))
1153 if (dc->funcs->pSetArcDirection)
1155 dc->funcs->pSetArcDirection(dc->physDev, nDirection);
1157 nOldDirection = dc->ArcDirection;
1158 dc->ArcDirection = nDirection;
1159 DC_ReleaseDCPtr( dc );
1161 return nOldDirection;
1165 /***********************************************************************
1166 * GetWorldTransform (GDI32.@)
1168 BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
1170 DC * dc;
1171 if (!xform) return FALSE;
1172 if (!(dc = DC_GetDCPtr( hdc ))) return FALSE;
1173 *xform = dc->xformWorld2Wnd;
1174 DC_ReleaseDCPtr( dc );
1175 return TRUE;
1179 /***********************************************************************
1180 * GetTransform (GDI32.@)
1182 BOOL WINAPI GetTransform( HDC hdc, DWORD unknown, LPXFORM xform )
1184 if (unknown == 0x0203) return GetWorldTransform( hdc, xform );
1185 FIXME("stub: don't know what to do for code %x\n", unknown );
1186 return FALSE;
1190 /***********************************************************************
1191 * SetWorldTransform (GDI32.@)
1193 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
1195 BOOL ret = FALSE;
1196 DC *dc = DC_GetDCPtr( hdc );
1198 if (!dc) return FALSE;
1199 if (!xform) goto done;
1201 /* Check that graphics mode is GM_ADVANCED */
1202 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1204 if (dc->funcs->pSetWorldTransform)
1206 ret = dc->funcs->pSetWorldTransform(dc->physDev, xform);
1207 if (!ret) goto done;
1210 dc->xformWorld2Wnd = *xform;
1211 DC_UpdateXforms( dc );
1212 ret = TRUE;
1213 done:
1214 DC_ReleaseDCPtr( dc );
1215 return ret;
1219 /****************************************************************************
1220 * ModifyWorldTransform [GDI32.@]
1221 * Modifies the world transformation for a device context.
1223 * PARAMS
1224 * hdc [I] Handle to device context
1225 * xform [I] XFORM structure that will be used to modify the world
1226 * transformation
1227 * iMode [I] Specifies in what way to modify the world transformation
1228 * Possible values:
1229 * MWT_IDENTITY
1230 * Resets the world transformation to the identity matrix.
1231 * The parameter xform is ignored.
1232 * MWT_LEFTMULTIPLY
1233 * Multiplies xform into the world transformation matrix from
1234 * the left.
1235 * MWT_RIGHTMULTIPLY
1236 * Multiplies xform into the world transformation matrix from
1237 * the right.
1239 * RETURNS
1240 * Success: TRUE.
1241 * Failure: FALSE. Use GetLastError() to determine the cause.
1243 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform,
1244 DWORD iMode )
1246 BOOL ret = FALSE;
1247 DC *dc = DC_GetDCPtr( hdc );
1249 /* Check for illegal parameters */
1250 if (!dc) return FALSE;
1251 if (!xform && iMode != MWT_IDENTITY) goto done;
1253 /* Check that graphics mode is GM_ADVANCED */
1254 if (dc->GraphicsMode!=GM_ADVANCED) goto done;
1256 if (dc->funcs->pModifyWorldTransform)
1258 ret = dc->funcs->pModifyWorldTransform(dc->physDev, xform, iMode);
1259 if (!ret) goto done;
1262 switch (iMode)
1264 case MWT_IDENTITY:
1265 dc->xformWorld2Wnd.eM11 = 1.0f;
1266 dc->xformWorld2Wnd.eM12 = 0.0f;
1267 dc->xformWorld2Wnd.eM21 = 0.0f;
1268 dc->xformWorld2Wnd.eM22 = 1.0f;
1269 dc->xformWorld2Wnd.eDx = 0.0f;
1270 dc->xformWorld2Wnd.eDy = 0.0f;
1271 break;
1272 case MWT_LEFTMULTIPLY:
1273 CombineTransform( &dc->xformWorld2Wnd, xform,
1274 &dc->xformWorld2Wnd );
1275 break;
1276 case MWT_RIGHTMULTIPLY:
1277 CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd,
1278 xform );
1279 break;
1280 default:
1281 goto done;
1284 DC_UpdateXforms( dc );
1285 ret = TRUE;
1286 done:
1287 DC_ReleaseDCPtr( dc );
1288 return ret;
1292 /****************************************************************************
1293 * CombineTransform [GDI32.@]
1294 * Combines two transformation matrices.
1296 * PARAMS
1297 * xformResult [O] Stores the result of combining the two matrices
1298 * xform1 [I] Specifies the first matrix to apply
1299 * xform2 [I] Specifies the second matrix to apply
1301 * REMARKS
1302 * The same matrix can be passed in for more than one of the parameters.
1304 * RETURNS
1305 * Success: TRUE.
1306 * Failure: FALSE. Use GetLastError() to determine the cause.
1308 BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
1309 const XFORM *xform2 )
1311 XFORM xformTemp;
1313 /* Check for illegal parameters */
1314 if (!xformResult || !xform1 || !xform2)
1315 return FALSE;
1317 /* Create the result in a temporary XFORM, since xformResult may be
1318 * equal to xform1 or xform2 */
1319 xformTemp.eM11 = xform1->eM11 * xform2->eM11 +
1320 xform1->eM12 * xform2->eM21;
1321 xformTemp.eM12 = xform1->eM11 * xform2->eM12 +
1322 xform1->eM12 * xform2->eM22;
1323 xformTemp.eM21 = xform1->eM21 * xform2->eM11 +
1324 xform1->eM22 * xform2->eM21;
1325 xformTemp.eM22 = xform1->eM21 * xform2->eM12 +
1326 xform1->eM22 * xform2->eM22;
1327 xformTemp.eDx = xform1->eDx * xform2->eM11 +
1328 xform1->eDy * xform2->eM21 +
1329 xform2->eDx;
1330 xformTemp.eDy = xform1->eDx * xform2->eM12 +
1331 xform1->eDy * xform2->eM22 +
1332 xform2->eDy;
1334 /* Copy the result to xformResult */
1335 *xformResult = xformTemp;
1337 return TRUE;
1341 /***********************************************************************
1342 * SetDCHook (GDI32.@)
1344 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1346 BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD_PTR dwHookData )
1348 DC *dc = DC_GetDCPtr( hdc );
1350 if (!dc) return FALSE;
1352 if (!(dc->flags & DC_SAVED))
1354 dc->dwHookData = dwHookData;
1355 dc->hookThunk = hookProc;
1357 DC_ReleaseDCPtr( dc );
1358 return TRUE;
1362 /* relay function to call the 16-bit DC hook proc */
1363 static BOOL WINAPI call_dc_hook16( HDC hdc, WORD code, DWORD_PTR data, LPARAM lParam )
1365 WORD args[6];
1366 DWORD ret;
1367 FARPROC16 proc = NULL;
1368 DC *dc = DC_GetDCPtr( hdc );
1370 if (!dc) return FALSE;
1371 proc = dc->hookProc;
1372 DC_ReleaseDCPtr( dc );
1373 if (!proc) return FALSE;
1374 args[5] = HDC_16(hdc);
1375 args[4] = code;
1376 args[3] = HIWORD(data);
1377 args[2] = LOWORD(data);
1378 args[1] = HIWORD(lParam);
1379 args[0] = LOWORD(lParam);
1380 WOWCallback16Ex( (DWORD)proc, WCB16_PASCAL, sizeof(args), args, &ret );
1381 return LOWORD(ret);
1384 /***********************************************************************
1385 * SetDCHook (GDI.190)
1387 BOOL16 WINAPI SetDCHook16( HDC16 hdc16, FARPROC16 hookProc, DWORD dwHookData )
1389 HDC hdc = HDC_32( hdc16 );
1390 DC *dc = DC_GetDCPtr( hdc );
1391 if (!dc) return FALSE;
1393 dc->hookProc = hookProc;
1394 DC_ReleaseDCPtr( dc );
1395 return SetDCHook( hdc, call_dc_hook16, dwHookData );
1399 /***********************************************************************
1400 * GetDCHook (GDI.191)
1402 DWORD WINAPI GetDCHook16( HDC16 hdc16, FARPROC16 *phookProc )
1404 HDC hdc = HDC_32( hdc16 );
1405 DC *dc = DC_GetDCPtr( hdc );
1406 DWORD ret;
1408 if (!dc) return 0;
1409 *phookProc = dc->hookProc;
1410 ret = dc->dwHookData;
1411 DC_ReleaseDCPtr( dc );
1412 return ret;
1416 /***********************************************************************
1417 * SetHookFlags (GDI.192)
1419 WORD WINAPI SetHookFlags16(HDC16 hdc16, WORD flags)
1421 HDC hdc = HDC_32( hdc16 );
1422 DC *dc = DC_GetDCPtr( hdc );
1424 if( dc )
1426 WORD wRet = dc->flags & DC_DIRTY;
1428 /* "Undocumented Windows" info is slightly confusing.
1431 TRACE("hDC %p, flags %04x\n",hdc,flags);
1433 if( flags & DCHF_INVALIDATEVISRGN )
1434 dc->flags |= DC_DIRTY;
1435 else if( flags & DCHF_VALIDATEVISRGN || !flags )
1436 dc->flags &= ~DC_DIRTY;
1437 DC_ReleaseDCPtr( dc );
1438 return wRet;
1440 return 0;
1443 /***********************************************************************
1444 * SetICMMode (GDI32.@)
1446 INT WINAPI SetICMMode(HDC hdc, INT iEnableICM)
1448 /*FIXME Asuming that ICM is always off, and cannot be turned on */
1449 if (iEnableICM == ICM_OFF) return ICM_OFF;
1450 if (iEnableICM == ICM_ON) return 0;
1451 if (iEnableICM == ICM_QUERY) return ICM_OFF;
1452 return 0;
1455 /***********************************************************************
1456 * GetDeviceGammaRamp (GDI32.@)
1458 BOOL WINAPI GetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1460 BOOL ret = FALSE;
1461 DC *dc = DC_GetDCPtr( hDC );
1463 if( dc )
1465 if (dc->funcs->pGetDeviceGammaRamp)
1466 ret = dc->funcs->pGetDeviceGammaRamp(dc->physDev, ptr);
1467 DC_ReleaseDCPtr( dc );
1469 return ret;
1472 /***********************************************************************
1473 * SetDeviceGammaRamp (GDI32.@)
1475 BOOL WINAPI SetDeviceGammaRamp(HDC hDC, LPVOID ptr)
1477 BOOL ret = FALSE;
1478 DC *dc = DC_GetDCPtr( hDC );
1480 if( dc )
1482 if (dc->funcs->pSetDeviceGammaRamp)
1483 ret = dc->funcs->pSetDeviceGammaRamp(dc->physDev, ptr);
1484 DC_ReleaseDCPtr( dc );
1486 return ret;
1489 /***********************************************************************
1490 * GetColorSpace (GDI32.@)
1492 HCOLORSPACE WINAPI GetColorSpace(HDC hdc)
1494 /*FIXME Need to to whatever GetColorSpace actually does */
1495 return 0;
1498 /***********************************************************************
1499 * CreateColorSpaceA (GDI32.@)
1501 HCOLORSPACE WINAPI CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace )
1503 FIXME( "stub\n" );
1504 return 0;
1507 /***********************************************************************
1508 * CreateColorSpaceW (GDI32.@)
1510 HCOLORSPACE WINAPI CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace )
1512 FIXME( "stub\n" );
1513 return 0;
1516 /***********************************************************************
1517 * DeleteColorSpace (GDI32.@)
1519 BOOL WINAPI DeleteColorSpace( HCOLORSPACE hColorSpace )
1521 FIXME( "stub\n" );
1523 return TRUE;
1526 /***********************************************************************
1527 * SetColorSpace (GDI32.@)
1529 HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
1531 FIXME( "stub\n" );
1533 return hColorSpace;
1536 /***********************************************************************
1537 * GetBoundsRect (GDI32.@)
1539 UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
1541 UINT ret;
1542 DC *dc = DC_GetDCPtr( hdc );
1544 if ( !dc ) return 0;
1546 if (rect) *rect = dc->BoundsRect;
1548 ret = ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1550 if (flags & DCB_RESET)
1552 dc->BoundsRect.left = 0;
1553 dc->BoundsRect.top = 0;
1554 dc->BoundsRect.right = 0;
1555 dc->BoundsRect.bottom = 0;
1556 dc->flags &= ~DC_BOUNDS_SET;
1558 DC_ReleaseDCPtr( dc );
1559 return ret;
1563 /***********************************************************************
1564 * SetBoundsRect (GDI32.@)
1566 UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
1568 UINT ret;
1569 DC *dc;
1571 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
1572 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
1574 ret = ((dc->flags & DC_BOUNDS_ENABLE) ? DCB_ENABLE : DCB_DISABLE) |
1575 ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
1577 if (flags & DCB_RESET)
1579 dc->BoundsRect.left = 0;
1580 dc->BoundsRect.top = 0;
1581 dc->BoundsRect.right = 0;
1582 dc->BoundsRect.bottom = 0;
1583 dc->flags &= ~DC_BOUNDS_SET;
1586 if ((flags & DCB_ACCUMULATE) && rect && rect->left < rect->right && rect->top < rect->bottom)
1588 if (dc->flags & DC_BOUNDS_SET)
1590 dc->BoundsRect.left = min( dc->BoundsRect.left, rect->left );
1591 dc->BoundsRect.top = min( dc->BoundsRect.top, rect->top );
1592 dc->BoundsRect.right = max( dc->BoundsRect.right, rect->right );
1593 dc->BoundsRect.bottom = max( dc->BoundsRect.bottom, rect->bottom );
1595 else
1597 dc->BoundsRect = *rect;
1598 dc->flags |= DC_BOUNDS_SET;
1602 if (flags & DCB_ENABLE) dc->flags |= DC_BOUNDS_ENABLE;
1603 if (flags & DCB_DISABLE) dc->flags &= ~DC_BOUNDS_ENABLE;
1605 DC_ReleaseDCPtr( dc );
1606 return ret;
1610 /***********************************************************************
1611 * GetRelAbs (GDI32.@)
1613 INT WINAPI GetRelAbs( HDC hdc, DWORD dwIgnore )
1615 INT ret = 0;
1616 DC *dc = DC_GetDCPtr( hdc );
1617 if (dc)
1619 ret = dc->relAbsMode;
1620 DC_ReleaseDCPtr( dc );
1622 return ret;
1628 /***********************************************************************
1629 * GetBkMode (GDI32.@)
1631 INT WINAPI GetBkMode( HDC hdc )
1633 INT ret = 0;
1634 DC * dc = DC_GetDCPtr( hdc );
1635 if (dc)
1637 ret = dc->backgroundMode;
1638 DC_ReleaseDCPtr( dc );
1640 return ret;
1644 /***********************************************************************
1645 * SetBkMode (GDI32.@)
1647 INT WINAPI SetBkMode( HDC hdc, INT mode )
1649 INT ret;
1650 DC *dc;
1651 if ((mode <= 0) || (mode > BKMODE_LAST))
1653 SetLastError(ERROR_INVALID_PARAMETER);
1654 return 0;
1656 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
1658 ret = dc->backgroundMode;
1659 if (dc->funcs->pSetBkMode)
1660 if (!dc->funcs->pSetBkMode( dc->physDev, mode ))
1661 ret = 0;
1662 if (ret)
1663 dc->backgroundMode = mode;
1664 DC_ReleaseDCPtr( dc );
1665 return ret;
1669 /***********************************************************************
1670 * GetROP2 (GDI32.@)
1672 INT WINAPI GetROP2( HDC hdc )
1674 INT ret = 0;
1675 DC * dc = DC_GetDCPtr( hdc );
1676 if (dc)
1678 ret = dc->ROPmode;
1679 DC_ReleaseDCPtr( dc );
1681 return ret;
1685 /***********************************************************************
1686 * SetROP2 (GDI32.@)
1688 INT WINAPI SetROP2( HDC hdc, INT mode )
1690 INT ret;
1691 DC *dc;
1692 if ((mode < R2_BLACK) || (mode > R2_WHITE))
1694 SetLastError(ERROR_INVALID_PARAMETER);
1695 return 0;
1697 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
1698 ret = dc->ROPmode;
1699 if (dc->funcs->pSetROP2)
1700 if (!dc->funcs->pSetROP2( dc->physDev, mode ))
1701 ret = 0;
1702 if (ret)
1703 dc->ROPmode = mode;
1704 DC_ReleaseDCPtr( dc );
1705 return ret;
1709 /***********************************************************************
1710 * SetRelAbs (GDI32.@)
1712 INT WINAPI SetRelAbs( HDC hdc, INT mode )
1714 INT ret;
1715 DC *dc;
1716 if ((mode != ABSOLUTE) && (mode != RELATIVE))
1718 SetLastError(ERROR_INVALID_PARAMETER);
1719 return 0;
1721 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
1722 if (dc->funcs->pSetRelAbs)
1723 ret = dc->funcs->pSetRelAbs( dc->physDev, mode );
1724 else
1726 ret = dc->relAbsMode;
1727 dc->relAbsMode = mode;
1729 DC_ReleaseDCPtr( dc );
1730 return ret;
1734 /***********************************************************************
1735 * GetPolyFillMode (GDI32.@)
1737 INT WINAPI GetPolyFillMode( HDC hdc )
1739 INT ret = 0;
1740 DC * dc = DC_GetDCPtr( hdc );
1741 if (dc)
1743 ret = dc->polyFillMode;
1744 DC_ReleaseDCPtr( dc );
1746 return ret;
1750 /***********************************************************************
1751 * SetPolyFillMode (GDI32.@)
1753 INT WINAPI SetPolyFillMode( HDC hdc, INT mode )
1755 INT ret;
1756 DC *dc;
1757 if ((mode <= 0) || (mode > POLYFILL_LAST))
1759 SetLastError(ERROR_INVALID_PARAMETER);
1760 return 0;
1762 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
1763 ret = dc->polyFillMode;
1764 if (dc->funcs->pSetPolyFillMode)
1765 if (!dc->funcs->pSetPolyFillMode( dc->physDev, mode ))
1766 ret = 0;
1767 if (ret)
1768 dc->polyFillMode = mode;
1769 DC_ReleaseDCPtr( dc );
1770 return ret;
1774 /***********************************************************************
1775 * GetStretchBltMode (GDI32.@)
1777 INT WINAPI GetStretchBltMode( HDC hdc )
1779 INT ret = 0;
1780 DC * dc = DC_GetDCPtr( hdc );
1781 if (dc)
1783 ret = dc->stretchBltMode;
1784 DC_ReleaseDCPtr( dc );
1786 return ret;
1790 /***********************************************************************
1791 * SetStretchBltMode (GDI32.@)
1793 INT WINAPI SetStretchBltMode( HDC hdc, INT mode )
1795 INT ret;
1796 DC *dc;
1797 if ((mode <= 0) || (mode > MAXSTRETCHBLTMODE))
1799 SetLastError(ERROR_INVALID_PARAMETER);
1800 return 0;
1802 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
1803 ret = dc->stretchBltMode;
1804 if (dc->funcs->pSetStretchBltMode)
1805 if (!dc->funcs->pSetStretchBltMode( dc->physDev, mode ))
1806 ret = 0;
1807 if (ret)
1808 dc->stretchBltMode = mode;
1809 DC_ReleaseDCPtr( dc );
1810 return ret;
1814 /***********************************************************************
1815 * GetMapMode (GDI32.@)
1817 INT WINAPI GetMapMode( HDC hdc )
1819 INT ret = 0;
1820 DC * dc = DC_GetDCPtr( hdc );
1821 if (dc)
1823 ret = dc->MapMode;
1824 DC_ReleaseDCPtr( dc );
1826 return ret;
1830 /***********************************************************************
1831 * GetBrushOrgEx (GDI32.@)
1833 BOOL WINAPI GetBrushOrgEx( HDC hdc, LPPOINT pt )
1835 DC * dc = DC_GetDCPtr( hdc );
1836 if (!dc) return FALSE;
1837 pt->x = dc->brushOrgX;
1838 pt->y = dc->brushOrgY;
1839 DC_ReleaseDCPtr( dc );
1840 return TRUE;
1844 /***********************************************************************
1845 * GetCurrentPositionEx (GDI32.@)
1847 BOOL WINAPI GetCurrentPositionEx( HDC hdc, LPPOINT pt )
1849 DC * dc = DC_GetDCPtr( hdc );
1850 if (!dc) return FALSE;
1851 pt->x = dc->CursPosX;
1852 pt->y = dc->CursPosY;
1853 DC_ReleaseDCPtr( dc );
1854 return TRUE;
1858 /***********************************************************************
1859 * GetViewportExtEx (GDI32.@)
1861 BOOL WINAPI GetViewportExtEx( HDC hdc, LPSIZE size )
1863 DC * dc = DC_GetDCPtr( hdc );
1864 if (!dc) return FALSE;
1865 size->cx = dc->vportExtX;
1866 size->cy = dc->vportExtY;
1867 DC_ReleaseDCPtr( dc );
1868 return TRUE;
1872 /***********************************************************************
1873 * GetViewportOrgEx (GDI32.@)
1875 BOOL WINAPI GetViewportOrgEx( HDC hdc, LPPOINT pt )
1877 DC * dc = DC_GetDCPtr( hdc );
1878 if (!dc) return FALSE;
1879 pt->x = dc->vportOrgX;
1880 pt->y = dc->vportOrgY;
1881 DC_ReleaseDCPtr( dc );
1882 return TRUE;
1886 /***********************************************************************
1887 * GetWindowExtEx (GDI32.@)
1889 BOOL WINAPI GetWindowExtEx( HDC hdc, LPSIZE size )
1891 DC * dc = DC_GetDCPtr( hdc );
1892 if (!dc) return FALSE;
1893 size->cx = dc->wndExtX;
1894 size->cy = dc->wndExtY;
1895 DC_ReleaseDCPtr( dc );
1896 return TRUE;
1900 /***********************************************************************
1901 * GetWindowOrgEx (GDI32.@)
1903 BOOL WINAPI GetWindowOrgEx( HDC hdc, LPPOINT pt )
1905 DC * dc = DC_GetDCPtr( hdc );
1906 if (!dc) return FALSE;
1907 pt->x = dc->wndOrgX;
1908 pt->y = dc->wndOrgY;
1909 DC_ReleaseDCPtr( dc );
1910 return TRUE;
1914 /***********************************************************************
1915 * InquireVisRgn (GDI.131)
1917 HRGN16 WINAPI InquireVisRgn16( HDC16 hdc )
1919 HRGN16 ret = 0;
1920 DC * dc = DC_GetDCPtr( HDC_32(hdc) );
1921 if (dc)
1923 ret = HRGN_16(dc->hVisRgn);
1924 DC_ReleaseDCPtr( dc );
1926 return ret;
1930 /***********************************************************************
1931 * GetClipRgn (GDI.173)
1933 HRGN16 WINAPI GetClipRgn16( HDC16 hdc )
1935 HRGN16 ret = 0;
1936 DC * dc = DC_GetDCPtr( HDC_32(hdc) );
1937 if (dc)
1939 ret = HRGN_16(dc->hClipRgn);
1940 DC_ReleaseDCPtr( dc );
1942 return ret;
1946 /***********************************************************************
1947 * GetLayout (GDI32.@)
1949 * Gets left->right or right->left text layout flags of a dc.
1952 DWORD WINAPI GetLayout(HDC hdc)
1954 DWORD layout = GDI_ERROR;
1956 DC * dc = DC_GetDCPtr( hdc );
1957 if (dc)
1959 layout = dc->layout;
1960 DC_ReleaseDCPtr( dc );
1963 TRACE("hdc : %p, layout : %08x\n", hdc, layout);
1965 return layout;
1968 /***********************************************************************
1969 * SetLayout (GDI32.@)
1971 * Sets left->right or right->left text layout flags of a dc.
1974 DWORD WINAPI SetLayout(HDC hdc, DWORD layout)
1976 DWORD oldlayout = GDI_ERROR;
1978 DC * dc = DC_GetDCPtr( hdc );
1979 if (dc)
1981 oldlayout = dc->layout;
1982 dc->layout = layout;
1983 DC_ReleaseDCPtr( dc );
1986 TRACE("hdc : %p, old layout : %08x, new layout : %08x\n", hdc, oldlayout, layout);
1988 return oldlayout;
1991 /***********************************************************************
1992 * GetDCBrushColor (GDI32.@)
1994 * Retrieves the current brush color for the specified device
1995 * context (DC).
1998 COLORREF WINAPI GetDCBrushColor(HDC hdc)
2000 DC *dc;
2001 COLORREF dcBrushColor = CLR_INVALID;
2003 TRACE("hdc(%p)\n", hdc);
2005 dc = DC_GetDCPtr( hdc );
2006 if (dc)
2008 dcBrushColor = dc->dcBrushColor;
2009 DC_ReleaseDCPtr( dc );
2012 return dcBrushColor;
2015 /***********************************************************************
2016 * SetDCBrushColor (GDI32.@)
2018 * Sets the current device context (DC) brush color to the specified
2019 * color value. If the device cannot represent the specified color
2020 * value, the color is set to the nearest physical color.
2023 COLORREF WINAPI SetDCBrushColor(HDC hdc, COLORREF crColor)
2025 DC *dc;
2026 COLORREF oldClr = CLR_INVALID;
2028 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2030 dc = DC_GetDCPtr( hdc );
2031 if (dc)
2033 if (dc->funcs->pSetDCBrushColor)
2034 crColor = dc->funcs->pSetDCBrushColor( dc->physDev, crColor );
2035 else if (dc->hBrush == GetStockObject( DC_BRUSH ))
2037 /* If DC_BRUSH is selected, update driver pen color */
2038 HBRUSH hBrush = CreateSolidBrush( crColor );
2039 dc->funcs->pSelectBrush( dc->physDev, hBrush );
2040 DeleteObject( hBrush );
2043 if (crColor != CLR_INVALID)
2045 oldClr = dc->dcBrushColor;
2046 dc->dcBrushColor = crColor;
2049 DC_ReleaseDCPtr( dc );
2052 return oldClr;
2055 /***********************************************************************
2056 * GetDCPenColor (GDI32.@)
2058 * Retrieves the current pen color for the specified device
2059 * context (DC).
2062 COLORREF WINAPI GetDCPenColor(HDC hdc)
2064 DC *dc;
2065 COLORREF dcPenColor = CLR_INVALID;
2067 TRACE("hdc(%p)\n", hdc);
2069 dc = DC_GetDCPtr( hdc );
2070 if (dc)
2072 dcPenColor = dc->dcPenColor;
2073 DC_ReleaseDCPtr( dc );
2076 return dcPenColor;
2079 /***********************************************************************
2080 * SetDCPenColor (GDI32.@)
2082 * Sets the current device context (DC) pen color to the specified
2083 * color value. If the device cannot represent the specified color
2084 * value, the color is set to the nearest physical color.
2087 COLORREF WINAPI SetDCPenColor(HDC hdc, COLORREF crColor)
2089 DC *dc;
2090 COLORREF oldClr = CLR_INVALID;
2092 TRACE("hdc(%p) crColor(%08x)\n", hdc, crColor);
2094 dc = DC_GetDCPtr( hdc );
2095 if (dc)
2097 if (dc->funcs->pSetDCPenColor)
2098 crColor = dc->funcs->pSetDCPenColor( dc->physDev, crColor );
2099 else if (dc->hPen == GetStockObject( DC_PEN ))
2101 /* If DC_PEN is selected, update the driver pen color */
2102 LOGPEN logpen = { PS_SOLID, { 0, 0 }, crColor };
2103 HPEN hPen = CreatePenIndirect( &logpen );
2104 dc->funcs->pSelectPen( dc->physDev, hPen );
2105 DeleteObject( hPen );
2108 if (crColor != CLR_INVALID)
2110 oldClr = dc->dcPenColor;
2111 dc->dcPenColor = crColor;
2114 DC_ReleaseDCPtr( dc );
2117 return oldClr;
2120 /***********************************************************************
2121 * CancelDC (GDI32.@)
2123 BOOL WINAPI CancelDC(HDC hdc)
2125 FIXME("stub\n");
2126 return TRUE;
2129 /***********************************************************************
2130 * SetVirtualResolution (GDI32.@)
2132 * Undocumented on msdn. Called when PowerPoint XP saves a file.
2134 DWORD WINAPI SetVirtualResolution(HDC hdc, DWORD dw2, DWORD dw3, DWORD dw4, DWORD dw5)
2136 FIXME("(%p %08x %08x %08x %08x): stub!\n", hdc, dw2, dw3, dw4, dw5);
2137 return FALSE;
2140 /*******************************************************************
2141 * GetMiterLimit [GDI32.@]
2145 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
2147 BOOL bRet = FALSE;
2148 DC *dc;
2150 TRACE("(%p,%p)\n", hdc, peLimit);
2152 dc = DC_GetDCPtr( hdc );
2153 if (dc)
2155 if (peLimit)
2156 *peLimit = dc->miterLimit;
2158 DC_ReleaseDCPtr( dc );
2159 bRet = TRUE;
2161 return bRet;
2164 /*******************************************************************
2165 * SetMiterLimit [GDI32.@]
2169 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
2171 BOOL bRet = FALSE;
2172 DC *dc;
2174 TRACE("(%p,%f,%p)\n", hdc, eNewLimit, peOldLimit);
2176 dc = DC_GetDCPtr( hdc );
2177 if (dc)
2179 if (peOldLimit)
2180 *peOldLimit = dc->miterLimit;
2181 dc->miterLimit = eNewLimit;
2182 DC_ReleaseDCPtr( dc );
2183 bRet = TRUE;
2185 return bRet;
2188 /*******************************************************************
2189 * GdiIsMetaPrintDC [GDI32.@]
2191 BOOL WINAPI GdiIsMetaPrintDC(HDC hdc)
2193 FIXME("%p\n", hdc);
2194 return FALSE;
2197 /*******************************************************************
2198 * GdiIsMetaFileDC [GDI32.@]
2200 BOOL WINAPI GdiIsMetaFileDC(HDC hdc)
2202 TRACE("%p\n", hdc);
2204 switch( GetObjectType( hdc ) )
2206 case OBJ_METADC:
2207 case OBJ_ENHMETADC:
2208 return TRUE;
2210 return FALSE;
2213 /*******************************************************************
2214 * GdiIsPlayMetafileDC [GDI32.@]
2216 BOOL WINAPI GdiIsPlayMetafileDC(HDC hdc)
2218 FIXME("%p\n", hdc);
2219 return FALSE;