Release 940405
[wine.git] / windows / dc.c
blob58dd531dbb5801ea43543e53285f354eeaafb26c
1 /*
2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <stdlib.h>
10 #include <string.h>
11 #include "gdi.h"
12 #include "bitmap.h"
14 static DeviceCaps * displayDevCaps = NULL;
16 extern const WIN_DC_INFO DCVAL_defaultValues;
18 extern void CLIPPING_SetDeviceClipping( DC * dc ); /* objects/clipping.c */
19 extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );/* objects/color.c */
20 extern void COLOR_SetMapping( DC *dc, HANDLE, WORD ); /* objects/color.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 */
36 GXnoop, /* R2_NOP */
37 GXorInverted, /* R2_MERGENOTPEN */
38 GXcopy, /* R2_COPYPEN */
39 GXorReverse, /* R2_MERGEPENNOT */
40 GXor, /* R2_MERGEPEN */
41 GXset /* R2_WHITE */
45 /***********************************************************************
46 * DC_FillDevCaps
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;
59 caps->planes = 1;
60 caps->numBrushes = 0;
61 caps->numPens = 0;
62 caps->numMarkers = 0;
63 caps->numFonts = 0;
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; /* ?? */
82 caps->aspectXY = 51;
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;
87 caps->colorRes = 0;
91 /***********************************************************************
92 * DC_InitDC
94 * Setup device-specific DC values for a newly created DC.
96 static 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( XT_display, dc->u.x.gc, False );
106 CLIPPING_SetDeviceClipping( dc );
110 /***********************************************************************
111 * DC_SetupDCForBrush
113 * Setup dc->u.x.gc for drawing operations using current brush.
114 * Return 0 if brush is BS_NULL, 1 otherwise.
116 int DC_SetupGCForBrush( DC * dc )
118 XGCValues val;
119 unsigned long mask = 0;
121 if (dc->u.x.brush.style == BS_NULL) return 0;
122 if (dc->u.x.brush.pixel == -1)
124 /* Special case used for monochrome pattern brushes.
125 * We need to swap foreground and background because
126 * Windows does it the wrong way...
128 val.foreground = dc->w.backgroundPixel;
129 val.background = dc->w.textPixel;
131 else
133 val.foreground = dc->u.x.brush.pixel;
134 val.background = dc->w.backgroundPixel;
136 val.function = DC_XROPfunction[dc->w.ROPmode-1];
137 val.fill_style = dc->u.x.brush.fillStyle;
138 if (val.fill_style == FillStippled)
140 if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
141 val.stipple = dc->u.x.brush.pixmap;
142 mask = GCStipple;
144 else if (val.fill_style == FillTiled)
146 val.tile = dc->u.x.brush.pixmap;
147 mask = GCTile;
149 val.ts_x_origin = dc->w.DCOrgX + dc->w.brushOrgX;
150 val.ts_y_origin = dc->w.DCOrgY + dc->w.brushOrgY;
151 val.fill_rule = (dc->w.polyFillMode==WINDING) ? WindingRule : EvenOddRule;
152 XChangeGC( display, dc->u.x.gc,
153 GCFunction | GCForeground | GCBackground | GCFillStyle |
154 GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
155 &val );
156 return 1;
160 /***********************************************************************
161 * DC_SetupDCForPen
163 * Setup dc->u.x.gc for drawing operations using current pen.
164 * Return 0 if pen is PS_NULL, 1 otherwise.
166 int DC_SetupGCForPen( DC * dc )
168 XGCValues val;
170 if (dc->u.x.pen.style == PS_NULL) return 0;
171 val.function = DC_XROPfunction[dc->w.ROPmode-1];
172 val.foreground = dc->u.x.pen.pixel;
173 val.background = dc->w.backgroundPixel;
174 val.fill_style = FillSolid;
175 if ((dc->u.x.pen.style!=PS_SOLID) && (dc->u.x.pen.style!=PS_INSIDEFRAME))
177 XSetDashes( display, dc->u.x.gc, 0,
178 dc->u.x.pen.dashes, dc->u.x.pen.dash_len );
179 val.line_style = (dc->w.backgroundMode == OPAQUE) ?
180 LineDoubleDash : LineOnOffDash;
182 else val.line_style = LineSolid;
183 val.line_width = dc->u.x.pen.width;
184 val.cap_style = CapRound;
185 val.join_style = JoinBevel;
186 XChangeGC( display, dc->u.x.gc,
187 GCFunction | GCForeground | GCBackground | GCLineWidth |
188 GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
189 return 1;
193 /***********************************************************************
194 * DC_SetupDCForText
196 * Setup dc->u.x.gc for text drawing operations.
197 * Return 0 if the font is null, 1 otherwise.
199 int DC_SetupGCForText( DC * dc )
201 XGCValues val;
203 if (!dc->u.x.font.fstruct)
205 FONT_SelectObject(dc, STOCK_SYSTEM_FIXED_FONT, NULL);
207 val.function = DC_XROPfunction[dc->w.ROPmode-1];
208 val.foreground = dc->w.textPixel;
209 val.background = dc->w.backgroundPixel;
210 val.fill_style = FillSolid;
211 val.font = dc->u.x.font.fstruct->fid;
212 XChangeGC( display, dc->u.x.gc,
213 GCFunction | GCForeground | GCBackground | GCFillStyle |
214 GCFont, &val );
215 return 1;
219 /***********************************************************************
220 * GetDCState (GDI.179)
222 HDC GetDCState( HDC hdc )
224 DC * newdc, * dc;
225 HANDLE handle;
227 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
228 if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return 0;
229 newdc = (DC *) GDI_HEAP_ADDR( handle );
231 #ifdef DEBUG_DC
232 printf( "GetDCState(%d): returning %d\n", hdc, handle );
233 #endif
235 memcpy( &newdc->w, &dc->w, sizeof(dc->w) );
236 newdc->saveLevel = 0;
237 newdc->w.flags |= DC_SAVED;
239 if (dc->w.hClipRgn)
241 newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
242 CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
244 if (dc->w.hVisRgn)
246 newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
247 CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );
249 newdc->w.hGCClipRgn = 0;
250 COLOR_SetMapping( newdc, dc->u.x.pal.hMapping, dc->u.x.pal.mappingSize );
251 return handle;
255 /***********************************************************************
256 * SetDCState (GDI.180)
258 void SetDCState( HDC hdc, HDC hdcs )
260 DC * dc, * dcs;
262 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
263 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return;
264 if (!dcs->w.flags & DC_SAVED) return;
265 #ifdef DEBUG_DC
266 printf( "SetDCState: %d %d\n", hdc, hdcs );
267 #endif
268 if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
269 if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
270 if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
272 memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
273 memcpy( &dc->u.x.pen, &dcs->u.x.pen, sizeof(dc->u.x.pen) );
274 dc->w.hClipRgn = dc->w.hVisRgn = dc->w.hGCClipRgn = 0;
275 dc->w.flags &= ~DC_SAVED;
277 SelectObject( hdc, dcs->w.hBrush );
278 SelectObject( hdc, dcs->w.hFont );
279 COLOR_SetMapping( dc, dcs->u.x.pal.hMapping, dcs->u.x.pal.mappingSize );
281 SelectClipRgn( hdc, dcs->w.hClipRgn );
282 SelectVisRgn( hdc, dcs->w.hVisRgn );
286 /***********************************************************************
287 * SaveDC (GDI.30)
289 int SaveDC( HDC hdc )
291 HDC hdcs;
292 DC * dc, * dcs;
294 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
295 if (!(hdcs = GetDCState( hdc ))) return 0;
296 dcs = (DC *) GDI_HEAP_ADDR( hdcs );
297 dcs->header.hNext = dc->header.hNext;
298 dc->header.hNext = hdcs;
299 #ifdef DEBUG_DC
300 printf( "SaveDC(%d): returning %d\n", hdc, dc->saveLevel+1 );
301 #endif
302 return ++dc->saveLevel;
306 /***********************************************************************
307 * RestoreDC (GDI.39)
309 BOOL RestoreDC( HDC hdc, short level )
311 DC * dc, * dcs;
313 #ifdef DEBUG_DC
314 printf( "RestoreDC: %d %d\n", hdc, level );
315 #endif
316 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
317 if (level == -1) level = dc->saveLevel;
318 if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
320 while ((short)dc->saveLevel >= level)
322 HDC hdcs = dc->header.hNext;
323 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
324 dc->header.hNext = dcs->header.hNext;
325 if ((short)--dc->saveLevel < level) SetDCState( hdc, hdcs );
326 DeleteDC( hdcs );
328 return TRUE;
332 /***********************************************************************
333 * CreateDC (GDI.53)
335 HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
337 DC * dc;
338 HANDLE handle;
340 handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
341 if (!handle) return 0;
342 dc = (DC *) GDI_HEAP_ADDR( handle );
344 #ifdef DEBUG_DC
345 printf( "CreateDC(%s %s %s): returning %d\n", driver, device, output, handle );
346 #endif
348 if (!displayDevCaps)
350 displayDevCaps = (DeviceCaps *) malloc( sizeof(DeviceCaps) );
351 DC_FillDevCaps( displayDevCaps );
354 dc->saveLevel = 0;
355 memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
356 memset( &dc->u.x, 0, sizeof(dc->u.x) );
358 dc->u.x.drawable = rootWindow;
359 dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
360 dc->w.flags = 0;
361 dc->w.devCaps = displayDevCaps;
362 dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
363 dc->w.DCSizeX = displayDevCaps->horzRes;
364 dc->w.DCSizeY = displayDevCaps->vertRes;
366 DC_InitDC( handle );
368 return handle;
372 /***********************************************************************
373 * CreateIC (GDI.153)
375 HDC CreateIC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
377 /* Nothing special yet for ICs */
378 return CreateDC( driver, device, output, initData );
382 /***********************************************************************
383 * CreateCompatibleDC (GDI.52)
385 HDC CreateCompatibleDC( HDC hdc )
387 DC * dc;
388 HANDLE handle;
390 handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
391 if (!handle) return 0;
392 dc = (DC *) GDI_HEAP_ADDR( handle );
394 #ifdef DEBUG_DC
395 printf( "CreateCompatibleDC(%d): returning %d\n", hdc, handle );
396 #endif
398 dc->saveLevel = 0;
399 memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
400 memset( &dc->u.x, 0, sizeof(dc->u.x) );
402 dc->u.x.drawable = XCreatePixmap( display, rootWindow, 1, 1, 1 );
403 dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
404 dc->w.flags = DC_MEMORY;
405 dc->w.bitsPerPixel = 1;
406 dc->w.devCaps = displayDevCaps;
407 dc->w.DCSizeX = 1;
408 dc->w.DCSizeY = 1;
410 SelectObject( handle, BITMAP_hbitmapMemDC );
411 DC_InitDC( handle );
413 return handle;
417 /***********************************************************************
418 * DeleteDC (GDI.68)
420 BOOL DeleteDC( HDC hdc )
422 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
423 if (!dc) return FALSE;
425 #ifdef DEBUG_DC
426 printf( "DeleteDC: %d\n", hdc );
427 #endif
429 while (dc->saveLevel)
431 DC * dcs;
432 HDC hdcs = dc->header.hNext;
433 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
434 dc->header.hNext = dcs->header.hNext;
435 dc->saveLevel--;
436 DeleteDC( hdcs );
439 if (!(dc->w.flags & DC_SAVED))
441 SelectObject( hdc, STOCK_BLACK_PEN );
442 SelectObject( hdc, STOCK_WHITE_BRUSH );
443 SelectObject( hdc, STOCK_SYSTEM_FONT );
444 XFreeGC( display, dc->u.x.gc );
447 if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
448 if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
449 if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
451 return GDI_FreeObject( hdc );
455 /***********************************************************************
456 * GetDeviceCaps (GDI.80)
458 int GetDeviceCaps( HDC hdc, WORD cap )
460 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
461 if (!dc) return 0;
463 if (cap > sizeof(DeviceCaps)-sizeof(WORD)) return 0;
465 #ifdef DEBUG_DC
466 printf( "GetDeviceCaps(%d,%d): returning %d\n",
467 hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
468 #endif
469 return *(WORD *)(((char *)dc->w.devCaps) + cap);
473 /***********************************************************************
474 * SetBkColor (GDI.1)
476 COLORREF SetBkColor( HDC hdc, COLORREF color )
478 COLORREF oldColor;
479 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
480 if (!dc) return 0x80000000;
482 oldColor = dc->w.backgroundColor;
483 dc->w.backgroundColor = color;
484 dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
485 return oldColor;
489 /***********************************************************************
490 * SetTextColor (GDI.9)
492 COLORREF SetTextColor( HDC hdc, COLORREF color )
494 COLORREF oldColor;
495 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
496 if (!dc) return 0x80000000;
498 oldColor = dc->w.textColor;
499 dc->w.textColor = color;
500 dc->w.textPixel = COLOR_ToPhysical( dc, color );
501 return oldColor;
505 /***********************************************************************
506 * SetDCOrg (GDI.117)
508 DWORD SetDCOrg( HDC hdc, short x, short y )
510 DWORD prevOrg;
511 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
512 if (!dc) return 0;
513 prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
514 dc->w.DCOrgX = x;
515 dc->w.DCOrgY = y;
516 return prevOrg;