2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
15 static DeviceCaps
* displayDevCaps
= NULL
;
17 extern const WIN_DC_INFO DCVAL_defaultValues
;
19 extern void CLIPPING_SetDeviceClipping( DC
* dc
); /* objects/clipping.c */
20 extern WORD
COLOR_ToPhysical( DC
*dc
, COLORREF color
);/* objects/color.c */
21 extern void COLOR_SetMapping( DC
*dc
, HANDLE
, WORD
); /* objects/color.c */
24 /* ROP code to GC function conversion */
25 const int DC_XROPfunction
[16] =
27 GXclear
, /* R2_BLACK */
28 GXnor
, /* R2_NOTMERGEPEN */
29 GXandInverted
, /* R2_MASKNOTPEN */
30 GXcopyInverted
, /* R2_NOTCOPYPEN */
31 GXandReverse
, /* R2_MASKPENNOT */
32 GXinvert
, /* R2_NOT */
33 GXxor
, /* R2_XORPEN */
34 GXnand
, /* R2_NOTMASKPEN */
35 GXand
, /* R2_MASKPEN */
36 GXequiv
, /* R2_NOTXORPEN */
38 GXorInverted
, /* R2_MERGENOTPEN */
39 GXcopy
, /* R2_COPYPEN */
40 GXorReverse
, /* R2_MERGEPENNOT */
41 GXor
, /* R2_MERGEPEN */
46 /***********************************************************************
49 * Fill the device caps structure.
51 void DC_FillDevCaps( DeviceCaps
* caps
)
53 caps
->version
= 0x300;
54 caps
->technology
= DT_RASDISPLAY
;
55 caps
->horzSize
= WidthMMOfScreen(screen
) * screenWidth
/ WidthOfScreen(screen
);
56 caps
->vertSize
= HeightMMOfScreen(screen
) * screenHeight
/ HeightOfScreen(screen
);
57 caps
->horzRes
= screenWidth
;
58 caps
->vertRes
= screenHeight
;
59 caps
->bitsPixel
= screenDepth
;
65 caps
->numColors
= 1 << caps
->bitsPixel
;
66 caps
->pdeviceSize
= 0;
67 caps
->curveCaps
= CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
|
68 CC_WIDE
| CC_STYLED
| CC_WIDESTYLED
|
69 CC_INTERIORS
| CC_ROUNDRECT
;
70 caps
->lineCaps
= LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
71 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
;
72 caps
->polygonalCaps
= PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
|
73 PC_SCANLINE
| PC_WIDE
| PC_STYLED
|
74 PC_WIDESTYLED
| PC_INTERIORS
;
75 caps
->textCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
76 TC_IA_ABLE
| TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
77 caps
->clipCaps
= CP_REGION
;
78 caps
->rasterCaps
= RC_BITBLT
| RC_BANDING
| RC_SCALING
| RC_BITMAP64
|
79 RC_DI_BITMAP
| RC_PALETTE
| RC_DIBTODEV
| RC_BIGFONT
|
80 RC_STRETCHBLT
| RC_STRETCHDIB
| RC_DEVBITS
;
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
= DefaultVisual(display
,DefaultScreen(display
))->map_entries
;
87 caps
->numReserved
= 0;
92 /***********************************************************************
95 * Setup device-specific DC values for a newly created DC.
97 static void DC_InitDC( HDC hdc
)
99 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
100 RealizeDefaultPalette( hdc
);
101 SetTextColor( hdc
, dc
->w
.textColor
);
102 SetBkColor( hdc
, dc
->w
.backgroundColor
);
103 SelectObject( hdc
, dc
->w
.hPen
);
104 SelectObject( hdc
, dc
->w
.hBrush
);
105 SelectObject( hdc
, dc
->w
.hFont
);
106 XSetGraphicsExposures( XT_display
, dc
->u
.x
.gc
, False
);
107 CLIPPING_SetDeviceClipping( dc
);
108 FONT_SelectObject(dc
, STOCK_SYSTEM_FIXED_FONT
, NULL
);
112 /***********************************************************************
115 * Setup dc->u.x.gc for drawing operations using current brush.
116 * Return 0 if brush is BS_NULL, 1 otherwise.
118 int DC_SetupGCForBrush( DC
* dc
)
121 unsigned long mask
= 0;
123 if (dc
->u
.x
.brush
.style
== BS_NULL
) return 0;
124 if (dc
->u
.x
.brush
.pixel
== -1)
126 /* Special case used for monochrome pattern brushes.
127 * We need to swap foreground and background because
128 * Windows does it the wrong way...
130 val
.foreground
= dc
->w
.backgroundPixel
;
131 val
.background
= dc
->w
.textPixel
;
135 val
.foreground
= dc
->u
.x
.brush
.pixel
;
136 val
.background
= dc
->w
.backgroundPixel
;
138 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
139 val
.fill_style
= dc
->u
.x
.brush
.fillStyle
;
140 if (val
.fill_style
== FillStippled
)
142 if (dc
->w
.backgroundMode
==OPAQUE
) val
.fill_style
= FillOpaqueStippled
;
143 val
.stipple
= dc
->u
.x
.brush
.pixmap
;
146 else if (val
.fill_style
== FillTiled
)
148 val
.tile
= dc
->u
.x
.brush
.pixmap
;
151 val
.ts_x_origin
= dc
->w
.DCOrgX
+ dc
->w
.brushOrgX
;
152 val
.ts_y_origin
= dc
->w
.DCOrgY
+ dc
->w
.brushOrgY
;
153 val
.fill_rule
= (dc
->w
.polyFillMode
==WINDING
) ? WindingRule
: EvenOddRule
;
154 XChangeGC( display
, dc
->u
.x
.gc
,
155 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
156 GCFillRule
| GCTileStipXOrigin
| GCTileStipYOrigin
| mask
,
162 /***********************************************************************
165 * Setup dc->u.x.gc for drawing operations using current pen.
166 * Return 0 if pen is PS_NULL, 1 otherwise.
168 int DC_SetupGCForPen( DC
* dc
)
172 if (dc
->u
.x
.pen
.style
== PS_NULL
) return 0;
173 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
174 val
.foreground
= dc
->u
.x
.pen
.pixel
;
175 val
.background
= dc
->w
.backgroundPixel
;
176 val
.fill_style
= FillSolid
;
177 if ((dc
->u
.x
.pen
.style
!=PS_SOLID
) && (dc
->u
.x
.pen
.style
!=PS_INSIDEFRAME
))
179 XSetDashes( display
, dc
->u
.x
.gc
, 0,
180 dc
->u
.x
.pen
.dashes
, dc
->u
.x
.pen
.dash_len
);
181 val
.line_style
= (dc
->w
.backgroundMode
== OPAQUE
) ?
182 LineDoubleDash
: LineOnOffDash
;
184 else val
.line_style
= LineSolid
;
185 val
.line_width
= dc
->u
.x
.pen
.width
;
186 val
.cap_style
= CapRound
;
187 val
.join_style
= JoinBevel
;
188 XChangeGC( display
, dc
->u
.x
.gc
,
189 GCFunction
| GCForeground
| GCBackground
| GCLineWidth
|
190 GCLineStyle
| GCCapStyle
| GCJoinStyle
| GCFillStyle
, &val
);
195 /***********************************************************************
198 * Setup dc->u.x.gc for text drawing operations.
199 * Return 0 if the font is null, 1 otherwise.
201 int DC_SetupGCForText( DC
* dc
)
205 if (!dc
->u
.x
.font
.fstruct
)
207 FONT_SelectObject(dc
, STOCK_SYSTEM_FIXED_FONT
, NULL
);
209 val
.function
= DC_XROPfunction
[dc
->w
.ROPmode
-1];
210 val
.foreground
= dc
->w
.textPixel
;
211 val
.background
= dc
->w
.backgroundPixel
;
212 val
.fill_style
= FillSolid
;
213 val
.font
= dc
->u
.x
.font
.fstruct
->fid
;
214 XChangeGC( display
, dc
->u
.x
.gc
,
215 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
221 /***********************************************************************
222 * GetDCState (GDI.179)
224 HDC
GetDCState( HDC hdc
)
229 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
230 if (!(handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
))) return 0;
231 newdc
= (DC
*) GDI_HEAP_ADDR( handle
);
234 printf( "GetDCState(%d): returning %d\n", hdc
, handle
);
237 memcpy( &newdc
->w
, &dc
->w
, sizeof(dc
->w
) );
238 newdc
->saveLevel
= 0;
239 newdc
->w
.flags
|= DC_SAVED
;
243 newdc
->w
.hClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
244 CombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
248 newdc
->w
.hVisRgn
= CreateRectRgn( 0, 0, 0, 0 );
249 CombineRgn( newdc
->w
.hVisRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
251 newdc
->w
.hGCClipRgn
= 0;
252 COLOR_SetMapping( newdc
, dc
->u
.x
.pal
.hMapping
, dc
->u
.x
.pal
.mappingSize
);
257 /***********************************************************************
258 * SetDCState (GDI.180)
260 void SetDCState( HDC hdc
, HDC hdcs
)
264 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return;
265 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) return;
266 if (!dcs
->w
.flags
& DC_SAVED
) return;
268 printf( "SetDCState: %d %d\n", hdc
, hdcs
);
270 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
271 if (dc
->w
.hVisRgn
) DeleteObject( dc
->w
.hVisRgn
);
272 if (dc
->w
.hGCClipRgn
) DeleteObject( dc
->w
.hGCClipRgn
);
274 memcpy( &dc
->w
, &dcs
->w
, sizeof(dc
->w
) );
275 memcpy( &dc
->u
.x
.pen
, &dcs
->u
.x
.pen
, sizeof(dc
->u
.x
.pen
) );
276 dc
->w
.hClipRgn
= dc
->w
.hVisRgn
= dc
->w
.hGCClipRgn
= 0;
277 dc
->w
.flags
&= ~DC_SAVED
;
279 SelectObject( hdc
, dcs
->w
.hBrush
);
280 SelectObject( hdc
, dcs
->w
.hFont
);
281 COLOR_SetMapping( dc
, dcs
->u
.x
.pal
.hMapping
, dcs
->u
.x
.pal
.mappingSize
);
283 SelectClipRgn( hdc
, dcs
->w
.hClipRgn
);
284 SelectVisRgn( hdc
, dcs
->w
.hVisRgn
);
288 /***********************************************************************
291 int SaveDC( HDC hdc
)
296 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
297 if (!(hdcs
= GetDCState( hdc
))) return 0;
298 dcs
= (DC
*) GDI_HEAP_ADDR( hdcs
);
299 dcs
->header
.hNext
= dc
->header
.hNext
;
300 dc
->header
.hNext
= hdcs
;
302 printf( "SaveDC(%d): returning %d\n", hdc
, dc
->saveLevel
+1 );
304 return ++dc
->saveLevel
;
308 /***********************************************************************
311 BOOL
RestoreDC( HDC hdc
, short level
)
316 printf( "RestoreDC: %d %d\n", hdc
, level
);
318 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
319 if (level
== -1) level
= dc
->saveLevel
;
320 if ((level
< 1) || (level
> (short)dc
->saveLevel
)) return FALSE
;
322 while ((short)dc
->saveLevel
>= level
)
324 HDC hdcs
= dc
->header
.hNext
;
325 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) return FALSE
;
326 dc
->header
.hNext
= dcs
->header
.hNext
;
327 if ((short)--dc
->saveLevel
< level
) SetDCState( hdc
, hdcs
);
334 /***********************************************************************
337 HDC
CreateDC( LPSTR driver
, LPSTR device
, LPSTR output
, LPSTR initData
)
342 handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
);
343 if (!handle
) return 0;
344 dc
= (DC
*) GDI_HEAP_ADDR( handle
);
347 printf( "CreateDC(%s %s %s): returning %d\n", driver
, device
, output
, handle
);
352 displayDevCaps
= (DeviceCaps
*) malloc( sizeof(DeviceCaps
) );
353 DC_FillDevCaps( displayDevCaps
);
357 memcpy( &dc
->w
, &DCVAL_defaultValues
, sizeof(DCVAL_defaultValues
) );
358 memset( &dc
->u
.x
, 0, sizeof(dc
->u
.x
) );
360 dc
->u
.x
.drawable
= rootWindow
;
361 dc
->u
.x
.gc
= XCreateGC( display
, dc
->u
.x
.drawable
, 0, NULL
);
363 dc
->w
.devCaps
= displayDevCaps
;
364 dc
->w
.bitsPerPixel
= displayDevCaps
->bitsPixel
;
365 dc
->w
.DCSizeX
= displayDevCaps
->horzRes
;
366 dc
->w
.DCSizeY
= displayDevCaps
->vertRes
;
374 /***********************************************************************
377 HDC
CreateIC( LPSTR driver
, LPSTR device
, LPSTR output
, LPSTR initData
)
379 /* Nothing special yet for ICs */
380 return CreateDC( driver
, device
, output
, initData
);
384 /***********************************************************************
385 * CreateCompatibleDC (GDI.52)
387 HDC
CreateCompatibleDC( HDC hdc
)
392 handle
= GDI_AllocObject( sizeof(DC
), DC_MAGIC
);
393 if (!handle
) return 0;
394 dc
= (DC
*) GDI_HEAP_ADDR( handle
);
397 printf( "CreateCompatibleDC(%d): returning %d\n", hdc
, handle
);
401 memcpy( &dc
->w
, &DCVAL_defaultValues
, sizeof(DCVAL_defaultValues
) );
402 memset( &dc
->u
.x
, 0, sizeof(dc
->u
.x
) );
404 dc
->u
.x
.drawable
= XCreatePixmap( display
, rootWindow
, 1, 1, 1 );
405 dc
->u
.x
.gc
= XCreateGC( display
, dc
->u
.x
.drawable
, 0, NULL
);
406 dc
->w
.flags
= DC_MEMORY
;
407 dc
->w
.bitsPerPixel
= 1;
408 dc
->w
.devCaps
= displayDevCaps
;
412 SelectObject( handle
, BITMAP_hbitmapMemDC
);
419 /***********************************************************************
422 BOOL
DeleteDC( HDC hdc
)
424 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
425 if (!dc
) return FALSE
;
428 printf( "DeleteDC: %d\n", hdc
);
431 while (dc
->saveLevel
)
434 HDC hdcs
= dc
->header
.hNext
;
435 if (!(dcs
= (DC
*) GDI_GetObjPtr( hdcs
, DC_MAGIC
))) break;
436 dc
->header
.hNext
= dcs
->header
.hNext
;
441 if (!(dc
->w
.flags
& DC_SAVED
))
443 SelectObject( hdc
, STOCK_BLACK_PEN
);
444 SelectObject( hdc
, STOCK_WHITE_BRUSH
);
445 SelectObject( hdc
, STOCK_SYSTEM_FONT
);
446 XFreeGC( display
, dc
->u
.x
.gc
);
449 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
450 if (dc
->w
.hVisRgn
) DeleteObject( dc
->w
.hVisRgn
);
451 if (dc
->w
.hGCClipRgn
) DeleteObject( dc
->w
.hGCClipRgn
);
453 return GDI_FreeObject( hdc
);
457 /***********************************************************************
458 * GetDeviceCaps (GDI.80)
460 int GetDeviceCaps( HDC hdc
, WORD cap
)
462 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
465 if (cap
> sizeof(DeviceCaps
)-sizeof(WORD
)) return 0;
468 printf( "GetDeviceCaps(%d,%d): returning %d\n",
469 hdc
, cap
, *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
) );
471 return *(WORD
*)(((char *)dc
->w
.devCaps
) + cap
);
475 /***********************************************************************
478 COLORREF
SetBkColor( HDC hdc
, COLORREF color
)
481 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
484 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
485 if (!dc
) return 0x80000000;
486 MF_MetaParam2(dc
, META_SETBKCOLOR
, HIWORD(color
), LOWORD(color
));
490 oldColor
= dc
->w
.backgroundColor
;
491 dc
->w
.backgroundColor
= color
;
492 dc
->w
.backgroundPixel
= COLOR_ToPhysical( dc
, color
);
497 /***********************************************************************
498 * SetTextColor (GDI.9)
500 COLORREF
SetTextColor( HDC hdc
, COLORREF color
)
503 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
506 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
507 if (!dc
) return 0x80000000;
508 MF_MetaParam2(dc
, META_SETTEXTCOLOR
, HIWORD(color
), LOWORD(color
));
512 oldColor
= dc
->w
.textColor
;
513 dc
->w
.textColor
= color
;
514 dc
->w
.textPixel
= COLOR_ToPhysical( dc
, color
);
519 /***********************************************************************
522 DWORD
SetDCOrg( HDC hdc
, short x
, short y
)
525 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
527 prevOrg
= dc
->w
.DCOrgX
| (dc
->w
.DCOrgY
<< 16);