2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
20 /* ROP code to GC function conversion */
21 const int DC_XROPfunction
[16] =
23 GXclear
, /* R2_BLACK */
24 GXnor
, /* R2_NOTMERGEPEN */
25 GXandInverted
, /* R2_MASKNOTPEN */
26 GXcopyInverted
, /* R2_NOTCOPYPEN */
27 GXandReverse
, /* R2_MASKPENNOT */
28 GXinvert
, /* R2_NOT */
29 GXxor
, /* R2_XORPEN */
30 GXnand
, /* R2_NOTMASKPEN */
31 GXand
, /* R2_MASKPEN */
32 GXequiv
, /* R2_NOTXORPEN */
34 GXorInverted
, /* R2_MERGENOTPEN */
35 GXcopy
, /* R2_COPYPEN */
36 GXorReverse
, /* R2_MERGEPENNOT */
37 GXor
, /* R2_MERGEPEN */
42 /***********************************************************************
45 * Fill the device caps structure.
47 void DC_FillDevCaps( DeviceCaps
* caps
)
49 caps
->version
= 0x300;
50 caps
->technology
= DT_RASDISPLAY
;
51 caps
->horzSize
= WidthMMOfScreen(screen
) * screenWidth
/ WidthOfScreen(screen
);
52 caps
->vertSize
= HeightMMOfScreen(screen
) * screenHeight
/ HeightOfScreen(screen
);
53 caps
->horzRes
= screenWidth
;
54 caps
->vertRes
= screenHeight
;
55 caps
->bitsPixel
= screenDepth
;
57 caps
->numBrushes
= 16+6; /* 16 solid + 6 hatched brushes */
58 caps
->numPens
= 16; /* 16 solid pens */
61 caps
->numColors
= 100;
62 caps
->pdeviceSize
= 0;
63 caps
->curveCaps
= CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
|
64 CC_WIDE
| CC_STYLED
| CC_WIDESTYLED
|
65 CC_INTERIORS
| CC_ROUNDRECT
;
66 caps
->lineCaps
= LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
67 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
;
68 caps
->polygonalCaps
= PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
|
69 PC_SCANLINE
| PC_WIDE
| PC_STYLED
|
70 PC_WIDESTYLED
| PC_INTERIORS
;
71 caps
->textCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
72 TC_IA_ABLE
| TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
73 caps
->clipCaps
= CP_REGION
;
74 caps
->rasterCaps
= RC_BITBLT
| RC_BANDING
| RC_SCALING
| RC_BITMAP64
|
75 RC_DI_BITMAP
| RC_DIBTODEV
| RC_BIGFONT
|
76 RC_STRETCHBLT
| RC_STRETCHDIB
| RC_DEVBITS
;
78 if( !(COLOR_GetSystemPaletteFlags() & COLOR_VIRTUAL
) )
79 caps
->rasterCaps
|= RC_PALETTE
;
81 caps
->aspectX
= 36; /* ?? */
82 caps
->aspectY
= 36; /* ?? */
84 caps
->logPixelsX
= (int)(caps
->horzRes
* 25.4 / caps
->horzSize
);
85 caps
->logPixelsY
= (int)(caps
->vertRes
* 25.4 / caps
->vertSize
);
86 caps
->sizePalette
= (caps
->rasterCaps
& RC_PALETTE
)
87 ? DefaultVisual(display
,DefaultScreen(display
))->map_entries
89 caps
->numReserved
= 0;
94 /***********************************************************************
97 * Fill the WIN_DC_INFO structure.
99 static void DC_Init_DC_INFO( WIN_DC_INFO
*win_dc_info
)
101 win_dc_info
->flags
= 0;
102 win_dc_info
->devCaps
= NULL
;
103 win_dc_info
->hClipRgn
= 0;
104 win_dc_info
->hVisRgn
= 0;
105 win_dc_info
->hGCClipRgn
= 0;
106 win_dc_info
->hPen
= STOCK_BLACK_PEN
;
107 win_dc_info
->hBrush
= STOCK_WHITE_BRUSH
;
108 win_dc_info
->hFont
= STOCK_SYSTEM_FONT
;
109 win_dc_info
->hBitmap
= 0;
110 win_dc_info
->hFirstBitmap
= 0;
111 win_dc_info
->hDevice
= 0;
112 win_dc_info
->hPalette
= STOCK_DEFAULT_PALETTE
;
113 win_dc_info
->ROPmode
= R2_COPYPEN
;
114 win_dc_info
->polyFillMode
= ALTERNATE
;
115 win_dc_info
->stretchBltMode
= BLACKONWHITE
;
116 win_dc_info
->relAbsMode
= ABSOLUTE
;
117 win_dc_info
->backgroundMode
= OPAQUE
;
118 win_dc_info
->backgroundColor
= RGB( 255, 255, 255 );
119 win_dc_info
->textColor
= RGB( 0, 0, 0 );
120 win_dc_info
->brushOrgX
= 0;
121 win_dc_info
->brushOrgY
= 0;
122 win_dc_info
->textAlign
= TA_LEFT
| TA_TOP
| TA_NOUPDATECP
;
123 win_dc_info
->charExtra
= 0;
124 win_dc_info
->breakTotalExtra
= 0;
125 win_dc_info
->breakCount
= 0;
126 win_dc_info
->breakExtra
= 0;
127 win_dc_info
->breakRem
= 0;
128 win_dc_info
->bitsPerPixel
= 1;
129 win_dc_info
->MapMode
= MM_TEXT
;
130 win_dc_info
->GraphicsMode
= GM_COMPATIBLE
;
131 win_dc_info
->DCOrgX
= 0;
132 win_dc_info
->DCOrgY
= 0;
133 win_dc_info
->lpfnPrint
= NULL
;
134 win_dc_info
->CursPosX
= 0;
135 win_dc_info
->CursPosY
= 0;
136 win_dc_info
->ArcDirection
= AD_COUNTERCLOCKWISE
;
137 win_dc_info
->xformWorld2Wnd
.eM11
= 1.0f
;
138 win_dc_info
->xformWorld2Wnd
.eM12
= 0.0f
;
139 win_dc_info
->xformWorld2Wnd
.eM21
= 0.0f
;
140 win_dc_info
->xformWorld2Wnd
.eM22
= 1.0f
;
141 win_dc_info
->xformWorld2Wnd
.eDx
= 0.0f
;
142 win_dc_info
->xformWorld2Wnd
.eDy
= 0.0f
;
143 win_dc_info
->xformWorld2Vport
= win_dc_info
->xformWorld2Wnd
;
144 win_dc_info
->xformVport2World
= win_dc_info
->xformWorld2Wnd
;
145 win_dc_info
->vport2WorldValid
= TRUE
;
147 PATH_InitGdiPath(&win_dc_info
->path
);
151 /***********************************************************************
154 DC
*DC_AllocDC( const DC_FUNCTIONS
*funcs
)
159 if (!(hdc
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
))) return NULL
;
160 dc
= (DC
*) GDI_HEAP_LOCK( hdc
);
177 DC_Init_DC_INFO( &dc
->w
);
184 /***********************************************************************
187 DC
*DC_GetDCPtr( HDC32 hdc
)
189 GDIOBJHDR
*ptr
= (GDIOBJHDR
*)GDI_HEAP_LOCK( hdc
);
190 if (!ptr
) return NULL
;
191 if ((ptr
->wMagic
== DC_MAGIC
) || (ptr
->wMagic
== METAFILE_DC_MAGIC
))
193 GDI_HEAP_UNLOCK( hdc
);
198 /***********************************************************************
201 * Setup device-specific DC values for a newly created DC.
203 void DC_InitDC( DC
* dc
)
205 RealizeDefaultPalette( dc
->hSelf
);
206 SetTextColor32( dc
->hSelf
, dc
->w
.textColor
);
207 SetBkColor32( dc
->hSelf
, dc
->w
.backgroundColor
);
208 SelectObject32( dc
->hSelf
, dc
->w
.hPen
);
209 SelectObject32( dc
->hSelf
, dc
->w
.hBrush
);
210 SelectObject32( dc
->hSelf
, dc
->w
.hFont
);
211 CLIPPING_UpdateGCRegion( dc
);
215 /***********************************************************************
216 * DC_SetupGCForPatBlt
218 * Setup the GC for a PatBlt operation using current brush.
219 * If fMapColors is TRUE, X pixels are mapped to Windows colors.
220 * Return FALSE if brush is BS_NULL, TRUE otherwise.
222 BOOL32
DC_SetupGCForPatBlt( DC
* dc
, GC gc
, BOOL32 fMapColors
)
228 if (dc
->u
.x
.brush
.style
== BS_NULL
) return FALSE
;
229 if (dc
->u
.x
.brush
.pixel
== -1)
231 /* Special case used for monochrome pattern brushes.
232 * We need to swap foreground and background because
233 * Windows does it the wrong way...
235 val
.foreground
= dc
->u
.x
.backgroundPixel
;
236 val
.background
= dc
->u
.x
.textPixel
;
240 val
.foreground
= dc
->u
.x
.brush
.pixel
;
241 val
.background
= dc
->u
.x
.backgroundPixel
;
243 if (fMapColors
&& COLOR_PixelToPalette
)
245 val
.foreground
= COLOR_PixelToPalette
[val
.foreground
];
246 val
.background
= COLOR_PixelToPalette
[val
.background
];
249 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
251 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
253 ** Let's replace GXinvert by GXxor with (black xor white)
254 ** This solves the selection color and leak problems in excel
255 ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
257 if (val
.function
== GXinvert
)
259 val
.foreground
= BlackPixelOfScreen(screen
) ^ WhitePixelOfScreen(screen
);
260 val
.function
= GXxor
;
262 val
.fill_style
= dc
->u
.x
.brush
.fillStyle
;
263 switch(val
.fill_style
)
266 case FillOpaqueStippled
:
267 if (dc
->w
.backgroundMode
==OPAQUE
) val
.fill_style
= FillOpaqueStippled
;
268 val
.stipple
= dc
->u
.x
.brush
.pixmap
;
273 if (fMapColors
&& COLOR_PixelToPalette
)
277 EnterCriticalSection( &X11DRV_CritSection
);
278 pixmap
= XCreatePixmap( display
, rootWindow
, 8, 8, screenDepth
);
279 image
= XGetImage( display
, dc
->u
.x
.brush
.pixmap
, 0, 0, 8, 8,
280 AllPlanes
, ZPixmap
);
281 for (y
= 0; y
< 8; y
++)
282 for (x
= 0; x
< 8; x
++)
283 XPutPixel( image
, x
, y
,
284 COLOR_PixelToPalette
[XGetPixel( image
, x
, y
)] );
285 XPutImage( display
, pixmap
, gc
, image
, 0, 0, 0, 0, 8, 8 );
286 XDestroyImage( image
);
287 LeaveCriticalSection( &X11DRV_CritSection
);
290 else val
.tile
= dc
->u
.x
.brush
.pixmap
;
298 val
.ts_x_origin
= dc
->w
.DCOrgX
+ dc
->w
.brushOrgX
;
299 val
.ts_y_origin
= dc
->w
.DCOrgY
+ dc
->w
.brushOrgY
;
300 val
.fill_rule
= (dc
->w
.polyFillMode
==WINDING
) ? WindingRule
: EvenOddRule
;
301 TSXChangeGC( display
, gc
,
302 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
303 GCFillRule
| GCTileStipXOrigin
| GCTileStipYOrigin
| mask
,
305 if (pixmap
) TSXFreePixmap( display
, pixmap
);
310 /***********************************************************************
313 * Setup dc->u.x.gc for drawing operations using current brush.
314 * Return FALSE if brush is BS_NULL, TRUE otherwise.
316 BOOL32
DC_SetupGCForBrush( DC
* dc
)
318 return DC_SetupGCForPatBlt( dc
, dc
->u
.x
.gc
, FALSE
);
322 /***********************************************************************
325 * Setup dc->u.x.gc for drawing operations using current pen.
326 * Return FALSE if pen is PS_NULL, TRUE otherwise.
328 BOOL32
DC_SetupGCForPen( DC
* dc
)
332 if (dc
->u
.x
.pen
.style
== PS_NULL
) return FALSE
;
334 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
336 switch (dc
->w
.ROPmode
)
339 val
.foreground
= BlackPixelOfScreen( screen
);
340 val
.function
= GXcopy
;
343 val
.foreground
= WhitePixelOfScreen( screen
);
344 val
.function
= GXcopy
;
347 val
.foreground
= dc
->u
.x
.pen
.pixel
;
348 /* It is very unlikely someone wants to XOR with 0 */
349 /* This fixes the rubber-drawings in paintbrush */
350 if (val
.foreground
== 0)
351 val
.foreground
= BlackPixelOfScreen( screen
)
352 ^ WhitePixelOfScreen( screen
);
353 val
.function
= GXxor
;
356 val
.foreground
= dc
->u
.x
.pen
.pixel
;
357 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
359 val
.background
= dc
->u
.x
.backgroundPixel
;
360 val
.fill_style
= FillSolid
;
361 if ((dc
->u
.x
.pen
.style
!=PS_SOLID
) && (dc
->u
.x
.pen
.style
!=PS_INSIDEFRAME
))
363 TSXSetDashes( display
, dc
->u
.x
.gc
, 0,
364 dc
->u
.x
.pen
.dashes
, dc
->u
.x
.pen
.dash_len
);
365 val
.line_style
= (dc
->w
.backgroundMode
== OPAQUE
) ?
366 LineDoubleDash
: LineOnOffDash
;
368 else val
.line_style
= LineSolid
;
369 val
.line_width
= dc
->u
.x
.pen
.width
;
370 if (val
.line_width
<= 1) {
371 val
.cap_style
= CapNotLast
;
373 switch (dc
->u
.x
.pen
.endcap
)
375 case PS_ENDCAP_SQUARE
:
376 val
.cap_style
= CapProjecting
;
379 val
.cap_style
= CapButt
;
381 case PS_ENDCAP_ROUND
:
383 val
.cap_style
= CapRound
;
386 switch (dc
->u
.x
.pen
.linejoin
)
389 val
.join_style
= JoinBevel
;
392 val
.join_style
= JoinMiter
;
396 val
.join_style
= JoinRound
;
398 TSXChangeGC( display
, dc
->u
.x
.gc
,
399 GCFunction
| GCForeground
| GCBackground
| GCLineWidth
|
400 GCLineStyle
| GCCapStyle
| GCJoinStyle
| GCFillStyle
, &val
);
405 /***********************************************************************
408 * Setup dc->u.x.gc for text drawing operations.
409 * Return FALSE if the font is null, TRUE otherwise.
411 BOOL32
DC_SetupGCForText( DC
* dc
)
413 XFontStruct
* xfs
= XFONT_GetFontStruct( dc
->u
.x
.font
);
419 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
421 val
.function
= GXcopy
; /* Text is always GXcopy */
422 val
.foreground
= dc
->u
.x
.textPixel
;
423 val
.background
= dc
->u
.x
.backgroundPixel
;
424 val
.fill_style
= FillSolid
;
427 TSXChangeGC( display
, dc
->u
.x
.gc
,
428 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
432 WARN(dc
, "Physical font failure\n" );
437 /***********************************************************************
440 * Computes the inverse of the transformation xformSrc and stores it to
441 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
444 static BOOL32
DC_InvertXform( const XFORM
*xformSrc
, XFORM
*xformDest
)
448 determinant
= xformSrc
->eM11
*xformSrc
->eM22
-
449 xformSrc
->eM12
*xformSrc
->eM21
;
450 if (determinant
> -1e-12 && determinant
< 1e-12)
453 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
454 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
455 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
456 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
457 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
-
458 xformSrc
->eDy
* xformDest
->eM21
;
459 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
-
460 xformSrc
->eDy
* xformDest
->eM22
;
466 /***********************************************************************
469 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
470 * fields of the specified DC by creating a transformation that
471 * represents the current mapping mode and combining it with the DC's
472 * world transform. This function should be called whenever the
473 * parameters associated with the mapping mode (window and viewport
474 * extents and origins) or the world transform change.
476 void DC_UpdateXforms( DC
*dc
)
478 XFORM xformWnd2Vport
;
479 FLOAT scaleX
, scaleY
;
481 /* Construct a transformation to do the window-to-viewport conversion */
482 scaleX
= (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
;
483 scaleY
= (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
;
484 xformWnd2Vport
.eM11
= scaleX
;
485 xformWnd2Vport
.eM12
= 0.0;
486 xformWnd2Vport
.eM21
= 0.0;
487 xformWnd2Vport
.eM22
= scaleY
;
488 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
-
489 scaleX
* (FLOAT
)dc
->wndOrgX
;
490 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
-
491 scaleY
* (FLOAT
)dc
->wndOrgY
;
493 /* Combine with the world transformation */
494 CombineTransform( &dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
,
497 /* Create inverse of world-to-viewport transformation */
498 dc
->w
.vport2WorldValid
= DC_InvertXform( &dc
->w
.xformWorld2Vport
,
499 &dc
->w
.xformVport2World
);
503 /***********************************************************************
504 * GetDCState (GDI.179)
506 HDC16 WINAPI
GetDCState( HDC16 hdc
)
511 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
512 if (!(handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
)))
514 GDI_HEAP_UNLOCK( hdc
);
517 newdc
= (DC
*) GDI_HEAP_LOCK( handle
);
519 TRACE(dc
, "(%04x): returning %04x\n", hdc
, handle
);
521 memset( &newdc
->u
.x
, 0, sizeof(newdc
->u
.x
) );
522 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
523 newdc
->w
.devCaps
= dc
->w
.devCaps
;
524 newdc
->w
.hPen
= dc
->w
.hPen
;
525 newdc
->w
.hBrush
= dc
->w
.hBrush
;
526 newdc
->w
.hFont
= dc
->w
.hFont
;
527 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
528 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
529 newdc
->w
.hDevice
= dc
->w
.hDevice
;
530 newdc
->w
.hPalette
= dc
->w
.hPalette
;
531 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
532 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
533 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
534 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
535 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
536 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
537 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
538 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
539 newdc
->w
.textColor
= dc
->w
.textColor
;
540 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
541 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
542 newdc
->w
.textAlign
= dc
->w
.textAlign
;
543 newdc
->w
.charExtra
= dc
->w
.charExtra
;
544 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
545 newdc
->w
.breakCount
= dc
->w
.breakCount
;
546 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
547 newdc
->w
.breakRem
= dc
->w
.breakRem
;
548 newdc
->w
.MapMode
= dc
->w
.MapMode
;
549 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
551 /* Apparently, the DC origin is not changed by [GS]etDCState */
552 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
553 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
555 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
556 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
557 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
558 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
559 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
560 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
561 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
562 newdc
->wndOrgX
= dc
->wndOrgX
;
563 newdc
->wndOrgY
= dc
->wndOrgY
;
564 newdc
->wndExtX
= dc
->wndExtX
;
565 newdc
->wndExtY
= dc
->wndExtY
;
566 newdc
->vportOrgX
= dc
->vportOrgX
;
567 newdc
->vportOrgY
= dc
->vportOrgY
;
568 newdc
->vportExtX
= dc
->vportExtX
;
569 newdc
->vportExtY
= dc
->vportExtY
;
571 newdc
->hSelf
= (HDC32
)handle
;
572 newdc
->saveLevel
= 0;
574 PATH_InitGdiPath( &newdc
->w
.path
);
576 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
578 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
581 newdc
->w
.hClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
582 CombineRgn32( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
585 newdc
->w
.hClipRgn
= 0;
586 GDI_HEAP_UNLOCK( handle
);
587 GDI_HEAP_UNLOCK( hdc
);
592 /***********************************************************************
593 * SetDCState (GDI.180)
595 void WINAPI
SetDCState( HDC16 hdc
, HDC16 hdcs
)
599 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return;
600 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
)))
602 GDI_HEAP_UNLOCK( hdc
);
605 if (!dcs
->w
.flags
& DC_SAVED
)
607 GDI_HEAP_UNLOCK( hdc
);
608 GDI_HEAP_UNLOCK( hdcs
);
611 TRACE(dc
, "%04x %04x\n", hdc
, hdcs
);
613 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
614 dc
->w
.devCaps
= dcs
->w
.devCaps
;
615 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
616 dc
->w
.hDevice
= dcs
->w
.hDevice
;
617 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
618 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
619 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
620 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
621 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
622 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
623 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
624 dc
->w
.textColor
= dcs
->w
.textColor
;
625 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
626 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
627 dc
->w
.textAlign
= dcs
->w
.textAlign
;
628 dc
->w
.charExtra
= dcs
->w
.charExtra
;
629 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
630 dc
->w
.breakCount
= dcs
->w
.breakCount
;
631 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
632 dc
->w
.breakRem
= dcs
->w
.breakRem
;
633 dc
->w
.MapMode
= dcs
->w
.MapMode
;
634 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
636 /* Apparently, the DC origin is not changed by [GS]etDCState */
637 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
638 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
640 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
641 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
642 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
643 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
644 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
645 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
646 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
648 dc
->wndOrgX
= dcs
->wndOrgX
;
649 dc
->wndOrgY
= dcs
->wndOrgY
;
650 dc
->wndExtX
= dcs
->wndExtX
;
651 dc
->wndExtY
= dcs
->wndExtY
;
652 dc
->vportOrgX
= dcs
->vportOrgX
;
653 dc
->vportOrgY
= dcs
->vportOrgY
;
654 dc
->vportExtX
= dcs
->vportExtX
;
655 dc
->vportExtY
= dcs
->vportExtY
;
657 if (!(dc
->w
.flags
& DC_MEMORY
)) dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
661 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
662 CombineRgn32( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
666 if (dc
->w
.hClipRgn
) DeleteObject16( dc
->w
.hClipRgn
);
669 CLIPPING_UpdateGCRegion( dc
);
671 SelectObject32( hdc
, dcs
->w
.hBitmap
);
672 SelectObject32( hdc
, dcs
->w
.hBrush
);
673 SelectObject32( hdc
, dcs
->w
.hFont
);
674 SelectObject32( hdc
, dcs
->w
.hPen
);
675 SetBkColor32( hdc
, dcs
->w
.backgroundColor
);
676 SetTextColor32( hdc
, dcs
->w
.textColor
);
677 GDISelectPalette( hdc
, dcs
->w
.hPalette
, FALSE
);
678 GDI_HEAP_UNLOCK( hdc
);
679 GDI_HEAP_UNLOCK( hdcs
);
683 /***********************************************************************
686 INT16 WINAPI
SaveDC16( HDC16 hdc
)
688 return (INT16
)SaveDC32( hdc
);
692 /***********************************************************************
693 * SaveDC32 (GDI32.292)
695 INT32 WINAPI
SaveDC32( HDC32 hdc
)
701 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
704 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
706 MF_MetaParam0(dc
, META_SAVEDC
);
707 GDI_HEAP_UNLOCK( hdc
);
710 if (!(hdcs
= GetDCState( hdc
)))
712 GDI_HEAP_UNLOCK( hdc
);
715 dcs
= (DC
*) GDI_HEAP_LOCK( hdcs
);
717 /* Copy path. The reason why path saving / restoring is in SaveDC/
718 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
719 * functions are only in Win16 (which doesn't have paths) and that
720 * SetDCState doesn't allow us to signal an error (which can happen
721 * when copying paths).
723 if (!PATH_AssignGdiPath( &dcs
->w
.path
, &dc
->w
.path
))
725 GDI_HEAP_UNLOCK( hdc
);
726 GDI_HEAP_UNLOCK( hdcs
);
731 dcs
->header
.hNext
= dc
->header
.hNext
;
732 dc
->header
.hNext
= hdcs
;
733 TRACE(dc
, "(%04x): returning %d\n", hdc
, dc
->saveLevel
+1 );
734 ret
= ++dc
->saveLevel
;
735 GDI_HEAP_UNLOCK( hdcs
);
736 GDI_HEAP_UNLOCK( hdc
);
741 /***********************************************************************
742 * RestoreDC16 (GDI.39)
744 BOOL16 WINAPI
RestoreDC16( HDC16 hdc
, INT16 level
)
746 return RestoreDC32( hdc
, level
);
750 /***********************************************************************
751 * RestoreDC32 (GDI32.290)
753 BOOL32 WINAPI
RestoreDC32( HDC32 hdc
, INT32 level
)
758 TRACE(dc
, "%04x %d\n", hdc
, level
);
759 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
762 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
763 if (!dc
) return FALSE
;
766 GDI_HEAP_UNLOCK( hdc
);
769 MF_MetaParam1(dc
, META_RESTOREDC
, level
);
770 GDI_HEAP_UNLOCK( hdc
);
773 if (level
== -1) level
= dc
->saveLevel
;
774 if ((level
< 1) || (level
> dc
->saveLevel
))
776 GDI_HEAP_UNLOCK( hdc
);
781 while (dc
->saveLevel
>= level
)
783 HDC16 hdcs
= dc
->header
.hNext
;
784 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
)))
786 GDI_HEAP_UNLOCK( hdc
);
789 dc
->header
.hNext
= dcs
->header
.hNext
;
790 if (--dc
->saveLevel
< level
)
792 SetDCState( hdc
, hdcs
);
793 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
794 /* FIXME: This might not be quite right, since we're
795 * returning FALSE but still destroying the saved DC state */
800 GDI_HEAP_UNLOCK( hdc
);
805 /***********************************************************************
806 * CreateDC16 (GDI.53)
808 HDC16 WINAPI
CreateDC16( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
809 const DEVMODE16
*initData
)
812 const DC_FUNCTIONS
*funcs
;
814 if (!(funcs
= DRIVER_FindDriver( driver
))) return 0;
815 if (!(dc
= DC_AllocDC( funcs
))) return 0;
818 TRACE(dc
, "(driver=%s, device=%s, output=%s): returning %04x\n",
819 debugstr_a(driver
), debugstr_a(device
), debugstr_a(output
), dc
->hSelf
);
821 if (dc
->funcs
->pCreateDC
&&
822 !dc
->funcs
->pCreateDC( dc
, driver
, device
, output
, initData
))
824 WARN(dc
, "creation aborted by device\n" );
825 GDI_HEAP_FREE( dc
->hSelf
);
830 GDI_HEAP_UNLOCK( dc
->hSelf
);
835 /***********************************************************************
836 * CreateDC32A (GDI32.)
838 HDC32 WINAPI
CreateDC32A( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
839 const DEVMODE32A
*initData
)
841 return CreateDC16( driver
, device
, output
, (const DEVMODE16
*)initData
);
845 /***********************************************************************
846 * CreateDC32W (GDI32.)
848 HDC32 WINAPI
CreateDC32W( LPCWSTR driver
, LPCWSTR device
, LPCWSTR output
,
849 const DEVMODE32W
*initData
)
851 LPSTR driverA
= HEAP_strdupWtoA( GetProcessHeap(), 0, driver
);
852 LPSTR deviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, device
);
853 LPSTR outputA
= HEAP_strdupWtoA( GetProcessHeap(), 0, output
);
854 HDC32 res
= CreateDC16( driverA
, deviceA
, outputA
,
855 (const DEVMODE16
*)initData
/*FIXME*/ );
856 HeapFree( GetProcessHeap(), 0, driverA
);
857 HeapFree( GetProcessHeap(), 0, deviceA
);
858 HeapFree( GetProcessHeap(), 0, outputA
);
863 /***********************************************************************
864 * CreateIC16 (GDI.153)
866 HDC16 WINAPI
CreateIC16( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
867 const DEVMODE16
* initData
)
869 /* Nothing special yet for ICs */
870 return CreateDC16( driver
, device
, output
, initData
);
874 /***********************************************************************
875 * CreateIC32A (GDI32.49)
877 HDC32 WINAPI
CreateIC32A( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
878 const DEVMODE32A
* initData
)
880 /* Nothing special yet for ICs */
881 return CreateDC32A( driver
, device
, output
, initData
);
885 /***********************************************************************
886 * CreateIC32W (GDI32.50)
888 HDC32 WINAPI
CreateIC32W( LPCWSTR driver
, LPCWSTR device
, LPCWSTR output
,
889 const DEVMODE32W
* initData
)
891 /* Nothing special yet for ICs */
892 return CreateDC32W( driver
, device
, output
, initData
);
896 /***********************************************************************
897 * CreateCompatibleDC16 (GDI.52)
899 HDC16 WINAPI
CreateCompatibleDC16( HDC16 hdc
)
901 return (HDC16
)CreateCompatibleDC32( hdc
);
905 /***********************************************************************
906 * CreateCompatibleDC32 (GDI32.31)
908 HDC32 WINAPI
CreateCompatibleDC32( HDC32 hdc
)
912 const DC_FUNCTIONS
*funcs
;
914 if ((origDC
= (DC
*)GDI_GetObjPtr( hdc
, DC_MAGIC
))) funcs
= origDC
->funcs
;
915 else funcs
= DRIVER_FindDriver( "DISPLAY" );
916 if (!funcs
) return 0;
918 if (!(dc
= DC_AllocDC( funcs
))) return 0;
920 TRACE(dc
, "(%04x): returning %04x\n",
923 /* Create default bitmap */
924 if (!(hbitmap
= CreateBitmap32( 1, 1, 1, 1, NULL
)))
926 GDI_HEAP_FREE( dc
->hSelf
);
929 dc
->w
.flags
= DC_MEMORY
;
930 dc
->w
.bitsPerPixel
= 1;
931 dc
->w
.hBitmap
= hbitmap
;
932 dc
->w
.hFirstBitmap
= hbitmap
;
934 if (dc
->funcs
->pCreateDC
&&
935 !dc
->funcs
->pCreateDC( dc
, NULL
, NULL
, NULL
, NULL
))
937 WARN(dc
, "creation aborted by device\n");
938 DeleteObject32( hbitmap
);
939 GDI_HEAP_FREE( dc
->hSelf
);
944 GDI_HEAP_UNLOCK( dc
->hSelf
);
949 /***********************************************************************
950 * DeleteDC16 (GDI.68)
952 BOOL16 WINAPI
DeleteDC16( HDC16 hdc
)
954 return DeleteDC32( hdc
);
958 /***********************************************************************
959 * DeleteDC32 (GDI32.67)
961 BOOL32 WINAPI
DeleteDC32( HDC32 hdc
)
963 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
964 if (!dc
) return FALSE
;
966 TRACE(dc
, "%04x\n", hdc
);
968 while (dc
->saveLevel
)
971 HDC16 hdcs
= dc
->header
.hNext
;
972 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) break;
973 dc
->header
.hNext
= dcs
->header
.hNext
;
978 if (!(dc
->w
.flags
& DC_SAVED
))
980 SelectObject32( hdc
, STOCK_BLACK_PEN
);
981 SelectObject32( hdc
, STOCK_WHITE_BRUSH
);
982 SelectObject32( hdc
, STOCK_SYSTEM_FONT
);
983 if (dc
->w
.flags
& DC_MEMORY
) DeleteObject32( dc
->w
.hFirstBitmap
);
984 if (dc
->funcs
->pDeleteDC
) dc
->funcs
->pDeleteDC(dc
);
987 if (dc
->w
.hClipRgn
) DeleteObject32( dc
->w
.hClipRgn
);
988 if (dc
->w
.hVisRgn
) DeleteObject32( dc
->w
.hVisRgn
);
989 if (dc
->w
.hGCClipRgn
) DeleteObject32( dc
->w
.hGCClipRgn
);
991 PATH_DestroyGdiPath(&dc
->w
.path
);
993 return GDI_FreeObject( hdc
);
997 /***********************************************************************
998 * ResetDC16 (GDI.376)
1000 HDC16 WINAPI
ResetDC16( HDC16 hdc
, const DEVMODE16
*devmode
)
1002 FIXME(dc
, "stub\n" );
1007 /***********************************************************************
1008 * ResetDC32A (GDI32.287)
1010 HDC32 WINAPI
ResetDC32A( HDC32 hdc
, const DEVMODE32A
*devmode
)
1012 FIXME(dc
, "stub\n" );
1017 /***********************************************************************
1018 * ResetDC32W (GDI32.288)
1020 HDC32 WINAPI
ResetDC32W( HDC32 hdc
, const DEVMODE32W
*devmode
)
1022 FIXME(dc
, "stub\n" );
1027 /***********************************************************************
1028 * GetDeviceCaps16 (GDI.80)
1030 INT16 WINAPI
GetDeviceCaps16( HDC16 hdc
, INT16 cap
)
1032 return GetDeviceCaps32( hdc
, cap
);
1036 /***********************************************************************
1037 * GetDeviceCaps32 (GDI32.171)
1039 INT32 WINAPI
GetDeviceCaps32( HDC32 hdc
, INT32 cap
)
1041 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1046 if ((cap
< 0) || (cap
> sizeof(DeviceCaps
)-sizeof(WORD
)))
1048 GDI_HEAP_UNLOCK( hdc
);
1052 TRACE(dc
, "(%04x,%d): returning %d\n",
1053 hdc
, cap
, *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
) );
1054 ret
= *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
);
1055 GDI_HEAP_UNLOCK( hdc
);
1060 /***********************************************************************
1061 * SetBkColor16 (GDI.1)
1063 COLORREF WINAPI
SetBkColor16( HDC16 hdc
, COLORREF color
)
1065 return SetBkColor32( hdc
, color
);
1069 /***********************************************************************
1070 * SetBkColor32 (GDI32.305)
1072 COLORREF WINAPI
SetBkColor32( HDC32 hdc
, COLORREF color
)
1075 DC
* dc
= DC_GetDCPtr( hdc
);
1077 if (!dc
) return 0x80000000;
1078 if (dc
->funcs
->pSetBkColor
)
1079 oldColor
= dc
->funcs
->pSetBkColor(dc
, color
);
1081 oldColor
= dc
->w
.backgroundColor
;
1082 dc
->w
.backgroundColor
= color
;
1084 GDI_HEAP_UNLOCK( hdc
);
1089 /***********************************************************************
1090 * SetTextColor16 (GDI.9)
1092 COLORREF WINAPI
SetTextColor16( HDC16 hdc
, COLORREF color
)
1094 return SetTextColor32( hdc
, color
);
1098 /***********************************************************************
1099 * SetTextColor32 (GDI32.338)
1101 COLORREF WINAPI
SetTextColor32( HDC32 hdc
, COLORREF color
)
1104 DC
* dc
= DC_GetDCPtr( hdc
);
1106 if (!dc
) return 0x80000000;
1107 if (dc
->funcs
->pSetTextColor
)
1108 oldColor
= dc
->funcs
->pSetTextColor(dc
, color
);
1110 oldColor
= dc
->w
.textColor
;
1111 dc
->w
.textColor
= color
;
1113 GDI_HEAP_UNLOCK( hdc
);
1118 /***********************************************************************
1119 * SetTextAlign16 (GDI.346)
1121 UINT16 WINAPI
SetTextAlign16( HDC16 hdc
, UINT16 textAlign
)
1123 return SetTextAlign32( hdc
, textAlign
);
1127 /***********************************************************************
1128 * SetTextAlign32 (GDI32.336)
1130 UINT32 WINAPI
SetTextAlign32( HDC32 hdc
, UINT32 textAlign
)
1133 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1136 if (!(dc
= (DC
*)GDI_GetObjPtr( hdc
, METAFILE_DC_MAGIC
))) return 0;
1137 MF_MetaParam1( dc
, META_SETTEXTALIGN
, textAlign
);
1138 GDI_HEAP_UNLOCK( hdc
);
1141 prevAlign
= dc
->w
.textAlign
;
1142 dc
->w
.textAlign
= textAlign
;
1143 GDI_HEAP_UNLOCK( hdc
);
1148 /***********************************************************************
1149 * GetDCOrgEx (GDI32.168)
1151 BOOL32 WINAPI
GetDCOrgEx( HDC32 hDC
, LPPOINT32 lpp
)
1154 if (!lpp
) return FALSE
;
1155 if (!(dc
= (DC
*) GDI_GetObjPtr( hDC
, DC_MAGIC
))) return FALSE
;
1157 if (!(dc
->w
.flags
& DC_MEMORY
))
1160 int w
, h
, border
, depth
;
1161 /* FIXME: this is not correct for managed windows */
1162 TSXGetGeometry( display
, dc
->u
.x
.drawable
, &root
,
1163 &lpp
->x
, &lpp
->y
, &w
, &h
, &border
, &depth
);
1165 else lpp
->x
= lpp
->y
= 0;
1166 lpp
->x
+= dc
->w
.DCOrgX
; lpp
->y
+= dc
->w
.DCOrgY
;
1167 GDI_HEAP_UNLOCK( hDC
);
1172 /***********************************************************************
1175 DWORD WINAPI
GetDCOrg( HDC16 hdc
)
1178 if( GetDCOrgEx( hdc
, &pt
) )
1179 return MAKELONG( (WORD
)pt
.x
, (WORD
)pt
.y
);
1184 /***********************************************************************
1185 * SetDCOrg (GDI.117)
1187 DWORD WINAPI
SetDCOrg( HDC16 hdc
, INT16 x
, INT16 y
)
1190 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1192 prevOrg
= dc
->w
.DCOrgX
| (dc
->w
.DCOrgY
<< 16);
1195 GDI_HEAP_UNLOCK( hdc
);
1200 /***********************************************************************
1201 * GetGraphicsMode (GDI32.188)
1203 INT32 WINAPI
GetGraphicsMode( HDC32 hdc
)
1205 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1207 return dc
->w
.GraphicsMode
;
1211 /***********************************************************************
1212 * SetGraphicsMode (GDI32.317)
1214 INT32 WINAPI
SetGraphicsMode( HDC32 hdc
, INT32 mode
)
1217 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1219 /* One would think that setting the graphics mode to GM_COMPATIBLE
1220 * would also reset the world transformation matrix to the unity
1221 * matrix. However, in Windows, this is not the case. This doesn't
1222 * make a lot of sense to me, but that's the way it is.
1226 if ((mode
<= 0) || (mode
> GM_LAST
)) return 0;
1227 ret
= dc
->w
.GraphicsMode
;
1228 dc
->w
.GraphicsMode
= mode
;
1233 /***********************************************************************
1234 * GetArcDirection16 (GDI.524)
1236 INT16 WINAPI
GetArcDirection16( HDC16 hdc
)
1238 return GetArcDirection32( (HDC32
)hdc
);
1242 /***********************************************************************
1243 * GetArcDirection32 (GDI32.141)
1245 INT32 WINAPI
GetArcDirection32( HDC32 hdc
)
1247 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1252 return dc
->w
.ArcDirection
;
1256 /***********************************************************************
1257 * SetArcDirection16 (GDI.525)
1259 INT16 WINAPI
SetArcDirection16( HDC16 hdc
, INT16 nDirection
)
1261 return SetArcDirection32( (HDC32
)hdc
, (INT32
)nDirection
);
1265 /***********************************************************************
1266 * SetArcDirection32 (GDI32.302)
1268 INT32 WINAPI
SetArcDirection32( HDC32 hdc
, INT32 nDirection
)
1270 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1271 INT32 nOldDirection
;
1276 if (nDirection
!=AD_COUNTERCLOCKWISE
&& nDirection
!=AD_CLOCKWISE
)
1278 SetLastError(ERROR_INVALID_PARAMETER
);
1282 nOldDirection
= dc
->w
.ArcDirection
;
1283 dc
->w
.ArcDirection
= nDirection
;
1285 return nOldDirection
;
1289 /***********************************************************************
1290 * GetWorldTransform (GDI32.244)
1292 BOOL32 WINAPI
GetWorldTransform( HDC32 hdc
, LPXFORM xform
)
1294 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1301 *xform
= dc
->w
.xformWorld2Wnd
;
1307 /***********************************************************************
1308 * SetWorldTransform (GDI32.346)
1310 BOOL32 WINAPI
SetWorldTransform( HDC32 hdc
, const XFORM
*xform
)
1312 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1316 SetLastError( ERROR_INVALID_HANDLE
);
1323 /* Check that graphics mode is GM_ADVANCED */
1324 if (dc
->w
.GraphicsMode
!=GM_ADVANCED
)
1327 dc
->w
.xformWorld2Wnd
= *xform
;
1329 DC_UpdateXforms( dc
);
1335 /****************************************************************************
1336 * ModifyWorldTransform [GDI32.253]
1337 * Modifies the world transformation for a device context.
1340 * hdc [I] Handle to device context
1341 * xform [I] XFORM structure that will be used to modify the world
1343 * iMode [I] Specifies in what way to modify the world transformation
1346 * Resets the world transformation to the identity matrix.
1347 * The parameter xform is ignored.
1349 * Multiplies xform into the world transformation matrix from
1352 * Multiplies xform into the world transformation matrix from
1357 BOOL32 WINAPI
ModifyWorldTransform( HDC32 hdc
, const XFORM
*xform
,
1360 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1362 /* Check for illegal parameters */
1365 SetLastError( ERROR_INVALID_HANDLE
);
1371 /* Check that graphics mode is GM_ADVANCED */
1372 if (dc
->w
.GraphicsMode
!=GM_ADVANCED
)
1378 dc
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
1379 dc
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
1380 dc
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
1381 dc
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
1382 dc
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
1383 dc
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
1385 case MWT_LEFTMULTIPLY
:
1386 CombineTransform( &dc
->w
.xformWorld2Wnd
, xform
,
1387 &dc
->w
.xformWorld2Wnd
);
1389 case MWT_RIGHTMULTIPLY
:
1390 CombineTransform( &dc
->w
.xformWorld2Wnd
, &dc
->w
.xformWorld2Wnd
,
1397 DC_UpdateXforms( dc
);
1403 /****************************************************************************
1404 * CombineTransform [GDI32.20]
1405 * Combines two transformation matrices.
1408 * xformResult [O] Stores the result of combining the two matrices
1409 * xform1 [I] Specifies the first matrix to apply
1410 * xform2 [I] Specifies the second matrix to apply
1413 * The same matrix can be passed in for more than one of the parameters.
1417 BOOL32 WINAPI
CombineTransform( LPXFORM xformResult
, const XFORM
*xform1
,
1418 const XFORM
*xform2
)
1422 /* Check for illegal parameters */
1423 if (!xformResult
|| !xform1
|| !xform2
)
1426 /* Create the result in a temporary XFORM, since xformResult may be
1427 * equal to xform1 or xform2 */
1428 xformTemp
.eM11
= xform1
->eM11
* xform2
->eM11
+
1429 xform1
->eM12
* xform2
->eM21
;
1430 xformTemp
.eM12
= xform1
->eM11
* xform2
->eM12
+
1431 xform1
->eM12
* xform2
->eM22
;
1432 xformTemp
.eM21
= xform1
->eM21
* xform2
->eM11
+
1433 xform1
->eM22
* xform2
->eM21
;
1434 xformTemp
.eM22
= xform1
->eM21
* xform2
->eM12
+
1435 xform1
->eM22
* xform2
->eM22
;
1436 xformTemp
.eDx
= xform1
->eDx
* xform2
->eM11
+
1437 xform1
->eDy
* xform2
->eM21
+
1439 xformTemp
.eDy
= xform1
->eDx
* xform2
->eM12
+
1440 xform1
->eDy
* xform2
->eM22
+
1443 /* Copy the result to xformResult */
1444 *xformResult
= xformTemp
;
1450 /***********************************************************************
1451 * SetDCHook (GDI.190)
1453 BOOL16 WINAPI
SetDCHook( HDC16 hdc
, FARPROC16 hookProc
, DWORD dwHookData
)
1455 DC
*dc
= (DC
*)GDI_GetObjPtr( hdc
, DC_MAGIC
);
1457 TRACE(dc
, "hookProc %08x, default is %08x\n",
1458 (UINT32
)hookProc
, (UINT32
)DCHook
);
1460 if (!dc
) return FALSE
;
1461 dc
->hookProc
= hookProc
;
1462 dc
->dwHookData
= dwHookData
;
1463 GDI_HEAP_UNLOCK( hdc
);
1468 /***********************************************************************
1469 * GetDCHook (GDI.191)
1471 DWORD WINAPI
GetDCHook( HDC16 hdc
, FARPROC16
*phookProc
)
1473 DC
*dc
= (DC
*)GDI_GetObjPtr( hdc
, DC_MAGIC
);
1475 *phookProc
= dc
->hookProc
;
1476 GDI_HEAP_UNLOCK( hdc
);
1477 return dc
->dwHookData
;
1481 /***********************************************************************
1482 * SetHookFlags (GDI.192)
1484 WORD WINAPI
SetHookFlags(HDC16 hDC
, WORD flags
)
1486 DC
* dc
= (DC
*)GDI_GetObjPtr( hDC
, DC_MAGIC
);
1490 WORD wRet
= dc
->w
.flags
& DC_DIRTY
;
1492 /* "Undocumented Windows" info is slightly confusing.
1495 TRACE(dc
,"hDC %04x, flags %04x\n",hDC
,flags
);
1497 if( flags
& DCHF_INVALIDATEVISRGN
)
1498 dc
->w
.flags
|= DC_DIRTY
;
1499 else if( flags
& DCHF_VALIDATEVISRGN
|| !flags
)
1500 dc
->w
.flags
&= ~DC_DIRTY
;
1501 GDI_HEAP_UNLOCK( hDC
);
1507 /***********************************************************************
1508 * SetICMMode (GDI32.318)
1510 INT32 WINAPI
SetICMMode(HDC32 hdc
, INT32 iEnableICM
)
1512 /*FIXME Asuming that ICM is always off, and cannot be turned on */
1513 if (iEnableICM
== ICM_OFF
) return ICM_OFF
;
1514 if (iEnableICM
== ICM_ON
) return 0;
1515 if (iEnableICM
== ICM_QUERY
) return ICM_OFF
;
1520 /***********************************************************************
1521 * GetColorSpace (GDI32.165)
1523 HCOLORSPACE32 WINAPI
GetColorSpace(HDC32 hdc
)
1525 /*FIXME Need to to whatever GetColorSpace actually does */
1529 /***********************************************************************
1530 * GetBoundsRect16 (GDI.194)
1532 UINT16 WINAPI
GetBoundsRect16(HDC16 hdc
, LPRECT16 rect
, UINT16 flags
)
1534 FIXME(dc
, "(): stub\n");
1535 return DCB_RESET
; /* bounding rectangle always empty */
1538 /***********************************************************************
1539 * SetBoundsRect16 (GDI.193)
1541 UINT16 WINAPI
SetBoundsRect16(HDC16 hdc
, const RECT16
* rect
, UINT16 flags
)
1543 FIXME(dc
, "(): stub\n");
1544 return DCB_DISABLE
; /* bounding rectangle always empty */