2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
20 extern void CLIPPING_UpdateGCRegion( DC
* dc
); /* objects/clipping.c */
23 /* ROP code to GC function conversion */
24 const int DC_XROPfunction
[16] =
26 GXclear
, /* R2_BLACK */
27 GXnor
, /* R2_NOTMERGEPEN */
28 GXandInverted
, /* R2_MASKNOTPEN */
29 GXcopyInverted
, /* R2_NOTCOPYPEN */
30 GXandReverse
, /* R2_MASKPENNOT */
31 GXinvert
, /* R2_NOT */
32 GXxor
, /* R2_XORPEN */
33 GXnand
, /* R2_NOTMASKPEN */
34 GXand
, /* R2_MASKPEN */
35 GXequiv
, /* R2_NOTXORPEN */
37 GXorInverted
, /* R2_MERGENOTPEN */
38 GXcopy
, /* R2_COPYPEN */
39 GXorReverse
, /* R2_MERGEPENNOT */
40 GXor
, /* R2_MERGEPEN */
45 /***********************************************************************
48 * Fill the device caps structure.
50 void DC_FillDevCaps( DeviceCaps
* caps
)
52 caps
->version
= 0x300;
53 caps
->technology
= DT_RASDISPLAY
;
54 caps
->horzSize
= WidthMMOfScreen(screen
) * screenWidth
/ WidthOfScreen(screen
);
55 caps
->vertSize
= HeightMMOfScreen(screen
) * screenHeight
/ HeightOfScreen(screen
);
56 caps
->horzRes
= screenWidth
;
57 caps
->vertRes
= screenHeight
;
58 caps
->bitsPixel
= screenDepth
;
60 caps
->numBrushes
= 16+6; /* 16 solid + 6 hatched brushes */
61 caps
->numPens
= 16; /* 16 solid pens */
64 caps
->numColors
= 100;
65 caps
->pdeviceSize
= 0;
66 caps
->curveCaps
= CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
|
67 CC_WIDE
| CC_STYLED
| CC_WIDESTYLED
|
68 CC_INTERIORS
| CC_ROUNDRECT
;
69 caps
->lineCaps
= LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
70 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
;
71 caps
->polygonalCaps
= PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
|
72 PC_SCANLINE
| PC_WIDE
| PC_STYLED
|
73 PC_WIDESTYLED
| PC_INTERIORS
;
74 caps
->textCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
75 TC_IA_ABLE
| TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
76 caps
->clipCaps
= CP_REGION
;
77 caps
->rasterCaps
= RC_BITBLT
| RC_BANDING
| RC_SCALING
| RC_BITMAP64
|
78 RC_DI_BITMAP
| RC_DIBTODEV
| RC_BIGFONT
|
79 RC_STRETCHBLT
| RC_STRETCHDIB
| RC_DEVBITS
;
81 if( !(COLOR_GetSystemPaletteFlags() & COLOR_VIRTUAL
) )
82 caps
->rasterCaps
|= RC_PALETTE
;
84 caps
->aspectX
= 36; /* ?? */
85 caps
->aspectY
= 36; /* ?? */
87 caps
->logPixelsX
= (int)(caps
->horzRes
* 25.4 / caps
->horzSize
);
88 caps
->logPixelsY
= (int)(caps
->vertRes
* 25.4 / caps
->vertSize
);
89 caps
->sizePalette
= (caps
->rasterCaps
& RC_PALETTE
)
90 ? DefaultVisual(display
,DefaultScreen(display
))->map_entries
92 caps
->numReserved
= 0;
97 /***********************************************************************
100 * Fill the WIN_DC_INFO structure.
102 static void DC_Init_DC_INFO( WIN_DC_INFO
*win_dc_info
)
104 win_dc_info
->flags
= 0;
105 win_dc_info
->devCaps
= NULL
;
106 win_dc_info
->hClipRgn
= 0;
107 win_dc_info
->hVisRgn
= 0;
108 win_dc_info
->hGCClipRgn
= 0;
109 win_dc_info
->hPen
= STOCK_BLACK_PEN
;
110 win_dc_info
->hBrush
= STOCK_WHITE_BRUSH
;
111 win_dc_info
->hFont
= STOCK_SYSTEM_FONT
;
112 win_dc_info
->hBitmap
= 0;
113 win_dc_info
->hFirstBitmap
= 0;
114 win_dc_info
->hDevice
= 0;
115 win_dc_info
->hPalette
= STOCK_DEFAULT_PALETTE
;
116 win_dc_info
->ROPmode
= R2_COPYPEN
;
117 win_dc_info
->polyFillMode
= ALTERNATE
;
118 win_dc_info
->stretchBltMode
= BLACKONWHITE
;
119 win_dc_info
->relAbsMode
= ABSOLUTE
;
120 win_dc_info
->backgroundMode
= OPAQUE
;
121 win_dc_info
->backgroundColor
= RGB( 255, 255, 255 );
122 win_dc_info
->textColor
= RGB( 0, 0, 0 );
123 win_dc_info
->backgroundPixel
= 0;
124 win_dc_info
->textPixel
= 0;
125 win_dc_info
->brushOrgX
= 0;
126 win_dc_info
->brushOrgY
= 0;
127 win_dc_info
->textAlign
= TA_LEFT
| TA_TOP
| TA_NOUPDATECP
;
128 win_dc_info
->charExtra
= 0;
129 win_dc_info
->breakTotalExtra
= 0;
130 win_dc_info
->breakCount
= 0;
131 win_dc_info
->breakExtra
= 0;
132 win_dc_info
->breakRem
= 0;
133 win_dc_info
->bitsPerPixel
= 1;
134 win_dc_info
->MapMode
= MM_TEXT
;
135 win_dc_info
->GraphicsMode
= GM_COMPATIBLE
;
136 win_dc_info
->DCOrgX
= 0;
137 win_dc_info
->DCOrgY
= 0;
138 win_dc_info
->CursPosX
= 0;
139 win_dc_info
->CursPosY
= 0;
140 win_dc_info
->ArcDirection
= AD_COUNTERCLOCKWISE
;
141 win_dc_info
->UseWorldXform
= FALSE
;
142 win_dc_info
->WorldXform
.eM11
= 1.0f
;
143 win_dc_info
->WorldXform
.eM12
= 0.0f
;
144 win_dc_info
->WorldXform
.eM21
= 0.0f
;
145 win_dc_info
->WorldXform
.eM22
= 1.0f
;
146 win_dc_info
->WorldXform
.eDx
= 0.0f
;
147 win_dc_info
->WorldXform
.eDy
= 0.0f
;
149 PATH_InitGdiPath(&win_dc_info
->path
);
153 /***********************************************************************
156 DC
*DC_AllocDC( const DC_FUNCTIONS
*funcs
)
161 if (!(hdc
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
))) return NULL
;
162 dc
= (DC
*) GDI_HEAP_LOCK( hdc
);
179 DC_Init_DC_INFO( &dc
->w
);
186 /***********************************************************************
189 DC
*DC_GetDCPtr( HDC32 hdc
)
191 GDIOBJHDR
*ptr
= (GDIOBJHDR
*)GDI_HEAP_LOCK( hdc
);
192 if (!ptr
) return NULL
;
193 if ((ptr
->wMagic
== DC_MAGIC
) || (ptr
->wMagic
== METAFILE_DC_MAGIC
))
195 GDI_HEAP_UNLOCK( hdc
);
200 /***********************************************************************
203 * Setup device-specific DC values for a newly created DC.
205 void DC_InitDC( DC
* dc
)
207 RealizeDefaultPalette( dc
->hSelf
);
208 SetTextColor32( dc
->hSelf
, dc
->w
.textColor
);
209 SetBkColor32( dc
->hSelf
, dc
->w
.backgroundColor
);
210 SelectObject32( dc
->hSelf
, dc
->w
.hPen
);
211 SelectObject32( dc
->hSelf
, dc
->w
.hBrush
);
212 SelectObject32( dc
->hSelf
, dc
->w
.hFont
);
213 CLIPPING_UpdateGCRegion( dc
);
217 /***********************************************************************
218 * DC_SetupGCForPatBlt
220 * Setup the GC for a PatBlt operation using current brush.
221 * If fMapColors is TRUE, X pixels are mapped to Windows colors.
222 * Return FALSE if brush is BS_NULL, TRUE otherwise.
224 BOOL32
DC_SetupGCForPatBlt( DC
* dc
, GC gc
, BOOL32 fMapColors
)
230 if (dc
->u
.x
.brush
.style
== BS_NULL
) return FALSE
;
231 if (dc
->u
.x
.brush
.pixel
== -1)
233 /* Special case used for monochrome pattern brushes.
234 * We need to swap foreground and background because
235 * Windows does it the wrong way...
237 val
.foreground
= dc
->w
.backgroundPixel
;
238 val
.background
= dc
->w
.textPixel
;
242 val
.foreground
= dc
->u
.x
.brush
.pixel
;
243 val
.background
= dc
->w
.backgroundPixel
;
245 if (fMapColors
&& COLOR_PixelToPalette
)
247 val
.foreground
= COLOR_PixelToPalette
[val
.foreground
];
248 val
.background
= COLOR_PixelToPalette
[val
.background
];
251 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
253 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
255 ** Let's replace GXinvert by GXxor with (black xor white)
256 ** This solves the selection color and leak problems in excel
257 ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
259 if (val
.function
== GXinvert
)
261 val
.foreground
= BlackPixelOfScreen(screen
) ^ WhitePixelOfScreen(screen
);
262 val
.function
= GXxor
;
264 val
.fill_style
= dc
->u
.x
.brush
.fillStyle
;
265 switch(val
.fill_style
)
268 case FillOpaqueStippled
:
269 if (dc
->w
.backgroundMode
==OPAQUE
) val
.fill_style
= FillOpaqueStippled
;
270 val
.stipple
= dc
->u
.x
.brush
.pixmap
;
275 if (fMapColors
&& COLOR_PixelToPalette
)
279 EnterCriticalSection( &X11DRV_CritSection
);
280 pixmap
= XCreatePixmap( display
, rootWindow
, 8, 8, screenDepth
);
281 image
= XGetImage( display
, dc
->u
.x
.brush
.pixmap
, 0, 0, 8, 8,
282 AllPlanes
, ZPixmap
);
283 for (y
= 0; y
< 8; y
++)
284 for (x
= 0; x
< 8; x
++)
285 XPutPixel( image
, x
, y
,
286 COLOR_PixelToPalette
[XGetPixel( image
, x
, y
)] );
287 XPutImage( display
, pixmap
, gc
, image
, 0, 0, 0, 0, 8, 8 );
288 XDestroyImage( image
);
289 LeaveCriticalSection( &X11DRV_CritSection
);
292 else val
.tile
= dc
->u
.x
.brush
.pixmap
;
300 val
.ts_x_origin
= dc
->w
.DCOrgX
+ dc
->w
.brushOrgX
;
301 val
.ts_y_origin
= dc
->w
.DCOrgY
+ dc
->w
.brushOrgY
;
302 val
.fill_rule
= (dc
->w
.polyFillMode
==WINDING
) ? WindingRule
: EvenOddRule
;
303 TSXChangeGC( display
, gc
,
304 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
305 GCFillRule
| GCTileStipXOrigin
| GCTileStipYOrigin
| mask
,
307 if (pixmap
) TSXFreePixmap( display
, pixmap
);
312 /***********************************************************************
315 * Setup dc->u.x.gc for drawing operations using current brush.
316 * Return FALSE if brush is BS_NULL, TRUE otherwise.
318 BOOL32
DC_SetupGCForBrush( DC
* dc
)
320 return DC_SetupGCForPatBlt( dc
, dc
->u
.x
.gc
, FALSE
);
324 /***********************************************************************
327 * Setup dc->u.x.gc for drawing operations using current pen.
328 * Return FALSE if pen is PS_NULL, TRUE otherwise.
330 BOOL32
DC_SetupGCForPen( DC
* dc
)
334 if (dc
->u
.x
.pen
.style
== PS_NULL
) return FALSE
;
336 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
338 switch (dc
->w
.ROPmode
)
341 val
.foreground
= BlackPixelOfScreen( screen
);
342 val
.function
= GXcopy
;
345 val
.foreground
= WhitePixelOfScreen( screen
);
346 val
.function
= GXcopy
;
349 val
.foreground
= dc
->u
.x
.pen
.pixel
;
350 /* It is very unlikely someone wants to XOR with 0 */
351 /* This fixes the rubber-drawings in paintbrush */
352 if (val
.foreground
== 0)
353 val
.foreground
= BlackPixelOfScreen( screen
)
354 ^ WhitePixelOfScreen( screen
);
355 val
.function
= GXxor
;
358 val
.foreground
= dc
->u
.x
.pen
.pixel
;
359 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
361 val
.background
= dc
->w
.backgroundPixel
;
362 val
.fill_style
= FillSolid
;
363 if ((dc
->u
.x
.pen
.style
!=PS_SOLID
) && (dc
->u
.x
.pen
.style
!=PS_INSIDEFRAME
))
365 TSXSetDashes( display
, dc
->u
.x
.gc
, 0,
366 dc
->u
.x
.pen
.dashes
, dc
->u
.x
.pen
.dash_len
);
367 val
.line_style
= (dc
->w
.backgroundMode
== OPAQUE
) ?
368 LineDoubleDash
: LineOnOffDash
;
370 else val
.line_style
= LineSolid
;
371 val
.line_width
= dc
->u
.x
.pen
.width
;
372 if (val
.line_width
<= 1) {
373 val
.cap_style
= CapNotLast
;
375 switch (dc
->u
.x
.pen
.endcap
)
377 case PS_ENDCAP_SQUARE
:
378 val
.cap_style
= CapProjecting
;
381 val
.cap_style
= CapButt
;
383 case PS_ENDCAP_ROUND
:
385 val
.cap_style
= CapRound
;
388 switch (dc
->u
.x
.pen
.linejoin
)
391 val
.join_style
= JoinBevel
;
393 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
->w
.textPixel
;
423 val
.background
= dc
->w
.backgroundPixel
;
424 val
.fill_style
= FillSolid
;
427 TSXChangeGC( display
, dc
->u
.x
.gc
,
428 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
432 fprintf( stderr
, "DC_SetupGCForText: physical font failure\n" );
437 /***********************************************************************
438 * GetDCState (GDI.179)
440 HDC16 WINAPI
GetDCState( HDC16 hdc
)
445 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
446 if (!(handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
)))
448 GDI_HEAP_UNLOCK( hdc
);
451 newdc
= (DC
*) GDI_HEAP_LOCK( handle
);
453 dprintf_dc(stddeb
, "GetDCState(%04x): returning %04x\n", hdc
, handle
);
455 memset( &newdc
->u
.x
, 0, sizeof(newdc
->u
.x
) );
456 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
457 newdc
->w
.devCaps
= dc
->w
.devCaps
;
458 newdc
->w
.hPen
= dc
->w
.hPen
;
459 newdc
->w
.hBrush
= dc
->w
.hBrush
;
460 newdc
->w
.hFont
= dc
->w
.hFont
;
461 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
462 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
463 newdc
->w
.hDevice
= dc
->w
.hDevice
;
464 newdc
->w
.hPalette
= dc
->w
.hPalette
;
465 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
466 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
467 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
468 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
469 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
470 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
471 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
472 newdc
->w
.textColor
= dc
->w
.textColor
;
473 newdc
->w
.backgroundPixel
= dc
->w
.backgroundPixel
;
474 newdc
->w
.textPixel
= dc
->w
.textPixel
;
475 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
476 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
477 newdc
->w
.textAlign
= dc
->w
.textAlign
;
478 newdc
->w
.charExtra
= dc
->w
.charExtra
;
479 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
480 newdc
->w
.breakCount
= dc
->w
.breakCount
;
481 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
482 newdc
->w
.breakRem
= dc
->w
.breakRem
;
483 newdc
->w
.MapMode
= dc
->w
.MapMode
;
484 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
485 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
486 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
487 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
488 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
489 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
490 newdc
->w
.UseWorldXform
= dc
->w
.UseWorldXform
;
491 newdc
->w
.WorldXform
= dc
->w
.WorldXform
;
492 newdc
->wndOrgX
= dc
->wndOrgX
;
493 newdc
->wndOrgY
= dc
->wndOrgY
;
494 newdc
->wndExtX
= dc
->wndExtX
;
495 newdc
->wndExtY
= dc
->wndExtY
;
496 newdc
->vportOrgX
= dc
->vportOrgX
;
497 newdc
->vportOrgY
= dc
->vportOrgY
;
498 newdc
->vportExtX
= dc
->vportExtX
;
499 newdc
->vportExtY
= dc
->vportExtY
;
501 newdc
->hSelf
= (HDC32
)handle
;
502 newdc
->saveLevel
= 0;
504 PATH_InitGdiPath( &newdc
->w
.path
);
506 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
508 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
511 newdc
->w
.hClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
512 CombineRgn32( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
515 newdc
->w
.hClipRgn
= 0;
516 GDI_HEAP_UNLOCK( handle
);
517 GDI_HEAP_UNLOCK( hdc
);
522 /***********************************************************************
523 * SetDCState (GDI.180)
525 void WINAPI
SetDCState( HDC16 hdc
, HDC16 hdcs
)
529 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return;
530 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
)))
532 GDI_HEAP_UNLOCK( hdc
);
535 if (!dcs
->w
.flags
& DC_SAVED
)
537 GDI_HEAP_UNLOCK( hdc
);
538 GDI_HEAP_UNLOCK( hdcs
);
541 dprintf_dc(stddeb
, "SetDCState: %04x %04x\n", hdc
, hdcs
);
543 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
544 dc
->w
.devCaps
= dcs
->w
.devCaps
;
545 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
546 dc
->w
.hDevice
= dcs
->w
.hDevice
;
547 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
548 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
549 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
550 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
551 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
552 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
553 dc
->w
.textColor
= dcs
->w
.textColor
;
554 dc
->w
.backgroundPixel
= dcs
->w
.backgroundPixel
;
555 dc
->w
.textPixel
= dcs
->w
.textPixel
;
556 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
557 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
558 dc
->w
.textAlign
= dcs
->w
.textAlign
;
559 dc
->w
.charExtra
= dcs
->w
.charExtra
;
560 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
561 dc
->w
.breakCount
= dcs
->w
.breakCount
;
562 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
563 dc
->w
.breakRem
= dcs
->w
.breakRem
;
564 dc
->w
.MapMode
= dcs
->w
.MapMode
;
565 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
566 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
567 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
568 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
569 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
570 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
571 dc
->w
.UseWorldXform
= dcs
->w
.UseWorldXform
;
572 dc
->w
.WorldXform
= dcs
->w
.WorldXform
;
574 dc
->wndOrgX
= dcs
->wndOrgX
;
575 dc
->wndOrgY
= dcs
->wndOrgY
;
576 dc
->wndExtX
= dcs
->wndExtX
;
577 dc
->wndExtY
= dcs
->wndExtY
;
578 dc
->vportOrgX
= dcs
->vportOrgX
;
579 dc
->vportOrgY
= dcs
->vportOrgY
;
580 dc
->vportExtX
= dcs
->vportExtX
;
581 dc
->vportExtY
= dcs
->vportExtY
;
583 if (!(dc
->w
.flags
& DC_MEMORY
)) dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
584 SelectClipRgn32( hdc
, dcs
->w
.hClipRgn
);
586 SelectObject32( hdc
, dcs
->w
.hBitmap
);
587 SelectObject32( hdc
, dcs
->w
.hBrush
);
588 SelectObject32( hdc
, dcs
->w
.hFont
);
589 SelectObject32( hdc
, dcs
->w
.hPen
);
590 GDISelectPalette( hdc
, dcs
->w
.hPalette
, FALSE
);
591 GDI_HEAP_UNLOCK( hdc
);
592 GDI_HEAP_UNLOCK( hdcs
);
596 /***********************************************************************
599 INT16 WINAPI
SaveDC16( HDC16 hdc
)
601 return (INT16
)SaveDC32( hdc
);
605 /***********************************************************************
606 * SaveDC32 (GDI32.292)
608 INT32 WINAPI
SaveDC32( HDC32 hdc
)
614 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
617 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
619 MF_MetaParam0(dc
, META_SAVEDC
);
620 GDI_HEAP_UNLOCK( hdc
);
623 if (!(hdcs
= GetDCState( hdc
)))
625 GDI_HEAP_UNLOCK( hdc
);
628 dcs
= (DC
*) GDI_HEAP_LOCK( hdcs
);
630 /* Copy path. The reason why path saving / restoring is in SaveDC/
631 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
632 * functions are only in Win16 (which doesn't have paths) and that
633 * SetDCState doesn't allow us to signal an error (which can happen
634 * when copying paths).
636 if (!PATH_AssignGdiPath( &dcs
->w
.path
, &dc
->w
.path
))
638 GDI_HEAP_UNLOCK( hdc
);
639 GDI_HEAP_UNLOCK( hdcs
);
644 dcs
->header
.hNext
= dc
->header
.hNext
;
645 dc
->header
.hNext
= hdcs
;
646 dprintf_dc(stddeb
, "SaveDC(%04x): returning %d\n", hdc
, dc
->saveLevel
+1 );
647 ret
= ++dc
->saveLevel
;
648 GDI_HEAP_UNLOCK( hdcs
);
649 GDI_HEAP_UNLOCK( hdc
);
654 /***********************************************************************
655 * RestoreDC16 (GDI.39)
657 BOOL16 WINAPI
RestoreDC16( HDC16 hdc
, INT16 level
)
659 return RestoreDC32( hdc
, level
);
663 /***********************************************************************
664 * RestoreDC32 (GDI32.290)
666 BOOL32 WINAPI
RestoreDC32( HDC32 hdc
, INT32 level
)
671 dprintf_dc(stddeb
, "RestoreDC: %04x %d\n", hdc
, level
);
672 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
675 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
676 if (!dc
) return FALSE
;
679 GDI_HEAP_UNLOCK( hdc
);
682 MF_MetaParam1(dc
, META_RESTOREDC
, level
);
683 GDI_HEAP_UNLOCK( hdc
);
686 if (level
== -1) level
= dc
->saveLevel
;
687 if ((level
< 1) || (level
> dc
->saveLevel
))
689 GDI_HEAP_UNLOCK( hdc
);
694 while (dc
->saveLevel
>= level
)
696 HDC16 hdcs
= dc
->header
.hNext
;
697 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
)))
699 GDI_HEAP_UNLOCK( hdc
);
702 dc
->header
.hNext
= dcs
->header
.hNext
;
703 if (--dc
->saveLevel
< level
)
705 SetDCState( hdc
, hdcs
);
706 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
707 /* FIXME: This might not be quite right, since we're
708 * returning FALSE but still destroying the saved DC state */
713 GDI_HEAP_UNLOCK( hdc
);
718 /***********************************************************************
719 * CreateDC16 (GDI.53)
721 HDC16 WINAPI
CreateDC16( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
722 const DEVMODE16
*initData
)
725 const DC_FUNCTIONS
*funcs
;
727 if (!(funcs
= DRIVER_FindDriver( driver
))) return 0;
728 if (!(dc
= DC_AllocDC( funcs
))) return 0;
731 dprintf_dc(stddeb
, "CreateDC(%s %s %s): returning %04x\n",
732 driver
, device
, output
, dc
->hSelf
);
734 if (dc
->funcs
->pCreateDC
&&
735 !dc
->funcs
->pCreateDC( dc
, driver
, device
, output
, initData
))
737 dprintf_dc( stddeb
, "CreateDC: creation aborted by device\n" );
738 GDI_HEAP_FREE( dc
->hSelf
);
743 GDI_HEAP_UNLOCK( dc
->hSelf
);
748 /***********************************************************************
749 * CreateDC32A (GDI32.)
751 HDC32 WINAPI
CreateDC32A( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
752 const DEVMODE32A
*initData
)
754 return CreateDC16( driver
, device
, output
, (const DEVMODE16
*)initData
);
758 /***********************************************************************
759 * CreateDC32W (GDI32.)
761 HDC32 WINAPI
CreateDC32W( LPCWSTR driver
, LPCWSTR device
, LPCWSTR output
,
762 const DEVMODE32W
*initData
)
764 LPSTR driverA
= HEAP_strdupWtoA( GetProcessHeap(), 0, driver
);
765 LPSTR deviceA
= HEAP_strdupWtoA( GetProcessHeap(), 0, device
);
766 LPSTR outputA
= HEAP_strdupWtoA( GetProcessHeap(), 0, output
);
767 HDC32 res
= CreateDC16( driverA
, deviceA
, outputA
,
768 (const DEVMODE16
*)initData
/*FIXME*/ );
769 HeapFree( GetProcessHeap(), 0, driverA
);
770 HeapFree( GetProcessHeap(), 0, deviceA
);
771 HeapFree( GetProcessHeap(), 0, outputA
);
776 /***********************************************************************
777 * CreateIC16 (GDI.153)
779 HDC16 WINAPI
CreateIC16( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
780 const DEVMODE16
* initData
)
782 /* Nothing special yet for ICs */
783 return CreateDC16( driver
, device
, output
, initData
);
787 /***********************************************************************
788 * CreateIC32A (GDI32.49)
790 HDC32 WINAPI
CreateIC32A( LPCSTR driver
, LPCSTR device
, LPCSTR output
,
791 const DEVMODE32A
* initData
)
793 /* Nothing special yet for ICs */
794 return CreateDC32A( driver
, device
, output
, initData
);
798 /***********************************************************************
799 * CreateIC32W (GDI32.50)
801 HDC32 WINAPI
CreateIC32W( LPCWSTR driver
, LPCWSTR device
, LPCWSTR output
,
802 const DEVMODE32W
* initData
)
804 /* Nothing special yet for ICs */
805 return CreateDC32W( driver
, device
, output
, initData
);
809 /***********************************************************************
810 * CreateCompatibleDC16 (GDI.52)
812 HDC16 WINAPI
CreateCompatibleDC16( HDC16 hdc
)
814 return (HDC16
)CreateCompatibleDC32( hdc
);
818 /***********************************************************************
819 * CreateCompatibleDC32 (GDI32.31)
821 HDC32 WINAPI
CreateCompatibleDC32( HDC32 hdc
)
825 const DC_FUNCTIONS
*funcs
;
827 if ((origDC
= (DC
*)GDI_GetObjPtr( hdc
, DC_MAGIC
))) funcs
= origDC
->funcs
;
828 else funcs
= DRIVER_FindDriver( "DISPLAY" );
829 if (!funcs
) return 0;
831 if (!(dc
= DC_AllocDC( funcs
))) return 0;
833 dprintf_dc(stddeb
, "CreateCompatibleDC(%04x): returning %04x\n",
836 /* Create default bitmap */
837 if (!(hbitmap
= CreateBitmap32( 1, 1, 1, 1, NULL
)))
839 GDI_HEAP_FREE( dc
->hSelf
);
842 dc
->w
.flags
= DC_MEMORY
;
843 dc
->w
.bitsPerPixel
= 1;
844 dc
->w
.hBitmap
= hbitmap
;
845 dc
->w
.hFirstBitmap
= hbitmap
;
847 if (dc
->funcs
->pCreateDC
&&
848 !dc
->funcs
->pCreateDC( dc
, NULL
, NULL
, NULL
, NULL
))
850 dprintf_dc(stddeb
, "CreateCompatibleDC: creation aborted by device\n");
851 DeleteObject32( hbitmap
);
852 GDI_HEAP_FREE( dc
->hSelf
);
857 GDI_HEAP_UNLOCK( dc
->hSelf
);
862 /***********************************************************************
863 * DeleteDC16 (GDI.68)
865 BOOL16 WINAPI
DeleteDC16( HDC16 hdc
)
867 return DeleteDC32( hdc
);
871 /***********************************************************************
872 * DeleteDC32 (GDI32.67)
874 BOOL32 WINAPI
DeleteDC32( HDC32 hdc
)
876 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
877 if (!dc
) return FALSE
;
879 dprintf_dc(stddeb
, "DeleteDC: %04x\n", hdc
);
881 while (dc
->saveLevel
)
884 HDC16 hdcs
= dc
->header
.hNext
;
885 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) break;
886 dc
->header
.hNext
= dcs
->header
.hNext
;
891 if (!(dc
->w
.flags
& DC_SAVED
))
893 SelectObject32( hdc
, STOCK_BLACK_PEN
);
894 SelectObject32( hdc
, STOCK_WHITE_BRUSH
);
895 SelectObject32( hdc
, STOCK_SYSTEM_FONT
);
896 if (dc
->w
.flags
& DC_MEMORY
) DeleteObject32( dc
->w
.hFirstBitmap
);
897 if (dc
->funcs
->pDeleteDC
) dc
->funcs
->pDeleteDC(dc
);
900 if (dc
->w
.hClipRgn
) DeleteObject32( dc
->w
.hClipRgn
);
901 if (dc
->w
.hVisRgn
) DeleteObject32( dc
->w
.hVisRgn
);
902 if (dc
->w
.hGCClipRgn
) DeleteObject32( dc
->w
.hGCClipRgn
);
904 PATH_DestroyGdiPath(&dc
->w
.path
);
906 return GDI_FreeObject( hdc
);
910 /***********************************************************************
911 * ResetDC16 (GDI.376)
913 HDC16 WINAPI
ResetDC16( HDC16 hdc
, const DEVMODE16
*devmode
)
915 fprintf( stderr
, "ResetDC16: empty stub!\n" );
920 /***********************************************************************
921 * ResetDC32A (GDI32.287)
923 HDC32 WINAPI
ResetDC32A( HDC32 hdc
, const DEVMODE32A
*devmode
)
925 fprintf( stderr
, "ResetDC32A: empty stub!\n" );
930 /***********************************************************************
931 * ResetDC32W (GDI32.288)
933 HDC32 WINAPI
ResetDC32W( HDC32 hdc
, const DEVMODE32W
*devmode
)
935 fprintf( stderr
, "ResetDC32A: empty stub!\n" );
940 /***********************************************************************
941 * GetDeviceCaps16 (GDI.80)
943 INT16 WINAPI
GetDeviceCaps16( HDC16 hdc
, INT16 cap
)
945 return GetDeviceCaps32( hdc
, cap
);
949 /***********************************************************************
950 * GetDeviceCaps32 (GDI32.171)
952 INT32 WINAPI
GetDeviceCaps32( HDC32 hdc
, INT32 cap
)
954 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
959 if ((cap
< 0) || (cap
> sizeof(DeviceCaps
)-sizeof(WORD
)))
961 GDI_HEAP_UNLOCK( hdc
);
965 dprintf_dc(stddeb
, "GetDeviceCaps(%04x,%d): returning %d\n",
966 hdc
, cap
, *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
) );
967 ret
= *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
);
968 GDI_HEAP_UNLOCK( hdc
);
973 /***********************************************************************
974 * SetBkColor16 (GDI.1)
976 COLORREF WINAPI
SetBkColor16( HDC16 hdc
, COLORREF color
)
978 return SetBkColor32( hdc
, color
);
982 /***********************************************************************
983 * SetBkColor32 (GDI32.305)
985 COLORREF WINAPI
SetBkColor32( HDC32 hdc
, COLORREF color
)
988 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
991 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
992 if (!dc
) return 0x80000000;
993 MF_MetaParam2(dc
, META_SETBKCOLOR
, HIWORD(color
), LOWORD(color
));
994 GDI_HEAP_UNLOCK( hdc
);
998 oldColor
= dc
->w
.backgroundColor
;
999 dc
->w
.backgroundColor
= color
;
1000 dc
->w
.backgroundPixel
= COLOR_ToPhysical( dc
, color
);
1001 GDI_HEAP_UNLOCK( hdc
);
1006 /***********************************************************************
1007 * SetTextColor16 (GDI.9)
1009 COLORREF WINAPI
SetTextColor16( HDC16 hdc
, COLORREF color
)
1011 return SetTextColor32( hdc
, color
);
1015 /***********************************************************************
1016 * SetTextColor32 (GDI32.338)
1018 COLORREF WINAPI
SetTextColor32( HDC32 hdc
, COLORREF color
)
1021 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1024 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
1025 if (!dc
) return 0x80000000;
1026 MF_MetaParam2(dc
, META_SETTEXTCOLOR
, HIWORD(color
), LOWORD(color
));
1027 GDI_HEAP_UNLOCK( hdc
);
1031 oldColor
= dc
->w
.textColor
;
1032 dc
->w
.textColor
= color
;
1033 dc
->w
.textPixel
= COLOR_ToPhysical( dc
, color
);
1034 GDI_HEAP_UNLOCK( hdc
);
1039 /***********************************************************************
1040 * SetTextAlign16 (GDI.346)
1042 UINT16 WINAPI
SetTextAlign16( HDC16 hdc
, UINT16 textAlign
)
1044 return SetTextAlign32( hdc
, textAlign
);
1048 /***********************************************************************
1049 * SetTextAlign32 (GDI32.336)
1051 UINT32 WINAPI
SetTextAlign32( HDC32 hdc
, UINT32 textAlign
)
1054 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1057 if (!(dc
= (DC
*)GDI_GetObjPtr( hdc
, METAFILE_DC_MAGIC
))) return 0;
1058 MF_MetaParam1( dc
, META_SETTEXTALIGN
, textAlign
);
1059 GDI_HEAP_UNLOCK( hdc
);
1062 prevAlign
= dc
->w
.textAlign
;
1063 dc
->w
.textAlign
= textAlign
;
1064 GDI_HEAP_UNLOCK( hdc
);
1069 /***********************************************************************
1070 * GetDCOrgEx (GDI32.168)
1072 BOOL32 WINAPI
GetDCOrgEx( HDC32 hDC
, LPPOINT32 lpp
)
1075 if (!lpp
) return FALSE
;
1076 if (!(dc
= (DC
*) GDI_GetObjPtr( hDC
, DC_MAGIC
))) return FALSE
;
1078 if (!(dc
->w
.flags
& DC_MEMORY
))
1081 int w
, h
, border
, depth
;
1082 /* FIXME: this is not correct for managed windows */
1083 TSXGetGeometry( display
, dc
->u
.x
.drawable
, &root
,
1084 &lpp
->x
, &lpp
->y
, &w
, &h
, &border
, &depth
);
1086 else lpp
->x
= lpp
->y
= 0;
1087 lpp
->x
+= dc
->w
.DCOrgX
; lpp
->y
+= dc
->w
.DCOrgY
;
1088 GDI_HEAP_UNLOCK( hDC
);
1093 /***********************************************************************
1096 DWORD WINAPI
GetDCOrg( HDC16 hdc
)
1099 if( GetDCOrgEx( hdc
, &pt
) )
1100 return MAKELONG( (WORD
)pt
.x
, (WORD
)pt
.y
);
1105 /***********************************************************************
1106 * SetDCOrg (GDI.117)
1108 DWORD WINAPI
SetDCOrg( HDC16 hdc
, INT16 x
, INT16 y
)
1111 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1113 prevOrg
= dc
->w
.DCOrgX
| (dc
->w
.DCOrgY
<< 16);
1116 GDI_HEAP_UNLOCK( hdc
);
1121 /***********************************************************************
1122 * GetGraphicsMode (GDI32.188)
1124 INT32 WINAPI
GetGraphicsMode( HDC32 hdc
)
1126 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1128 return dc
->w
.GraphicsMode
;
1132 /***********************************************************************
1133 * SetGraphicsMode (GDI32.317)
1135 INT32 WINAPI
SetGraphicsMode( HDC32 hdc
, INT32 mode
)
1138 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1140 /* One would think that setting the graphics mode to GM_COMPATIBLE
1141 * would also reset the world transformation matrix to the unity
1142 * matrix. However, in Windows, this is not the case. This doesn't
1143 * make a lot of sense to me, but that's the way it is.
1147 if ((mode
<= 0) || (mode
> GM_LAST
)) return 0;
1148 ret
= dc
->w
.GraphicsMode
;
1149 dc
->w
.GraphicsMode
= mode
;
1154 /***********************************************************************
1155 * GetArcDirection16 (GDI.524)
1157 INT16 WINAPI
GetArcDirection16( HDC16 hdc
)
1159 return GetArcDirection32( (HDC32
)hdc
);
1163 /***********************************************************************
1164 * GetArcDirection32 (GDI32.141)
1166 INT32 WINAPI
GetArcDirection32( HDC32 hdc
)
1168 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1173 return dc
->w
.ArcDirection
;
1177 /***********************************************************************
1178 * SetArcDirection16 (GDI.525)
1180 INT16 WINAPI
SetArcDirection16( HDC16 hdc
, INT16 nDirection
)
1182 return SetArcDirection32( (HDC32
)hdc
, (INT32
)nDirection
);
1186 /***********************************************************************
1187 * SetArcDirection32 (GDI32.302)
1189 INT32 WINAPI
SetArcDirection32( HDC32 hdc
, INT32 nDirection
)
1191 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1192 INT32 nOldDirection
;
1197 if (nDirection
!=AD_COUNTERCLOCKWISE
&& nDirection
!=AD_CLOCKWISE
)
1199 SetLastError(ERROR_INVALID_PARAMETER
);
1203 nOldDirection
= dc
->w
.ArcDirection
;
1204 dc
->w
.ArcDirection
= nDirection
;
1206 return nOldDirection
;
1210 /***********************************************************************
1211 * GetWorldTransform (GDI32.244)
1213 BOOL32 WINAPI
GetWorldTransform( HDC32 hdc
, LPXFORM xform
)
1214 /* FIXME: Check that SetLastError is being called correctly */
1216 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1219 /* FIXME: Call SetLastError? */
1222 /* FIXME: Call SetLastError? */
1225 *xform
= dc
->w
.WorldXform
;
1231 /***********************************************************************
1232 * SetWorldTransform (GDI32.346)
1234 BOOL32 WINAPI
SetWorldTransform( HDC32 hdc
, const XFORM
*xform
)
1236 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
1240 SetLastError( ERROR_INVALID_HANDLE
);
1247 /* Check that graphics mode is GM_ADVANCED */
1248 if (dc
->w
.GraphicsMode
!=GM_ADVANCED
)
1251 dc
->w
.WorldXform
= *xform
;
1253 /* We only have to use the new world transform if it's not the
1254 * identity transformation
1256 dc
->w
.UseWorldXform
=
1257 (xform
->eM11
!=1.0f
|| xform
->eM12
!=0.0f
||
1258 xform
->eM21
!=0.0f
|| xform
->eM22
!=1.0f
||
1259 xform
->eDx
!=0.0f
|| xform
->eDy
!=0.0f
);
1265 /***********************************************************************
1266 * SetDCHook (GDI.190)
1268 BOOL16 WINAPI
SetDCHook( HDC16 hdc
, FARPROC16 hookProc
, DWORD dwHookData
)
1270 DC
*dc
= (DC
*)GDI_GetObjPtr( hdc
, DC_MAGIC
);
1272 dprintf_dc( stddeb
, "SetDCHook: hookProc %08x, default is %08x\n",
1273 (UINT32
)hookProc
, (UINT32
)DCHook
);
1275 if (!dc
) return FALSE
;
1276 dc
->hookProc
= hookProc
;
1277 dc
->dwHookData
= dwHookData
;
1278 GDI_HEAP_UNLOCK( hdc
);
1283 /***********************************************************************
1284 * GetDCHook (GDI.191)
1286 DWORD WINAPI
GetDCHook( HDC16 hdc
, FARPROC16
*phookProc
)
1288 DC
*dc
= (DC
*)GDI_GetObjPtr( hdc
, DC_MAGIC
);
1290 *phookProc
= dc
->hookProc
;
1291 GDI_HEAP_UNLOCK( hdc
);
1292 return dc
->dwHookData
;
1296 /***********************************************************************
1297 * SetHookFlags (GDI.192)
1299 WORD WINAPI
SetHookFlags(HDC16 hDC
, WORD flags
)
1301 DC
* dc
= (DC
*)GDI_GetObjPtr( hDC
, DC_MAGIC
);
1305 WORD wRet
= dc
->w
.flags
& DC_DIRTY
;
1307 /* "Undocumented Windows" info is slightly confusing.
1310 dprintf_dc(stddeb
,"SetHookFlags: hDC %04x, flags %04x\n",hDC
,flags
);
1312 if( flags
& DCHF_INVALIDATEVISRGN
)
1313 dc
->w
.flags
|= DC_DIRTY
;
1314 else if( flags
& DCHF_VALIDATEVISRGN
|| !flags
)
1315 dc
->w
.flags
&= ~DC_DIRTY
;
1316 GDI_HEAP_UNLOCK( hDC
);