2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "gdi_private.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dc
);
39 static const WCHAR displayW
[] = { 'd','i','s','p','l','a','y',0 };
41 static BOOL
DC_DeleteObject( HGDIOBJ handle
);
43 static const struct gdi_obj_funcs dc_funcs
=
45 NULL
, /* pSelectObject */
46 NULL
, /* pGetObjectA */
47 NULL
, /* pGetObjectW */
48 NULL
, /* pUnrealizeObject */
49 DC_DeleteObject
/* pDeleteObject */
53 static inline DC
*get_dc_obj( HDC hdc
)
55 DC
*dc
= GDI_GetObjPtr( hdc
, 0 );
58 if ((dc
->header
.type
!= OBJ_DC
) &&
59 (dc
->header
.type
!= OBJ_MEMDC
) &&
60 (dc
->header
.type
!= OBJ_METADC
) &&
61 (dc
->header
.type
!= OBJ_ENHMETADC
))
63 GDI_ReleaseObj( hdc
);
64 SetLastError( ERROR_INVALID_HANDLE
);
71 /***********************************************************************
74 DC
*alloc_dc_ptr( const DC_FUNCTIONS
*funcs
, WORD magic
)
78 if (!(dc
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dc
) ))) return NULL
;
81 dc
->nulldrv
.funcs
= &null_driver
;
82 dc
->nulldrv
.next
= NULL
;
83 dc
->physDev
= &dc
->nulldrv
;
84 dc
->thread
= GetCurrentThreadId();
99 dc
->miterLimit
= 10.0f
; /* 10.0 is the default, from MSDN */
104 dc
->hMetaClipRgn
= 0;
106 dc
->hPen
= GDI_inc_ref_count( GetStockObject( BLACK_PEN
));
107 dc
->hBrush
= GDI_inc_ref_count( GetStockObject( WHITE_BRUSH
));
108 dc
->hFont
= GDI_inc_ref_count( GetStockObject( SYSTEM_FONT
));
111 dc
->hPalette
= GetStockObject( DEFAULT_PALETTE
);
113 dc
->font_code_page
= CP_ACP
;
114 dc
->ROPmode
= R2_COPYPEN
;
115 dc
->polyFillMode
= ALTERNATE
;
116 dc
->stretchBltMode
= BLACKONWHITE
;
117 dc
->relAbsMode
= ABSOLUTE
;
118 dc
->backgroundMode
= OPAQUE
;
119 dc
->backgroundColor
= RGB( 255, 255, 255 );
120 dc
->dcBrushColor
= RGB( 255, 255, 255 );
121 dc
->dcPenColor
= RGB( 0, 0, 0 );
122 dc
->textColor
= RGB( 0, 0, 0 );
126 dc
->textAlign
= TA_LEFT
| TA_TOP
| TA_NOUPDATECP
;
130 dc
->MapMode
= MM_TEXT
;
131 dc
->GraphicsMode
= GM_COMPATIBLE
;
132 dc
->pAbortProc
= NULL
;
135 dc
->ArcDirection
= AD_COUNTERCLOCKWISE
;
136 dc
->xformWorld2Wnd
.eM11
= 1.0f
;
137 dc
->xformWorld2Wnd
.eM12
= 0.0f
;
138 dc
->xformWorld2Wnd
.eM21
= 0.0f
;
139 dc
->xformWorld2Wnd
.eM22
= 1.0f
;
140 dc
->xformWorld2Wnd
.eDx
= 0.0f
;
141 dc
->xformWorld2Wnd
.eDy
= 0.0f
;
142 dc
->xformWorld2Vport
= dc
->xformWorld2Wnd
;
143 dc
->xformVport2World
= dc
->xformWorld2Wnd
;
144 dc
->vport2WorldValid
= TRUE
;
145 dc
->BoundsRect
.left
= 0;
146 dc
->BoundsRect
.top
= 0;
147 dc
->BoundsRect
.right
= 0;
148 dc
->BoundsRect
.bottom
= 0;
149 PATH_InitGdiPath(&dc
->path
);
151 if (!(dc
->hSelf
= alloc_gdi_handle( &dc
->header
, magic
, &dc_funcs
)))
153 HeapFree( GetProcessHeap(), 0, dc
);
156 dc
->nulldrv
.hdc
= dc
->hSelf
;
162 /***********************************************************************
165 BOOL
free_dc_ptr( DC
*dc
)
167 assert( dc
->refcount
== 1 );
168 if (free_gdi_handle( dc
->hSelf
) != dc
) return FALSE
; /* shouldn't happen */
169 if (dc
->hClipRgn
) DeleteObject( dc
->hClipRgn
);
170 if (dc
->hMetaRgn
) DeleteObject( dc
->hMetaRgn
);
171 if (dc
->hMetaClipRgn
) DeleteObject( dc
->hMetaClipRgn
);
172 if (dc
->hVisRgn
) DeleteObject( dc
->hVisRgn
);
173 PATH_DestroyGdiPath( &dc
->path
);
174 return HeapFree( GetProcessHeap(), 0, dc
);
178 /***********************************************************************
181 * Retrieve a DC pointer but release the GDI lock.
183 DC
*get_dc_ptr( HDC hdc
)
185 DC
*dc
= get_dc_obj( hdc
);
186 if (!dc
) return NULL
;
188 if (!InterlockedCompareExchange( &dc
->refcount
, 1, 0 ))
190 dc
->thread
= GetCurrentThreadId();
192 else if (dc
->thread
!= GetCurrentThreadId())
194 WARN( "dc %p belongs to thread %04x\n", hdc
, dc
->thread
);
195 GDI_ReleaseObj( hdc
);
198 else InterlockedIncrement( &dc
->refcount
);
200 GDI_ReleaseObj( hdc
);
205 /***********************************************************************
208 void release_dc_ptr( DC
*dc
)
213 ref
= InterlockedDecrement( &dc
->refcount
);
215 if (ref
) dc
->thread
= GetCurrentThreadId(); /* we still own it */
219 /***********************************************************************
222 * Make sure the DC vis region is up to date.
223 * This function may call up to USER so the GDI lock should _not_
224 * be held when calling it.
226 void update_dc( DC
*dc
)
228 if (InterlockedExchange( &dc
->dirty
, 0 ) && dc
->hookProc
)
229 dc
->hookProc( dc
->hSelf
, DCHC_INVALIDVISRGN
, dc
->dwHookData
, 0 );
233 /***********************************************************************
236 * Push a driver on top of the DC driver stack.
238 void push_dc_driver( DC
* dc
, PHYSDEV physdev
)
240 physdev
->next
= dc
->physDev
;
241 physdev
->hdc
= dc
->hSelf
;
242 dc
->physDev
= physdev
;
243 dc
->funcs
= physdev
->funcs
;
247 /***********************************************************************
250 * Pop the top driver from the DC driver stack.
252 void pop_dc_driver( DC
* dc
, PHYSDEV physdev
)
254 assert( physdev
== dc
->physDev
);
255 assert( physdev
!= &dc
->nulldrv
);
256 dc
->physDev
= physdev
->next
;
257 dc
->funcs
= dc
->physDev
->funcs
;
261 /***********************************************************************
264 static BOOL
DC_DeleteObject( HGDIOBJ handle
)
266 return DeleteDC( handle
);
270 /***********************************************************************
273 * Setup device-specific DC values for a newly created DC.
275 void DC_InitDC( DC
* dc
)
277 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pRealizeDefaultPalette
);
278 physdev
->funcs
->pRealizeDefaultPalette( physdev
);
279 SetTextColor( dc
->hSelf
, dc
->textColor
);
280 SetBkColor( dc
->hSelf
, dc
->backgroundColor
);
281 SelectObject( dc
->hSelf
, dc
->hPen
);
282 SelectObject( dc
->hSelf
, dc
->hBrush
);
283 SelectObject( dc
->hSelf
, dc
->hFont
);
284 CLIPPING_UpdateGCRegion( dc
);
285 SetVirtualResolution( dc
->hSelf
, 0, 0, 0, 0 );
289 /***********************************************************************
292 * Computes the inverse of the transformation xformSrc and stores it to
293 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
296 static BOOL
DC_InvertXform( const XFORM
*xformSrc
, XFORM
*xformDest
)
300 determinant
= xformSrc
->eM11
*xformSrc
->eM22
-
301 xformSrc
->eM12
*xformSrc
->eM21
;
302 if (determinant
> -1e-12 && determinant
< 1e-12)
305 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
306 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
307 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
308 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
309 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
-
310 xformSrc
->eDy
* xformDest
->eM21
;
311 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
-
312 xformSrc
->eDy
* xformDest
->eM22
;
317 /* Construct a transformation to do the window-to-viewport conversion */
318 static void construct_window_to_viewport(DC
*dc
, XFORM
*xform
)
320 double scaleX
, scaleY
;
321 scaleX
= (double)dc
->vportExtX
/ (double)dc
->wndExtX
;
322 scaleY
= (double)dc
->vportExtY
/ (double)dc
->wndExtY
;
324 if (dc
->layout
& LAYOUT_RTL
) scaleX
= -scaleX
;
325 xform
->eM11
= scaleX
;
328 xform
->eM22
= scaleY
;
329 xform
->eDx
= (double)dc
->vportOrgX
- scaleX
* (double)dc
->wndOrgX
;
330 xform
->eDy
= (double)dc
->vportOrgY
- scaleY
* (double)dc
->wndOrgY
;
331 if (dc
->layout
& LAYOUT_RTL
) xform
->eDx
= dc
->vis_rect
.right
- dc
->vis_rect
.left
- 1 - xform
->eDx
;
334 /***********************************************************************
337 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
338 * fields of the specified DC by creating a transformation that
339 * represents the current mapping mode and combining it with the DC's
340 * world transform. This function should be called whenever the
341 * parameters associated with the mapping mode (window and viewport
342 * extents and origins) or the world transform change.
344 void DC_UpdateXforms( DC
*dc
)
346 XFORM xformWnd2Vport
, oldworld2vport
;
348 construct_window_to_viewport(dc
, &xformWnd2Vport
);
350 oldworld2vport
= dc
->xformWorld2Vport
;
351 /* Combine with the world transformation */
352 CombineTransform( &dc
->xformWorld2Vport
, &dc
->xformWorld2Wnd
,
355 /* Create inverse of world-to-viewport transformation */
356 dc
->vport2WorldValid
= DC_InvertXform( &dc
->xformWorld2Vport
,
357 &dc
->xformVport2World
);
359 /* Reselect the font and pen back into the dc so that the size
361 if (memcmp(&oldworld2vport
, &dc
->xformWorld2Vport
, sizeof(oldworld2vport
)) &&
362 !GdiIsMetaFileDC(dc
->hSelf
))
364 SelectObject(dc
->hSelf
, GetCurrentObject(dc
->hSelf
, OBJ_FONT
));
365 SelectObject(dc
->hSelf
, GetCurrentObject(dc
->hSelf
, OBJ_PEN
));
370 /***********************************************************************
373 INT CDECL
nulldrv_SaveDC( PHYSDEV dev
)
375 DC
*newdc
, *dc
= get_nulldrv_dc( dev
);
378 if (!(newdc
= HeapAlloc( GetProcessHeap(), 0, sizeof(*newdc
)))) return 0;
379 newdc
->flags
= dc
->flags
| DC_SAVED
;
380 newdc
->layout
= dc
->layout
;
381 newdc
->hPen
= dc
->hPen
;
382 newdc
->hBrush
= dc
->hBrush
;
383 newdc
->hFont
= dc
->hFont
;
384 newdc
->hBitmap
= dc
->hBitmap
;
385 newdc
->hDevice
= dc
->hDevice
;
386 newdc
->hPalette
= dc
->hPalette
;
387 newdc
->ROPmode
= dc
->ROPmode
;
388 newdc
->polyFillMode
= dc
->polyFillMode
;
389 newdc
->stretchBltMode
= dc
->stretchBltMode
;
390 newdc
->relAbsMode
= dc
->relAbsMode
;
391 newdc
->backgroundMode
= dc
->backgroundMode
;
392 newdc
->backgroundColor
= dc
->backgroundColor
;
393 newdc
->textColor
= dc
->textColor
;
394 newdc
->dcBrushColor
= dc
->dcBrushColor
;
395 newdc
->dcPenColor
= dc
->dcPenColor
;
396 newdc
->brushOrgX
= dc
->brushOrgX
;
397 newdc
->brushOrgY
= dc
->brushOrgY
;
398 newdc
->mapperFlags
= dc
->mapperFlags
;
399 newdc
->textAlign
= dc
->textAlign
;
400 newdc
->charExtra
= dc
->charExtra
;
401 newdc
->breakExtra
= dc
->breakExtra
;
402 newdc
->breakRem
= dc
->breakRem
;
403 newdc
->MapMode
= dc
->MapMode
;
404 newdc
->GraphicsMode
= dc
->GraphicsMode
;
405 newdc
->CursPosX
= dc
->CursPosX
;
406 newdc
->CursPosY
= dc
->CursPosY
;
407 newdc
->ArcDirection
= dc
->ArcDirection
;
408 newdc
->xformWorld2Wnd
= dc
->xformWorld2Wnd
;
409 newdc
->xformWorld2Vport
= dc
->xformWorld2Vport
;
410 newdc
->xformVport2World
= dc
->xformVport2World
;
411 newdc
->vport2WorldValid
= dc
->vport2WorldValid
;
412 newdc
->wndOrgX
= dc
->wndOrgX
;
413 newdc
->wndOrgY
= dc
->wndOrgY
;
414 newdc
->wndExtX
= dc
->wndExtX
;
415 newdc
->wndExtY
= dc
->wndExtY
;
416 newdc
->vportOrgX
= dc
->vportOrgX
;
417 newdc
->vportOrgY
= dc
->vportOrgY
;
418 newdc
->vportExtX
= dc
->vportExtX
;
419 newdc
->vportExtY
= dc
->vportExtY
;
420 newdc
->virtual_res
= dc
->virtual_res
;
421 newdc
->virtual_size
= dc
->virtual_size
;
422 newdc
->BoundsRect
= dc
->BoundsRect
;
423 newdc
->gdiFont
= dc
->gdiFont
;
425 newdc
->thread
= GetCurrentThreadId();
427 newdc
->saveLevel
= 0;
430 PATH_InitGdiPath( &newdc
->path
);
432 newdc
->pAbortProc
= NULL
;
433 newdc
->hookProc
= NULL
;
435 if (!(newdc
->hSelf
= alloc_gdi_handle( &newdc
->header
, dc
->header
.type
, &dc_funcs
)))
437 HeapFree( GetProcessHeap(), 0, newdc
);
441 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
446 newdc
->hMetaClipRgn
= 0;
449 newdc
->hClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
450 CombineRgn( newdc
->hClipRgn
, dc
->hClipRgn
, 0, RGN_COPY
);
454 newdc
->hMetaRgn
= CreateRectRgn( 0, 0, 0, 0 );
455 CombineRgn( newdc
->hMetaRgn
, dc
->hMetaRgn
, 0, RGN_COPY
);
457 /* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
459 if (!PATH_AssignGdiPath( &newdc
->path
, &dc
->path
))
461 release_dc_ptr( dc
);
462 free_dc_ptr( newdc
);
466 newdc
->saved_dc
= dc
->saved_dc
;
467 dc
->saved_dc
= newdc
->hSelf
;
468 ret
= ++dc
->saveLevel
;
469 release_dc_ptr( newdc
);
474 /***********************************************************************
477 BOOL CDECL
nulldrv_RestoreDC( PHYSDEV dev
, INT level
)
479 DC
*dcs
, *dc
= get_nulldrv_dc( dev
);
483 /* find the state level to restore */
485 if (abs(level
) > dc
->saveLevel
|| level
== 0) return FALSE
;
486 if (level
< 0) level
= dc
->saveLevel
+ level
+ 1;
487 first_dcs
= dc
->saved_dc
;
488 for (hdcs
= first_dcs
, save_level
= dc
->saveLevel
; save_level
> level
; save_level
--)
490 if (!(dcs
= get_dc_ptr( hdcs
))) return FALSE
;
491 hdcs
= dcs
->saved_dc
;
492 release_dc_ptr( dcs
);
495 /* restore the state */
497 if (!(dcs
= get_dc_ptr( hdcs
))) return FALSE
;
498 if (!PATH_AssignGdiPath( &dc
->path
, &dcs
->path
))
500 release_dc_ptr( dcs
);
504 dc
->flags
= dcs
->flags
& ~DC_SAVED
;
505 dc
->layout
= dcs
->layout
;
506 dc
->hDevice
= dcs
->hDevice
;
507 dc
->ROPmode
= dcs
->ROPmode
;
508 dc
->polyFillMode
= dcs
->polyFillMode
;
509 dc
->stretchBltMode
= dcs
->stretchBltMode
;
510 dc
->relAbsMode
= dcs
->relAbsMode
;
511 dc
->backgroundMode
= dcs
->backgroundMode
;
512 dc
->backgroundColor
= dcs
->backgroundColor
;
513 dc
->textColor
= dcs
->textColor
;
514 dc
->dcBrushColor
= dcs
->dcBrushColor
;
515 dc
->dcPenColor
= dcs
->dcPenColor
;
516 dc
->brushOrgX
= dcs
->brushOrgX
;
517 dc
->brushOrgY
= dcs
->brushOrgY
;
518 dc
->mapperFlags
= dcs
->mapperFlags
;
519 dc
->textAlign
= dcs
->textAlign
;
520 dc
->charExtra
= dcs
->charExtra
;
521 dc
->breakExtra
= dcs
->breakExtra
;
522 dc
->breakRem
= dcs
->breakRem
;
523 dc
->MapMode
= dcs
->MapMode
;
524 dc
->GraphicsMode
= dcs
->GraphicsMode
;
525 dc
->CursPosX
= dcs
->CursPosX
;
526 dc
->CursPosY
= dcs
->CursPosY
;
527 dc
->ArcDirection
= dcs
->ArcDirection
;
528 dc
->xformWorld2Wnd
= dcs
->xformWorld2Wnd
;
529 dc
->xformWorld2Vport
= dcs
->xformWorld2Vport
;
530 dc
->xformVport2World
= dcs
->xformVport2World
;
531 dc
->vport2WorldValid
= dcs
->vport2WorldValid
;
532 dc
->BoundsRect
= dcs
->BoundsRect
;
534 dc
->wndOrgX
= dcs
->wndOrgX
;
535 dc
->wndOrgY
= dcs
->wndOrgY
;
536 dc
->wndExtX
= dcs
->wndExtX
;
537 dc
->wndExtY
= dcs
->wndExtY
;
538 dc
->vportOrgX
= dcs
->vportOrgX
;
539 dc
->vportOrgY
= dcs
->vportOrgY
;
540 dc
->vportExtX
= dcs
->vportExtX
;
541 dc
->vportExtY
= dcs
->vportExtY
;
542 dc
->virtual_res
= dcs
->virtual_res
;
543 dc
->virtual_size
= dcs
->virtual_size
;
547 if (!dc
->hClipRgn
) dc
->hClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
548 CombineRgn( dc
->hClipRgn
, dcs
->hClipRgn
, 0, RGN_COPY
);
552 if (dc
->hClipRgn
) DeleteObject( dc
->hClipRgn
);
557 if (!dc
->hMetaRgn
) dc
->hMetaRgn
= CreateRectRgn( 0, 0, 0, 0 );
558 CombineRgn( dc
->hMetaRgn
, dcs
->hMetaRgn
, 0, RGN_COPY
);
562 if (dc
->hMetaRgn
) DeleteObject( dc
->hMetaRgn
);
565 DC_UpdateXforms( dc
);
566 CLIPPING_UpdateGCRegion( dc
);
568 SelectObject( dev
->hdc
, dcs
->hBitmap
);
569 SelectObject( dev
->hdc
, dcs
->hBrush
);
570 SelectObject( dev
->hdc
, dcs
->hFont
);
571 SelectObject( dev
->hdc
, dcs
->hPen
);
572 SetBkColor( dev
->hdc
, dcs
->backgroundColor
);
573 SetTextColor( dev
->hdc
, dcs
->textColor
);
574 GDISelectPalette( dev
->hdc
, dcs
->hPalette
, FALSE
);
576 dc
->saved_dc
= dcs
->saved_dc
;
578 dc
->saveLevel
= save_level
- 1;
580 release_dc_ptr( dcs
);
582 /* now destroy all the saved DCs */
586 if (!(dcs
= get_dc_ptr( first_dcs
))) break;
587 hdcs
= dcs
->saved_dc
;
595 /***********************************************************************
598 INT WINAPI
SaveDC( HDC hdc
)
603 if ((dc
= get_dc_ptr( hdc
)))
605 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSaveDC
);
606 ret
= physdev
->funcs
->pSaveDC( physdev
);
607 release_dc_ptr( dc
);
613 /***********************************************************************
614 * RestoreDC (GDI32.@)
616 BOOL WINAPI
RestoreDC( HDC hdc
, INT level
)
619 BOOL success
= FALSE
;
621 TRACE("%p %d\n", hdc
, level
);
622 if ((dc
= get_dc_ptr( hdc
)))
624 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pRestoreDC
);
626 success
= physdev
->funcs
->pRestoreDC( physdev
, level
);
627 release_dc_ptr( dc
);
633 /***********************************************************************
634 * CreateDCW (GDI32.@)
636 HDC WINAPI
CreateDCW( LPCWSTR driver
, LPCWSTR device
, LPCWSTR output
,
637 const DEVMODEW
*initData
)
642 const DC_FUNCTIONS
*funcs
;
647 if (!device
|| !DRIVER_GetDriverName( device
, buf
, 300 ))
651 ERR( "no device found for %s\n", debugstr_w(device
) );
654 strcpyW(buf
, driver
);
657 if (!(funcs
= DRIVER_load_driver( buf
)))
659 ERR( "no driver found for %s\n", debugstr_w(buf
) );
662 if (!(dc
= alloc_dc_ptr( funcs
, OBJ_DC
))) goto error
;
665 dc
->hBitmap
= GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP
));
666 if (!(dc
->hVisRgn
= CreateRectRgn( 0, 0, 1, 1 ))) goto error
;
668 TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
669 debugstr_w(driver
), debugstr_w(device
), debugstr_w(output
), dc
->hSelf
);
671 if (dc
->funcs
->pCreateDC
&&
672 !dc
->funcs
->pCreateDC( hdc
, &physdev
, buf
, device
, output
, initData
))
674 WARN("creation aborted by device\n" );
678 physdev
->funcs
= funcs
;
679 push_dc_driver( dc
, physdev
);
681 dc
->vis_rect
.left
= 0;
682 dc
->vis_rect
.top
= 0;
683 dc
->vis_rect
.right
= GetDeviceCaps( hdc
, DESKTOPHORZRES
);
684 dc
->vis_rect
.bottom
= GetDeviceCaps( hdc
, DESKTOPVERTRES
);
685 SetRectRgn(dc
->hVisRgn
, dc
->vis_rect
.left
, dc
->vis_rect
.top
, dc
->vis_rect
.right
, dc
->vis_rect
.bottom
);
688 release_dc_ptr( dc
);
692 if (dc
) free_dc_ptr( dc
);
697 /***********************************************************************
698 * CreateDCA (GDI32.@)
700 HDC WINAPI
CreateDCA( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
701 const DEVMODEA
*initData
)
703 UNICODE_STRING driverW
, deviceW
, outputW
;
707 if (driver
) RtlCreateUnicodeStringFromAsciiz(&driverW
, driver
);
708 else driverW
.Buffer
= NULL
;
710 if (device
) RtlCreateUnicodeStringFromAsciiz(&deviceW
, device
);
711 else deviceW
.Buffer
= NULL
;
713 if (output
) RtlCreateUnicodeStringFromAsciiz(&outputW
, output
);
714 else outputW
.Buffer
= NULL
;
719 /* don't convert initData for DISPLAY driver, it's not used */
720 if (!driverW
.Buffer
|| strcmpiW( driverW
.Buffer
, displayW
))
721 initDataW
= GdiConvertToDevmodeW(initData
);
724 ret
= CreateDCW( driverW
.Buffer
, deviceW
.Buffer
, outputW
.Buffer
, initDataW
);
726 RtlFreeUnicodeString(&driverW
);
727 RtlFreeUnicodeString(&deviceW
);
728 RtlFreeUnicodeString(&outputW
);
729 HeapFree(GetProcessHeap(), 0, initDataW
);
734 /***********************************************************************
735 * CreateICA (GDI32.@)
737 HDC WINAPI
CreateICA( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
738 const DEVMODEA
* initData
)
740 /* Nothing special yet for ICs */
741 return CreateDCA( driver
, device
, output
, initData
);
745 /***********************************************************************
746 * CreateICW (GDI32.@)
748 HDC WINAPI
CreateICW( LPCWSTR driver
, LPCWSTR device
, LPCWSTR output
,
749 const DEVMODEW
* initData
)
751 /* Nothing special yet for ICs */
752 return CreateDCW( driver
, device
, output
, initData
);
756 /***********************************************************************
757 * CreateCompatibleDC (GDI32.@)
759 HDC WINAPI
CreateCompatibleDC( HDC hdc
)
763 const DC_FUNCTIONS
*funcs
= NULL
;
764 PHYSDEV physDev
= NULL
;
770 if (!(origDC
= get_dc_ptr( hdc
))) return 0;
771 if (GetObjectType( hdc
) == OBJ_DC
)
773 funcs
= origDC
->funcs
;
774 physDev
= origDC
->physDev
;
776 release_dc_ptr( origDC
);
779 if (!funcs
&& !(funcs
= DRIVER_get_display_driver())) return 0;
781 if (!(dc
= alloc_dc_ptr( funcs
, OBJ_MEMDC
))) goto error
;
783 TRACE("(%p): returning %p\n", hdc
, dc
->hSelf
);
785 dc
->hBitmap
= GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP
));
786 dc
->vis_rect
.left
= 0;
787 dc
->vis_rect
.top
= 0;
788 dc
->vis_rect
.right
= 1;
789 dc
->vis_rect
.bottom
= 1;
790 if (!(dc
->hVisRgn
= CreateRectRgn( 0, 0, 1, 1 ))) goto error
; /* default bitmap is 1x1 */
794 /* Pass the driver-specific physical device info into
795 * the new DC. The driver may use this read-only info
796 * while creating the compatible DC. */
797 if (dc
->funcs
->pCreateDC
&&
798 !dc
->funcs
->pCreateDC( dc
->hSelf
, &physDev
, NULL
, NULL
, NULL
, NULL
))
800 WARN("creation aborted by device\n");
804 physDev
->funcs
= funcs
;
805 push_dc_driver( dc
, physDev
);
807 release_dc_ptr( dc
);
811 if (dc
) free_dc_ptr( dc
);
816 /***********************************************************************
819 BOOL WINAPI
DeleteDC( HDC hdc
)
827 if (!(dc
= get_dc_ptr( hdc
))) return FALSE
;
828 if (dc
->refcount
!= 1)
830 FIXME( "not deleting busy DC %p refcount %u\n", dc
->hSelf
, dc
->refcount
);
831 release_dc_ptr( dc
);
835 /* Call hook procedure to check whether is it OK to delete this DC */
836 if (dc
->hookProc
&& !dc
->hookProc( hdc
, DCHC_DELETEDC
, dc
->dwHookData
, 0 ))
838 release_dc_ptr( dc
);
842 while (dc
->saveLevel
)
845 HDC hdcs
= dc
->saved_dc
;
846 if (!(dcs
= get_dc_ptr( hdcs
))) break;
847 dc
->saved_dc
= dcs
->saved_dc
;
852 if (!(dc
->flags
& DC_SAVED
))
854 SelectObject( hdc
, GetStockObject(BLACK_PEN
) );
855 SelectObject( hdc
, GetStockObject(WHITE_BRUSH
) );
856 SelectObject( hdc
, GetStockObject(SYSTEM_FONT
) );
857 SelectObject( hdc
, GetStockObject(DEFAULT_BITMAP
) );
858 if (dc
->funcs
->pDeleteDC
) dc
->funcs
->pDeleteDC(dc
->physDev
);
867 /***********************************************************************
870 HDC WINAPI
ResetDCW( HDC hdc
, const DEVMODEW
*devmode
)
875 if ((dc
= get_dc_ptr( hdc
)))
877 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pResetDC
);
878 ret
= physdev
->funcs
->pResetDC( physdev
, devmode
);
879 if (ret
) /* reset the visible region */
882 dc
->vis_rect
.left
= 0;
883 dc
->vis_rect
.top
= 0;
884 dc
->vis_rect
.right
= GetDeviceCaps( hdc
, DESKTOPHORZRES
);
885 dc
->vis_rect
.bottom
= GetDeviceCaps( hdc
, DESKTOPVERTRES
);
886 SetRectRgn( dc
->hVisRgn
, dc
->vis_rect
.left
, dc
->vis_rect
.top
,
887 dc
->vis_rect
.right
, dc
->vis_rect
.bottom
);
888 CLIPPING_UpdateGCRegion( dc
);
890 release_dc_ptr( dc
);
896 /***********************************************************************
899 HDC WINAPI
ResetDCA( HDC hdc
, const DEVMODEA
*devmode
)
904 if (devmode
) devmodeW
= GdiConvertToDevmodeW(devmode
);
905 else devmodeW
= NULL
;
907 ret
= ResetDCW(hdc
, devmodeW
);
909 HeapFree(GetProcessHeap(), 0, devmodeW
);
914 /***********************************************************************
915 * GetDeviceCaps (GDI32.@)
917 INT WINAPI
GetDeviceCaps( HDC hdc
, INT cap
)
922 if ((dc
= get_dc_ptr( hdc
)))
924 if (dc
->funcs
->pGetDeviceCaps
) ret
= dc
->funcs
->pGetDeviceCaps( dc
->physDev
, cap
);
925 else switch(cap
) /* return meaningful values for some entries */
927 case HORZRES
: ret
= 640; break;
928 case VERTRES
: ret
= 480; break;
929 case BITSPIXEL
: ret
= 1; break;
930 case PLANES
: ret
= 1; break;
931 case NUMCOLORS
: ret
= 2; break;
932 case ASPECTX
: ret
= 36; break;
933 case ASPECTY
: ret
= 36; break;
934 case ASPECTXY
: ret
= 51; break;
935 case LOGPIXELSX
: ret
= 72; break;
936 case LOGPIXELSY
: ret
= 72; break;
937 case SIZEPALETTE
: ret
= 2; break;
939 ret
= (TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
940 TC_CR_ANY
| TC_SF_X_YINDEP
| TC_SA_DOUBLE
| TC_SA_INTEGER
|
941 TC_SA_CONTIN
| TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
| TC_VA_ABLE
);
944 release_dc_ptr( dc
);
950 /***********************************************************************
951 * GetBkColor (GDI32.@)
953 COLORREF WINAPI
GetBkColor( HDC hdc
)
956 DC
* dc
= get_dc_ptr( hdc
);
959 ret
= dc
->backgroundColor
;
960 release_dc_ptr( dc
);
966 /***********************************************************************
967 * SetBkColor (GDI32.@)
969 COLORREF WINAPI
SetBkColor( HDC hdc
, COLORREF color
)
971 COLORREF ret
= CLR_INVALID
;
972 DC
* dc
= get_dc_ptr( hdc
);
974 TRACE("hdc=%p color=0x%08x\n", hdc
, color
);
978 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetBkColor
);
979 color
= physdev
->funcs
->pSetBkColor( physdev
, color
);
980 if (color
!= CLR_INVALID
)
982 ret
= dc
->backgroundColor
;
983 dc
->backgroundColor
= color
;
985 release_dc_ptr( dc
);
991 /***********************************************************************
992 * GetTextColor (GDI32.@)
994 COLORREF WINAPI
GetTextColor( HDC hdc
)
997 DC
* dc
= get_dc_ptr( hdc
);
1000 ret
= dc
->textColor
;
1001 release_dc_ptr( dc
);
1007 /***********************************************************************
1008 * SetTextColor (GDI32.@)
1010 COLORREF WINAPI
SetTextColor( HDC hdc
, COLORREF color
)
1012 COLORREF ret
= CLR_INVALID
;
1013 DC
* dc
= get_dc_ptr( hdc
);
1015 TRACE(" hdc=%p color=0x%08x\n", hdc
, color
);
1019 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextColor
);
1020 color
= physdev
->funcs
->pSetTextColor( physdev
, color
);
1021 if (color
!= CLR_INVALID
)
1023 ret
= dc
->textColor
;
1024 dc
->textColor
= color
;
1026 release_dc_ptr( dc
);
1032 /***********************************************************************
1033 * GetTextAlign (GDI32.@)
1035 UINT WINAPI
GetTextAlign( HDC hdc
)
1038 DC
* dc
= get_dc_ptr( hdc
);
1041 ret
= dc
->textAlign
;
1042 release_dc_ptr( dc
);
1048 /***********************************************************************
1049 * SetTextAlign (GDI32.@)
1051 UINT WINAPI
SetTextAlign( HDC hdc
, UINT align
)
1053 UINT ret
= GDI_ERROR
;
1054 DC
*dc
= get_dc_ptr( hdc
);
1056 TRACE("hdc=%p align=%d\n", hdc
, align
);
1060 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextAlign
);
1061 align
= physdev
->funcs
->pSetTextAlign( physdev
, align
);
1062 if (align
!= GDI_ERROR
)
1064 ret
= dc
->textAlign
;
1065 dc
->textAlign
= align
;
1067 release_dc_ptr( dc
);
1072 /***********************************************************************
1073 * GetDCOrgEx (GDI32.@)
1075 BOOL WINAPI
GetDCOrgEx( HDC hDC
, LPPOINT lpp
)
1079 if (!lpp
) return FALSE
;
1080 if (!(dc
= get_dc_ptr( hDC
))) return FALSE
;
1081 lpp
->x
= dc
->vis_rect
.left
;
1082 lpp
->y
= dc
->vis_rect
.top
;
1083 release_dc_ptr( dc
);
1088 /***********************************************************************
1089 * GetGraphicsMode (GDI32.@)
1091 INT WINAPI
GetGraphicsMode( HDC hdc
)
1094 DC
* dc
= get_dc_ptr( hdc
);
1097 ret
= dc
->GraphicsMode
;
1098 release_dc_ptr( dc
);
1104 /***********************************************************************
1105 * SetGraphicsMode (GDI32.@)
1107 INT WINAPI
SetGraphicsMode( HDC hdc
, INT mode
)
1110 DC
*dc
= get_dc_ptr( hdc
);
1112 /* One would think that setting the graphics mode to GM_COMPATIBLE
1113 * would also reset the world transformation matrix to the unity
1114 * matrix. However, in Windows, this is not the case. This doesn't
1115 * make a lot of sense to me, but that's the way it is.
1118 if ((mode
> 0) && (mode
<= GM_LAST
))
1120 ret
= dc
->GraphicsMode
;
1121 dc
->GraphicsMode
= mode
;
1123 release_dc_ptr( dc
);
1128 /***********************************************************************
1129 * GetArcDirection (GDI32.@)
1131 INT WINAPI
GetArcDirection( HDC hdc
)
1134 DC
* dc
= get_dc_ptr( hdc
);
1137 ret
= dc
->ArcDirection
;
1138 release_dc_ptr( dc
);
1144 /***********************************************************************
1145 * SetArcDirection (GDI32.@)
1147 INT WINAPI
SetArcDirection( HDC hdc
, INT dir
)
1152 if (dir
!= AD_COUNTERCLOCKWISE
&& dir
!= AD_CLOCKWISE
)
1154 SetLastError(ERROR_INVALID_PARAMETER
);
1158 if ((dc
= get_dc_ptr( hdc
)))
1160 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetArcDirection
);
1161 dir
= physdev
->funcs
->pSetArcDirection( physdev
, dir
);
1164 ret
= dc
->ArcDirection
;
1165 dc
->ArcDirection
= dir
;
1167 release_dc_ptr( dc
);
1173 /***********************************************************************
1174 * GetWorldTransform (GDI32.@)
1176 BOOL WINAPI
GetWorldTransform( HDC hdc
, LPXFORM xform
)
1179 if (!xform
) return FALSE
;
1180 if (!(dc
= get_dc_ptr( hdc
))) return FALSE
;
1181 *xform
= dc
->xformWorld2Wnd
;
1182 release_dc_ptr( dc
);
1187 /***********************************************************************
1188 * GetTransform (GDI32.@)
1192 * Returns one of the co-ordinate space transforms
1195 * hdc [I] Device context.
1196 * which [I] Which xform to return:
1197 * 0x203 World -> Page transform (that set by SetWorldTransform).
1198 * 0x304 Page -> Device transform (the mapping mode transform).
1199 * 0x204 World -> Device transform (the combination of the above two).
1200 * 0x402 Device -> World transform (the inversion of the above).
1201 * xform [O] The xform.
1204 BOOL WINAPI
GetTransform( HDC hdc
, DWORD which
, XFORM
*xform
)
1207 DC
*dc
= get_dc_ptr( hdc
);
1208 if (!dc
) return FALSE
;
1213 *xform
= dc
->xformWorld2Wnd
;
1217 construct_window_to_viewport(dc
, xform
);
1221 *xform
= dc
->xformWorld2Vport
;
1225 *xform
= dc
->xformVport2World
;
1229 FIXME("Unknown code %x\n", which
);
1233 release_dc_ptr( dc
);
1238 /****************************************************************************
1239 * CombineTransform [GDI32.@]
1240 * Combines two transformation matrices.
1243 * xformResult [O] Stores the result of combining the two matrices
1244 * xform1 [I] Specifies the first matrix to apply
1245 * xform2 [I] Specifies the second matrix to apply
1248 * The same matrix can be passed in for more than one of the parameters.
1252 * Failure: FALSE. Use GetLastError() to determine the cause.
1254 BOOL WINAPI
CombineTransform( LPXFORM xformResult
, const XFORM
*xform1
,
1255 const XFORM
*xform2
)
1259 /* Check for illegal parameters */
1260 if (!xformResult
|| !xform1
|| !xform2
)
1263 /* Create the result in a temporary XFORM, since xformResult may be
1264 * equal to xform1 or xform2 */
1265 xformTemp
.eM11
= xform1
->eM11
* xform2
->eM11
+
1266 xform1
->eM12
* xform2
->eM21
;
1267 xformTemp
.eM12
= xform1
->eM11
* xform2
->eM12
+
1268 xform1
->eM12
* xform2
->eM22
;
1269 xformTemp
.eM21
= xform1
->eM21
* xform2
->eM11
+
1270 xform1
->eM22
* xform2
->eM21
;
1271 xformTemp
.eM22
= xform1
->eM21
* xform2
->eM12
+
1272 xform1
->eM22
* xform2
->eM22
;
1273 xformTemp
.eDx
= xform1
->eDx
* xform2
->eM11
+
1274 xform1
->eDy
* xform2
->eM21
+
1276 xformTemp
.eDy
= xform1
->eDx
* xform2
->eM12
+
1277 xform1
->eDy
* xform2
->eM22
+
1280 /* Copy the result to xformResult */
1281 *xformResult
= xformTemp
;
1287 /***********************************************************************
1288 * SetDCHook (GDI32.@)
1290 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1292 BOOL WINAPI
SetDCHook( HDC hdc
, DCHOOKPROC hookProc
, DWORD_PTR dwHookData
)
1294 DC
*dc
= get_dc_ptr( hdc
);
1296 if (!dc
) return FALSE
;
1298 if (!(dc
->flags
& DC_SAVED
))
1300 dc
->dwHookData
= dwHookData
;
1301 dc
->hookProc
= hookProc
;
1303 release_dc_ptr( dc
);
1308 /***********************************************************************
1309 * GetDCHook (GDI32.@)
1311 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1313 DWORD_PTR WINAPI
GetDCHook( HDC hdc
, DCHOOKPROC
*proc
)
1315 DC
*dc
= get_dc_ptr( hdc
);
1319 if (proc
) *proc
= dc
->hookProc
;
1320 ret
= dc
->dwHookData
;
1321 release_dc_ptr( dc
);
1326 /***********************************************************************
1327 * SetHookFlags (GDI32.@)
1329 * Note: this doesn't exist in Win32, we add it here because user32 needs it.
1331 WORD WINAPI
SetHookFlags( HDC hdc
, WORD flags
)
1333 DC
*dc
= get_dc_obj( hdc
); /* not get_dc_ptr, this needs to work from any thread */
1338 /* "Undocumented Windows" info is slightly confusing. */
1340 TRACE("hDC %p, flags %04x\n",hdc
,flags
);
1342 if (flags
& DCHF_INVALIDATEVISRGN
)
1343 ret
= InterlockedExchange( &dc
->dirty
, 1 );
1344 else if (flags
& DCHF_VALIDATEVISRGN
|| !flags
)
1345 ret
= InterlockedExchange( &dc
->dirty
, 0 );
1347 GDI_ReleaseObj( hdc
);
1351 /***********************************************************************
1352 * SetICMMode (GDI32.@)
1354 INT WINAPI
SetICMMode(HDC hdc
, INT iEnableICM
)
1356 /*FIXME: Assume that ICM is always off, and cannot be turned on */
1357 if (iEnableICM
== ICM_OFF
) return ICM_OFF
;
1358 if (iEnableICM
== ICM_ON
) return 0;
1359 if (iEnableICM
== ICM_QUERY
) return ICM_OFF
;
1363 /***********************************************************************
1364 * GetDeviceGammaRamp (GDI32.@)
1366 BOOL WINAPI
GetDeviceGammaRamp(HDC hDC
, LPVOID ptr
)
1369 DC
*dc
= get_dc_ptr( hDC
);
1373 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetDeviceGammaRamp
);
1374 ret
= physdev
->funcs
->pGetDeviceGammaRamp( physdev
, ptr
);
1375 release_dc_ptr( dc
);
1380 /***********************************************************************
1381 * SetDeviceGammaRamp (GDI32.@)
1383 BOOL WINAPI
SetDeviceGammaRamp(HDC hDC
, LPVOID ptr
)
1386 DC
*dc
= get_dc_ptr( hDC
);
1390 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDeviceGammaRamp
);
1391 ret
= physdev
->funcs
->pSetDeviceGammaRamp( physdev
, ptr
);
1392 release_dc_ptr( dc
);
1397 /***********************************************************************
1398 * GetColorSpace (GDI32.@)
1400 HCOLORSPACE WINAPI
GetColorSpace(HDC hdc
)
1402 /*FIXME Need to to whatever GetColorSpace actually does */
1406 /***********************************************************************
1407 * CreateColorSpaceA (GDI32.@)
1409 HCOLORSPACE WINAPI
CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace
)
1415 /***********************************************************************
1416 * CreateColorSpaceW (GDI32.@)
1418 HCOLORSPACE WINAPI
CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace
)
1424 /***********************************************************************
1425 * DeleteColorSpace (GDI32.@)
1427 BOOL WINAPI
DeleteColorSpace( HCOLORSPACE hColorSpace
)
1434 /***********************************************************************
1435 * SetColorSpace (GDI32.@)
1437 HCOLORSPACE WINAPI
SetColorSpace( HDC hDC
, HCOLORSPACE hColorSpace
)
1444 /***********************************************************************
1445 * GetBoundsRect (GDI32.@)
1447 UINT WINAPI
GetBoundsRect(HDC hdc
, LPRECT rect
, UINT flags
)
1450 DC
*dc
= get_dc_ptr( hdc
);
1452 if ( !dc
) return 0;
1456 *rect
= dc
->BoundsRect
;
1457 ret
= ((dc
->flags
& DC_BOUNDS_SET
) ? DCB_SET
: DCB_RESET
);
1462 if (flags
& DCB_RESET
)
1464 dc
->BoundsRect
.left
= 0;
1465 dc
->BoundsRect
.top
= 0;
1466 dc
->BoundsRect
.right
= 0;
1467 dc
->BoundsRect
.bottom
= 0;
1468 dc
->flags
&= ~DC_BOUNDS_SET
;
1470 release_dc_ptr( dc
);
1475 /***********************************************************************
1476 * SetBoundsRect (GDI32.@)
1478 UINT WINAPI
SetBoundsRect(HDC hdc
, const RECT
* rect
, UINT flags
)
1483 if ((flags
& DCB_ENABLE
) && (flags
& DCB_DISABLE
)) return 0;
1484 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1486 ret
= ((dc
->flags
& DC_BOUNDS_ENABLE
) ? DCB_ENABLE
: DCB_DISABLE
) |
1487 ((dc
->flags
& DC_BOUNDS_SET
) ? DCB_SET
: DCB_RESET
);
1489 if (flags
& DCB_RESET
)
1491 dc
->BoundsRect
.left
= 0;
1492 dc
->BoundsRect
.top
= 0;
1493 dc
->BoundsRect
.right
= 0;
1494 dc
->BoundsRect
.bottom
= 0;
1495 dc
->flags
&= ~DC_BOUNDS_SET
;
1498 if ((flags
& DCB_ACCUMULATE
) && rect
&& rect
->left
< rect
->right
&& rect
->top
< rect
->bottom
)
1500 if (dc
->flags
& DC_BOUNDS_SET
)
1502 dc
->BoundsRect
.left
= min( dc
->BoundsRect
.left
, rect
->left
);
1503 dc
->BoundsRect
.top
= min( dc
->BoundsRect
.top
, rect
->top
);
1504 dc
->BoundsRect
.right
= max( dc
->BoundsRect
.right
, rect
->right
);
1505 dc
->BoundsRect
.bottom
= max( dc
->BoundsRect
.bottom
, rect
->bottom
);
1509 dc
->BoundsRect
= *rect
;
1510 dc
->flags
|= DC_BOUNDS_SET
;
1514 if (flags
& DCB_ENABLE
) dc
->flags
|= DC_BOUNDS_ENABLE
;
1515 if (flags
& DCB_DISABLE
) dc
->flags
&= ~DC_BOUNDS_ENABLE
;
1517 release_dc_ptr( dc
);
1522 /***********************************************************************
1523 * GetRelAbs (GDI32.@)
1525 INT WINAPI
GetRelAbs( HDC hdc
, DWORD dwIgnore
)
1528 DC
*dc
= get_dc_ptr( hdc
);
1531 ret
= dc
->relAbsMode
;
1532 release_dc_ptr( dc
);
1540 /***********************************************************************
1541 * GetBkMode (GDI32.@)
1543 INT WINAPI
GetBkMode( HDC hdc
)
1546 DC
* dc
= get_dc_ptr( hdc
);
1549 ret
= dc
->backgroundMode
;
1550 release_dc_ptr( dc
);
1556 /***********************************************************************
1557 * SetBkMode (GDI32.@)
1559 INT WINAPI
SetBkMode( HDC hdc
, INT mode
)
1564 if ((mode
<= 0) || (mode
> BKMODE_LAST
))
1566 SetLastError(ERROR_INVALID_PARAMETER
);
1569 if ((dc
= get_dc_ptr( hdc
)))
1571 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetBkMode
);
1572 mode
= physdev
->funcs
->pSetBkMode( physdev
, mode
);
1575 ret
= dc
->backgroundMode
;
1576 dc
->backgroundMode
= mode
;
1578 release_dc_ptr( dc
);
1584 /***********************************************************************
1587 INT WINAPI
GetROP2( HDC hdc
)
1590 DC
* dc
= get_dc_ptr( hdc
);
1594 release_dc_ptr( dc
);
1600 /***********************************************************************
1603 INT WINAPI
SetROP2( HDC hdc
, INT mode
)
1608 if ((mode
< R2_BLACK
) || (mode
> R2_WHITE
))
1610 SetLastError(ERROR_INVALID_PARAMETER
);
1613 if ((dc
= get_dc_ptr( hdc
)))
1615 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetROP2
);
1616 mode
= physdev
->funcs
->pSetROP2( physdev
, mode
);
1622 release_dc_ptr( dc
);
1628 /***********************************************************************
1629 * SetRelAbs (GDI32.@)
1631 INT WINAPI
SetRelAbs( HDC hdc
, INT mode
)
1636 if ((mode
!= ABSOLUTE
) && (mode
!= RELATIVE
))
1638 SetLastError(ERROR_INVALID_PARAMETER
);
1641 if ((dc
= get_dc_ptr( hdc
)))
1643 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetRelAbs
);
1644 mode
= physdev
->funcs
->pSetRelAbs( physdev
, mode
);
1647 ret
= dc
->relAbsMode
;
1648 dc
->relAbsMode
= mode
;
1650 release_dc_ptr( dc
);
1656 /***********************************************************************
1657 * GetPolyFillMode (GDI32.@)
1659 INT WINAPI
GetPolyFillMode( HDC hdc
)
1662 DC
* dc
= get_dc_ptr( hdc
);
1665 ret
= dc
->polyFillMode
;
1666 release_dc_ptr( dc
);
1672 /***********************************************************************
1673 * SetPolyFillMode (GDI32.@)
1675 INT WINAPI
SetPolyFillMode( HDC hdc
, INT mode
)
1680 if ((mode
<= 0) || (mode
> POLYFILL_LAST
))
1682 SetLastError(ERROR_INVALID_PARAMETER
);
1685 if ((dc
= get_dc_ptr( hdc
)))
1687 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetPolyFillMode
);
1688 mode
= physdev
->funcs
->pSetPolyFillMode( physdev
, mode
);
1691 ret
= dc
->polyFillMode
;
1692 dc
->polyFillMode
= mode
;
1694 release_dc_ptr( dc
);
1700 /***********************************************************************
1701 * GetStretchBltMode (GDI32.@)
1703 INT WINAPI
GetStretchBltMode( HDC hdc
)
1706 DC
* dc
= get_dc_ptr( hdc
);
1709 ret
= dc
->stretchBltMode
;
1710 release_dc_ptr( dc
);
1716 /***********************************************************************
1717 * SetStretchBltMode (GDI32.@)
1719 INT WINAPI
SetStretchBltMode( HDC hdc
, INT mode
)
1724 if ((mode
<= 0) || (mode
> MAXSTRETCHBLTMODE
))
1726 SetLastError(ERROR_INVALID_PARAMETER
);
1729 if ((dc
= get_dc_ptr( hdc
)))
1731 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetStretchBltMode
);
1732 mode
= physdev
->funcs
->pSetStretchBltMode( physdev
, mode
);
1735 ret
= dc
->stretchBltMode
;
1736 dc
->stretchBltMode
= mode
;
1738 release_dc_ptr( dc
);
1744 /***********************************************************************
1745 * GetMapMode (GDI32.@)
1747 INT WINAPI
GetMapMode( HDC hdc
)
1750 DC
* dc
= get_dc_ptr( hdc
);
1754 release_dc_ptr( dc
);
1760 /***********************************************************************
1761 * GetBrushOrgEx (GDI32.@)
1763 BOOL WINAPI
GetBrushOrgEx( HDC hdc
, LPPOINT pt
)
1765 DC
* dc
= get_dc_ptr( hdc
);
1766 if (!dc
) return FALSE
;
1767 pt
->x
= dc
->brushOrgX
;
1768 pt
->y
= dc
->brushOrgY
;
1769 release_dc_ptr( dc
);
1774 /***********************************************************************
1775 * GetCurrentPositionEx (GDI32.@)
1777 BOOL WINAPI
GetCurrentPositionEx( HDC hdc
, LPPOINT pt
)
1779 DC
* dc
= get_dc_ptr( hdc
);
1780 if (!dc
) return FALSE
;
1781 pt
->x
= dc
->CursPosX
;
1782 pt
->y
= dc
->CursPosY
;
1783 release_dc_ptr( dc
);
1788 /***********************************************************************
1789 * GetViewportExtEx (GDI32.@)
1791 BOOL WINAPI
GetViewportExtEx( HDC hdc
, LPSIZE size
)
1793 DC
* dc
= get_dc_ptr( hdc
);
1794 if (!dc
) return FALSE
;
1795 size
->cx
= dc
->vportExtX
;
1796 size
->cy
= dc
->vportExtY
;
1797 release_dc_ptr( dc
);
1802 /***********************************************************************
1803 * GetViewportOrgEx (GDI32.@)
1805 BOOL WINAPI
GetViewportOrgEx( HDC hdc
, LPPOINT pt
)
1807 DC
* dc
= get_dc_ptr( hdc
);
1808 if (!dc
) return FALSE
;
1809 pt
->x
= dc
->vportOrgX
;
1810 pt
->y
= dc
->vportOrgY
;
1811 release_dc_ptr( dc
);
1816 /***********************************************************************
1817 * GetWindowExtEx (GDI32.@)
1819 BOOL WINAPI
GetWindowExtEx( HDC hdc
, LPSIZE size
)
1821 DC
* dc
= get_dc_ptr( hdc
);
1822 if (!dc
) return FALSE
;
1823 size
->cx
= dc
->wndExtX
;
1824 size
->cy
= dc
->wndExtY
;
1825 release_dc_ptr( dc
);
1830 /***********************************************************************
1831 * GetWindowOrgEx (GDI32.@)
1833 BOOL WINAPI
GetWindowOrgEx( HDC hdc
, LPPOINT pt
)
1835 DC
* dc
= get_dc_ptr( hdc
);
1836 if (!dc
) return FALSE
;
1837 pt
->x
= dc
->wndOrgX
;
1838 pt
->y
= dc
->wndOrgY
;
1839 release_dc_ptr( dc
);
1844 /***********************************************************************
1845 * GetLayout (GDI32.@)
1847 * Gets left->right or right->left text layout flags of a dc.
1850 DWORD WINAPI
GetLayout(HDC hdc
)
1852 DWORD layout
= GDI_ERROR
;
1854 DC
* dc
= get_dc_ptr( hdc
);
1857 layout
= dc
->layout
;
1858 release_dc_ptr( dc
);
1861 TRACE("hdc : %p, layout : %08x\n", hdc
, layout
);
1866 /***********************************************************************
1867 * SetLayout (GDI32.@)
1869 * Sets left->right or right->left text layout flags of a dc.
1872 DWORD WINAPI
SetLayout(HDC hdc
, DWORD layout
)
1874 DWORD oldlayout
= GDI_ERROR
;
1876 DC
* dc
= get_dc_ptr( hdc
);
1879 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetLayout
);
1880 layout
= physdev
->funcs
->pSetLayout( physdev
, layout
);
1881 if (layout
!= GDI_ERROR
)
1883 oldlayout
= dc
->layout
;
1884 dc
->layout
= layout
;
1885 if (layout
!= oldlayout
)
1887 if (layout
& LAYOUT_RTL
) dc
->MapMode
= MM_ANISOTROPIC
;
1888 DC_UpdateXforms( dc
);
1891 release_dc_ptr( dc
);
1894 TRACE("hdc : %p, old layout : %08x, new layout : %08x\n", hdc
, oldlayout
, layout
);
1899 /***********************************************************************
1900 * GetDCBrushColor (GDI32.@)
1902 COLORREF WINAPI
GetDCBrushColor(HDC hdc
)
1905 COLORREF dcBrushColor
= CLR_INVALID
;
1907 TRACE("hdc(%p)\n", hdc
);
1909 dc
= get_dc_ptr( hdc
);
1912 dcBrushColor
= dc
->dcBrushColor
;
1913 release_dc_ptr( dc
);
1916 return dcBrushColor
;
1919 /***********************************************************************
1920 * SetDCBrushColor (GDI32.@)
1922 COLORREF WINAPI
SetDCBrushColor(HDC hdc
, COLORREF crColor
)
1925 COLORREF oldClr
= CLR_INVALID
;
1927 TRACE("hdc(%p) crColor(%08x)\n", hdc
, crColor
);
1929 dc
= get_dc_ptr( hdc
);
1932 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDCBrushColor
);
1933 crColor
= physdev
->funcs
->pSetDCBrushColor( physdev
, crColor
);
1934 if (crColor
!= CLR_INVALID
)
1936 oldClr
= dc
->dcBrushColor
;
1937 dc
->dcBrushColor
= crColor
;
1939 release_dc_ptr( dc
);
1945 /***********************************************************************
1946 * GetDCPenColor (GDI32.@)
1948 COLORREF WINAPI
GetDCPenColor(HDC hdc
)
1951 COLORREF dcPenColor
= CLR_INVALID
;
1953 TRACE("hdc(%p)\n", hdc
);
1955 dc
= get_dc_ptr( hdc
);
1958 dcPenColor
= dc
->dcPenColor
;
1959 release_dc_ptr( dc
);
1965 /***********************************************************************
1966 * SetDCPenColor (GDI32.@)
1968 COLORREF WINAPI
SetDCPenColor(HDC hdc
, COLORREF crColor
)
1971 COLORREF oldClr
= CLR_INVALID
;
1973 TRACE("hdc(%p) crColor(%08x)\n", hdc
, crColor
);
1975 dc
= get_dc_ptr( hdc
);
1978 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDCPenColor
);
1979 crColor
= physdev
->funcs
->pSetDCPenColor( physdev
, crColor
);
1980 if (crColor
!= CLR_INVALID
)
1982 oldClr
= dc
->dcPenColor
;
1983 dc
->dcPenColor
= crColor
;
1985 release_dc_ptr( dc
);
1991 /***********************************************************************
1992 * CancelDC (GDI32.@)
1994 BOOL WINAPI
CancelDC(HDC hdc
)
2000 /*******************************************************************
2001 * GetMiterLimit [GDI32.@]
2005 BOOL WINAPI
GetMiterLimit(HDC hdc
, PFLOAT peLimit
)
2010 TRACE("(%p,%p)\n", hdc
, peLimit
);
2012 dc
= get_dc_ptr( hdc
);
2016 *peLimit
= dc
->miterLimit
;
2018 release_dc_ptr( dc
);
2024 /*******************************************************************
2025 * SetMiterLimit [GDI32.@]
2029 BOOL WINAPI
SetMiterLimit(HDC hdc
, FLOAT eNewLimit
, PFLOAT peOldLimit
)
2034 TRACE("(%p,%f,%p)\n", hdc
, eNewLimit
, peOldLimit
);
2036 dc
= get_dc_ptr( hdc
);
2040 *peOldLimit
= dc
->miterLimit
;
2041 dc
->miterLimit
= eNewLimit
;
2042 release_dc_ptr( dc
);
2048 /*******************************************************************
2049 * GdiIsMetaPrintDC [GDI32.@]
2051 BOOL WINAPI
GdiIsMetaPrintDC(HDC hdc
)
2057 /*******************************************************************
2058 * GdiIsMetaFileDC [GDI32.@]
2060 BOOL WINAPI
GdiIsMetaFileDC(HDC hdc
)
2064 switch( GetObjectType( hdc
) )
2073 /*******************************************************************
2074 * GdiIsPlayMetafileDC [GDI32.@]
2076 BOOL WINAPI
GdiIsPlayMetafileDC(HDC hdc
)