2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
6 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
18 static DeviceCaps
* displayDevCaps
= NULL
;
20 extern const WIN_DC_INFO DCVAL_defaultValues
;
21 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
;
64 caps
->numColors
= 1 << caps
->bitsPixel
;
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_PALETTE
| RC_DIBTODEV
| RC_BIGFONT
|
79 RC_STRETCHBLT
| RC_STRETCHDIB
| RC_DEVBITS
;
80 caps
->aspectX
= 36; /* ?? */
81 caps
->aspectY
= 36; /* ?? */
83 caps
->logPixelsX
= (int)(caps
->horzRes
* 25.4 / caps
->horzSize
);
84 caps
->logPixelsY
= (int)(caps
->vertRes
* 25.4 / caps
->vertSize
);
85 caps
->sizePalette
= DefaultVisual(display
,DefaultScreen(display
))->map_entries
;
86 caps
->numReserved
= 0;
91 /***********************************************************************
94 * Setup device-specific DC values for a newly created DC.
96 void DC_InitDC( HDC hdc
)
98 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
99 RealizeDefaultPalette( hdc
);
100 SetTextColor( hdc
, dc
->w
.textColor
);
101 SetBkColor( hdc
, dc
->w
.backgroundColor
);
102 SelectObject( hdc
, dc
->w
.hPen
);
103 SelectObject( hdc
, dc
->w
.hBrush
);
104 SelectObject( hdc
, dc
->w
.hFont
);
105 XSetGraphicsExposures( display
, dc
->u
.x
.gc
, False
);
106 XSetSubwindowMode( display
, dc
->u
.x
.gc
, IncludeInferiors
);
107 CLIPPING_UpdateGCRegion( dc
);
111 /***********************************************************************
114 * Setup dc->u.x.gc for drawing operations using current brush.
115 * Return 0 if brush is BS_NULL, 1 otherwise.
117 int DC_SetupGCForBrush( DC
* dc
)
120 unsigned long mask
= 0;
122 if (dc
->u
.x
.brush
.style
== BS_NULL
) return 0;
123 if (dc
->u
.x
.brush
.pixel
== -1)
125 /* Special case used for monochrome pattern brushes.
126 * We need to swap foreground and background because
127 * Windows does it the wrong way...
129 val
.foreground
= dc
->w
.backgroundPixel
;
130 val
.background
= dc
->w
.textPixel
;
134 val
.foreground
= dc
->u
.x
.brush
.pixel
;
135 val
.background
= dc
->w
.backgroundPixel
;
137 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
138 val
.fill_style
= dc
->u
.x
.brush
.fillStyle
;
139 if ((val
.fill_style
==FillStippled
) || (val
.fill_style
==FillOpaqueStippled
))
141 if (dc
->w
.backgroundMode
==OPAQUE
) val
.fill_style
= FillOpaqueStippled
;
142 val
.stipple
= dc
->u
.x
.brush
.pixmap
;
145 else if (val
.fill_style
== FillTiled
)
147 val
.tile
= dc
->u
.x
.brush
.pixmap
;
150 val
.ts_x_origin
= dc
->w
.DCOrgX
+ dc
->w
.brushOrgX
;
151 val
.ts_y_origin
= dc
->w
.DCOrgY
+ dc
->w
.brushOrgY
;
152 val
.fill_rule
= (dc
->w
.polyFillMode
==WINDING
) ? WindingRule
: EvenOddRule
;
153 XChangeGC( display
, dc
->u
.x
.gc
,
154 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
155 GCFillRule
| GCTileStipXOrigin
| GCTileStipYOrigin
| mask
,
161 /***********************************************************************
164 * Setup dc->u.x.gc for drawing operations using current pen.
165 * Return 0 if pen is PS_NULL, 1 otherwise.
167 int DC_SetupGCForPen( DC
* dc
)
171 if (dc
->u
.x
.pen
.style
== PS_NULL
) return 0;
172 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
173 val
.foreground
= dc
->u
.x
.pen
.pixel
;
174 val
.background
= dc
->w
.backgroundPixel
;
175 val
.fill_style
= FillSolid
;
176 if ((dc
->u
.x
.pen
.style
!=PS_SOLID
) && (dc
->u
.x
.pen
.style
!=PS_INSIDEFRAME
))
178 XSetDashes( display
, dc
->u
.x
.gc
, 0,
179 dc
->u
.x
.pen
.dashes
, dc
->u
.x
.pen
.dash_len
);
180 val
.line_style
= (dc
->w
.backgroundMode
== OPAQUE
) ?
181 LineDoubleDash
: LineOnOffDash
;
183 else val
.line_style
= LineSolid
;
184 val
.line_width
= dc
->u
.x
.pen
.width
;
185 val
.cap_style
= CapRound
;
186 val
.join_style
= JoinBevel
;
187 XChangeGC( display
, dc
->u
.x
.gc
,
188 GCFunction
| GCForeground
| GCBackground
| GCLineWidth
|
189 GCLineStyle
| GCCapStyle
| GCJoinStyle
| GCFillStyle
, &val
);
194 /***********************************************************************
197 * Setup dc->u.x.gc for text drawing operations.
198 * Return 0 if the font is null, 1 otherwise.
200 int DC_SetupGCForText( DC
* dc
)
204 if (!dc
->u
.x
.font
.fstruct
)
206 FONT_SelectObject(dc
, STOCK_SYSTEM_FONT
, NULL
);
208 val
.function
= GXcopy
; /* Text is always GXcopy */
209 val
.foreground
= dc
->w
.textPixel
;
210 val
.background
= dc
->w
.backgroundPixel
;
211 val
.fill_style
= FillSolid
;
212 val
.font
= dc
->u
.x
.font
.fstruct
->fid
;
213 XChangeGC( display
, dc
->u
.x
.gc
,
214 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
220 /***********************************************************************
221 * GetDCState (GDI.179)
223 HDC
GetDCState( HDC hdc
)
228 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
229 if (!(handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
))) return 0;
230 newdc
= (DC
*) GDI_HEAP_ADDR( handle
);
232 dprintf_dc(stddeb
, "GetDCState(%d): returning %d\n", hdc
, handle
);
234 memcpy( &newdc
->w
, &dc
->w
, sizeof(dc
->w
) );
235 memcpy( &newdc
->u
.x
.pen
, &dc
->u
.x
.pen
, sizeof(dc
->u
.x
.pen
) );
236 newdc
->saveLevel
= 0;
237 newdc
->w
.flags
|= DC_SAVED
;
239 newdc
->w
.hGCClipRgn
= 0;
240 newdc
->w
.hVisRgn
= CreateRectRgn( 0, 0, 0, 0 );
241 CombineRgn( newdc
->w
.hVisRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
244 newdc
->w
.hClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
245 CombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
247 COLOR_SetMapping( newdc
, dc
->u
.x
.pal
.hMapping
,
248 dc
->u
.x
.pal
.hRevMapping
, dc
->u
.x
.pal
.mappingSize
);
253 /***********************************************************************
254 * SetDCState (GDI.180)
256 void SetDCState( HDC hdc
, HDC hdcs
)
259 HRGN hVisRgn
, hClipRgn
, hGCClipRgn
;
261 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return;
262 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) return;
263 if (!dcs
->w
.flags
& DC_SAVED
) return;
264 dprintf_dc(stddeb
, "SetDCState: %d %d\n", hdc
, hdcs
);
266 /* Save the regions before overwriting everything */
267 hVisRgn
= dc
->w
.hVisRgn
;
268 hClipRgn
= dc
->w
.hClipRgn
;
269 hGCClipRgn
= dc
->w
.hGCClipRgn
;
270 memcpy( &dc
->w
, &dcs
->w
, sizeof(dc
->w
) );
271 memcpy( &dc
->u
.x
.pen
, &dcs
->u
.x
.pen
, sizeof(dc
->u
.x
.pen
) );
272 dc
->w
.flags
&= ~DC_SAVED
;
274 /* Restore the regions */
275 dc
->w
.hVisRgn
= hVisRgn
;
276 dc
->w
.hClipRgn
= hClipRgn
;
277 dc
->w
.hGCClipRgn
= hGCClipRgn
;
278 CombineRgn( dc
->w
.hVisRgn
, dcs
->w
.hVisRgn
, 0, RGN_COPY
);
279 SelectClipRgn( hdc
, dcs
->w
.hClipRgn
);
281 SelectObject( hdc
, dcs
->w
.hBrush
);
282 SelectObject( hdc
, dcs
->w
.hFont
);
283 COLOR_SetMapping( dc
, dcs
->u
.x
.pal
.hMapping
,
284 dcs
->u
.x
.pal
.hRevMapping
, dcs
->u
.x
.pal
.mappingSize
);
288 /***********************************************************************
291 int SaveDC( HDC hdc
)
296 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
299 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
301 MF_MetaParam0(dc
, META_SAVEDC
);
304 if (!(hdcs
= GetDCState( hdc
))) return 0;
305 dcs
= (DC
*) GDI_HEAP_ADDR( hdcs
);
306 dcs
->header
.hNext
= dc
->header
.hNext
;
307 dc
->header
.hNext
= hdcs
;
308 dprintf_dc(stddeb
, "SaveDC(%d): returning %d\n", hdc
, dc
->saveLevel
+1 );
309 return ++dc
->saveLevel
;
313 /***********************************************************************
316 BOOL
RestoreDC( HDC hdc
, short level
)
320 dprintf_dc(stddeb
, "RestoreDC: %d %d\n", hdc
, level
);
321 dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
324 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
325 if (!dc
) return FALSE
;
326 if (level
!= -1) return FALSE
;
327 MF_MetaParam1(dc
, META_RESTOREDC
, level
);
330 if (level
== -1) level
= dc
->saveLevel
;
331 if ((level
< 1) || (level
> (short)dc
->saveLevel
)) return FALSE
;
333 while ((short)dc
->saveLevel
>= level
)
335 HDC hdcs
= dc
->header
.hNext
;
336 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) return FALSE
;
337 dc
->header
.hNext
= dcs
->header
.hNext
;
338 if ((short)--dc
->saveLevel
< level
) SetDCState( hdc
, hdcs
);
345 /***********************************************************************
348 HDC
CreateDC( LPSTR driver
, LPSTR device
, LPSTR output
, LPSTR initData
)
353 handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
);
354 if (!handle
) return 0;
355 dc
= (DC
*) GDI_HEAP_ADDR( handle
);
357 dprintf_dc(stddeb
, "CreateDC(%s %s %s): returning %d\n",
358 driver
, device
, output
, handle
);
362 displayDevCaps
= (DeviceCaps
*) malloc( sizeof(DeviceCaps
) );
363 DC_FillDevCaps( displayDevCaps
);
367 memcpy( &dc
->w
, &DCVAL_defaultValues
, sizeof(DCVAL_defaultValues
) );
368 memset( &dc
->u
.x
, 0, sizeof(dc
->u
.x
) );
370 dc
->u
.x
.drawable
= rootWindow
;
371 dc
->u
.x
.gc
= XCreateGC( display
, dc
->u
.x
.drawable
, 0, NULL
);
373 dc
->w
.devCaps
= displayDevCaps
;
374 dc
->w
.bitsPerPixel
= displayDevCaps
->bitsPixel
;
375 dc
->w
.hVisRgn
= CreateRectRgn( 0, 0, displayDevCaps
->horzRes
,
376 displayDevCaps
->vertRes
);
379 GDI_HEAP_FREE( handle
);
389 /***********************************************************************
392 HDC
CreateIC( LPSTR driver
, LPSTR device
, LPSTR output
, LPSTR initData
)
394 /* Nothing special yet for ICs */
395 return CreateDC( driver
, device
, output
, initData
);
399 /***********************************************************************
400 * CreateCompatibleDC (GDI.52)
402 HDC
CreateCompatibleDC( HDC hdc
)
409 handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
);
410 if (!handle
) return 0;
411 dc
= (DC
*) GDI_HEAP_ADDR( handle
);
413 dprintf_dc(stddeb
, "CreateCompatibleDC(%d): returning %d\n", hdc
, handle
);
415 /* Create default bitmap */
416 if (!(hbitmap
= CreateBitmap( 1, 1, 1, 1, NULL
)))
418 GDI_HEAP_FREE( handle
);
421 bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
);
424 memcpy( &dc
->w
, &DCVAL_defaultValues
, sizeof(DCVAL_defaultValues
) );
425 memset( &dc
->u
.x
, 0, sizeof(dc
->u
.x
) );
427 dc
->u
.x
.drawable
= bmp
->pixmap
;
428 dc
->u
.x
.gc
= XCreateGC( display
, dc
->u
.x
.drawable
, 0, NULL
);
429 dc
->w
.flags
= DC_MEMORY
;
430 dc
->w
.bitsPerPixel
= 1;
431 dc
->w
.devCaps
= displayDevCaps
;
432 dc
->w
.hBitmap
= hbitmap
;
433 dc
->w
.hVisRgn
= CreateRectRgn( 0, 0, 1, 1 );
437 DeleteObject( hbitmap
);
438 GDI_HEAP_FREE( handle
);
448 /***********************************************************************
451 BOOL
DeleteDC( HDC hdc
)
453 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
454 if (!dc
) return FALSE
;
456 dprintf_dc(stddeb
, "DeleteDC: %d\n", hdc
);
458 while (dc
->saveLevel
)
461 HDC hdcs
= dc
->header
.hNext
;
462 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) break;
463 dc
->header
.hNext
= dcs
->header
.hNext
;
468 if (!(dc
->w
.flags
& DC_SAVED
))
470 SelectObject( hdc
, STOCK_BLACK_PEN
);
471 SelectObject( hdc
, STOCK_WHITE_BRUSH
);
472 SelectObject( hdc
, STOCK_SYSTEM_FONT
);
473 XFreeGC( display
, dc
->u
.x
.gc
);
476 if (dc
->w
.flags
& DC_MEMORY
) DeleteObject( dc
->w
.hBitmap
);
478 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
479 if (dc
->w
.hVisRgn
) DeleteObject( dc
->w
.hVisRgn
);
480 if (dc
->w
.hGCClipRgn
) DeleteObject( dc
->w
.hGCClipRgn
);
482 return GDI_FreeObject( hdc
);
486 /***********************************************************************
487 * GetDeviceCaps (GDI.80)
489 int GetDeviceCaps( HDC hdc
, WORD cap
)
491 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
494 if (cap
> sizeof(DeviceCaps
)-sizeof(WORD
)) return 0;
496 dprintf_dc(stddeb
, "GetDeviceCaps(%d,%d): returning %d\n",
497 hdc
, cap
, *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
) );
498 return *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
);
502 /***********************************************************************
505 COLORREF
SetBkColor( HDC hdc
, COLORREF color
)
508 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
511 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
512 if (!dc
) return 0x80000000;
513 MF_MetaParam2(dc
, META_SETBKCOLOR
, HIWORD(color
), LOWORD(color
));
517 oldColor
= dc
->w
.backgroundColor
;
518 dc
->w
.backgroundColor
= color
;
519 dc
->w
.backgroundPixel
= COLOR_ToPhysical( dc
, color
);
524 /***********************************************************************
525 * SetTextColor (GDI.9)
527 COLORREF
SetTextColor( HDC hdc
, COLORREF color
)
530 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
533 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
534 if (!dc
) return 0x80000000;
535 MF_MetaParam2(dc
, META_SETTEXTCOLOR
, HIWORD(color
), LOWORD(color
));
539 oldColor
= dc
->w
.textColor
;
540 dc
->w
.textColor
= color
;
541 dc
->w
.textPixel
= COLOR_ToPhysical( dc
, color
);
546 /***********************************************************************
549 DWORD
GetDCOrg( HDC hdc
)
552 int x
, y
, w
, h
, border
, depth
;
554 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
556 if (dc
->w
.flags
& DC_MEMORY
) return 0;
557 XGetGeometry( display
, dc
->u
.x
.drawable
, &root
,
558 &x
, &y
, &w
, &h
, &border
, &depth
);
559 return MAKELONG( dc
->w
.DCOrgX
+ (WORD
)x
, dc
->w
.DCOrgY
+ (WORD
)y
);
563 /***********************************************************************
566 DWORD
SetDCOrg( HDC hdc
, short x
, short y
)
569 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
571 prevOrg
= dc
->w
.DCOrgX
| (dc
->w
.DCOrgY
<< 16);