Release 941210
[wine] / objects / dc.c
1 /*
2  * GDI Device Context functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
7 */
8 #include <stdlib.h>
9 #include <string.h>
10 #include "gdi.h"
11 #include "bitmap.h"
12 #include "metafile.h"
13 #include "stddebug.h"
14 #include "color.h"
15 #include "debug.h"
16 #include "font.h"
17
18 static DeviceCaps * displayDevCaps = NULL;
19
20 extern const WIN_DC_INFO DCVAL_defaultValues;
21 extern void CLIPPING_UpdateGCRegion( DC * dc );     /* objects/clipping.c */
22
23   /* ROP code to GC function conversion */
24 const int DC_XROPfunction[16] =
25 {
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 */
42 };
43
44
45 /***********************************************************************
46  *           DC_FillDevCaps
47  *
48  * Fill the device caps structure.
49  */
50 void DC_FillDevCaps( DeviceCaps * caps )
51 {
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;
88 }
89
90
91 /***********************************************************************
92  *           DC_InitDC
93  *
94  * Setup device-specific DC values for a newly created DC.
95  */
96 void DC_InitDC( HDC hdc )
97 {
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 );
108 }
109
110
111 /***********************************************************************
112  *           DC_SetupDCForBrush
113  *
114  * Setup dc->u.x.gc for drawing operations using current brush.
115  * Return 0 if brush is BS_NULL, 1 otherwise.
116  */
117 int DC_SetupGCForBrush( DC * dc )
118 {
119     XGCValues val;
120     unsigned long mask = 0;
121
122     if (dc->u.x.brush.style == BS_NULL) return 0;
123     if (dc->u.x.brush.pixel == -1)
124     {
125         /* Special case used for monochrome pattern brushes.
126          * We need to swap foreground and background because
127          * Windows does it the wrong way...
128          */
129         val.foreground = dc->w.backgroundPixel;
130         val.background = dc->w.textPixel;
131     }
132     else
133     {
134         val.foreground = dc->u.x.brush.pixel;
135         val.background = dc->w.backgroundPixel;
136     }
137     val.function = DC_XROPfunction[dc->w.ROPmode-1];
138     val.fill_style = dc->u.x.brush.fillStyle;
139     if (val.fill_style == FillStippled)
140     {
141         if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
142         val.stipple = dc->u.x.brush.pixmap;
143         mask = GCStipple;
144     }
145     else if (val.fill_style == FillTiled)
146     {
147         val.tile = dc->u.x.brush.pixmap;
148         mask = GCTile;
149     }
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,
156                &val );
157     return 1;
158 }
159
160
161 /***********************************************************************
162  *           DC_SetupDCForPen
163  *
164  * Setup dc->u.x.gc for drawing operations using current pen.
165  * Return 0 if pen is PS_NULL, 1 otherwise.
166  */
167 int DC_SetupGCForPen( DC * dc )
168 {
169     XGCValues val;
170
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))
177     {
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;
182     }
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 );
190     return 1;    
191 }
192
193
194 /***********************************************************************
195  *           DC_SetupGCForText
196  *
197  * Setup dc->u.x.gc for text drawing operations.
198  * Return 0 if the font is null, 1 otherwise.
199  */
200 int DC_SetupGCForText( DC * dc )
201 {
202     XGCValues val;
203
204     if (!dc->u.x.font.fstruct)
205     {
206         FONT_SelectObject(dc, STOCK_SYSTEM_FONT, NULL);
207     }
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 |
215                GCFont, &val );
216     return 1;
217 }
218
219
220 /***********************************************************************
221  *           GetDCState    (GDI.179)
222  */
223 HDC GetDCState( HDC hdc )
224 {
225     DC * newdc, * dc;
226     HANDLE handle;
227     
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 );
231
232     dprintf_dc(stddeb, "GetDCState(%d): returning %d\n", hdc, handle );
233
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;
238
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 ); 
242     if (dc->w.hClipRgn)
243     {
244         newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
245         CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
246     }
247     COLOR_SetMapping( newdc, dc->u.x.pal.hMapping, dc->u.x.pal.mappingSize );
248     return handle;
249 }
250
251
252 /***********************************************************************
253  *           SetDCState    (GDI.180)
254  */
255 void SetDCState( HDC hdc, HDC hdcs )
256 {
257     DC * dc, * dcs;
258     HRGN hVisRgn, hClipRgn, hGCClipRgn;
259
260     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
261     if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return;
262     if (!dcs->w.flags & DC_SAVED) return;
263     dprintf_dc(stddeb, "SetDCState: %d %d\n", hdc, hdcs );
264
265       /* Save the regions before overwriting everything */
266     hVisRgn    = dc->w.hVisRgn;
267     hClipRgn   = dc->w.hClipRgn;
268     hGCClipRgn = dc->w.hGCClipRgn;
269     memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
270     memcpy( &dc->u.x.pen, &dcs->u.x.pen, sizeof(dc->u.x.pen) );
271     dc->w.flags &= ~DC_SAVED;
272
273       /* Restore the regions */
274     dc->w.hVisRgn    = hVisRgn;
275     dc->w.hClipRgn   = hClipRgn;
276     dc->w.hGCClipRgn = hGCClipRgn;
277     CombineRgn( dc->w.hVisRgn, dcs->w.hVisRgn, 0, RGN_COPY );
278     SelectClipRgn( hdc, dcs->w.hClipRgn );
279
280     SelectObject( hdc, dcs->w.hBrush );
281     SelectObject( hdc, dcs->w.hFont );
282     COLOR_SetMapping( dc, dcs->u.x.pal.hMapping, dcs->u.x.pal.mappingSize );
283 }
284
285
286 /***********************************************************************
287  *           SaveDC    (GDI.30)
288  */
289 int SaveDC( HDC hdc )
290 {
291     HDC hdcs;
292     DC * dc, * dcs;
293
294     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
295     if (!dc) 
296     {
297         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
298         if (!dc) return 0;
299         MF_MetaParam0(dc, META_SAVEDC);
300         return 1;  /* ?? */
301     }
302     if (!(hdcs = GetDCState( hdc ))) return 0;
303     dcs = (DC *) GDI_HEAP_ADDR( hdcs );
304     dcs->header.hNext = dc->header.hNext;
305     dc->header.hNext = hdcs;
306     dprintf_dc(stddeb, "SaveDC(%d): returning %d\n", hdc, dc->saveLevel+1 );
307     return ++dc->saveLevel;
308 }
309
310
311 /***********************************************************************
312  *           RestoreDC    (GDI.39)
313  */
314 BOOL RestoreDC( HDC hdc, short level )
315 {
316     DC * dc, * dcs;
317
318     dprintf_dc(stddeb, "RestoreDC: %d %d\n", hdc, level );
319     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
320     if (!dc) 
321     {
322         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
323         if (!dc) return FALSE;
324         if (level != -1) return FALSE;
325         MF_MetaParam1(dc, META_RESTOREDC, level);
326         return TRUE;
327     }
328     if (level == -1) level = dc->saveLevel;
329     if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
330     
331     while ((short)dc->saveLevel >= level)
332     {
333         HDC hdcs = dc->header.hNext;
334         if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
335         dc->header.hNext = dcs->header.hNext;
336         if ((short)--dc->saveLevel < level) SetDCState( hdc, hdcs );
337         DeleteDC( hdcs );
338     }
339     return TRUE;
340 }
341
342
343 /***********************************************************************
344  *           CreateDC    (GDI.53)
345  */
346 HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
347 {
348     DC * dc;
349     HANDLE handle;
350     
351     handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
352     if (!handle) return 0;
353     dc = (DC *) GDI_HEAP_ADDR( handle );
354
355     dprintf_dc(stddeb, "CreateDC(%s %s %s): returning %d\n", 
356             driver, device, output, handle );
357
358     if (!displayDevCaps)
359     {
360         displayDevCaps = (DeviceCaps *) malloc( sizeof(DeviceCaps) );
361         DC_FillDevCaps( displayDevCaps );
362     }
363
364     dc->saveLevel = 0;
365     memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
366     memset( &dc->u.x, 0, sizeof(dc->u.x) );
367
368     dc->u.x.drawable   = rootWindow;
369     dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
370     dc->w.flags        = 0;
371     dc->w.devCaps      = displayDevCaps;
372     dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
373     dc->w.hVisRgn      = CreateRectRgn( 0, 0, displayDevCaps->horzRes,
374                                         displayDevCaps->vertRes );
375     if (!dc->w.hVisRgn)
376     {
377         GDI_HEAP_FREE( handle );
378         return 0;
379     }
380
381     DC_InitDC( handle );
382
383     return handle;
384 }
385
386
387 /***********************************************************************
388  *           CreateIC    (GDI.153)
389  */
390 HDC CreateIC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
391 {
392       /* Nothing special yet for ICs */
393     return CreateDC( driver, device, output, initData );
394 }
395
396
397 /***********************************************************************
398  *           CreateCompatibleDC    (GDI.52)
399  */
400 HDC CreateCompatibleDC( HDC hdc )
401 {
402     DC * dc;
403     HANDLE handle;
404     HBITMAP hbitmap;
405     BITMAPOBJ *bmp;
406
407     handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
408     if (!handle) return 0;
409     dc = (DC *) GDI_HEAP_ADDR( handle );
410
411     dprintf_dc(stddeb, "CreateCompatibleDC(%d): returning %d\n", hdc, handle );
412
413       /* Create default bitmap */
414     if (!(hbitmap = CreateBitmap( 1, 1, 1, 1, NULL )))
415     {
416         GDI_HEAP_FREE( handle );
417         return 0;
418     }
419     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
420     
421     dc->saveLevel = 0;
422     memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
423     memset( &dc->u.x, 0, sizeof(dc->u.x) );
424
425     dc->u.x.drawable   = bmp->pixmap;
426     dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
427     dc->w.flags        = DC_MEMORY;
428     dc->w.bitsPerPixel = 1;
429     dc->w.devCaps      = displayDevCaps;
430     dc->w.hBitmap      = hbitmap;
431     dc->w.hVisRgn      = CreateRectRgn( 0, 0, 1, 1 );
432
433     if (!dc->w.hVisRgn)
434     {
435         DeleteObject( hbitmap );
436         GDI_HEAP_FREE( handle );
437         return 0;
438     }
439
440     DC_InitDC( handle );
441
442     return handle;
443 }
444
445
446 /***********************************************************************
447  *           DeleteDC    (GDI.68)
448  */
449 BOOL DeleteDC( HDC hdc )
450 {
451     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
452     if (!dc) return FALSE;
453
454     dprintf_dc(stddeb, "DeleteDC: %d\n", hdc );
455
456     while (dc->saveLevel)
457     {
458         DC * dcs;
459         HDC hdcs = dc->header.hNext;
460         if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
461         dc->header.hNext = dcs->header.hNext;
462         dc->saveLevel--;
463         DeleteDC( hdcs );
464     }
465     
466     if (!(dc->w.flags & DC_SAVED))
467     {
468         SelectObject( hdc, STOCK_BLACK_PEN );
469         SelectObject( hdc, STOCK_WHITE_BRUSH );
470         SelectObject( hdc, STOCK_SYSTEM_FONT );
471         XFreeGC( display, dc->u.x.gc );
472     }
473
474     if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hBitmap );
475
476     if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
477     if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
478     if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
479     
480     return GDI_FreeObject( hdc );
481 }
482
483
484 /***********************************************************************
485  *           GetDeviceCaps    (GDI.80)
486  */
487 int GetDeviceCaps( HDC hdc, WORD cap )
488 {
489     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
490     if (!dc) return 0;
491
492     if (cap > sizeof(DeviceCaps)-sizeof(WORD)) return 0;
493     
494     dprintf_dc(stddeb, "GetDeviceCaps(%d,%d): returning %d\n",
495             hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
496     return *(WORD *)(((char *)dc->w.devCaps) + cap);
497 }
498
499
500 /***********************************************************************
501  *           SetBkColor    (GDI.1)
502  */
503 COLORREF SetBkColor( HDC hdc, COLORREF color )
504 {
505     COLORREF oldColor;
506     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
507     if (!dc) 
508     {
509         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
510         if (!dc) return 0x80000000;
511         MF_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
512         return 0;  /* ?? */
513     }
514
515     oldColor = dc->w.backgroundColor;
516     dc->w.backgroundColor = color;
517     dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
518     return oldColor;
519 }
520
521
522 /***********************************************************************
523  *           SetTextColor    (GDI.9)
524  */
525 COLORREF SetTextColor( HDC hdc, COLORREF color )
526 {
527     COLORREF oldColor;
528     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
529     if (!dc) 
530     {
531         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
532         if (!dc) return 0x80000000;
533         MF_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color));
534         return 0;  /* ?? */
535     }
536
537     oldColor = dc->w.textColor;
538     dc->w.textColor = color;
539     dc->w.textPixel = COLOR_ToPhysical( dc, color );
540     return oldColor;
541 }
542
543
544 /***********************************************************************
545  *           GetDCOrg    (GDI.79)
546  */
547 DWORD GetDCOrg( HDC hdc )
548 {
549     Window root;
550     int x, y, w, h, border, depth;
551
552     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
553     if (!dc) return 0;
554     if (dc->w.flags & DC_MEMORY) return 0;
555     XGetGeometry( display, dc->u.x.drawable, &root,
556                   &x, &y, &w, &h, &border, &depth );
557     return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y );
558 }
559
560
561 /***********************************************************************
562  *           SetDCOrg    (GDI.117)
563  */
564 DWORD SetDCOrg( HDC hdc, short x, short y )
565 {
566     DWORD prevOrg;
567     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
568     if (!dc) return 0;
569     prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
570     dc->w.DCOrgX = x;
571     dc->w.DCOrgY = y;
572     return prevOrg;
573 }