Moved all the files in graphics/x11drv to dlls/x11drv.
[wine] / dlls / x11drv / clipping.c
1 /*
2  * X11DRV clipping functions
3  *
4  * Copyright 1998 Huw Davies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24
25 #include "gdi.h"
26 #include "x11drv.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
30
31 /***********************************************************************
32  *           X11DRV_GetRegionData
33  *
34  * Calls GetRegionData on the given region and converts the rectangle
35  * array to XRectangle format. The returned buffer must be freed by
36  * caller using HeapFree(GetProcessHeap(),...).
37  * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
38  */
39 RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp )
40 {
41     RGNDATA *data;
42     DWORD size;
43     int i;
44     RECT *rect, tmp;
45     XRectangle *xrect;
46
47     if (!(size = GetRegionData( hrgn, 0, NULL ))) return NULL;
48     if (sizeof(XRectangle) > sizeof(RECT))
49     {
50         /* add extra size for XRectangle array */
51         int count = (size - sizeof(RGNDATAHEADER)) / sizeof(RECT);
52         size += count * (sizeof(XRectangle) - sizeof(RECT));
53     }
54     if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
55     if (!GetRegionData( hrgn, size, data ))
56     {
57         HeapFree( GetProcessHeap(), 0, data );
58         return NULL;
59     }
60
61     rect = (RECT *)data->Buffer;
62     xrect = (XRectangle *)data->Buffer;
63     if (hdc_lptodp)  /* map to device coordinates */
64     {
65         LPtoDP( hdc_lptodp, (POINT *)rect, data->rdh.nCount * 2 );
66         for (i = 0; i < data->rdh.nCount; i++)
67         {
68             if (rect[i].right < rect[i].left)
69             {
70                 INT tmp = rect[i].right;
71                 rect[i].right = rect[i].left;
72                 rect[i].left = tmp;
73             }
74             if (rect[i].bottom < rect[i].top)
75             {
76                 INT tmp = rect[i].bottom;
77                 rect[i].bottom = rect[i].top;
78                 rect[i].top = tmp;
79             }
80         }
81     }
82
83     if (sizeof(XRectangle) > sizeof(RECT))
84     {
85         /* need to start from the end */
86         for (i = data->rdh.nCount-1; i >=0; i--)
87         {
88             tmp = rect[i];
89             xrect[i].x      = tmp.left;
90             xrect[i].y      = tmp.top;
91             xrect[i].width  = tmp.right - tmp.left;
92             xrect[i].height = tmp.bottom - tmp.top;
93         }
94     }
95     else
96     {
97         for (i = 0; i < data->rdh.nCount; i++)
98         {
99             tmp = rect[i];
100             xrect[i].x      = tmp.left;
101             xrect[i].y      = tmp.top;
102             xrect[i].width  = tmp.right - tmp.left;
103             xrect[i].height = tmp.bottom - tmp.top;
104         }
105     }
106     return data;
107 }
108
109
110 /***********************************************************************
111  *           X11DRV_SetDeviceClipping
112  */
113 void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN hrgn )
114 {
115     RGNDATA *data;
116
117     if (!(data = X11DRV_GetRegionData( hrgn, 0 ))) return;
118     wine_tsx11_lock();
119     XSetClipRectangles( gdi_display, physDev->gc, physDev->org.x, physDev->org.y,
120                         (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded );
121     wine_tsx11_unlock();
122     HeapFree( GetProcessHeap(), 0, data );
123 }
124
125
126 /***********************************************************************
127  *           X11DRV_SetDrawable
128  *
129  * Set the drawable, clipping mode and origin for a DC.
130  */
131 void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, const POINT *org,
132                          const POINT *drawable_org )
133 {
134     DC *dc = DC_GetDCPtr( hdc );
135     if (dc)
136     {
137         X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
138
139         if(physDev->xrender)
140             X11DRV_XRender_UpdateDrawable( physDev );
141
142         physDev->org = *org;
143         physDev->drawable = drawable;
144         physDev->drawable_org = *drawable_org;
145         wine_tsx11_lock();
146         XSetSubwindowMode( gdi_display, physDev->gc, mode );
147         wine_tsx11_unlock();
148         GDI_ReleaseObj( hdc );
149     }
150 }
151
152
153 /***********************************************************************
154  *           X11DRV_StartGraphicsExposures
155  *
156  * Set the DC in graphics exposures mode
157  */
158 void X11DRV_StartGraphicsExposures( HDC hdc )
159 {
160     DC *dc = DC_GetDCPtr( hdc );
161     if (dc)
162     {
163         X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
164         wine_tsx11_lock();
165         XSetGraphicsExposures( gdi_display, physDev->gc, True );
166         wine_tsx11_unlock();
167         physDev->exposures = 0;
168         GDI_ReleaseObj( hdc );
169     }
170 }
171
172
173 /***********************************************************************
174  *           X11DRV_EndGraphicsExposures
175  *
176  * End the graphics exposures mode and process the events
177  */
178 void X11DRV_EndGraphicsExposures( HDC hdc, HRGN hrgn )
179 {
180     HRGN tmp = 0;
181     DC *dc = DC_GetDCPtr( hdc );
182
183     if (dc)
184     {
185         XEvent event;
186         X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
187
188         SetRectRgn( hrgn, 0, 0, 0, 0 );
189         wine_tsx11_lock();
190         XSetGraphicsExposures( gdi_display, physDev->gc, False );
191         if (physDev->exposures)
192         {
193             for (;;)
194             {
195                 XWindowEvent( gdi_display, physDev->drawable, ~0, &event );
196                 if (event.type == NoExpose) break;
197                 if (event.type == GraphicsExpose)
198                 {
199                     int x = event.xgraphicsexpose.x - physDev->org.x;
200                     int y = event.xgraphicsexpose.y - physDev->org.y;
201
202                     TRACE( "got %d,%d %dx%d count %d\n",
203                            x, y, event.xgraphicsexpose.width, event.xgraphicsexpose.height,
204                            event.xgraphicsexpose.count );
205
206                     if (!tmp) tmp = CreateRectRgn( 0, 0, 0, 0 );
207                     SetRectRgn( tmp, x, y,
208                                 x + event.xgraphicsexpose.width,
209                                 y + event.xgraphicsexpose.height );
210                     CombineRgn( hrgn, hrgn, tmp, RGN_OR );
211                     if (!event.xgraphicsexpose.count) break;
212                 }
213                 else
214                 {
215                     ERR( "got unexpected event %d\n", event.type );
216                     break;
217                 }
218             }
219             if (tmp) DeleteObject( tmp );
220         }
221         wine_tsx11_unlock();
222         GDI_ReleaseObj( hdc );
223     }
224 }