2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
15 /* #define DEBUG_DC /* */
16 /* #undef DEBUG_DC /* */
20 static DeviceCaps
* displayDevCaps
= NULL
;
22 extern const WIN_DC_INFO DCVAL_defaultValues
;
24 extern void CLIPPING_SetDeviceClipping( DC
* dc
); /* objects/clipping.c */
25 extern WORD
COLOR_ToPhysical( DC
*dc
, COLORREF color
);/* objects/color.c */
26 extern void COLOR_SetMapping( DC
*dc
, HANDLE
, WORD
); /* objects/color.c */
29 /* ROP code to GC function conversion */
30 const int DC_XROPfunction
[16] =
32 GXclear
, /* R2_BLACK */
33 GXnor
, /* R2_NOTMERGEPEN */
34 GXandInverted
, /* R2_MASKNOTPEN */
35 GXcopyInverted
, /* R2_NOTCOPYPEN */
36 GXandReverse
, /* R2_MASKPENNOT */
37 GXinvert
, /* R2_NOT */
38 GXxor
, /* R2_XORPEN */
39 GXnand
, /* R2_NOTMASKPEN */
40 GXand
, /* R2_MASKPEN */
41 GXequiv
, /* R2_NOTXORPEN */
43 GXorInverted
, /* R2_MERGENOTPEN */
44 GXcopy
, /* R2_COPYPEN */
45 GXorReverse
, /* R2_MERGEPENNOT */
46 GXor
, /* R2_MERGEPEN */
51 /***********************************************************************
54 * Fill the device caps structure.
56 void DC_FillDevCaps( DeviceCaps
* caps
)
58 caps
->version
= 0x300;
59 caps
->technology
= DT_RASDISPLAY
;
60 caps
->horzSize
= WidthMMOfScreen(screen
) * screenWidth
/ WidthOfScreen(screen
);
61 caps
->vertSize
= HeightMMOfScreen(screen
) * screenHeight
/ HeightOfScreen(screen
);
62 caps
->horzRes
= screenWidth
;
63 caps
->vertRes
= screenHeight
;
64 caps
->bitsPixel
= screenDepth
;
70 caps
->numColors
= 1 << caps
->bitsPixel
;
71 caps
->pdeviceSize
= 0;
72 caps
->curveCaps
= CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
|
73 CC_WIDE
| CC_STYLED
| CC_WIDESTYLED
|
74 CC_INTERIORS
| CC_ROUNDRECT
;
75 caps
->lineCaps
= LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
76 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
;
77 caps
->polygonalCaps
= PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
|
78 PC_SCANLINE
| PC_WIDE
| PC_STYLED
|
79 PC_WIDESTYLED
| PC_INTERIORS
;
80 caps
->textCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
81 TC_IA_ABLE
| TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
82 caps
->clipCaps
= CP_REGION
;
83 caps
->rasterCaps
= RC_BITBLT
| RC_BANDING
| RC_SCALING
| RC_BITMAP64
|
84 RC_DI_BITMAP
| RC_PALETTE
| RC_DIBTODEV
| RC_BIGFONT
|
85 RC_STRETCHBLT
| RC_STRETCHDIB
| RC_DEVBITS
;
86 caps
->aspectX
= 36; /* ?? */
87 caps
->aspectY
= 36; /* ?? */
89 caps
->logPixelsX
= (int)(caps
->horzRes
* 25.4 / caps
->horzSize
);
90 caps
->logPixelsY
= (int)(caps
->vertRes
* 25.4 / caps
->vertSize
);
91 caps
->sizePalette
= DefaultVisual(display
,DefaultScreen(display
))->map_entries
;
92 caps
->numReserved
= 0;
97 /***********************************************************************
100 * Setup device-specific DC values for a newly created DC.
102 void DC_InitDC( HDC hdc
)
104 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
105 RealizeDefaultPalette( hdc
);
106 SetTextColor( hdc
, dc
->w
.textColor
);
107 SetBkColor( hdc
, dc
->w
.backgroundColor
);
108 SelectObject( hdc
, dc
->w
.hPen
);
109 SelectObject( hdc
, dc
->w
.hBrush
);
110 SelectObject( hdc
, dc
->w
.hFont
);
111 XSetGraphicsExposures( display
, dc
->u
.x
.gc
, False
);
112 XSetSubwindowMode( display
, dc
->u
.x
.gc
, IncludeInferiors
);
113 CLIPPING_SetDeviceClipping( dc
);
117 /***********************************************************************
120 * Setup dc->u.x.gc for drawing operations using current brush.
121 * Return 0 if brush is BS_NULL, 1 otherwise.
123 int DC_SetupGCForBrush( DC
* dc
)
126 unsigned long mask
= 0;
128 if (dc
->u
.x
.brush
.style
== BS_NULL
) return 0;
129 if (dc
->u
.x
.brush
.pixel
== -1)
131 /* Special case used for monochrome pattern brushes.
132 * We need to swap foreground and background because
133 * Windows does it the wrong way...
135 val
.foreground
= dc
->w
.backgroundPixel
;
136 val
.background
= dc
->w
.textPixel
;
140 val
.foreground
= dc
->u
.x
.brush
.pixel
;
141 val
.background
= dc
->w
.backgroundPixel
;
143 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
144 val
.fill_style
= dc
->u
.x
.brush
.fillStyle
;
145 if (val
.fill_style
== FillStippled
)
147 if (dc
->w
.backgroundMode
==OPAQUE
) val
.fill_style
= FillOpaqueStippled
;
148 val
.stipple
= dc
->u
.x
.brush
.pixmap
;
151 else if (val
.fill_style
== FillTiled
)
153 val
.tile
= dc
->u
.x
.brush
.pixmap
;
156 val
.ts_x_origin
= dc
->w
.DCOrgX
+ dc
->w
.brushOrgX
;
157 val
.ts_y_origin
= dc
->w
.DCOrgY
+ dc
->w
.brushOrgY
;
158 val
.fill_rule
= (dc
->w
.polyFillMode
==WINDING
) ? WindingRule
: EvenOddRule
;
159 XChangeGC( display
, dc
->u
.x
.gc
,
160 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
161 GCFillRule
| GCTileStipXOrigin
| GCTileStipYOrigin
| mask
,
167 /***********************************************************************
170 * Setup dc->u.x.gc for drawing operations using current pen.
171 * Return 0 if pen is PS_NULL, 1 otherwise.
173 int DC_SetupGCForPen( DC
* dc
)
177 if (dc
->u
.x
.pen
.style
== PS_NULL
) return 0;
178 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
179 val
.foreground
= dc
->u
.x
.pen
.pixel
;
180 val
.background
= dc
->w
.backgroundPixel
;
181 val
.fill_style
= FillSolid
;
182 if ((dc
->u
.x
.pen
.style
!=PS_SOLID
) && (dc
->u
.x
.pen
.style
!=PS_INSIDEFRAME
))
184 XSetDashes( display
, dc
->u
.x
.gc
, 0,
185 dc
->u
.x
.pen
.dashes
, dc
->u
.x
.pen
.dash_len
);
186 val
.line_style
= (dc
->w
.backgroundMode
== OPAQUE
) ?
187 LineDoubleDash
: LineOnOffDash
;
189 else val
.line_style
= LineSolid
;
190 val
.line_width
= dc
->u
.x
.pen
.width
;
191 val
.cap_style
= CapRound
;
192 val
.join_style
= JoinBevel
;
193 XChangeGC( display
, dc
->u
.x
.gc
,
194 GCFunction
| GCForeground
| GCBackground
| GCLineWidth
|
195 GCLineStyle
| GCCapStyle
| GCJoinStyle
| GCFillStyle
, &val
);
200 /***********************************************************************
203 * Setup dc->u.x.gc for text drawing operations.
204 * Return 0 if the font is null, 1 otherwise.
206 int DC_SetupGCForText( DC
* dc
)
210 if (!dc
->u
.x
.font
.fstruct
)
212 FONT_SelectObject(dc
, STOCK_SYSTEM_FONT
, NULL
);
214 val
.function
= GXcopy
; /* Text is always GXcopy */
215 val
.foreground
= dc
->w
.textPixel
;
216 val
.background
= dc
->w
.backgroundPixel
;
217 val
.fill_style
= FillSolid
;
218 val
.font
= dc
->u
.x
.font
.fstruct
->fid
;
219 XChangeGC( display
, dc
->u
.x
.gc
,
220 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
226 /***********************************************************************
227 * GetDCState (GDI.179)
229 HDC
GetDCState( HDC hdc
)
234 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
235 if (!(handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
))) return 0;
236 newdc
= (DC
*) GDI_HEAP_ADDR( handle
);
238 dprintf_dc(stddeb
, "GetDCState(%d): returning %d\n", hdc
, handle
);
240 memcpy( &newdc
->w
, &dc
->w
, sizeof(dc
->w
) );
241 memcpy( &newdc
->u
.x
.pen
, &dc
->u
.x
.pen
, sizeof(dc
->u
.x
.pen
) );
242 newdc
->saveLevel
= 0;
243 newdc
->w
.flags
|= DC_SAVED
;
247 newdc
->w
.hClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
248 CombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
252 newdc
->w
.hVisRgn
= CreateRectRgn( 0, 0, 0, 0 );
253 CombineRgn( newdc
->w
.hVisRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
255 newdc
->w
.hGCClipRgn
= 0;
256 COLOR_SetMapping( newdc
, dc
->u
.x
.pal
.hMapping
, dc
->u
.x
.pal
.mappingSize
);
261 /***********************************************************************
262 * SetDCState (GDI.180)
264 void SetDCState( HDC hdc
, HDC hdcs
)
268 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return;
269 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) return;
270 if (!dcs
->w
.flags
& DC_SAVED
) return;
271 dprintf_dc(stddeb
, "SetDCState: %d %d\n", hdc
, hdcs
);
272 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
273 if (dc
->w
.hVisRgn
) DeleteObject( dc
->w
.hVisRgn
);
274 if (dc
->w
.hGCClipRgn
) DeleteObject( dc
->w
.hGCClipRgn
);
276 memcpy( &dc
->w
, &dcs
->w
, sizeof(dc
->w
) );
277 memcpy( &dc
->u
.x
.pen
, &dcs
->u
.x
.pen
, sizeof(dc
->u
.x
.pen
) );
278 dc
->w
.hClipRgn
= dc
->w
.hVisRgn
= dc
->w
.hGCClipRgn
= 0;
279 dc
->w
.flags
&= ~DC_SAVED
;
281 SelectObject( hdc
, dcs
->w
.hBrush
);
282 SelectObject( hdc
, dcs
->w
.hFont
);
283 COLOR_SetMapping( dc
, dcs
->u
.x
.pal
.hMapping
, dcs
->u
.x
.pal
.mappingSize
);
285 SelectClipRgn( hdc
, dcs
->w
.hClipRgn
);
286 SelectVisRgn( hdc
, dcs
->w
.hVisRgn
);
290 /***********************************************************************
293 int SaveDC( HDC hdc
)
298 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
301 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
303 MF_MetaParam0(dc
, META_SAVEDC
);
306 if (!(hdcs
= GetDCState( hdc
))) return 0;
307 dcs
= (DC
*) GDI_HEAP_ADDR( hdcs
);
308 dcs
->header
.hNext
= dc
->header
.hNext
;
309 dc
->header
.hNext
= hdcs
;
310 dprintf_dc(stddeb
, "SaveDC(%d): returning %d\n", hdc
, dc
->saveLevel
+1 );
311 return ++dc
->saveLevel
;
315 /***********************************************************************
318 BOOL
RestoreDC( HDC hdc
, short level
)
322 dprintf_dc(stddeb
, "RestoreDC: %d %d\n", hdc
, level
);
323 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
326 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
327 if (!dc
) return FALSE
;
328 if (level
!= -1) return FALSE
;
329 MF_MetaParam1(dc
, META_RESTOREDC
, level
);
332 if (level
== -1) level
= dc
->saveLevel
;
333 if ((level
< 1) || (level
> (short)dc
->saveLevel
)) return FALSE
;
335 while ((short)dc
->saveLevel
>= level
)
337 HDC hdcs
= dc
->header
.hNext
;
338 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) return FALSE
;
339 dc
->header
.hNext
= dcs
->header
.hNext
;
340 if ((short)--dc
->saveLevel
< level
) SetDCState( hdc
, hdcs
);
347 /***********************************************************************
350 HDC
CreateDC( LPSTR driver
, LPSTR device
, LPSTR output
, LPSTR initData
)
355 handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
);
356 if (!handle
) return 0;
357 dc
= (DC
*) GDI_HEAP_ADDR( handle
);
359 dprintf_dc(stddeb
, "CreateDC(%s %s %s): returning %d\n",
360 driver
, device
, output
, handle
);
364 displayDevCaps
= (DeviceCaps
*) malloc( sizeof(DeviceCaps
) );
365 DC_FillDevCaps( displayDevCaps
);
369 memcpy( &dc
->w
, &DCVAL_defaultValues
, sizeof(DCVAL_defaultValues
) );
370 memset( &dc
->u
.x
, 0, sizeof(dc
->u
.x
) );
372 dc
->u
.x
.drawable
= rootWindow
;
373 dc
->u
.x
.gc
= XCreateGC( display
, dc
->u
.x
.drawable
, 0, NULL
);
375 dc
->w
.devCaps
= displayDevCaps
;
376 dc
->w
.bitsPerPixel
= displayDevCaps
->bitsPixel
;
377 dc
->w
.DCSizeX
= displayDevCaps
->horzRes
;
378 dc
->w
.DCSizeY
= displayDevCaps
->vertRes
;
386 /***********************************************************************
389 HDC
CreateIC( LPSTR driver
, LPSTR device
, LPSTR output
, LPSTR initData
)
391 /* Nothing special yet for ICs */
392 return CreateDC( driver
, device
, output
, initData
);
396 /***********************************************************************
397 * CreateCompatibleDC (GDI.52)
399 HDC
CreateCompatibleDC( HDC hdc
)
406 handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
);
407 if (!handle
) return 0;
408 dc
= (DC
*) GDI_HEAP_ADDR( handle
);
410 dprintf_dc(stddeb
, "CreateCompatibleDC(%d): returning %d\n", hdc
, handle
);
412 /* Create default bitmap */
413 if (!(hbitmap
= CreateBitmap( 1, 1, 1, 1, NULL
)))
415 GDI_HEAP_FREE( handle
);
418 bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
);
421 memcpy( &dc
->w
, &DCVAL_defaultValues
, sizeof(DCVAL_defaultValues
) );
422 memset( &dc
->u
.x
, 0, sizeof(dc
->u
.x
) );
424 dc
->u
.x
.drawable
= bmp
->pixmap
;
425 dc
->u
.x
.gc
= XCreateGC( display
, dc
->u
.x
.drawable
, 0, NULL
);
426 dc
->w
.flags
= DC_MEMORY
;
427 dc
->w
.bitsPerPixel
= 1;
428 dc
->w
.devCaps
= displayDevCaps
;
431 dc
->w
.hBitmap
= hbitmap
;
439 /***********************************************************************
442 BOOL
DeleteDC( HDC hdc
)
444 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
445 if (!dc
) return FALSE
;
447 dprintf_dc(stddeb
, "DeleteDC: %d\n", hdc
);
449 while (dc
->saveLevel
)
452 HDC hdcs
= dc
->header
.hNext
;
453 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) break;
454 dc
->header
.hNext
= dcs
->header
.hNext
;
459 if (!(dc
->w
.flags
& DC_SAVED
))
461 SelectObject( hdc
, STOCK_BLACK_PEN
);
462 SelectObject( hdc
, STOCK_WHITE_BRUSH
);
463 SelectObject( hdc
, STOCK_SYSTEM_FONT
);
464 XFreeGC( display
, dc
->u
.x
.gc
);
467 if (dc
->w
.flags
& DC_MEMORY
) DeleteObject( dc
->w
.hBitmap
);
469 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
470 if (dc
->w
.hVisRgn
) DeleteObject( dc
->w
.hVisRgn
);
471 if (dc
->w
.hGCClipRgn
) DeleteObject( dc
->w
.hGCClipRgn
);
473 return GDI_FreeObject( hdc
);
477 /***********************************************************************
478 * GetDeviceCaps (GDI.80)
480 int GetDeviceCaps( HDC hdc
, WORD cap
)
482 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
485 if (cap
> sizeof(DeviceCaps
)-sizeof(WORD
)) return 0;
487 dprintf_dc(stddeb
, "GetDeviceCaps(%d,%d): returning %d\n",
488 hdc
, cap
, *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
) );
489 return *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
);
493 /***********************************************************************
496 COLORREF
SetBkColor( HDC hdc
, COLORREF color
)
499 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
502 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
503 if (!dc
) return 0x80000000;
504 MF_MetaParam2(dc
, META_SETBKCOLOR
, HIWORD(color
), LOWORD(color
));
508 oldColor
= dc
->w
.backgroundColor
;
509 dc
->w
.backgroundColor
= color
;
510 dc
->w
.backgroundPixel
= COLOR_ToPhysical( dc
, color
);
515 /***********************************************************************
516 * SetTextColor (GDI.9)
518 COLORREF
SetTextColor( HDC hdc
, COLORREF color
)
521 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
524 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
525 if (!dc
) return 0x80000000;
526 MF_MetaParam2(dc
, META_SETTEXTCOLOR
, HIWORD(color
), LOWORD(color
));
530 oldColor
= dc
->w
.textColor
;
531 dc
->w
.textColor
= color
;
532 dc
->w
.textPixel
= COLOR_ToPhysical( dc
, color
);
537 /***********************************************************************
540 DWORD
GetDCOrg( HDC hdc
)
543 int x
, y
, w
, h
, border
, depth
;
545 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
547 if (dc
->w
.flags
& DC_MEMORY
) return 0;
548 XGetGeometry( display
, dc
->u
.x
.drawable
, &root
,
549 &x
, &y
, &w
, &h
, &border
, &depth
);
550 return MAKELONG( dc
->w
.DCOrgX
+ (WORD
)x
, dc
->w
.DCOrgY
+ (WORD
)y
);
554 /***********************************************************************
557 DWORD
SetDCOrg( HDC hdc
, short x
, short y
)
560 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
562 prevOrg
= dc
->w
.DCOrgX
| (dc
->w
.DCOrgY
<< 16);