Release 940201
[wine.git] / windows / dc.c
blob4224b3ad3357682a402092bd397ff4c3ecabfc37
1 /*
2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <stdlib.h>
11 #include "gdi.h"
13 extern HBITMAP BITMAP_hbitmapMemDC;
15 static DeviceCaps * displayDevCaps = NULL;
17 extern const WIN_DC_INFO DCVAL_defaultValues;
19 extern void CLIPPING_SetDeviceClipping( DC * dc ); /* in objects/clipping.c */
22 /* ROP code to GC function conversion */
23 const int DC_XROPfunction[16] =
25 GXclear, /* R2_BLACK */
26 GXnor, /* R2_NOTMERGEPEN */
27 GXandInverted, /* R2_MASKNOTPEN */
28 GXcopyInverted, /* R2_NOTCOPYPEN */
29 GXandReverse, /* R2_MASKPENNOT */
30 GXinvert, /* R2_NOT */
31 GXxor, /* R2_XORPEN */
32 GXnand, /* R2_NOTMASKPEN */
33 GXand, /* R2_MASKPEN */
34 GXequiv, /* R2_NOTXORPEN */
35 GXnoop, /* R2_NOP */
36 GXorInverted, /* R2_MERGENOTPEN */
37 GXcopy, /* R2_COPYPEN */
38 GXorReverse, /* R2_MERGEPENNOT */
39 GXor, /* R2_MERGEPEN */
40 GXset /* R2_WHITE */
44 /***********************************************************************
45 * DC_FillDevCaps
47 * Fill the device caps structure.
49 void DC_FillDevCaps( DeviceCaps * caps )
51 caps->version = 0x300;
52 caps->technology = DT_RASDISPLAY;
53 caps->horzSize = WidthMMOfScreen( XT_screen );
54 caps->vertSize = HeightMMOfScreen( XT_screen );
55 caps->horzRes = WidthOfScreen( XT_screen );
56 caps->vertRes = HeightOfScreen( XT_screen );
57 caps->bitsPixel = DefaultDepthOfScreen( XT_screen );
58 caps->planes = 1;
59 caps->numBrushes = 0;
60 caps->numPens = 0;
61 caps->numMarkers = 0;
62 caps->numFonts = 0;
63 caps->numColors = 1 << caps->bitsPixel;
64 caps->pdeviceSize = 0;
65 caps->curveCaps = CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES |
66 CC_WIDE | CC_STYLED | CC_WIDESTYLED |
67 CC_INTERIORS | CC_ROUNDRECT;
68 caps->lineCaps = LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
69 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS;
70 caps->polygonalCaps = PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON |
71 PC_SCANLINE | PC_WIDE | PC_STYLED |
72 PC_WIDESTYLED | PC_INTERIORS;
73 caps->textCaps = TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
74 TC_IA_ABLE | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
75 caps->clipCaps = CP_REGION;
76 caps->rasterCaps = RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 |
77 RC_DI_BITMAP | RC_PALETTE | RC_DIBTODEV | RC_BIGFONT|
78 RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS;
79 caps->aspectX = 36; /* ?? */
80 caps->aspectY = 36; /* ?? */
81 caps->aspectXY = 51;
82 caps->logPixelsX = (int)(caps->horzRes * 25.4 / caps->horzSize);
83 caps->logPixelsY = (int)(caps->vertRes * 25.4 / caps->vertSize);
84 caps->sizePalette = DefaultVisual( XT_display, DefaultScreen(XT_display) )->map_entries;
85 caps->numReserved = 0;
86 caps->colorRes = 0;
90 /***********************************************************************
91 * DC_SetDeviceInfo
93 * Set device-specific info from device-independent info.
95 void DC_SetDeviceInfo( HDC hdc, DC * dc )
97 SetTextColor( hdc, dc->w.textColor );
98 SetBkColor( hdc, dc->w.backgroundColor );
99 SetROP2( hdc, dc->w.ROPmode );
100 SelectObject( hdc, dc->w.hPen );
101 SelectObject( hdc, dc->w.hBrush );
102 SelectObject( hdc, dc->w.hFont );
104 XSetGraphicsExposures( XT_display, dc->u.x.gc, False );
105 CLIPPING_SetDeviceClipping( dc );
109 /***********************************************************************
110 * DC_SetupDCForBrush
112 * Setup dc->u.x.gc for drawing operations using current brush.
113 * Return 0 if brush is BS_NULL, 1 otherwise.
115 int DC_SetupGCForBrush( DC * dc )
117 if (dc->u.x.brush.style == BS_NULL) return 0;
118 if (dc->u.x.brush.pixel == -1)
120 /* Special case used for monochrome pattern brushes.
121 * We need to swap foreground and background because
122 * Windows does it the wrong way...
124 XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
125 XSetBackground( XT_display, dc->u.x.gc, dc->w.textPixel );
127 else
129 XSetForeground( XT_display, dc->u.x.gc, dc->u.x.brush.pixel );
130 XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
133 if (dc->u.x.brush.fillStyle != FillStippled)
134 XSetFillStyle( XT_display, dc->u.x.gc, dc->u.x.brush.fillStyle );
135 else
136 XSetFillStyle( XT_display, dc->u.x.gc,
137 (dc->w.backgroundMode == OPAQUE) ?
138 FillOpaqueStippled : FillStippled );
139 XSetTSOrigin( XT_display, dc->u.x.gc, dc->w.DCOrgX + dc->w.brushOrgX,
140 dc->w.DCOrgY + dc->w.brushOrgY );
141 XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
142 XSetFillRule( XT_display, dc->u.x.gc,
143 (dc->w.polyFillMode == WINDING) ? WindingRule : EvenOddRule );
144 return 1;
148 /***********************************************************************
149 * DC_SetupDCForPen
151 * Setup dc->u.x.gc for drawing operations using current pen.
152 * Return 0 if pen is PS_NULL, 1 otherwise.
154 int DC_SetupGCForPen( DC * dc )
156 if (dc->u.x.pen.style == PS_NULL) return 0;
157 XSetForeground( XT_display, dc->u.x.gc, dc->u.x.pen.pixel );
158 XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
159 XSetFillStyle( XT_display, dc->u.x.gc, FillSolid );
160 if ((dc->u.x.pen.style == PS_SOLID) ||
161 (dc->u.x.pen.style == PS_INSIDEFRAME))
163 XSetLineAttributes( XT_display, dc->u.x.gc, dc->u.x.pen.width,
164 LineSolid, CapRound, JoinBevel );
166 else
168 XSetLineAttributes( XT_display, dc->u.x.gc, dc->u.x.pen.width,
169 (dc->w.backgroundMode == OPAQUE) ? LineDoubleDash : LineOnOffDash,
170 CapRound, JoinBevel );
172 XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
173 return 1;
177 /***********************************************************************
178 * DC_SetupDCForText
180 * Setup dc->u.x.gc for text drawing operations.
181 * Return 0 if the font is null, 1 otherwise.
183 int DC_SetupGCForText( DC * dc )
185 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
186 XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
187 XSetFillStyle( XT_display, dc->u.x.gc, FillSolid );
188 XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
189 if (!dc->u.x.font.fstruct) return 0;
190 XSetFont( XT_display, dc->u.x.gc, dc->u.x.font.fstruct->fid );
191 return 1;
195 /***********************************************************************
196 * GetDCState (GDI.179)
198 HDC GetDCState( HDC hdc )
200 DC * newdc, * dc;
201 HANDLE handle;
203 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
204 if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return 0;
205 newdc = (DC *) GDI_HEAP_ADDR( handle );
207 #ifdef DEBUG_DC
208 printf( "GetDCState(%d): returning %d\n", hdc, handle );
209 #endif
211 memcpy( &newdc->w, &dc->w, sizeof(dc->w) );
212 newdc->saveLevel = 0;
213 newdc->w.flags |= DC_SAVED;
215 if (dc->w.hClipRgn)
217 newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
218 CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
220 if (dc->w.hVisRgn)
222 newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
223 CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );
225 newdc->w.hGCClipRgn = 0;
226 return handle;
230 /***********************************************************************
231 * SetDCState (GDI.180)
233 void SetDCState( HDC hdc, HDC hdcs )
235 DC * dc, * dcs;
237 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
238 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return;
239 if (!dcs->w.flags & DC_SAVED) return;
240 #ifdef DEBUG_DC
241 printf( "SetDCState: %d %d\n", hdc, hdcs );
242 #endif
243 if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
244 if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
245 if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
246 memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
247 dc->w.hClipRgn = dc->w.hVisRgn = dc->w.hGCClipRgn = 0;
248 dc->w.flags &= ~DC_SAVED;
249 DC_SetDeviceInfo( hdc, dc );
250 SelectClipRgn( hdc, dcs->w.hClipRgn );
251 SelectVisRgn( hdc, dcs->w.hVisRgn );
255 /***********************************************************************
256 * SaveDC (GDI.30)
258 int SaveDC( HDC hdc )
260 HDC hdcs;
261 DC * dc, * dcs;
263 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
264 if (!(hdcs = GetDCState( hdc ))) return 0;
265 dcs = (DC *) GDI_HEAP_ADDR( hdcs );
266 dcs->header.hNext = dc->header.hNext;
267 dc->header.hNext = hdcs;
268 #ifdef DEBUG_DC
269 printf( "SaveDC(%d): returning %d\n", hdc, dc->saveLevel+1 );
270 #endif
271 return ++dc->saveLevel;
275 /***********************************************************************
276 * RestoreDC (GDI.39)
278 BOOL RestoreDC( HDC hdc, short level )
280 DC * dc, * dcs;
282 #ifdef DEBUG_DC
283 printf( "RestoreDC: %d %d\n", hdc, level );
284 #endif
285 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
286 if (level == -1) level = dc->saveLevel;
287 if ((level < 1) || (level > dc->saveLevel)) return FALSE;
289 while (dc->saveLevel >= level)
291 HDC hdcs = dc->header.hNext;
292 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
293 dc->header.hNext = dcs->header.hNext;
294 if (--dc->saveLevel < level) SetDCState( hdc, hdcs );
295 DeleteDC( hdcs );
297 return TRUE;
301 /***********************************************************************
302 * CreateDC (GDI.53)
304 HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
306 DC * dc;
307 HANDLE handle;
309 handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
310 if (!handle) return 0;
311 dc = (DC *) GDI_HEAP_ADDR( handle );
313 #ifdef DEBUG_DC
314 printf( "CreateDC(%s %s %s): returning %d\n", driver, device, output, handle );
315 #endif
317 if (!displayDevCaps)
319 displayDevCaps = (DeviceCaps *) malloc( sizeof(DeviceCaps) );
320 DC_FillDevCaps( displayDevCaps );
323 dc->saveLevel = 0;
324 memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
325 memset( &dc->u.x, 0, sizeof(dc->u.x) );
327 dc->u.x.drawable = DefaultRootWindow( XT_display );
328 dc->u.x.gc = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
329 dc->w.flags = 0;
330 dc->w.devCaps = displayDevCaps;
331 dc->w.planes = displayDevCaps->planes;
332 dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
333 dc->w.DCSizeX = displayDevCaps->horzRes;
334 dc->w.DCSizeY = displayDevCaps->vertRes;
336 DC_SetDeviceInfo( handle, dc );
338 return handle;
342 /***********************************************************************
343 * CreateCompatibleDC (GDI.52)
345 HDC CreateCompatibleDC( HDC hdc )
347 DC * dc;
348 HANDLE handle;
350 handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
351 if (!handle) return 0;
352 dc = (DC *) GDI_HEAP_ADDR( handle );
354 #ifdef DEBUG_DC
355 printf( "CreateCompatibleDC(%d): returning %d\n", hdc, handle );
356 #endif
358 dc->saveLevel = 0;
359 memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
360 memset( &dc->u.x, 0, sizeof(dc->u.x) );
362 dc->u.x.drawable = XCreatePixmap( XT_display,
363 DefaultRootWindow( XT_display ),
364 1, 1, 1 );
365 dc->u.x.gc = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
366 dc->w.flags = DC_MEMORY;
367 dc->w.planes = 1;
368 dc->w.bitsPerPixel = 1;
369 dc->w.devCaps = displayDevCaps;
370 dc->w.DCSizeX = 1;
371 dc->w.DCSizeY = 1;
373 SelectObject( handle, BITMAP_hbitmapMemDC );
374 DC_SetDeviceInfo( handle, dc );
376 return handle;
380 /***********************************************************************
381 * DeleteDC (GDI.68)
383 BOOL DeleteDC( HDC hdc )
385 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
386 if (!dc) return FALSE;
388 #ifdef DEBUG_DC
389 printf( "DeleteDC: %d\n", hdc );
390 #endif
392 while (dc->saveLevel)
394 DC * dcs;
395 HDC hdcs = dc->header.hNext;
396 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
397 dc->header.hNext = dcs->header.hNext;
398 dc->saveLevel--;
399 DeleteDC( hdcs );
402 if (!(dc->w.flags & DC_SAVED))
404 SelectObject( hdc, STOCK_BLACK_PEN );
405 SelectObject( hdc, STOCK_WHITE_BRUSH );
406 SelectObject( hdc, STOCK_SYSTEM_FONT );
408 XFreeGC( XT_display, dc->u.x.gc );
409 if (dc->w.flags & DC_MEMORY) BITMAP_UnselectBitmap( dc );
412 if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
413 if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
414 if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
416 return GDI_FreeObject( hdc );
420 /***********************************************************************
421 * GetDeviceCaps (GDI.80)
423 int GetDeviceCaps( HDC hdc, WORD cap )
425 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
426 if (!dc) return 0;
428 if (cap > sizeof(DeviceCaps)-sizeof(WORD)) return 0;
430 #ifdef DEBUG_DC
431 printf( "GetDeviceCaps(%d,%d): returning %d\n",
432 hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
433 #endif
434 return *(WORD *)(((char *)dc->w.devCaps) + cap);
438 /***********************************************************************
439 * SetBkColor (GDI.1)
441 COLORREF SetBkColor( HDC hdc, COLORREF color )
443 COLORREF oldColor;
444 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
445 if (!dc) return 0x80000000;
447 oldColor = dc->w.backgroundColor;
448 dc->w.backgroundColor = color;
449 dc->w.backgroundPixel = GetNearestPaletteIndex( dc->w.hPalette, color );
450 XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
451 return oldColor;
455 /***********************************************************************
456 * SetTextColor (GDI.9)
458 COLORREF SetTextColor( HDC hdc, COLORREF color )
460 COLORREF oldColor;
461 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
462 if (!dc) return 0x80000000;
464 oldColor = dc->w.textColor;
465 dc->w.textColor = color;
466 dc->w.textPixel = GetNearestPaletteIndex( dc->w.hPalette, color );
467 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
468 return oldColor;
472 /***********************************************************************
473 * SetDCOrg (GDI.117)
475 DWORD SetDCOrg( HDC hdc, short x, short y )
477 DWORD prevOrg;
478 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
479 if (!dc) return 0;
480 prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
481 dc->w.DCOrgX = x;
482 dc->w.DCOrgY = y;
483 return prevOrg;