Release 941017
[wine/gsoc-2012-control.git] / objects / dc.c
blob5365efb62db748f422904d2075de04af76e5addf
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"
13 #include "metafile.h"
14 #include "stddebug.h"
15 /* #define DEBUG_DC /* */
16 /* #undef DEBUG_DC /* */
17 #include "debug.h"
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 */
42 GXnoop, /* R2_NOP */
43 GXorInverted, /* R2_MERGENOTPEN */
44 GXcopy, /* R2_COPYPEN */
45 GXorReverse, /* R2_MERGEPENNOT */
46 GXor, /* R2_MERGEPEN */
47 GXset /* R2_WHITE */
51 /***********************************************************************
52 * DC_FillDevCaps
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;
65 caps->planes = 1;
66 caps->numBrushes = 0;
67 caps->numPens = 0;
68 caps->numMarkers = 0;
69 caps->numFonts = 0;
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; /* ?? */
88 caps->aspectXY = 51;
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;
93 caps->colorRes = 0;
97 /***********************************************************************
98 * DC_InitDC
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 /***********************************************************************
118 * DC_SetupDCForBrush
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 )
125 XGCValues val;
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;
138 else
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;
149 mask = GCStipple;
151 else if (val.fill_style == FillTiled)
153 val.tile = dc->u.x.brush.pixmap;
154 mask = GCTile;
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,
162 &val );
163 return 1;
167 /***********************************************************************
168 * DC_SetupDCForPen
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 )
175 XGCValues val;
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 );
196 return 1;
200 /***********************************************************************
201 * DC_SetupGCForText
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 )
208 XGCValues val;
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 |
221 GCFont, &val );
222 return 1;
226 /***********************************************************************
227 * GetDCState (GDI.179)
229 HDC GetDCState( HDC hdc )
231 DC * newdc, * dc;
232 HANDLE handle;
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;
245 if (dc->w.hClipRgn)
247 newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
248 CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
250 if (dc->w.hVisRgn)
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 );
257 return handle;
261 /***********************************************************************
262 * SetDCState (GDI.180)
264 void SetDCState( HDC hdc, HDC hdcs )
266 DC * dc, * dcs;
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 /***********************************************************************
291 * SaveDC (GDI.30)
293 int SaveDC( HDC hdc )
295 HDC hdcs;
296 DC * dc, * dcs;
298 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
299 if (!dc)
301 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
302 if (!dc) return 0;
303 MF_MetaParam0(dc, META_SAVEDC);
304 return 1; /* ?? */
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 /***********************************************************************
316 * RestoreDC (GDI.39)
318 BOOL RestoreDC( HDC hdc, short level )
320 DC * dc, * dcs;
322 dprintf_dc(stddeb, "RestoreDC: %d %d\n", hdc, level );
323 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
324 if (!dc)
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);
330 return TRUE;
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 );
341 DeleteDC( hdcs );
343 return TRUE;
347 /***********************************************************************
348 * CreateDC (GDI.53)
350 HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
352 DC * dc;
353 HANDLE handle;
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 );
362 if (!displayDevCaps)
364 displayDevCaps = (DeviceCaps *) malloc( sizeof(DeviceCaps) );
365 DC_FillDevCaps( displayDevCaps );
368 dc->saveLevel = 0;
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 );
374 dc->w.flags = 0;
375 dc->w.devCaps = displayDevCaps;
376 dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
377 dc->w.DCSizeX = displayDevCaps->horzRes;
378 dc->w.DCSizeY = displayDevCaps->vertRes;
380 DC_InitDC( handle );
382 return handle;
386 /***********************************************************************
387 * CreateIC (GDI.153)
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 )
401 DC * dc;
402 HANDLE handle;
403 HBITMAP hbitmap;
404 BITMAPOBJ *bmp;
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 );
416 return 0;
418 bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
420 dc->saveLevel = 0;
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;
429 dc->w.DCSizeX = 1;
430 dc->w.DCSizeY = 1;
431 dc->w.hBitmap = hbitmap;
433 DC_InitDC( handle );
435 return handle;
439 /***********************************************************************
440 * DeleteDC (GDI.68)
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)
451 DC * dcs;
452 HDC hdcs = dc->header.hNext;
453 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
454 dc->header.hNext = dcs->header.hNext;
455 dc->saveLevel--;
456 DeleteDC( hdcs );
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 );
483 if (!dc) return 0;
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 /***********************************************************************
494 * SetBkColor (GDI.1)
496 COLORREF SetBkColor( HDC hdc, COLORREF color )
498 COLORREF oldColor;
499 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
500 if (!dc)
502 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
503 if (!dc) return 0x80000000;
504 MF_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
505 return 0; /* ?? */
508 oldColor = dc->w.backgroundColor;
509 dc->w.backgroundColor = color;
510 dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
511 return oldColor;
515 /***********************************************************************
516 * SetTextColor (GDI.9)
518 COLORREF SetTextColor( HDC hdc, COLORREF color )
520 COLORREF oldColor;
521 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
522 if (!dc)
524 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
525 if (!dc) return 0x80000000;
526 MF_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color));
527 return 0; /* ?? */
530 oldColor = dc->w.textColor;
531 dc->w.textColor = color;
532 dc->w.textPixel = COLOR_ToPhysical( dc, color );
533 return oldColor;
537 /***********************************************************************
538 * GetDCOrg (GDI.79)
540 DWORD GetDCOrg( HDC hdc )
542 Window root;
543 int x, y, w, h, border, depth;
545 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
546 if (!dc) return 0;
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 /***********************************************************************
555 * SetDCOrg (GDI.117)
557 DWORD SetDCOrg( HDC hdc, short x, short y )
559 DWORD prevOrg;
560 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
561 if (!dc) return 0;
562 prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
563 dc->w.DCOrgX = x;
564 dc->w.DCOrgY = y;
565 return prevOrg;