Remove X_DC_INFO from DC and make it behave like any other PDEVICE.
[wine] / windows / graphics.c
1 /*
2  * X-specific shortcuts to speed up WM code.
3  * No coordinate transformations except origin translation.
4  *
5  * Copyright 1993, 1994 Alexandre Julliard
6  */
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include "ts_xlib.h"
11 #include "ts_xutil.h"
12 #include <X11/Intrinsic.h>
13 #include "graphics.h"
14 #include "color.h"
15 #include "bitmap.h"
16 #include "gdi.h"
17 #include "dc.h"
18 #include "x11drv.h"
19
20 #define MAX_DRAWLINES 8
21
22
23 /**********************************************************************
24  *          GRAPH_DrawLines
25  *
26  * Draw multiple unconnected lines (limited by MAX_DRAWLINES).
27  */
28 BOOL32 GRAPH_DrawLines( HDC32 hdc, LPPOINT32 pXY, INT32 N, HPEN32 hPen )
29 {
30     BOOL32      bRet = FALSE;
31     DC*         dc;
32
33     assert( N <= MAX_DRAWLINES );
34     if( (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )) )
35     {
36         HPEN32  hPrevPen  = 0;
37         X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
38
39         if( hPen ) hPrevPen = SelectObject32( hdc, hPen );
40         if( X11DRV_SetupGCForPen( dc ) )
41         {
42             XSegment    l[MAX_DRAWLINES];
43             INT32       i, j;
44
45             for( i = 0; i < N; i++ )
46             {
47                  j = 2 * i;
48                  l[i].x1 = pXY[j].x + dc->w.DCOrgX; 
49                  l[i].x2 = pXY[j + 1].x + dc->w.DCOrgX;
50                  l[i].y1 = pXY[j].y + dc->w.DCOrgY;
51                  l[i].y2 = pXY[j + 1].y + dc->w.DCOrgY;
52             }
53             TSXDrawSegments( display, physDev->drawable, physDev->gc, l, N );
54             bRet = TRUE;
55         }
56         if( hPrevPen ) SelectObject32( hdc, hPrevPen );
57         GDI_HEAP_UNLOCK( hdc );
58     }
59     return bRet;
60 }
61
62 /**********************************************************************
63  * 
64  *          GRAPH_DrawBitmap
65  *
66  * Short-cut function to blit a bitmap into a device.
67  * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
68  */
69 BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap, 
70                          INT32 xdest, INT32 ydest, INT32 xsrc, INT32 ysrc, 
71                          INT32 width, INT32 height, BOOL32 bMono )
72 {
73     BITMAPOBJ *bmp;
74     DC *dc;
75     BOOL32 ret = TRUE;
76     X11DRV_PHYSBITMAP *pbitmap;
77     X11DRV_PDEVICE *physDev;
78
79     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
80     if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
81     {
82         GDI_HEAP_UNLOCK( hdc );
83         return FALSE;
84     }
85     physDev = (X11DRV_PDEVICE *)dc->physDev;
86
87     /* HACK for now */
88     if(!bmp->DDBitmap)
89         X11DRV_CreateBitmap( hbitmap );
90     pbitmap = bmp->DDBitmap->physBitmap;
91
92     xdest += dc->w.DCOrgX; ydest += dc->w.DCOrgY;
93
94     TSXSetFunction( display, physDev->gc, GXcopy );
95     if (bmp->bitmap.bmBitsPixel == 1)
96     {
97         TSXSetForeground( display, physDev->gc, physDev->backgroundPixel );
98         TSXSetBackground( display, physDev->gc, physDev->textPixel );
99         TSXCopyPlane( display, pbitmap->pixmap, physDev->drawable, physDev->gc,
100                     xsrc, ysrc, width, height, xdest, ydest, 1 );
101     }
102     else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
103     {
104         if( bMono )
105         {
106             INT32       plane;
107
108             if( COLOR_GetMonoPlane(&plane) )
109             {
110                 TSXSetForeground( display, physDev->gc,
111                                   physDev->backgroundPixel );
112                 TSXSetBackground( display, physDev->gc, physDev->textPixel );
113             }
114             else
115             {
116                 TSXSetForeground( display, physDev->gc, physDev->textPixel );
117                 TSXSetBackground( display, physDev->gc,
118                                   physDev->backgroundPixel );
119             }
120             TSXCopyPlane( display, pbitmap->pixmap, physDev->drawable,
121                           physDev->gc, xsrc, ysrc, width, height, xdest, ydest,
122                           plane );
123         }
124         else 
125         {
126             TSXCopyArea( display, pbitmap->pixmap, physDev->drawable, 
127                          physDev->gc, xsrc, ysrc, width, height, xdest,
128                          ydest );
129         }
130     }
131     else 
132     {
133       ret = FALSE;
134     }
135
136     GDI_HEAP_UNLOCK( hdc );
137     GDI_HEAP_UNLOCK( hbitmap );
138     return ret;
139 }
140
141
142 /**********************************************************************
143  *          GRAPH_DrawReliefRect
144  *
145  * Used in the standard control code for button edge drawing.
146  */
147 void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect, INT32 highlight_size,
148                            INT32 shadow_size, BOOL32 pressed )
149 {
150     if(pressed)
151         GRAPH_DrawGenericReliefRect(hdc, rect, highlight_size, shadow_size,
152                                     GetSysColorBrush32(COLOR_BTNSHADOW),
153                                     GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
154     else
155         GRAPH_DrawGenericReliefRect(hdc, rect, highlight_size, shadow_size,
156                                     GetSysColorBrush32(COLOR_BTNHIGHLIGHT),
157                                     GetSysColorBrush32(COLOR_BTNSHADOW));
158
159     return;
160 }
161
162
163 /******************************************************************************
164  *             GRAPH_DrawGenericReliefRect
165  *
166  *   Creates a rectangle with the specified highlight and shadow colors.
167  *   Adapted from DrawReliefRect (which is somewhat misnamed).
168  */
169 void  GRAPH_DrawGenericReliefRect(
170     HDC32  hdc,
171     const  RECT32 *rect,
172     INT32  highlight_size,
173     INT32  shadow_size,
174     HBRUSH32  highlight,
175     HBRUSH32  shadow )
176 {
177     DC*         dc;
178     HBRUSH32    hPrevBrush;
179     INT32       w, h;
180     RECT32      r = *rect;
181     X11DRV_PDEVICE *physDev;
182
183     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
184     physDev = (X11DRV_PDEVICE *)dc->physDev;
185     OffsetRect32( &r, dc->w.DCOrgX, dc->w.DCOrgY);
186     h = rect->bottom - rect->top;  w = rect->right - rect->left;
187
188     hPrevBrush = SelectObject32(hdc, highlight);
189
190     if ( X11DRV_SetupGCForBrush( dc ) )
191     {
192          INT32  i;
193
194          TSXSetFunction( display, physDev->gc, GXcopy );
195          for (i = 0; i < highlight_size; i++)
196          {
197               TSXFillRectangle( display, physDev->drawable, physDev->gc,
198                                         r.left + i, r.top, 1, h - i );
199               TSXFillRectangle( display, physDev->drawable, physDev->gc,
200                                         r.left, r.top + i, w - i, 1 );
201          }
202     }
203
204     SelectObject32( hdc, shadow );
205     if ( X11DRV_SetupGCForBrush( dc ) )
206     {
207          INT32  i;
208
209          TSXSetFunction( display, physDev->gc, GXcopy );
210          for (i = 0; i < shadow_size; i++)
211          {
212               TSXFillRectangle( display, physDev->drawable, physDev->gc,
213                               r.right - i - 1, r.top + i, 1, h - i );
214               TSXFillRectangle( display, physDev->drawable, physDev->gc,
215                               r.left + i, r.bottom - i - 1, w - i, 1 );
216          }
217     }
218
219     SelectObject32( hdc, hPrevBrush );
220     GDI_HEAP_UNLOCK( hdc );
221 }
222
223
224
225 /**********************************************************************
226  *          GRAPH_DrawRectangle
227  */
228 void GRAPH_DrawRectangle( HDC32 hdc, INT32 x, INT32 y, 
229                                      INT32 w, INT32 h, HPEN32 hPen )
230 {
231     DC* dc;
232
233     if( (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )) ) 
234     {
235         HPEN32  hPrevPen  = 0; 
236         X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
237
238         if( hPen ) hPrevPen = SelectObject32( hdc, hPen );
239         if( X11DRV_SetupGCForPen( dc ) )
240             TSXDrawRectangle( display, physDev->drawable, physDev->gc, 
241                             x + dc->w.DCOrgX, y + dc->w.DCOrgY, w - 1, h - 1);
242         if( hPrevPen ) SelectObject32( hdc, hPrevPen );
243         GDI_HEAP_UNLOCK( hdc );
244     }
245 }
246
247 /**********************************************************************
248  *          GRAPH_SelectClipMask
249  */
250 BOOL32 GRAPH_SelectClipMask( HDC32 hdc, HBITMAP32 hMonoBitmap, INT32 x, INT32 y)
251 {
252     BITMAPOBJ *bmp = NULL;
253     DC *dc;
254     X11DRV_PHYSBITMAP *pbitmap = NULL;
255     X11DRV_PDEVICE *physDev;
256
257     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
258     physDev = (X11DRV_PDEVICE *)dc->physDev;
259     if ( hMonoBitmap ) 
260     {
261        if ( !(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hMonoBitmap, BITMAP_MAGIC)) 
262            || bmp->bitmap.bmBitsPixel != 1 ) 
263        {
264            GDI_HEAP_UNLOCK( hdc );
265            return FALSE;
266        }
267
268        /* HACK for now */
269        if(!bmp->DDBitmap)
270            X11DRV_CreateBitmap( hMonoBitmap );
271        pbitmap = bmp->DDBitmap->physBitmap;
272        TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX + x,
273                          dc->w.DCOrgY + y );
274     }
275
276     TSXSetClipMask( display, physDev->gc, (bmp) ? pbitmap->pixmap : None );
277
278     GDI_HEAP_UNLOCK( hdc );
279     GDI_HEAP_UNLOCK( hMonoBitmap );
280     return TRUE;
281 }
282