ecere/gfx/fontRendering: Improved rendering of some fonts e.g. MS Sans Serif having...
[sdk] / ecere / src / gfx / drivers / XDisplayDriver.ec
1 namespace gfx::drivers;
2
3 // Enable to work around some Linux drivers not supporting PictStandardA8 format properly
4 #define ENABLE_XRENDER_WORK_AROUND
5
6 import "instance"
7
8 #if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
9
10 default:
11
12 #define property _property
13 #define new _new
14 #define class _class
15 #define uint _uint
16
17 #define Window    X11Window
18 #define Cursor    X11Cursor
19 #define Font      X11Font
20 #define Display   X11Display
21 #define Time      X11Time
22 #define KeyCode   X11KeyCode
23 #define Picture   X11Picture
24 #define Glyph     X11Glyph
25
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/extensions/shape.h>
29 #include <X11/extensions/Xrender.h>
30 #include <X11/extensions/XShm.h>
31 #include <sys/ipc.h>
32 #include <sys/shm.h>
33
34 #undef Window
35 #undef Cursor
36 #undef Font
37 #undef Display
38 #undef Time
39 #undef KeyCode
40 #undef Picture
41 #undef Glyph
42
43 #undef uint
44 #undef new
45 #undef property
46 #undef class
47
48 private:
49
50 import "Display"
51 import "XInterface"
52
53 /*
54 static byte defaultRGBLookup[32768];
55 bool rgbLookupSet = false;
56 */
57 class XDisplay : LFBDisplay //struct
58 {
59    Pixmap pixmap;
60    Pixmap shapePixmap;
61    GC windowGC, gc;
62    Point offset;
63    Box updateBox;
64    X11Picture picture;
65    X11Picture shapePicture;
66    XShmSegmentInfo shminfo;
67    XImage * image;
68    XShmSegmentInfo shminfoShape;
69    XImage * shapeImage;
70 };
71
72 class XSurface : struct
73 {
74    Font font;
75    bool opaqueText;
76    int xOffset;
77    bool writingText;
78    bool writingOutline;
79
80    ColorAlpha foreground, background;
81    bool opaque;
82    bool clipped;
83    Pixmap pixmap;
84    X11Picture picture;
85    X11Picture colorPicture;
86    Pixmap colorPixmap;
87 };
88
89 class XBitmap : struct
90 {
91    Pixmap pixmap;
92    Pixmap mask;
93    X11Picture picture;
94    X11Picture maskPicture;
95 #ifdef ENABLE_XRENDER_WORK_AROUND
96    bool alphaTweak;
97 #endif
98 };
99
100 XRenderPictFormat * GetXRenderFormat(PixelFormat pixelFormat, bool alphaBlend)
101 {
102    XRenderPictFormat * format = null;
103    switch(pixelFormat)
104    {
105       case pixelFormatAlpha:
106          format = XRenderFindStandardFormat(xGlobalDisplay, PictStandardA8);
107          break;
108       case pixelFormat888:
109          format = XRenderFindStandardFormat(xGlobalDisplay, alphaBlend ? PictStandardARGB32 : PictStandardRGB24);
110          // printf("R: %d G: %d B: %d\n", format->direct.red, format->direct.green, format->direct.blue);
111          break;
112       case pixelFormat555:
113       {
114          XRenderPictFormat info = { 0 };
115
116          info.depth = 16;
117          info.type = PictTypeDirect;
118          info.direct.red = 10;
119          info.direct.green = 5;
120          info.direct.blue = 0;
121          info.direct.redMask   = 0x1F;
122          info.direct.greenMask = 0x1F;
123          info.direct.blueMask  = 0x1F;
124
125          format = XRenderFindFormat(xGlobalDisplay,
126             /*PictFormatDepth|*/PictFormatType| PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
127             PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
128          break;
129       }
130       case pixelFormat565:
131       {
132          XRenderPictFormat info = { 0 };
133
134          info.depth = 16;
135          info.type = PictTypeDirect;
136          info.direct.alpha = 0;
137          info.direct.red = 11;
138          info.direct.green = 5;
139          info.direct.blue = 0;
140          info.direct.redMask   = 0x1F;
141          info.direct.greenMask = 0x3F;
142          info.direct.blueMask  = 0x1F;
143          info.direct.alphaMask = 0;
144          info.id = 0xba;
145
146          format = XRenderFindFormat(xGlobalDisplay,
147             /*PictFormatDepth|*/PictFormatType|PictFormatAlpha|PictFormatRed|PictFormatGreen|PictFormatBlue|
148             PictFormatRedMask|PictFormatGreenMask|PictFormatBlueMask|PictFormatAlphaMask, &info, 0);
149          break;
150       }
151    }
152    return format;
153 }
154
155 static bool ClipBlitCoords(Surface surface, Bitmap src, int *dx, int *dy, int *sx, int *sy, int *w, int *h, bool * flip)
156 {
157    *flip = false;
158
159    if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top) return false;
160
161    if(*w < 0) { *w = -*w; *flip = true; }
162
163    //Clip against the edges of the source
164    if(*sx<0)
165    {
166       *dx+=-*sx;
167       *w-=-*sx;
168       *sx=0;
169    }
170    if(*sy<0)
171    {
172       *dy+=0-*sy;
173       *h-=0-*sy;
174       *sy=0;
175    }
176    if(*sx+*w>src.width-1)
177       *w-=*sx+*w-(src.width-1)-1;
178    if(*sy+*h>src.height-1)
179       *h-=*sy+*h-(src.height-1)-1;
180    //Clip against the edges of the destination
181    if(*dx<surface.box.left)
182    {
183       if(!*flip) *sx+=surface.box.left-*dx;
184       *w-=surface.box.left-*dx;
185       *dx=surface.box.left;
186    }
187    if(*dy<surface.box.top)
188    {
189       *sy+=surface.box.top-*dy;
190       *h-=surface.box.top-*dy;
191       *dy=surface.box.top;
192    }
193    if((*dx+*w)>surface.box.right)
194    {
195       if(*flip) *sx+=(uint)(*dx+*w)-surface.box.right-1;
196       *w-=((uint)(*dx+*w)-surface.box.right-1);
197    }
198    if((*dy+*h)>surface.box.bottom)
199       *h-=((*dy+*h)-surface.box.bottom-1);
200    if((*w<=0)||(*h<=0))
201       return false;
202    return true;
203 }
204
205 static bool ClipStretchCoords(Surface surface, Bitmap src, int *dx, int *dy, int *sx, int *sy, int *w, int *h, int *sw, int *sh, bool * flip)
206 {
207    float s2dw,s2dh,d2sw,d2sh;
208    *flip = false;
209
210    if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return false;
211
212    if(Sgn(*w) != Sgn(*sw))
213    {
214       *w = Abs(*w);
215       *sw = Abs(*sw);
216       *flip = true;
217    }
218
219    s2dw=(float)*w / *sw;
220    s2dh=(float)*h / *sh;
221    d2sw=(float)*sw / *w;
222    d2sh=(float)*sh / *h;
223
224    //Clip against the edges of the source
225    if(*sx < 0)
226    {
227       *dx += (int)((0-*sx) * s2dw);
228       *w -= (int)((0-*sx) * s2dw);
229       *sw -= 0-*sx;
230       *sx=0;
231    }
232    if(*sy < 0)
233    {
234       *dy += (int)((0-*sy) * s2dh);
235       *h -= (int)((0-*sy) * s2dh);
236
237       *sh -= 0-*sy;
238       *sy=0;
239    }
240    if(*sx+*sw>src.width-1)
241    {
242       *w-=(int)((*sx+*sw-(src.width-1)-1)*s2dw);
243       *sw-=*sx+*sw-(src.width-1)-1;
244    }
245    if(*sy+*sh>(src.height-1))
246    {
247       *h-=(int)((*sy+*sh-(src.height-1)-1)*s2dh);
248       *sh-=*sy+*sh-(src.height-1)-1;
249    }
250    //Clip against the edges of the destination
251    if(*dx < surface.box.left)
252    {
253       if(!*flip) *sx += (int)((surface.box.left-*dx)*d2sw);
254       *sw-=(int)((surface.box.left-*dx)*d2sw);
255       *w-=surface.box.left-*dx;
256       *dx=surface.box.left;
257    }
258    if(*dy < surface.box.top)
259    {
260       *sy += (int)((surface.box.top-*dy)*d2sh);
261       *sh -= (int)((surface.box.top-*dy)*d2sh);
262       *h -= surface.box.top-*dy;
263       *dy =surface.box.top;
264    }
265    if((*dx+*w)>surface.box.right)
266    {
267       if(*flip) *sx+=(int)(((*dx+*w)-surface.box.right-1)*d2sw);
268       *sw-=(int)(((*dx + *w)-surface.box.right-1)*d2sw);
269       *w-=((*dx+*w)-surface.box.right-1);
270    }
271    if((*dy+*h)>surface.box.bottom)
272    {
273       *sh-=(int)(((*dy+*h)-surface.box.bottom-1)*d2sh);
274       *h-=((*dy+*h)-surface.box.bottom-1);
275    }
276    if((*w<=0)||(*h<=0)||(*sw<=0)||(*sh<=0))
277       return false;
278    return true;
279 }
280
281 static void PutBitmapMask(Pixmap mask, Bitmap bitmap) {
282    XImage image = {0};
283    GC maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
284    uint wordWidth = (bitmap.width+31) >> 5;
285
286    uint x,y;
287    uint32 *b = new0 uint32[wordWidth * bitmap.height];
288    uint32 f = 1;
289
290    XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
291
292    image.width = bitmap.width;
293    image.height = bitmap.height;
294
295    image.format = XYBitmap;
296    #ifdef __BIG_ENDIAN__
297    image.byte_order = MSBFirst;
298    #else
299    image.byte_order = LSBFirst;
300    #endif
301    image.bitmap_unit = 32;
302    image.bitmap_bit_order = LSBFirst;
303    image.bitmap_pad = 32;
304    image.depth = 1;
305    image.bytes_per_line = wordWidth << 2;
306
307    image.data = (char*)b;
308
309    XInitImage(&image);
310
311    switch(bitmap.pixelFormat) {
312       case pixelFormat4: {
313
314       } break;
315       case pixelFormat8: {
316          byte *p = (byte*)bitmap.picture;
317
318          for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
319             for(x = 0; x<bitmap.width; x++) {
320                if(p[x])
321                   *b |= f; //XPutPixel(&image, x,y, 1);
322                if (!(f<<=1))
323                   b++, f=1;
324             }
325             if (f != 1)
326                b++, f=1;
327          }
328       } break;
329       case pixelFormat444:
330       case pixelFormat555:
331       case pixelFormat565: {
332          uint16 *p = (uint16*)bitmap.picture;
333 #ifdef _DEBUG
334          PrintLn(bitmap.pixelFormat);
335 #endif
336          for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
337             for(x = 0; x<bitmap.width; x++) {
338                if(p[x])
339                   *b |= f; //XPutPixel(&image, x,y, 1);
340                if (!(f<<=1))
341                   b++, f=1;
342             }
343             if (f != 1)
344                b++, f=1;
345          }
346       } break;
347       case pixelFormat888: {
348          ColorAlpha *p = (ColorAlpha*)bitmap.picture;
349          for(y = 0; y<bitmap.height; y++, p+=bitmap.stride) {
350             for(x = 0; x<bitmap.width; x++) {
351                if(p[x].a)
352                   *b |= f; //XPutPixel(&image, x,y, 1);
353                if (!(f<<=1))
354                   b++, f=1;
355             }
356             if (f != 1)
357                b++, f=1;
358          }
359       } break;
360       case pixelFormatAlpha: {
361
362       } break;
363       case pixelFormatText: {
364
365       } break;
366       case pixelFormatRGBA: {
367
368       } break;
369    }
370
371    XSetForeground(xGlobalDisplay, maskGC, 1);
372    XSetBackground(xGlobalDisplay, maskGC, 0);
373
374    XPutImage(xGlobalDisplay, mask, maskGC, &image,
375       0, 0, 0, 0, //coordinates
376       bitmap.width, bitmap.height);
377
378    XFreeGC(xGlobalDisplay, maskGC);
379    delete image.data;
380 }
381
382 class XDisplayDriver : DisplayDriver
383 {
384    class_property(name) = "X";
385
386    bool CreateDisplaySystem(DisplaySystem displaySystem)
387    {
388       //displaySystem.driverData = calloc(1, sizeof(LFBSystem));
389       displaySystem.flags.memBackBuffer = true;
390       displaySystem.pixelFormat = xSystemPixelFormat;
391       return true;
392    }
393
394    void DestroyDisplaySystem(DisplaySystem displaySystem)
395    {
396       // delete displaySystem.driverData;
397    }
398
399    void DestroyDisplay(Display display)
400    {
401       XDisplay xDisplay = display.driverData;
402
403       // Free Shared Memory Pixmap
404       if(xDisplay.shapePixmap)
405          XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
406       if(xDisplay.pixmap)
407          XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
408       if(xDisplay.image)
409       {
410          if(xDisplay.shminfoShape.shmid != -1)
411          {
412             XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
413             if(xDisplay.shminfo.shmaddr != (void *)-1)
414                shmdt(xDisplay.shminfo.shmaddr);
415             shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
416          }
417       }
418       if(xDisplay.shapeImage)
419       {
420          if(xDisplay.shminfoShape.shmid != -1)
421          {
422             XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
423             if(xDisplay.shminfoShape.shmaddr != (void *)-1)
424                shmdt(xDisplay.shminfoShape.shmaddr);
425             shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
426          }
427          XDestroyImage(xDisplay.shapeImage);
428          xDisplay.shapeImage = None;
429       }
430       if(xDisplay.picture)
431          XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
432       if(xDisplay.shapePicture)
433          XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
434       if(xDisplay.windowGC)
435          XFreeGC(xGlobalDisplay, xDisplay.windowGC);
436       if(xDisplay.gc)
437          XFreeGC(xGlobalDisplay, xDisplay.gc);
438       delete xDisplay;
439       display.driverData = null;
440    }
441
442    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
443    {
444
445
446    }
447
448    bool CreateDisplay(Display display)
449    {
450       bool result = false;
451       XDisplay xDisplay = display.driverData = XDisplay { };
452
453       if(display)
454       {
455          xDisplay.windowGC = XCreateGC(xGlobalDisplay, (X11Window)display.window, 0, null);
456          XSetGraphicsExposures(xGlobalDisplay, xDisplay.windowGC, False);
457          result = true;
458       }
459       return result;
460    }
461
462    bool DisplaySize(Display display, int width, int height)
463    {
464       XDisplay xDisplay = display.driverData;
465       bool result = false;
466
467       if(width > display.width || height > display.height)
468       {
469          display.width = width;
470          display.height = height;
471
472          if(xDisplay.picture)
473             XRenderFreePicture(xGlobalDisplay, xDisplay.picture);
474
475          {
476             XRenderPictureAttributes attributes = { 0 };
477             XRenderPictFormat * format = GetXRenderFormat(xSystemPixelFormat, display.alphaBlend);
478             attributes.component_alpha = 1;
479             attributes.poly_mode = PolyModeImprecise;
480             attributes.poly_edge = PolyEdgeSmooth;
481
482             if(xDisplay.pixmap)
483             {
484                XFreePixmap(xGlobalDisplay, xDisplay.pixmap);
485                xDisplay.pixmap = None;
486             }
487             if(xDisplay.shapePixmap)
488             {
489                XFreePixmap(xGlobalDisplay, xDisplay.shapePixmap);
490                xDisplay.shapePixmap = None;
491             }
492
493             // Free Shared Memory Pixmap
494             if(xDisplay.image)
495             {
496                if(xDisplay.shminfoShape.shmid != -1)
497                {
498                   XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
499                   if(xDisplay.shminfo.shmaddr != (void *)-1)
500                      shmdt(xDisplay.shminfo.shmaddr);
501                   shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
502                }
503                XDestroyImage(xDisplay.image);
504                xDisplay.image = None;
505             }
506             if(xDisplay.shapeImage)
507             {
508                if(xDisplay.shminfoShape.shmid != -1)
509                {
510                   XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
511                   if(xDisplay.shminfoShape.shmaddr != (void *)-1)
512                      shmdt(xDisplay.shminfoShape.shmaddr);
513                   shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
514                }
515                XDestroyImage(xDisplay.shapeImage);
516                xDisplay.shapeImage = None;
517             }
518
519             // Initialize Shared Memory Pixmap
520 #ifdef __linux__
521             if(xSharedMemory && display.useSharedMemory && format)
522             {
523 #ifdef _DEBUG
524                printf("Using shared memory!\n");
525 #endif
526                xDisplay.image = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
527                   format->depth, ZPixmap, null, &xDisplay.shminfo, width, height);
528             }
529             else if(display.useSharedMemory && !xSharedMemory)
530                printf("%s", $"Error: Requested shared memory but shared memory pixmaps are not supported by X server.\n");
531 #endif
532             if(xDisplay.image)
533             {
534                memset(&xDisplay.shminfo, 0, sizeof(XShmSegmentInfo));
535                // printf("shmget: %d\n", xDisplay.image->bytes_per_line * xDisplay.image->height);
536                xDisplay.shminfo.shmid = shmget(IPC_PRIVATE, xDisplay.image->bytes_per_line * xDisplay.image->height, IPC_CREAT|0777);
537                if(xDisplay.shminfo.shmid != -1)
538                {
539                   xDisplay.shminfo.shmaddr = shmat(xDisplay.shminfo.shmid, 0, 0);
540                   if(xDisplay.shminfo.shmaddr != (void *)-1)
541                   {
542                      // printf("%d,  %d\n", xDisplay.shminfo.shmid, xDisplay.shminfo.shmaddr);
543                      xDisplay.shminfo.readOnly = False;
544                      if(XShmAttach(xGlobalDisplay, &xDisplay.shminfo))
545                      {
546                         xDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfo.shmaddr, &xDisplay.shminfo, width, height, format->depth);
547
548                         xDisplay.bitmap.width = width;
549                         xDisplay.bitmap.height = height;
550                         xDisplay.bitmap.stride = xDisplay.image->bytes_per_line >> GetColorDepthShifts(display.pixelFormat);
551                         xDisplay.bitmap.pixelFormat = display.pixelFormat;
552                         xDisplay.bitmap.picture = (byte *)xDisplay.shminfo.shmaddr;
553                         xDisplay.bitmap.size = width * height;
554                         xDisplay.bitmap.sizeBytes = (uint)xDisplay.bitmap.size << GetColorDepthShifts(display.pixelFormat);
555                      }
556                   }
557                }
558                if(!xDisplay.pixmap)
559                {
560                   if(xDisplay.shminfo.shmid != -1)
561                   {
562                      XShmDetach(xGlobalDisplay, &xDisplay.shminfo);
563                      if(xDisplay.shminfo.shmaddr != (void *)-1)
564                         shmdt(xDisplay.shminfo.shmaddr);
565                      shmctl(xDisplay.shminfo.shmid, IPC_RMID, 0);
566                   }
567                   XDestroyImage(xDisplay.image);
568                   xDisplay.image = None;
569                }
570             }
571
572 #ifdef __linux__
573             // Initialize Shared Memory Shape Pixmap
574             if(xSharedMemory && display.useSharedMemory && display.alphaBlend)
575                xDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, xSystemVisual /*DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay))*/,
576                   1, ZPixmap, null, &xDisplay.shminfoShape, width, height);
577 #endif
578             if(xDisplay.shapeImage)
579             {
580                xDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE, xDisplay.shapeImage->bytes_per_line * xDisplay.shapeImage->height, IPC_CREAT|0777);
581                if(xDisplay.shminfoShape.shmid != -1)
582                {
583                   xDisplay.shminfoShape.shmaddr = shmat(xDisplay.shminfoShape.shmid, 0, 0);
584                   if(xDisplay.shminfoShape.shmaddr != (void *)-1)
585                   {
586                      xDisplay.shminfoShape.readOnly = False;
587                      if(XShmAttach(xGlobalDisplay, &xDisplay.shminfoShape))
588                      {
589                         xDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, xDisplay.shminfoShape.shmaddr, &xDisplay.shminfoShape, width, height, 1);
590                      }
591                   }
592                }
593                if(!xDisplay.shapePixmap)
594                {
595                   if(xDisplay.shminfoShape.shmid != -1)
596                   {
597                      XShmDetach(xGlobalDisplay, &xDisplay.shminfoShape);
598                      if(xDisplay.shminfoShape.shmaddr != (void *)-1)
599                         shmdt(xDisplay.shminfoShape.shmaddr);
600                      shmctl(xDisplay.shminfoShape.shmid, IPC_RMID, 0);
601                   }
602                   XDestroyImage(xDisplay.shapeImage);
603                   xDisplay.shapeImage = None;
604                }
605             }
606
607             if(!xDisplay.pixmap && format)
608                xDisplay.pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, format->depth);
609             if(display.alphaBlend && !xDisplay.shapePixmap)
610                xDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
611             if(!xDisplay.gc)
612             {
613                xDisplay.gc = XCreateGC(xGlobalDisplay, (Pixmap)xDisplay.pixmap, 0, null);
614                XSetGraphicsExposures(xGlobalDisplay, xDisplay.gc, False);
615             }
616
617             if(format)
618                xDisplay.picture = XRenderCreatePicture(xGlobalDisplay, xDisplay.pixmap, format, CPComponentAlpha, &attributes);
619
620             if(display.alphaBlend)
621                xDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, xDisplay.shapePixmap, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
622          }
623       }
624       xDisplay.updateBox.left = display.width;
625       xDisplay.updateBox.top = display.height;
626       xDisplay.updateBox.right = 0;
627       xDisplay.updateBox.bottom = 0;
628
629       result = true;
630       return result;
631    }
632
633    void DisplayPosition(Display display, int x, int y)
634    {
635       XDisplay xDisplay = display.driverData;
636       xDisplay.offset.x = x;
637       xDisplay.offset.y = y;
638    }
639
640    void RestorePalette(Display display)
641    {
642
643    }
644
645    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
646    {
647       XBitmap xBitmap = bitmap.driverData;
648       if(xBitmap)
649       {
650          if(xBitmap.pixmap)
651             XFreePixmap(xGlobalDisplay, xBitmap.pixmap);
652          if(xBitmap.mask)
653             XFreePixmap(xGlobalDisplay, xBitmap.mask);
654          if(xBitmap.picture)
655             XRenderFreePicture(xGlobalDisplay, xBitmap.picture);
656          if(xBitmap.maskPicture)
657             XRenderFreePicture(xGlobalDisplay, xBitmap.maskPicture);
658          delete xBitmap;
659          bitmap.driverData = null;
660       }
661       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
662    }
663
664    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps, int cubeMapFace)
665    {
666       //XDisplay xDisplay = display.driverData;
667       XBitmap xBitmap { };
668       XImage image = { 0 };
669       GC gc = 0;
670
671 #ifdef ENABLE_XRENDER_WORK_AROUND
672       if(bitmap.pixelFormat == pixelFormatAlpha)
673       {
674          xBitmap.alphaTweak = true;
675          bitmap.alphaBlend = true;
676       }
677 #else
678       if(bitmap.pixelFormat != pixelFormatAlpha)
679 #endif
680          bitmap.Convert(null, bitmap.alphaBlend ? pixelFormat888 : xSystemPixelFormat, null);
681
682       //bitmap.Convert(null, pixelFormatRGBA, null);
683       //bitmap.Convert(null, pixelFormat888, null);
684       xBitmap.pixmap =
685          XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height,
686             (bitmap.pixelFormat == pixelFormatAlpha) ? 8 : (bitmap.alphaBlend ? 32 : ((bitmap.pixelFormat == pixelFormat888) ? 24 : xSystemDepth)));
687       if(bitmap.transparent)
688          xBitmap.mask =
689             XCreatePixmap(xGlobalDisplay, confineWindow /*(X11Window)display.window*/, bitmap.width, bitmap.height, 1);
690
691       {
692          XRenderPictureAttributes attributes = { 0 };
693          XRenderPictFormat * format = GetXRenderFormat(bitmap.pixelFormat, bitmap.alphaBlend);
694          attributes.component_alpha = 1;
695
696          if(format)
697             xBitmap.picture = XRenderCreatePicture(xGlobalDisplay, xBitmap.pixmap, format, CPComponentAlpha, &attributes);
698          if(bitmap.transparent && bitmap.pixelFormat != pixelFormatAlpha)
699             xBitmap.maskPicture = XRenderCreatePicture(xGlobalDisplay, xBitmap.mask, XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), CPComponentAlpha, &attributes);
700       }
701
702       gc = XCreateGC(xGlobalDisplay, (Pixmap)xBitmap.pixmap, 0, null);
703
704       XSetGraphicsExposures(xGlobalDisplay, gc, False);
705
706       image.width = bitmap.width;
707       image.height = bitmap.height;
708
709       if(bitmap.pixelFormat == pixelFormatAlpha)
710       {
711          image.depth = 8;
712          image.bitmap_pad = 8;
713          image.bytes_per_line = bitmap.stride;
714          image.bits_per_pixel = 8;
715       }
716       else
717       {
718          image.depth = bitmap.alphaBlend ? 32 : ((bitmap.pixelFormat == pixelFormat888) ? 24 : xSystemDepth);
719          image.bitmap_pad = (bitmap.pixelFormat == pixelFormat888) ? 32 : 16;
720          image.bytes_per_line = ((bitmap.pixelFormat == pixelFormat888) ? 4 : 2) * bitmap.stride;
721          image.bits_per_pixel = (bitmap.pixelFormat == pixelFormat888) ? 32 : 16;
722       }
723
724       image.format = ZPixmap;
725       //image.bitmap_bit_order = MSBFirst;
726       #ifdef __BIG_ENDIAN__
727       image.byte_order = MSBFirst;
728       #endif
729       image.bitmap_unit = 8;
730       /*
731       image.red_mask   = 0xF800;
732       image.green_mask = 0x7E0;
733       image.blue_mask  = 0x1F;
734       */
735
736       /*
737       image.red_mask   = 0x0000FF;
738       image.green_mask = 0x00FF00;
739       image.blue_mask  = 0xFF0000;
740       */
741       // image.red_mask  = 0xFFFF0000;
742
743       image.data = (char *)bitmap.picture;
744       XInitImage(&image);
745
746       if(bitmap.pixelFormat != pixelFormatAlpha && bitmap.alphaBlend)
747       {
748          int x,y;
749          for(y = 0; y<bitmap.height; y++)
750          {
751             for(x = 0; x<bitmap.width; x++)
752             {
753                ColorAlpha * p = ((ColorAlpha *)bitmap.picture) + y * bitmap.stride + x;
754                int alpha = p->a;
755                p->color.r = (byte)(p->color.r * alpha / 255);
756                p->color.g = (byte)(p->color.g * alpha / 255);
757                p->color.b = (byte)(p->color.b * alpha / 255);
758             }
759          }
760       }
761
762       XPutImage(xGlobalDisplay, (Pixmap)xBitmap.pixmap, gc, &image,
763          0, 0, 0, 0, bitmap.width,bitmap.height);
764
765       if(bitmap.transparent && !bitmap.alphaBlend && bitmap.pixelFormat != pixelFormatAlpha)
766          PutBitmapMask(xBitmap.mask, bitmap);
767
768       XFreeGC(xGlobalDisplay, gc);
769
770       if(!bitmap.keepData)
771          delete bitmap.picture;
772
773       bitmap.driverData = xBitmap;
774       bitmap.driver = displaySystem.driver;
775       return true;
776    }
777
778    void ReleaseSurface(Display display, Surface surface)
779    {
780       XSurface xSurface = surface.driverData;
781       XDisplay xDisplay = display ? display.driverData : null;
782       XRectangle rectangle;
783
784       if(xSurface.colorPicture)
785          XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
786
787       rectangle.x = 0;
788       rectangle.y = 0;
789       if(display)
790       {
791          rectangle.width = (uint16)display.width;
792          rectangle.height = (uint16)display.height;
793          XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
794       }
795
796       if(xSurface.colorPixmap)
797          XFreePixmap(xGlobalDisplay, xSurface.colorPixmap);
798
799       delete xSurface;
800    }
801
802    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
803    {
804       bool result = false;
805       XBitmap xBitmap = bitmap.driverData;
806       XSurface xSurface;
807
808       if((surface.driverData = xSurface = XSurface { }))
809       {
810          surface.offset.x = x;
811          surface.offset.y = y;
812          surface.unclippedBox = surface.box = clip;
813
814          xSurface.pixmap = xBitmap.pixmap;
815
816          result = true;
817       }
818       return result;
819    }
820
821    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
822    {
823       bool result = false;
824       XDisplay xDisplay = display.driverData;
825       XSurface xSurface;
826       if((surface.driverData = xSurface = XSurface { }))
827       {
828          XRectangle rectangle;
829
830          surface.offset.x = x;
831          surface.offset.y = y;
832          surface.unclippedBox = surface.box = clip;
833          xSurface.pixmap = xDisplay.pixmap;
834          xSurface.picture = xDisplay.picture;
835
836          xSurface.colorPixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, 1, 1, /*(xSystemDepth == 16) ? 16 : */32);
837
838          rectangle.x = (short)(clip.left + x);
839          rectangle.y = (short)(clip.top + y);
840          rectangle.width = (short)(clip.right - clip.left + 1);
841          rectangle.height = (short)(clip.bottom - clip.top + 1);
842
843          XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
844          XRenderSetPictureClipRectangles(xGlobalDisplay, xDisplay.picture, 0, 0, &rectangle, 1);
845
846          xDisplay.updateBox.left  = Min(x + clip.left,  xDisplay.updateBox.left);
847          xDisplay.updateBox.top   = Min(y + clip.top,   xDisplay.updateBox.top);
848          xDisplay.updateBox.right = Max(x + clip.right, xDisplay.updateBox.right);
849          xDisplay.updateBox.bottom  = Max(y + clip.bottom,  xDisplay.updateBox.bottom);
850
851          result = true;
852       }
853       return result;
854    }
855
856    void Clip(Display display, Surface surface, Box clip)
857    {
858       XSurface xSurface = surface.driverData;
859       XDisplay xDisplay = display.driverData;
860       bool changed = false;
861       if(clip != null)
862       {
863          Box box = clip;
864
865          box.Clip(surface.unclippedBox);
866
867          surface.box = box;
868
869          xSurface.clipped = true;
870          changed = true;
871       }
872       else if(xSurface.clipped)
873       {
874          surface.box = surface.unclippedBox;
875          xSurface.clipped = false;
876          changed = true;
877       }
878       if(changed)
879       {
880          XRectangle rectangle =
881          {
882             (short)(surface.box.left + surface.offset.x),
883             (short)(surface.box.top + surface.offset.y),
884             (short)(surface.box.right - surface.box.left + 1),
885             (short)(surface.box.bottom - surface.box.top + 1)
886          };
887          XSetClipRectangles(xGlobalDisplay, xDisplay.gc,
888             0,0, &rectangle, 1, YXBanded);
889       }
890    }
891
892    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
893    {
894       bool result = false;
895       XDisplay xDisplay = display ? display.driverData : null;
896       XImage * xImage;
897       PixelFormat format = pixelFormat888;
898       Bitmap source { };
899       int sx = x, sy = y;
900       int dx = 0, dy = 0;
901       int sw = w, sh = h;
902
903       if(sx<0)
904       {
905          dx+=-sx;
906          sw-=-sx;
907          sx=0;
908       }
909       if(sy<0)
910       {
911          dy+=0-sy;
912          sh-=0-sy;
913          sy=0;
914       }
915       if(display)
916       {
917          if(sx+sw>display.width-1)
918             sw-=sx+sw-(display.width-1)-1;
919          if(sy+sh>display.height-1)
920             sh-=sy+sh-(display.height-1)-1;
921       }
922
923       if(display)
924          xImage = XGetImage(xGlobalDisplay, xDisplay.pixmap, sx, sy, sw, sh, MAXDWORD, ZPixmap);
925       else
926          xImage = XGetImage(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), sx, sy, sw, sh, MAXDWORD, ZPixmap);
927
928       source.pixelFormat = format;
929       source.picture = (byte *)xImage->data;
930       source.width = sw;
931       source.height = sh;
932       source.stride = xImage->bytes_per_line / 4;
933
934       if(!bitmap || bitmap.pixelFormat != format || bitmap.width < w || bitmap.height < h)
935       {
936          bitmap.Free();
937          bitmap.Allocate(null, w,h,w, format, (format == pixelFormat8)?true:false);
938       }
939       if(bitmap)
940       {
941          Surface surface = bitmap.GetSurface(0, 0, null);
942          surface.Blit(source, dx,dy,0,0,sw,sh);
943          delete surface;
944          result = true;
945       }
946       source.picture = null;
947       delete source;
948
949       XDestroyImage(xImage);
950       return result;
951    }
952
953    void SetForeground(Display display, Surface surface, ColorAlpha color)
954    {
955       XSurface xSurface = surface.driverData;
956       XDisplay xDisplay = display ? display.driverData : null;
957       XRenderColor renderColor = { (uint16)(color.color.r * color.a), (uint16)(color.color.g * color.a), (uint16)(color.color.b * color.a), (uint16)(color.a * 255) };
958
959       if(xSurface.colorPicture)
960          XRenderFreePicture(xGlobalDisplay, xSurface.colorPicture);
961       // xSurface.colorPicture = XRenderCreateSolidFill(xGlobalDisplay, &renderColor);
962
963       {
964          XRenderPictureAttributes attributes = { 0 };
965          // XRenderPictFormat * format = myXRenderFindStandardFormat(xGlobalDisplay, PictStandardARGB32  /*PictStandardRGB24 /*PictStandardARGB32*/, 1);
966          XRenderPictFormat * format = /*(xSystemPixelFormat != pixelFormat888) ? GetXRenderFormat(xSystemPixelFormat, false) : */XRenderFindStandardFormat(xGlobalDisplay, PictStandardARGB32);
967          #if !defined(__APPLE__) && !defined(__OLDX__)
968          attributes.repeat = RepeatNormal;
969          #else
970          attributes.repeat = 1;
971          #endif
972          ///attributes.component_alpha = 0;
973          if(format)
974             xSurface.colorPicture = XRenderCreatePicture(xGlobalDisplay, xSurface.colorPixmap, format, /*CPComponentAlpha | */CPRepeat, &attributes);
975          XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.colorPicture, &renderColor, 0, 0, 1, 1);
976       }
977
978       // xSurface.foreground = ARGB(A(color),B(color),G(color),R(color));
979       xSurface.foreground = color;
980
981       if(xDisplay)
982          XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
983             ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
984    }
985
986    void SetBackground(Display display, Surface surface, ColorAlpha color)
987    {
988       XSurface xSurface = surface.driverData;
989       XDisplay xDisplay = display ? display.driverData : null;
990       // xSurface.background = ARGB(A(color),B(color),G(color),R(color));
991       xSurface.background = color;
992
993       if(xDisplay)
994          XSetBackground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
995             ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
996    }
997
998    ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
999    {
1000       return 0;
1001    }
1002
1003    void PutPixel(Display display, Surface surface,int x,int y)
1004    {
1005       XSurface xSurface = surface.driverData;
1006       XDisplay xDisplay = display.driverData;
1007
1008       if(xSurface.foreground.a < 255)
1009          DrawLine(display, surface, x,y,x,y);
1010       else
1011          XDrawPoint(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1012             x + surface.offset.x,
1013             y + surface.offset.y);
1014    }
1015
1016    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1017    {
1018       XDisplay xDisplay = display ? display.driverData : null;
1019       XSurface xSurface = surface.driverData;
1020       if(!xDisplay || xSurface.foreground.a < 255)
1021       {
1022          XTrapezoid traps[3];
1023          int nTraps = 0;
1024          double offset = 0.5;
1025          double width = 0.5;
1026
1027          x1 += surface.offset.x;
1028          y1 += surface.offset.y;
1029          x2 += surface.offset.x;
1030          y2 += surface.offset.y;
1031
1032          if(y1 == y2)
1033          {
1034             x2++;
1035             x1--;
1036             {
1037                XTrapezoid trap1 =
1038                {
1039                   XDoubleToFixed(y1 - width + offset), XDoubleToFixed(y1 + width + offset),
1040                   { { XDoubleToFixed(Min(x1, x2) - 0 + offset), XDoubleToFixed(y1 - width + offset) }, { XDoubleToFixed(Min(x1, x2) + 0.0 + offset), XDoubleToFixed(y1 + width+ offset) } },
1041                   { { XDoubleToFixed(Max(x1, x2) - 0 + offset), XDoubleToFixed(y1 - width + offset) }, { XDoubleToFixed(Max(x1, x2) + 0.0 + offset), XDoubleToFixed(y1 + width+ offset) } }
1042                };
1043                traps[0] = trap1;
1044                nTraps = 1;
1045             }
1046          }
1047          else if(x1 == x2)
1048          {
1049             y2++;
1050             y1--;
1051             {
1052                XTrapezoid trap1 =
1053                {
1054                   XDoubleToFixed(Min(y1, y2) - 0.0 + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset),
1055                   { { XDoubleToFixed(x1 - width + offset), XDoubleToFixed(Min(y1, y2) - 0.0 + offset) }, { XDoubleToFixed(x1 - width + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset) } },
1056                   { { XDoubleToFixed(x1 + width + offset), XDoubleToFixed(Min(y1, y2) - 0.0 + offset) }, { XDoubleToFixed(x1 + width + offset), XDoubleToFixed(Max(y1, y2) + 0.0 + offset) } }
1057                };
1058                traps[0] = trap1;
1059                nTraps = 1;
1060             }
1061          }
1062          else
1063          {
1064             double dx, dy, l;
1065             Pointf A, B, C, D, E, F;
1066             if(y1 > y2)
1067             {
1068                int tmp = y2;
1069                y2 = y1;
1070                y1 = tmp;
1071                tmp = x2;
1072                x2 = x1;
1073                x1 = tmp;
1074             }
1075
1076             dx = x2 - x1;
1077             dy = y2 - y1;
1078             l = sqrt(dx * dx + dy * dy);
1079             dx /= l;
1080             dy /= l;
1081
1082             if(x2 > x1)
1083             {
1084                A = { (float)(x1 + dy * width), (float)(y1 - dx * width) };
1085                B = { (float)(x1 - dy * width), (float)(y1 + dx * width) };
1086                C = { (float)(A.x + ((B.y - A.y) * dx / dy)), B.y };
1087                E = { (float)(x2 + dy * width), (float)(y2 - dx * width) };
1088                F = { (float)(x2 - dy * width), (float)(y2 + dx * width) };
1089                D = { (float)(F.x + ((E.y - F.y) * dx / dy)), E.y };
1090
1091                {
1092                   XTrapezoid trap1 =
1093                   {
1094                      XDoubleToFixed(A.y + offset), XDoubleToFixed(B.y + offset),
1095                      { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) } },
1096                      { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) } }
1097                   };
1098                   XTrapezoid trap2 =
1099                   {
1100                      XDoubleToFixed(B.y + offset), XDoubleToFixed(D.y + offset),
1101                      { { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) }, { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) } },
1102                      { { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) }, { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) } }
1103                   };
1104                   XTrapezoid trap3 =
1105                   {
1106                      XDoubleToFixed(D.y + offset), XDoubleToFixed(F.y + offset),
1107                      { { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } },
1108                      { { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } }
1109                   };
1110                   traps[0] = trap1;
1111                   traps[1] = trap2;
1112                   traps[2] = trap3;
1113                   nTraps = 3;
1114                }
1115             }
1116             else
1117             {
1118                A = { (float)(x1 - dy * width), (float)(y1 + dx * width) };
1119                B = { (float)(x1 + dy * width), (float)(y1 - dx * width) };
1120                C = { (float)(A.x + ((B.y - A.y) * dx / dy)), B.y };
1121                E = { (float)(x2 - dy * width), (float)(y2 + dx * width) };
1122                F = { (float)(x2 + dy * width), (float)(y2 - dx * width) };
1123                D = { (float)(F.x + ((E.y - F.y) * dx / dy)), E.y };
1124
1125                {
1126                   XTrapezoid trap1 =
1127                   {
1128                      XDoubleToFixed(A.y + offset), XDoubleToFixed(B.y + offset),
1129                      { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) } },
1130                      { { XDoubleToFixed(A.x + offset), XDoubleToFixed(A.y + offset) }, { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) } }
1131                   };
1132                   XTrapezoid trap2 =
1133                   {
1134                      XDoubleToFixed(B.y + offset), XDoubleToFixed(D.y + offset),
1135                      { { XDoubleToFixed(C.x + offset), XDoubleToFixed(C.y + offset) }, { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) } },
1136                      { { XDoubleToFixed(B.x + offset), XDoubleToFixed(B.y + offset) }, { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) } }
1137                   };
1138                   XTrapezoid trap3 =
1139                   {
1140                      XDoubleToFixed(D.y + offset), XDoubleToFixed(F.y + offset),
1141                      { { XDoubleToFixed(E.x + offset), XDoubleToFixed(E.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } },
1142                      { { XDoubleToFixed(D.x + offset), XDoubleToFixed(D.y + offset) }, { XDoubleToFixed(F.x + offset), XDoubleToFixed(F.y + offset) } }
1143                   };
1144                   traps[0] = trap1;
1145                   traps[1] = trap2;
1146                   traps[2] = trap3;
1147                   nTraps = 3;
1148                }
1149             }
1150             /*
1151             printf("Line: (%d, %d)-(%d, %d)\n", x1,y1, x2,y2);
1152             printf("Line: A = (%.2f, %.2f), B = (%.2f, %.2f), C = (%.2f, %.2f)\n", A.x,A.y, B.x,B.y, C.x,C.y);
1153             printf("Line: D = (%.2f, %.2f), E = (%.2f, %.2f), F = (%.2f, %.2f)\n", D.x,D.y, E.x,E.y, F.x,F.y);
1154             printf("Trap1: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1155                traps[0].top / 65536.0, traps[0].bottom / 65536.0,
1156                traps[0].left.p1.x / 65536.0, traps[0].left.p1.y / 65536.0, traps[0].left.p2.x / 65536.0, traps[0].left.p2.y / 65536.0,
1157                traps[0].right.p1.x / 65536.0, traps[0].right.p1.y / 65536.0, traps[0].right.p2.x / 65536.0, traps[0].right.p2.y / 65536.0);
1158             printf("Trap2: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1159                traps[1].top / 65536.0, traps[1].bottom / 65536.0,
1160                traps[1].left.p1.x / 65536.0,  traps[1].left.p1.y / 65536.0,  traps[1].left.p2.x / 65536.0,  traps[1].left.p2.y / 65536.0,
1161                traps[1].right.p1.x / 65536.0, traps[1].right.p1.y / 65536.0, traps[1].right.p2.x / 65536.0, traps[1].right.p2.y / 65536.0);
1162             printf("Trap3: top = %.2f, bottom = %.2f, left = (%.2f, %.2f)-(%.2f, %.2f), right = (%.2f, %.2f)-(%.2f, %.2f)\n",
1163                traps[2].top / 65536.0, traps[2].bottom / 65536.0,
1164                traps[2].left.p1.x / 65536.0,  traps[2].left.p1.y / 65536.0,  traps[2].left.p2.x / 65536.0,  traps[2].left.p2.y / 65536.0,
1165                traps[2].right.p1.x / 65536.0, traps[2].right.p1.y / 65536.0, traps[2].right.p2.x / 65536.0, traps[2].right.p2.y / 65536.0);
1166             printf("\n");
1167             */
1168          }
1169          XRenderCompositeTrapezoids(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xSurface.picture, None, 0, 0, traps, nTraps);
1170       }
1171       else
1172          XDrawLine(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1173             x1 + surface.offset.x,
1174             y1 + surface.offset.y,
1175             x2 + surface.offset.x,
1176             y2 + surface.offset.y);
1177    }
1178
1179    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1180    {
1181       XDisplay xDisplay = display ? display.driverData : null;
1182       XSurface xSurface = surface.driverData;
1183
1184       if(!xDisplay || xSurface.foreground.a < 255)
1185       {
1186          DrawLine(display, surface,x1,y1,x2-1,y1);
1187          DrawLine(display, surface,x2,y1,x2,y2-1);
1188          DrawLine(display, surface,x1,y2,x2-1,y2);
1189          DrawLine(display, surface,x1,y1+1,x1,y2-1);
1190       }
1191       else
1192          XDrawRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1193             x1 + surface.offset.x,
1194             y1 + surface.offset.y,
1195             x2 - x1, y2 - y1);
1196    }
1197
1198    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1199    {
1200       XDisplay xDisplay = display ? display.driverData : null;
1201       XSurface xSurface = surface.driverData;
1202       if(!xDisplay || xSurface.background.a < 255)
1203       {
1204          XRenderColor renderColor =
1205          {
1206             (uint16)(xSurface.background.color.r * xSurface.background.a),
1207             (uint16)(xSurface.background.color.g * xSurface.background.a),
1208             (uint16)(xSurface.background.color.b * xSurface.background.a),
1209             (uint16)(xSurface.background.a * 255)
1210          };
1211          x1 += surface.offset.x;
1212          y1 += surface.offset.y;
1213          x2 += surface.offset.x;
1214          y2 += surface.offset.y;
1215          XRenderFillRectangle(xGlobalDisplay, PictOpOver, xSurface.picture, &renderColor, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1);
1216       }
1217       else
1218       {
1219          XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.background :
1220             ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.background) : ((Color555)xSurface.background)));
1221          XFillRectangle(xGlobalDisplay, (Pixmap) xDisplay.pixmap, xDisplay.gc,
1222             x1 + surface.offset.x,
1223             y1 + surface.offset.y,
1224             x2 - x1 + 1, y2 - y1 + 1);
1225          XSetForeground(xGlobalDisplay, xDisplay.gc, (xSystemPixelFormat == pixelFormat888) ? xSurface.foreground :
1226             ((xSystemPixelFormat == pixelFormat565) ? ((Color565)xSurface.foreground) : ((Color555)xSurface.foreground)));
1227       }
1228    }
1229
1230    void Clear(Display display, Surface surface, ClearType flags)
1231    {
1232       if(flags != depthBuffer)
1233       {
1234          // XDisplay xDisplay = display.driverData;
1235          XSurface xSurface = surface.driverData;
1236          if(xSurface.background.a < 255)
1237          {
1238             int x1 = surface.box.left;
1239             int y1 = surface.box.top;
1240             int x2 = surface.box.right;
1241             int y2 = surface.box.bottom;
1242             XRenderColor renderColor =
1243             {
1244                (uint16)(xSurface.background.color.r * xSurface.background.a),
1245                (uint16)(xSurface.background.color.g * xSurface.background.a),
1246                (uint16)(xSurface.background.color.b * xSurface.background.a),
1247                (uint16)(xSurface.background.a * 255)
1248             };
1249             x1 += surface.offset.x;
1250             y1 += surface.offset.y;
1251             x2 += surface.offset.x;
1252             y2 += surface.offset.y;
1253             XRenderFillRectangle(xGlobalDisplay, PictOpSrc, xSurface.picture, &renderColor, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1);
1254          }
1255          else
1256             Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1257       }
1258    }
1259
1260    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
1261    {
1262       return true;
1263    }
1264
1265    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1266    {
1267       bool result = false;
1268       XBitmap xBitmap = bitmap.driverData = XBitmap { };
1269       if(xBitmap)
1270       {
1271          if(!stride)
1272          {
1273             switch(GetColorDepthShifts(format))
1274             {
1275                case 0: stride = (width + 3) & 0xFFFFFFFC; break;
1276                case 1: stride = (width + 1) & 0xFFFFFFFE; break;
1277                case 2: stride = width;                    break;
1278             }
1279          }
1280
1281          bitmap.stride = stride;
1282          bitmap.width = width;
1283          bitmap.height = height;
1284          bitmap.size = (uint)stride * (uint)height;
1285          bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
1286          bitmap.pixelFormat = format;
1287          bitmap.transparent = false;
1288          bitmap.allocatePalette = allocatePalette;
1289          if(allocatePalette)
1290          {
1291             bitmap.palette = new ColorAlpha[256];
1292             if(bitmap.palette)
1293                CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
1294          }
1295          else
1296             bitmap.palette = GetDefaultPalette();
1297
1298          result = true;
1299
1300          if(!result)
1301             FreeBitmap(displaySystem, bitmap);
1302       }
1303
1304       return result;
1305    }
1306
1307    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1308    {
1309       XDisplay xDisplay = display.driverData;
1310       XSurface xSurface = surface.driverData;
1311       XBitmap xBitmap = src.driverData;
1312       if(xBitmap)
1313       {
1314          bool flip;
1315          if(!ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1316             return;
1317
1318          dx += surface.offset.x;
1319          dy += surface.offset.y;
1320
1321          if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1322          {
1323             XSetClipMask(xGlobalDisplay, xDisplay.gc, xBitmap.mask);
1324             XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx - sx, dy - sy);
1325          }
1326          if(xSurface.xOffset)
1327          {
1328             XTransform transform =
1329             {
1330                {
1331                   { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), -(xSurface.xOffset << 10) },
1332                   { (int)(0.0f), (int)(-1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1333                   { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1334                }
1335             };
1336             // printf("XOffset: %d\n", xSurface.xOffset);
1337             XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1338          }
1339
1340          if(src.alphaBlend || display.alphaBlend)
1341          {
1342             if(src.pixelFormat == pixelFormatAlpha
1343 #ifdef ENABLE_XRENDER_WORK_AROUND
1344                || xBitmap.alphaTweak
1345 #endif
1346                )
1347             {
1348                XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w + (xSurface.xOffset ? 1 : 1), h);
1349             }
1350             else if(src.alphaBlend)
1351                XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1352             else
1353                XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1354          }
1355          else
1356             XCopyArea(xGlobalDisplay, (Pixmap)xBitmap.pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc,
1357                sx, sy, w, h, dx, dy);
1358
1359          if(xSurface.xOffset)
1360          {
1361             XTransform identity =
1362             {
1363                {
1364                   { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1365                   { (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1366                   { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1367                }
1368             };
1369             XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1370          }
1371          if(src.transparent && !src.alphaBlend && !display.alphaBlend)
1372          {
1373             XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1374             {
1375                XRectangle rectangle;
1376
1377                rectangle.x = (short)(surface.unclippedBox.left + surface.offset.x);
1378                rectangle.y = (short)(surface.unclippedBox.top + surface.offset.y);
1379                rectangle.width = (short)(surface.unclippedBox.right - surface.unclippedBox.left + 1);
1380                rectangle.height = (short)(surface.unclippedBox.bottom - surface.unclippedBox.top + 1);
1381
1382                XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1383             }
1384          }
1385       }
1386    }
1387
1388    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1389    {
1390       XSurface xSurface = surface.driverData;
1391       XBitmap xBitmap = src.driverData;
1392       if(xBitmap)
1393       {
1394          XTransform transform =
1395          {
1396             {
1397                { (int)((float)sw / w * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1398                { (int)(0.0f * (1<<16)), (int)((float)sh / h * (1<<16)), (int)(0.0f * (1<<16)) },
1399                { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1400             }
1401          };
1402          XTransform identity =
1403          {
1404             {
1405                { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1406                { (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)) },
1407                { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)), (int)(1.0f * (1<<16)) }
1408             }
1409          };
1410          dx += surface.offset.x;
1411          dy += surface.offset.y;
1412
1413          XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &transform);
1414
1415          if(src.pixelFormat == pixelFormatAlpha
1416 #ifdef ENABLE_XRENDER_WORK_AROUND
1417             || xBitmap.alphaTweak
1418 #endif
1419             )
1420             XRenderComposite(xGlobalDisplay, PictOpOver, xSurface.colorPicture, xBitmap.picture, xSurface.picture, 0, 0, sx, sy, dx, dy, w, h);
1421          else if(src.alphaBlend)
1422             XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, None, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1423          else
1424          {
1425             XRenderSetPictureTransform(xGlobalDisplay, xBitmap.maskPicture, &transform);
1426             XRenderComposite(xGlobalDisplay, PictOpOver, xBitmap.picture, xBitmap.maskPicture, xSurface.picture, sx, sy, sx, sy, dx, dy, w, h);
1427             XRenderSetPictureTransform(xGlobalDisplay, xBitmap.maskPicture, &identity);
1428          }
1429          XRenderSetPictureTransform(xGlobalDisplay, xBitmap.picture, &identity);
1430       }
1431    }
1432
1433    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1434    {
1435       XBitmap xBitmap = src.driverData;
1436       if(xBitmap)
1437       {
1438          XRenderSetPictureFilter(xGlobalDisplay, xBitmap.picture, "bilinear", null, 0);
1439          Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
1440          XRenderSetPictureFilter(xGlobalDisplay, xBitmap.picture, "nearest", null, 0);
1441       }
1442    }
1443
1444    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1445    {
1446       XImage image = { 0 };
1447       XDisplay xDisplay = display ? display.driverData : null;
1448       XSurface xSurface = surface.driverData;
1449       bool flip;
1450
1451       if(!xDisplay || !src.picture || !ClipBlitCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &flip))
1452          return;
1453
1454       if(src.pixelFormat == display.pixelFormat)
1455       {
1456          image.width = src.width;
1457          image.height = src.height;
1458          image.depth = (src.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1459          image.bitmap_pad = (src.pixelFormat == pixelFormat888) ? 32 : 16;
1460          image.format = ZPixmap;
1461          image.bitmap_unit = 8;
1462          image.bytes_per_line = ((src.pixelFormat == pixelFormat888) ? 4 : 2) * src.stride;
1463          image.bits_per_pixel = (src.pixelFormat == pixelFormat888) ? 32 : 16;
1464
1465          image.data = (char *)src.picture;
1466          XInitImage(&image);
1467
1468          XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1469             sx, sy, dx + surface.offset.x, dy + surface.offset.y, w,h);
1470       }
1471       else
1472       {
1473          Bitmap temp { };
1474          Surface s;
1475          temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1476          s = temp.GetSurface(0,0,null);
1477          s.Blit(src, 0,0, sx,sy, flip ? -w : w, h);
1478
1479          image.width = w;
1480          image.height = h;
1481          image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1482          image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1483          image.format = ZPixmap;
1484          image.bitmap_unit = 8;
1485          image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1486          image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1487
1488          image.data = (char *)temp.picture;
1489
1490          XInitImage(&image);
1491          if(!src.transparent)
1492          {
1493             // printf("Stride: %d, dx: %d, dy: %d, w: %d, h: %d, %d\n", temp.stride, dx + surface.offset.x, dy + surface.offset.y, w,h, xSystemDepth);
1494             XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1495                0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1496          }
1497          else
1498          {
1499          #if 0
1500             GC maskGC = 0, gc = 0;
1501             Pixmap pixmap, mask;
1502
1503             pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1504             mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1505
1506             gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1507             maskGC = XCreateGC(xGlobalDisplay, mask, 0, null);
1508             XSetGraphicsExposures(xGlobalDisplay, gc, False);
1509             XSetGraphicsExposures(xGlobalDisplay, maskGC, False);
1510
1511             XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1512             XSetForeground(xGlobalDisplay, maskGC, 0);
1513             XFillRectangle(xGlobalDisplay, mask, maskGC, 0, 0, w, h);
1514             XSetForeground(xGlobalDisplay, maskGC, 1);
1515             if(temp.pixelFormat == pixelFormat888)
1516             {
1517                int x,y;
1518                for(y = 0; y<h; y++)
1519                {
1520                   for(x = 0; x<w; x++)
1521                   {
1522                      if(((ColorAlpha *)temp.picture)[y * temp.stride + x].a)
1523                         XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1524                   }
1525                }
1526             }
1527             else if(src.pixelFormat == pixelFormat8)
1528             {
1529                int x,y;
1530                for(y = 0; y<h; y++)
1531                {
1532                   for(x = 0; x<w; x++)
1533                   {
1534                      if(src.picture[(y + sy) * src.stride + (flip ? (w-1-(sx + x)) : (sx + x)])
1535                         XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1536                   }
1537                }
1538             }
1539             else
1540             {
1541                int x,y;
1542                for(y = 0; y<h; y++)
1543                {
1544                   for(x = 0; x<w; x++)
1545                   {
1546                      if(((uint16 *)temp.picture)[y * temp.stride + x])
1547                         XDrawPoint(xGlobalDisplay, mask, maskGC, x, y);
1548                   }
1549                }
1550             }
1551
1552             XFreeGC(xGlobalDisplay, maskGC);
1553          #else
1554          GC gc = 0;
1555             Pixmap pixmap, mask;
1556
1557             pixmap = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, xSystemDepth /*24*/);
1558             mask = XCreatePixmap(xGlobalDisplay, (X11Window)confineWindow /*display.window*/, w, h, 1);
1559
1560             gc = XCreateGC(xGlobalDisplay, pixmap, 0, null);
1561             XSetGraphicsExposures(xGlobalDisplay, gc, False);
1562
1563             XPutImage(xGlobalDisplay, pixmap, gc, &image, 0, 0, 0, 0, w,h);
1564
1565          PutBitmapMask(mask, temp);
1566          #endif
1567
1568             XSetClipMask(xGlobalDisplay, xDisplay.gc, mask);
1569             XSetClipOrigin(xGlobalDisplay, xDisplay.gc, dx + surface.offset.x, dy + surface.offset.y);
1570             XCopyArea(xGlobalDisplay, pixmap, (Pixmap)xSurface.pixmap, xDisplay.gc, 0, 0, w, h, dx + surface.offset.x, dy + surface.offset.y);
1571             XSetClipOrigin(xGlobalDisplay, xDisplay.gc, 0, 0);
1572             {
1573                XRectangle rectangle;
1574
1575                rectangle.x = (short)(surface.unclippedBox.left + surface.offset.x);
1576                rectangle.y = (short)(surface.unclippedBox.top + surface.offset.y);
1577                rectangle.width = (short)(surface.unclippedBox.right - surface.unclippedBox.left + 1);
1578                rectangle.height = (short)(surface.unclippedBox.bottom - surface.unclippedBox.top + 1);
1579
1580                XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1581             }
1582
1583             XFreeGC(xGlobalDisplay, gc);
1584             XFreePixmap(xGlobalDisplay, pixmap);
1585             XFreePixmap(xGlobalDisplay, mask);
1586          }
1587          delete s;
1588          delete temp;
1589       }
1590    }
1591
1592    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1593    {
1594       bool flip;
1595       if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1596       {
1597          XImage image = { 0 };
1598          XDisplay xDisplay = display.driverData;
1599          XSurface xSurface = surface.driverData;
1600          Bitmap temp { };
1601          Surface s;
1602          temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1603          s = temp.GetSurface(0,0,null);
1604          s.Stretch(src, 0,0, sx,sy, w, h, sw, sh);
1605
1606          image.width = w;
1607          image.height = h;
1608          image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1609          image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1610          image.format = ZPixmap;
1611          image.bitmap_unit = 8;
1612          image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1613          image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1614
1615          image.data = (char *)temp.picture;
1616          XInitImage(&image);
1617
1618          // printf("Blitting DI\n");
1619          XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1620             0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1621
1622          delete s;
1623          delete temp;
1624       }
1625    }
1626
1627    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1628    {
1629       bool flip;
1630       if(ClipStretchCoords(surface, src, &dx, &dy, &sx, &sy, &w, &h, &sw, &sh, &flip))
1631       {
1632          XImage image = { 0 };
1633          XDisplay xDisplay = display.driverData;
1634          XSurface xSurface = surface.driverData;
1635          Bitmap temp { };
1636          Surface s;
1637          temp.Allocate(null, w, h, 0, xSystemPixelFormat, false);
1638          s = temp.GetSurface(0,0,null);
1639          s.Filter(src, 0,0, sx,sy, w, h, sw, sh);
1640
1641          image.width = w;
1642          image.height = h;
1643          image.depth = (temp.pixelFormat == pixelFormat888) ? 24 : xSystemDepth;
1644          image.bitmap_pad = (temp.pixelFormat == pixelFormat888) ? 32 : 16;
1645          image.format = ZPixmap;
1646          image.bitmap_unit = 8;
1647          image.bytes_per_line = ((temp.pixelFormat == pixelFormat888) ? 4 : 2) * temp.stride;
1648          image.bits_per_pixel = (temp.pixelFormat == pixelFormat888) ? 32 : 16;;
1649
1650          image.data = (char *)temp.picture;
1651          XInitImage(&image);
1652
1653          // printf("Blitting DI\n");
1654          XPutImage(xGlobalDisplay, (Pixmap)xSurface.pixmap, xDisplay.gc, &image,
1655             0, 0, dx + surface.offset.x, dy + surface.offset.y, w,h);
1656
1657          delete s;
1658          delete temp;
1659       }
1660    }
1661
1662    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
1663    {
1664       Font font;
1665       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
1666       return font;
1667    }
1668
1669    void UnloadFont(DisplaySystem displaySystem, Font font)
1670    {
1671       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
1672    }
1673
1674    void TextFont(Display display, Surface surface, Font font)
1675    {
1676       // XSurface xSurface = surface.driverData;
1677       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
1678    }
1679
1680    void TextOpacity(Display display, Surface surface, bool opaque)
1681    {
1682       XSurface xSurface = surface.driverData;
1683       xSurface.opaque = opaque;
1684    }
1685
1686    #define CHAR_WIDTH   6
1687    #define CHAR_HEIGHT  14
1688
1689    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
1690    {
1691       XSurface xSurface = surface.driverData;
1692       //XDisplay xDisplay = display.driverData;
1693       int tw, th, adv;
1694
1695       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, &tw, &th, prevGlyph, rPrevGlyph, &adv);
1696       tw += adv;
1697       if(xSurface.opaque)
1698       {
1699 #if 0
1700          XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.background);
1701
1702          XFillRectangle(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1703             x + surface.offset.x, y + surface.offset.y,
1704             tw /*len * CHAR_WIDTH*/, th /*CHAR_HEIGHT*/);
1705
1706          XSetForeground(xGlobalDisplay, xDisplay.gc, xSurface.foreground);
1707 #endif
1708
1709          XRenderColor renderColor =
1710          {
1711             (uint16)(xSurface.background.color.r * xSurface.background.a),
1712             (uint16)(xSurface.background.color.g * xSurface.background.a),
1713             (uint16)(xSurface.background.color.b * xSurface.background.a),
1714             (uint16)xSurface.background.a
1715          };
1716          //printf("Filling rectangle\n");
1717          XRenderFillRectangle(xGlobalDisplay, PictOpSrc /*PictOpOver*/, xSurface.picture, &renderColor,
1718             x + surface.offset.x, y + surface.offset.y, tw, th);
1719       }
1720       /*
1721       XDrawString(xGlobalDisplay, (Pixmap)xDisplay.pixmap, xDisplay.gc,
1722          x + surface.offset.x, y + surface.offset.y + 12, text, len);
1723       */
1724
1725       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
1726    }
1727
1728    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
1729    {
1730       XSurface xSurface = surface.driverData;
1731       /*
1732       uint realLen;
1733       for(realLen = 0; realLen<len && text[realLen]; realLen++);
1734       if(width) *width = len * CHAR_WIDTH;
1735       if(height) *height = CHAR_HEIGHT;
1736       */
1737
1738       FontExtent(display.displaySystem, xSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
1739    }
1740
1741    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
1742    {
1743       /*
1744       if(width) *width = len * CHAR_WIDTH;
1745       if(height) *height = CHAR_HEIGHT;
1746       */
1747       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
1748    }
1749
1750    void DrawingChar(Display display, Surface surface, byte character)
1751    {
1752
1753    }
1754
1755    void LineStipple(Display display, Surface surface, uint stipple)
1756    {
1757       XDisplay xDisplay = display.driverData;
1758       char list[32] = { 0 };
1759       int count = 0;
1760
1761       if(stipple)
1762       {
1763          int c;
1764          int offset = 0;
1765          uint16 on = 0x8000;
1766
1767          for(c = 0; c<32; c++)
1768          {
1769             if((stipple & 0x8000) == on)
1770                list[count]++;
1771             else
1772             {
1773                if(!list[count])
1774                   offset = 1;
1775                else
1776                {
1777                   count++;
1778                   list[count]++;
1779                   on ^= 0x8000;
1780                }
1781             }
1782             stipple <<= 1;
1783          }
1784          XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineOnOffDash, CapButt, JoinMiter);
1785          XSetDashes(xGlobalDisplay, xDisplay.gc, offset, list, count);
1786       }
1787       else
1788       {
1789          list[0] = 4;
1790          count = 1;
1791          XSetLineAttributes(xGlobalDisplay, xDisplay.gc, 0, LineSolid, CapButt, JoinMiter);
1792          XSetDashes(xGlobalDisplay, xDisplay.gc, 0, list, count);
1793       }
1794    }
1795
1796    bool Lock(Display display)
1797    {
1798       //XLockDisplay(xGlobalDisplay);
1799       return true;
1800    }
1801
1802    void Unlock(Display display)
1803    {
1804       //XUnlockDisplay(xGlobalDisplay);
1805    }
1806
1807    void StartUpdate(Display display)
1808    {
1809
1810    }
1811
1812    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1813    {
1814
1815    }
1816
1817    void Update(Display display, Box updateBox)
1818    {
1819       XDisplay xDisplay = display.driverData;
1820       Box * box = (updateBox != null) ? updateBox : &xDisplay.updateBox;
1821
1822       {
1823          XRectangle rectangle;
1824          rectangle.x = 0;
1825          rectangle.y = 0;
1826          rectangle.width = (uint16)display.width;
1827          rectangle.height = (uint16)display.height;
1828          XSetClipRectangles(xGlobalDisplay, xDisplay.gc, 0,0, &rectangle, 1, YXBanded);
1829       }
1830       /*if(display.alphaBlend)
1831          XRenderComposite(xGlobalDisplay, PictOpSrc, xDisplay.picture, None, xDisplay.windowPicture, box->left, box->top, 0, 0, box->left, box->top,
1832             box->right - box->left + 1, box->bottom - box->top + 1);
1833       else*/
1834          XCopyArea(xGlobalDisplay, (Pixmap)xDisplay.pixmap, (X11Window)display.window, xDisplay.gc /*windowGC*/,
1835             box->left, box->top,
1836             box->right - box->left + 1,
1837             box->bottom - box->top + 1,
1838             box->left, box->top);
1839
1840       if(display.alphaBlend)
1841       {
1842          Box * box = &xDisplay.updateBox;
1843          XRenderComposite(xGlobalDisplay, PictOpSrc, xDisplay.picture, None, xDisplay.shapePicture, box->left, box->top, 0, 0, box->left, box->top,
1844             box->right - box->left + 1, box->bottom - box->top + 1);
1845          #if !defined(__APPLE__) && !defined(__OLDX__)
1846          XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, xDisplay.shapePixmap, ShapeSet);
1847          #else
1848          XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, 2, 0, 0, xDisplay.shapePixmap, ShapeSet);
1849          #endif
1850       }
1851
1852       XFlush(xGlobalDisplay);
1853       if(updateBox == null)
1854       {
1855          xDisplay.updateBox.left = display.width;
1856          xDisplay.updateBox.top = display.height;
1857          xDisplay.updateBox.right = 0;
1858          xDisplay.updateBox.bottom = 0;
1859       }
1860    }
1861
1862    void EndUpdate(Display display)
1863    {
1864
1865    }
1866 }
1867
1868 default dllexport long IS_XGetPixmap(Bitmap bitmap)
1869 {
1870    XBitmap xBitmap = bitmap.driverData;
1871    return xBitmap.pixmap;
1872 }
1873
1874 default dllexport void IS_XGetSurfaceInfo(Surface surface, Pixmap * pixmap, GC * gc, int *x, int * y)
1875 {
1876    Display display = surface.display;
1877    XDisplay xDisplay = display.driverData;
1878
1879    *pixmap = xDisplay.pixmap;
1880    *gc = xDisplay.gc;
1881    *x = surface.offset.x;
1882    *y = surface.offset.y;
1883 }
1884
1885 #endif