1 /*
2 
3 Copyright 1993 by Davor Matic
4 
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and that
8 both that copyright notice and this permission notice appear in
9 supporting documentation.  Davor Matic makes no representations about
10 the suitability of this software for any purpose.  It is provided "as
11 is" without express or implied warranty.
12 
13 */
14 
15 #ifdef HAVE_XNEST_CONFIG_H
16 #include <xnest-config.h>
17 #endif
18 
19 #include <X11/X.h>
20 #include <X11/Xproto.h>
21 #include "regionstr.h"
22 #include <X11/fonts/fontstruct.h>
23 #include "gcstruct.h"
24 #include "scrnintstr.h"
25 #include "windowstr.h"
26 #include "pixmapstr.h"
27 #include "region.h"
28 #include "servermd.h"
29 
30 #include "Xnest.h"
31 
32 #include "Display.h"
33 #include "Screen.h"
34 #include "XNGC.h"
35 #include "XNFont.h"
36 #include "GCOps.h"
37 #include "Drawable.h"
38 #include "Visual.h"
39 
40 void
xnestFillSpans(DrawablePtr pDrawable,GCPtr pGC,int nSpans,xPoint * pPoints,int * pWidths,int fSorted)41 xnestFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans, xPoint * pPoints,
42                int *pWidths, int fSorted)
43 {
44     ErrorF("xnest warning: function xnestFillSpans not implemented\n");
45 }
46 
47 void
xnestSetSpans(DrawablePtr pDrawable,GCPtr pGC,char * pSrc,xPoint * pPoints,int * pWidths,int nSpans,int fSorted)48 xnestSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc,
49               xPoint * pPoints, int *pWidths, int nSpans, int fSorted)
50 {
51     ErrorF("xnest warning: function xnestSetSpans not implemented\n");
52 }
53 
54 void
xnestGetSpans(DrawablePtr pDrawable,int maxWidth,DDXPointPtr pPoints,int * pWidths,int nSpans,char * pBuffer)55 xnestGetSpans(DrawablePtr pDrawable, int maxWidth, DDXPointPtr pPoints,
56               int *pWidths, int nSpans, char *pBuffer)
57 {
58     ErrorF("xnest warning: function xnestGetSpans not implemented\n");
59 }
60 
61 void
xnestQueryBestSize(int class,unsigned short * pWidth,unsigned short * pHeight,ScreenPtr pScreen)62 xnestQueryBestSize(int class, unsigned short *pWidth, unsigned short *pHeight,
63                    ScreenPtr pScreen)
64 {
65     unsigned int width, height;
66 
67     width = *pWidth;
68     height = *pHeight;
69 
70     XQueryBestSize(xnestDisplay, class,
71                    xnestDefaultWindows[pScreen->myNum],
72                    width, height, &width, &height);
73 
74     *pWidth = width;
75     *pHeight = height;
76 }
77 
78 void
xnestPutImage(DrawablePtr pDrawable,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * pImage)79 xnestPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
80               int w, int h, int leftPad, int format, char *pImage)
81 {
82     XImage *ximage;
83 
84     ximage = XCreateImage(xnestDisplay, xnestDefaultVisual(pDrawable->pScreen),
85                           depth, format, leftPad, (char *) pImage,
86                           w, h, BitmapPad(xnestDisplay),
87                           (format == ZPixmap) ?
88                           PixmapBytePad(w, depth) : BitmapBytePad(w + leftPad));
89 
90     if (ximage) {
91         XPutImage(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
92                   ximage, 0, 0, x, y, w, h);
93         XFree(ximage);
94     }
95 }
96 
97 static int
xnestIgnoreErrorHandler(Display * dpy,XErrorEvent * event)98 xnestIgnoreErrorHandler (Display     *dpy,
99                          XErrorEvent *event)
100 {
101     return False; /* return value is ignored */
102 }
103 
104 void
xnestGetImage(DrawablePtr pDrawable,int x,int y,int w,int h,unsigned int format,unsigned long planeMask,char * pImage)105 xnestGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
106               unsigned int format, unsigned long planeMask, char *pImage)
107 {
108     XImage *ximage;
109     int length;
110     int (*old_handler)(Display*, XErrorEvent*);
111 
112     /* we may get BadMatch error when xnest window is minimized */
113     XSync(xnestDisplay, False);
114     old_handler = XSetErrorHandler (xnestIgnoreErrorHandler);
115 
116     ximage = XGetImage(xnestDisplay, xnestDrawable(pDrawable),
117                        x, y, w, h, planeMask, format);
118     XSetErrorHandler(old_handler);
119 
120     if (ximage) {
121         length = ximage->bytes_per_line * ximage->height;
122 
123         memmove(pImage, ximage->data, length);
124 
125         XDestroyImage(ximage);
126     }
127 }
128 
129 static Bool
xnestBitBlitPredicate(Display * dpy,XEvent * event,char * args)130 xnestBitBlitPredicate(Display * dpy, XEvent * event, char *args)
131 {
132     return event->type == GraphicsExpose || event->type == NoExpose;
133 }
134 
135 static RegionPtr
xnestBitBlitHelper(GCPtr pGC)136 xnestBitBlitHelper(GCPtr pGC)
137 {
138     if (!pGC->graphicsExposures)
139         return NullRegion;
140     else {
141         XEvent event;
142         RegionPtr pReg, pTmpReg;
143         BoxRec Box;
144         Bool pending, overlap;
145 
146         pReg = RegionCreate(NULL, 1);
147         pTmpReg = RegionCreate(NULL, 1);
148         if (!pReg || !pTmpReg)
149             return NullRegion;
150 
151         pending = True;
152         while (pending) {
153             XIfEvent(xnestDisplay, &event, xnestBitBlitPredicate, NULL);
154 
155             switch (event.type) {
156             case NoExpose:
157                 pending = False;
158                 break;
159 
160             case GraphicsExpose:
161                 Box.x1 = event.xgraphicsexpose.x;
162                 Box.y1 = event.xgraphicsexpose.y;
163                 Box.x2 = event.xgraphicsexpose.x + event.xgraphicsexpose.width;
164                 Box.y2 = event.xgraphicsexpose.y + event.xgraphicsexpose.height;
165                 RegionReset(pTmpReg, &Box);
166                 RegionAppend(pReg, pTmpReg);
167                 pending = event.xgraphicsexpose.count;
168                 break;
169             }
170         }
171 
172         RegionDestroy(pTmpReg);
173         RegionValidate(pReg, &overlap);
174         return pReg;
175     }
176 }
177 
178 RegionPtr
xnestCopyArea(DrawablePtr pSrcDrawable,DrawablePtr pDstDrawable,GCPtr pGC,int srcx,int srcy,int width,int height,int dstx,int dsty)179 xnestCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
180               GCPtr pGC, int srcx, int srcy, int width, int height,
181               int dstx, int dsty)
182 {
183     XCopyArea(xnestDisplay,
184               xnestDrawable(pSrcDrawable), xnestDrawable(pDstDrawable),
185               xnestGC(pGC), srcx, srcy, width, height, dstx, dsty);
186 
187     return xnestBitBlitHelper(pGC);
188 }
189 
190 RegionPtr
xnestCopyPlane(DrawablePtr pSrcDrawable,DrawablePtr pDstDrawable,GCPtr pGC,int srcx,int srcy,int width,int height,int dstx,int dsty,unsigned long plane)191 xnestCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
192                GCPtr pGC, int srcx, int srcy, int width, int height,
193                int dstx, int dsty, unsigned long plane)
194 {
195     XCopyPlane(xnestDisplay,
196                xnestDrawable(pSrcDrawable), xnestDrawable(pDstDrawable),
197                xnestGC(pGC), srcx, srcy, width, height, dstx, dsty, plane);
198 
199     return xnestBitBlitHelper(pGC);
200 }
201 
202 void
xnestPolyPoint(DrawablePtr pDrawable,GCPtr pGC,int mode,int nPoints,DDXPointPtr pPoints)203 xnestPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int nPoints,
204                DDXPointPtr pPoints)
205 {
206     XDrawPoints(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
207                 (XPoint *) pPoints, nPoints, mode);
208 }
209 
210 void
xnestPolylines(DrawablePtr pDrawable,GCPtr pGC,int mode,int nPoints,DDXPointPtr pPoints)211 xnestPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int nPoints,
212                DDXPointPtr pPoints)
213 {
214     XDrawLines(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
215                (XPoint *) pPoints, nPoints, mode);
216 }
217 
218 void
xnestPolySegment(DrawablePtr pDrawable,GCPtr pGC,int nSegments,xSegment * pSegments)219 xnestPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nSegments,
220                  xSegment * pSegments)
221 {
222     XDrawSegments(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
223                   (XSegment *) pSegments, nSegments);
224 }
225 
226 void
xnestPolyRectangle(DrawablePtr pDrawable,GCPtr pGC,int nRectangles,xRectangle * pRectangles)227 xnestPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nRectangles,
228                    xRectangle *pRectangles)
229 {
230     XDrawRectangles(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
231                     (XRectangle *) pRectangles, nRectangles);
232 }
233 
234 void
xnestPolyArc(DrawablePtr pDrawable,GCPtr pGC,int nArcs,xArc * pArcs)235 xnestPolyArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
236 {
237     XDrawArcs(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
238               (XArc *) pArcs, nArcs);
239 }
240 
241 void
xnestFillPolygon(DrawablePtr pDrawable,GCPtr pGC,int shape,int mode,int nPoints,DDXPointPtr pPoints)242 xnestFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode,
243                  int nPoints, DDXPointPtr pPoints)
244 {
245     XFillPolygon(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
246                  (XPoint *) pPoints, nPoints, shape, mode);
247 }
248 
249 void
xnestPolyFillRect(DrawablePtr pDrawable,GCPtr pGC,int nRectangles,xRectangle * pRectangles)250 xnestPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nRectangles,
251                   xRectangle *pRectangles)
252 {
253     XFillRectangles(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
254                     (XRectangle *) pRectangles, nRectangles);
255 }
256 
257 void
xnestPolyFillArc(DrawablePtr pDrawable,GCPtr pGC,int nArcs,xArc * pArcs)258 xnestPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
259 {
260     XFillArcs(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
261               (XArc *) pArcs, nArcs);
262 }
263 
264 int
xnestPolyText8(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,char * string)265 xnestPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
266                char *string)
267 {
268     int width;
269 
270     XDrawString(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
271                 x, y, string, count);
272 
273     width = XTextWidth(xnestFontStruct(pGC->font), string, count);
274 
275     return width + x;
276 }
277 
278 int
xnestPolyText16(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,unsigned short * string)279 xnestPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
280                 unsigned short *string)
281 {
282     int width;
283 
284     XDrawString16(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
285                   x, y, (XChar2b *) string, count);
286 
287     width = XTextWidth16(xnestFontStruct(pGC->font), (XChar2b *) string, count);
288 
289     return width + x;
290 }
291 
292 void
xnestImageText8(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,char * string)293 xnestImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
294                 char *string)
295 {
296     XDrawImageString(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
297                      x, y, string, count);
298 }
299 
300 void
xnestImageText16(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,unsigned short * string)301 xnestImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count,
302                  unsigned short *string)
303 {
304     XDrawImageString16(xnestDisplay, xnestDrawable(pDrawable), xnestGC(pGC),
305                        x, y, (XChar2b *) string, count);
306 }
307 
308 void
xnestImageGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nGlyphs,CharInfoPtr * pCharInfo,void * pGlyphBase)309 xnestImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
310                    unsigned int nGlyphs, CharInfoPtr * pCharInfo,
311                    void *pGlyphBase)
312 {
313     ErrorF("xnest warning: function xnestImageGlyphBlt not implemented\n");
314 }
315 
316 void
xnestPolyGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nGlyphs,CharInfoPtr * pCharInfo,void * pGlyphBase)317 xnestPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
318                   unsigned int nGlyphs, CharInfoPtr * pCharInfo,
319                   void *pGlyphBase)
320 {
321     ErrorF("xnest warning: function xnestPolyGlyphBlt not implemented\n");
322 }
323 
324 void
xnestPushPixels(GCPtr pGC,PixmapPtr pBitmap,DrawablePtr pDst,int width,int height,int x,int y)325 xnestPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDst,
326                 int width, int height, int x, int y)
327 {
328     /* only works for solid bitmaps */
329     if (pGC->fillStyle == FillSolid) {
330         XSetStipple(xnestDisplay, xnestGC(pGC), xnestPixmap(pBitmap));
331         XSetTSOrigin(xnestDisplay, xnestGC(pGC), x, y);
332         XSetFillStyle(xnestDisplay, xnestGC(pGC), FillStippled);
333         XFillRectangle(xnestDisplay, xnestDrawable(pDst),
334                        xnestGC(pGC), x, y, width, height);
335         XSetFillStyle(xnestDisplay, xnestGC(pGC), FillSolid);
336     }
337     else
338         ErrorF("xnest warning: function xnestPushPixels not implemented\n");
339 }
340