ecere: Excluding OpenGL dependency for installer configuration
[sdk] / ecere / src / gfx / drivers / LFBDisplayDriver.ec
1 #define _Noreturn
2
3 namespace gfx::drivers;
4
5 #ifdef __MSC__
6 #pragma warning(disable:4244)
7 #pragma warning(disable:4018)
8 #endif
9
10 import "File"
11 import "Display"
12
13 public define LIGHTSHIFT = 5;
14 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
15
16 /*#ifndef ECERE_VANILLA
17 import "lfbRGBLookup"
18 static bool rgbLookupSet = true;
19 #else*/
20 /*static */byte defaultRGBLookup[32768];
21 /*static */bool rgbLookupSet = false;
22 //#endif
23
24 #if defined(ECERE_VANILLA)
25    #define ECERE_NOTRUETYPE
26 #endif
27
28 #if !defined(ECERE_NOTRUETYPE)
29 import "fontManagement"
30 import "fontRendering"
31 #else
32 public class Font : struct { }
33 #endif
34
35 import "lfbBlit"
36 import "lfbConvert"
37
38 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && !defined(ECERE_ONEDRIVER) && defined(__WIN32__)
39 import "OpenGLDisplayDriver"
40
41 #if !defined(_GLES) && !defined(ECERE_STATIC)
42 import "Direct3D8DisplayDriver"
43 import "Direct3D9DisplayDriver"
44 #endif
45
46 #endif
47
48 public class LFBDisplay : struct
49 {
50 public:
51    Bitmap bitmap { };
52    byte rgbLookup[32768];
53    byte lightTable[256][LIGHTSTEPS];
54    OldList updateBoxes;
55    int x,y;
56    bool selfManaged;
57    void (* displayCallback)(Display display, Box updateBox);
58 };
59
60 public class LFBSystem : struct
61 {
62 public:
63    int format;
64    ColorAlpha * palette;
65    byte rgbLookup[32768];
66
67    LFBSystem()
68    {
69       if(!rgbLookupSet)
70       {
71          int c, r, g, b;
72          ColorAlpha * palette = GetDefaultPalette();
73          for(c = 16; c < 232; c++)
74          {
75             Color555 color = palette[c].color;
76             for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
77                for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
78                   for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
79                      defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
80          }
81          for(c = 232; c < 246; c++)
82          {
83             Color555 color = palette[c].color;
84             defaultRGBLookup[color] = (byte)c;
85          }
86          /*
87          for(c = 246; c < 256; c++)
88          {
89             Color555 color = palette[c].color;
90             defaultRGBLookup[color] = (byte)c;
91          }
92          for(c = 0; c < 16; c++)
93          {
94             Color555 color = palette[c].color;
95             defaultRGBLookup[color] = (byte)c;
96          }*/
97          /*
98          for(c = 0; c<32768; c++)
99          {
100             Color color = (Color)(Color555)c;
101             defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
102             // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
103          }
104          */
105          rgbLookupSet = true;
106       }
107    }
108 };
109
110 public class LFBSurface : struct
111 {
112 public:
113    // For compatibility with 3D drivers as well
114    Font font;
115    bool opaqueText;
116    int xOffset;
117    bool writingText;
118    bool writingOutline;
119
120    Bitmap bitmap;
121
122    // Drawing attributes
123    uint foreground, background;
124    ColorAlpha foregroundRgb;
125    uint16 stipple;
126    byte drawingChar;
127    byte * paletteShades;
128    bool clearing;
129 };
130
131 /*
132 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
133 {
134    if(recordA->zMin > recordB->zMin)
135       return  1;
136    else if(recordA->zMin < recordB->zMin)
137       return -1;
138    else if(recordA > recordB)
139       return 1;
140    else if(recordA < recordB)
141       return -1;
142    else
143       return  0;
144 }
145 */
146
147 public class LFBDisplayDriver : DisplayDriver
148 {
149    class_property(name) = "LFB";
150
151    bool CreateDisplaySystem(DisplaySystem displaySystem)
152    {
153       displaySystem.flags.memBackBuffer = true;
154       // displaySystem.pixelFormat = pixelFormat888;
155       return true;
156    }
157
158    void DestroyDisplaySystem(DisplaySystem displaySystem)
159    {
160    }
161
162    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
163    {
164       delete bitmap.picture;
165       if(bitmap.allocatePalette)
166          delete bitmap.palette;
167    }
168
169    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
170    {
171       bool result = false;
172       if(!stride)
173       {
174          switch(GetColorDepthShifts(format))
175          {
176             case 0: stride = (width + 3) & 0xFFFFFFFC; break;
177             case 1: stride = (width + 1) & 0xFFFFFFFE; break;
178             case 2: stride = width;                    break;
179          }
180       }
181       bitmap.stride = stride;
182       bitmap.width = width;
183       bitmap.height = height;
184       bitmap.size = (uint32) stride * (uint32)height;
185       bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
186       bitmap.pixelFormat = format;
187       bitmap.transparent = false;
188    /*
189       surface.box.left = surface.box.top = 0;
190       surface.box.right = width - 1;
191       surface.box.bottom = height - 1;
192    */
193       bitmap.picture = new0 byte[bitmap.sizeBytes];
194       if(bitmap.picture)
195       {
196          bitmap.allocatePalette = allocatePalette;
197          if(allocatePalette)
198          {
199             bitmap.palette = new ColorAlpha[256];
200             if(bitmap.palette)
201             {
202                CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
203                result = true;
204             }
205          }
206          else
207          {
208             bitmap.palette = GetDefaultPalette();
209             result = true;
210          }
211       }
212       if(!result)
213          FreeBitmap(displaySystem, bitmap);
214       return result;
215    }
216
217    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
218    {
219       bool result = false;
220       LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
221
222       if(src)
223       {
224          if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
225          {
226             if(src.transparent && src.pixelFormat == pixelFormat888)
227             {
228                /*
229                DWORD c;
230                DWORD * picture = (DWORD *)src.picture;
231
232                for(c = 0; c<src.size; c++, picture++)
233                {
234                   if(*picture & 0xFFFFFF)
235                      *picture =  *picture | 0xFF000000;
236                   else
237                      *picture = *picture & 0xFFFFFF;
238                }
239                */
240             }
241             result = true;
242          }
243          else
244          {
245             Bitmap bitmap { };
246             if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
247             {
248                if(format == pixelFormat8)
249                {
250                   if(palette)
251                      bitmap.palette = palette;
252                   else if(lfbSystem && lfbSystem.palette)
253                      bitmap.palette = lfbSystem.palette;
254                   else
255                      bitmap.palette = src.palette;
256                }
257
258                if(converters_table[src.pixelFormat][bitmap.pixelFormat])
259                {
260                   converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
261                   bitmap.transparent = src.transparent;
262                   bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
263                   delete src.picture;
264                   if(src.palette != bitmap.palette)
265                   {
266                      if(src.allocatePalette)
267                         delete src.palette;
268                      src.allocatePalette = false;
269                   }
270                   src.picture = bitmap.picture;
271                   src.palette = bitmap.palette;
272                   src.stride = bitmap.stride;
273                   src.size = bitmap.size;
274                   src.sizeBytes = bitmap.sizeBytes;
275                   src.pixelFormat = bitmap.pixelFormat;
276
277                   result = true;
278                }
279
280                bitmap.palette = null;
281                bitmap.picture = null;
282             }
283             delete bitmap;
284          }
285       }
286       return result;
287    }
288
289    void DestroyDisplay(Display display)
290    {
291       LFBDisplay lfbDisplay = display.driverData;
292       delete lfbDisplay.bitmap.palette;
293    }
294
295    bool CreateDisplay(Display display)
296    {
297       bool result = false;
298       LFBDisplay lfbDisplay = display.driverData;
299       if(!lfbDisplay)
300       {
301          lfbDisplay = display.driverData = LFBDisplay { };
302          lfbDisplay.selfManaged = true;
303          lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
304       }
305
306       if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
307       {
308          CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
309          result = true;
310       }
311       return result;
312    }
313
314    bool DisplaySize(Display display, int width, int height)
315    {
316       LFBDisplay lfbDisplay = display.driverData;
317       //display.width = width;
318       //display.height = height;
319       lfbDisplay.bitmap.width = width;
320       lfbDisplay.bitmap.height = height;
321       /*
322       lfbDisplay.updateBox.left = display.width;
323       lfbDisplay.updateBox.top = display.height;
324       lfbDisplay.updateBox.right = 0;
325       lfbDisplay.updateBox.bottom = 0;
326       */
327
328       if(lfbDisplay.selfManaged)
329       {
330          lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
331          lfbDisplay.bitmap.stride = width;
332       }
333       lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
334       return true;
335    }
336
337    void DisplayPosition(Display display, int x, int y)
338    {
339       LFBDisplay lfbDisplay = display.driverData;
340       lfbDisplay.x = x;
341       lfbDisplay.y = y;
342    }
343
344    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
345    {
346       LFBDisplay lfbDisplay = display.driverData;
347       if(colorMatch)
348       {
349          int c;
350
351          if(!palette)
352          {
353             LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
354             palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
355             CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
356          }
357          else
358             for(c = 0; c<32768; c++)
359                lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
360
361          for(c=0; c<256; c++)
362          {
363             int i;
364             for(i=0; i<LIGHTSTEPS; i++)
365             {
366                lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
367                           (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
368                           (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
369                           (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
370             }
371          }
372       }
373       if(lfbDisplay.bitmap.palette)
374          CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
375    }
376
377    void Update(Display display, Box updateBox)
378    {
379       LFBDisplay lfbDisplay = display.driverData;
380       if(lfbDisplay.displayCallback)
381       {
382          if(updateBox == null)
383          {
384             Box box { 0,0, display.width,display.height };
385             lfbDisplay.displayCallback(display, box);
386          }
387          else
388             lfbDisplay.displayCallback(display, updateBox);
389       }
390    }
391
392    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps, int cubeMapFace)
393    {
394       if(bitmap.pixelFormat != pixelFormatAlpha)
395       {
396          if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
397          {
398             FreeBitmap(displaySystem, bitmap);
399             return false;
400          }
401       }
402       return true;
403    }
404
405    void ReleaseSurface(Display display, Surface surface)
406    {
407       LFBSurface lfbSurface = surface.driverData;
408       delete lfbSurface;
409       surface.driverData = null;
410    }
411
412    bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
413    {
414       LFBDisplay lfbDisplay = display.driverData;
415       LFBSurface lfbSurface = surface.driverData;
416       if(!lfbSurface)
417       {
418          lfbSurface = surface.driverData = LFBSurface { };
419       }
420
421       lfbSurface.bitmap = lfbDisplay.bitmap;
422
423       surface.offset.x = x;
424       surface.offset.y = y;
425       surface.box = clip;
426       if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
427       {
428          surface.offset.x /= textCellW;
429          surface.offset.y /= textCellH;
430          surface.box.left /= textCellW;
431          surface.box.top /= textCellH;
432          surface.box.right /= textCellW;
433          surface.box.bottom /= textCellH;
434       }
435
436       /*
437       lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
438       lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
439       lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
440       lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
441       */
442
443       surface.unclippedBox = surface.box;
444       lfbSurface.drawingChar = 219;
445       return true;
446    }
447
448    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
449    {
450       bool result = false;
451       LFBSurface lfbSurface = surface.driverData;
452       if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
453       {
454          lfbSurface.bitmap = bitmap;
455
456          surface.offset.x = x;
457          surface.offset.y = y;
458          surface.box = clip;
459          if(bitmap.pixelFormat == pixelFormatText)
460          {
461             surface.offset.x /= textCellW;
462             surface.offset.y /= textCellH;
463             surface.box.left /= textCellW;
464             surface.box.top /= textCellH;
465             surface.box.right /= textCellW;
466             surface.box.bottom /= textCellH;
467          }
468
469          surface.unclippedBox = *&surface.box;
470          lfbSurface.drawingChar = 219;
471
472          result = true;
473       }
474       return result;
475    }
476
477    void Clip(Display display, Surface surface, Box clip)
478    {
479       LFBSurface lfbSurface = surface.driverData;
480       if(clip != null)
481       {
482          Box box = clip;
483
484          if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
485          {
486             box.left /= textCellW;
487             box.top /= textCellH;
488             box.right /= textCellW;
489             box.bottom /= textCellH;
490          }
491          box.Clip(surface.unclippedBox);
492          surface.box = box;
493       }
494       else
495          surface.box = surface.unclippedBox;
496    }
497
498    void SetForeground(Display display, Surface surface, ColorAlpha color)
499    {
500       LFBDisplay lfbDisplay = display ? display.driverData : null;
501       LFBSurface lfbSurface = surface.driverData;
502       uint index;
503       //if(display) color = color & 0xFFFFFF;
504       lfbSurface.foregroundRgb = color;
505
506       if(lfbSurface.font && lfbDisplay)
507       {
508          index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
509          lfbSurface.paletteShades = lfbDisplay.lightTable[index];
510       }
511
512       switch(lfbSurface.bitmap.pixelFormat)
513       {
514          case pixelFormat8:
515             if(display)
516                lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
517             else
518                lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
519             break;
520          case pixelFormat444:  lfbSurface.foreground = (Color444)color; break;
521          case pixelFormat555:  lfbSurface.foreground = (Color555)color; break;
522          case pixelFormat565:  lfbSurface.foreground = (Color565)color; break;
523          case pixelFormat888:  lfbSurface.foreground = color; break;
524          case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
525          case pixelFormatText:
526             if(display)
527                lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
528             else
529                lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
530             break;
531       }
532    }
533
534    void SetBackground(Display display, Surface surface, ColorAlpha color)
535    {
536       LFBDisplay lfbDisplay = display ? display.driverData : null;
537       LFBSurface lfbSurface = surface.driverData;
538       //color = color & 0xFFFFFF;
539       switch(lfbSurface.bitmap.pixelFormat)
540       {
541          case pixelFormat8:
542             if(display)
543                lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
544             else
545                lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
546             break;
547          case pixelFormat444:  lfbSurface.background = (Color444)color; break;
548          case pixelFormat555:  lfbSurface.background = (Color555)color; break;
549          case pixelFormat565:  lfbSurface.background = (Color565)color; break;
550          case pixelFormat888:  lfbSurface.background = color; break;
551          case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
552          case pixelFormatText:
553             if(display)
554                lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
555             else
556                lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
557             break;
558       }
559    }
560
561    ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
562    {
563       LFBSurface lfbSurface = surface.driverData;
564       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
565       {
566          x /= textCellW;
567          y /= textCellH;
568       }
569       if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
570       {
571          x += surface.offset.x;
572          y += surface.offset.y;
573          if(lfbSurface.bitmap.picture)
574          {
575             switch(lfbSurface.bitmap.pixelFormat)
576             {
577                case pixelFormatText:
578                case pixelFormat8:
579                   if(!lfbSurface.bitmap.palette) return 0;
580                   return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
581                case pixelFormat444:  return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
582                case pixelFormat555:  return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
583                case pixelFormat565:  return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
584                case pixelFormat888:  return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
585             }
586          }
587       }
588       return 0;
589    }
590
591    void PutPixel(Display display, Surface surface,int x,int y)
592    {
593       LFBSurface lfbSurface = surface.driverData;
594       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
595       {
596          x /= textCellW;
597          y /= textCellH;
598       }
599       if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
600       {
601          x += surface.offset.x;
602          y += surface.offset.y;
603          if(lfbSurface.bitmap.picture)
604          {
605             switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
606             {
607                case 0:
608                   ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
609                   break;
610                case 1:
611                   ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
612                   break;
613                case 2:
614                   if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
615                      ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
616                   break;
617             }
618          }
619       }
620    }
621
622    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
623    {
624       LFBSurface lfbSurface = surface.driverData;
625
626       int xd, yd;
627       int xu,yu;
628       int errorterm;
629       uint offset;
630       uint color = lfbSurface.foreground;
631       uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
632       bool invert = false;
633       if(!lfbSurface.bitmap.picture) return;
634       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
635       {
636          x1 /= textCellW;
637          x2 /= textCellW;
638          y1 /= textCellH;
639          y2 /= textCellH;
640          if(surface.textOpacity)
641             color |= lfbSurface.background;
642          color |= lfbSurface.drawingChar;
643       }
644       if(y1 == y2)
645       {
646          if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
647
648          if((y1>surface.box.bottom)||(y1<surface.box.top))return;
649          if((x1>surface.box.right)||(x2<surface.box.left))return;
650          if(x1<surface.box.left)x1=surface.box.left;
651          if(x2>surface.box.right)x2=surface.box.right;
652
653          if(x2 < x1) return;
654
655          offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
656          if(stipple != 0xFFFF)
657          {
658             int x;
659             switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
660             {
661                case 0:
662                   for(x=x1; x<=x2; x++, offset++)
663                   {
664                      if(stipple & 0x8000)
665                         ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
666                      if(invert)
667                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
668                      else
669                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
670                   }
671                   break;
672                case 1:
673                   for(x=x1; x<=x2; x++, offset++)
674                   {
675                      if(stipple & 0x8000)
676                         ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
677                      if(invert)
678                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
679                      else
680                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
681                   }
682                   break;
683                case 2:
684                   for(x=x1; x<=x2; x++, offset++)
685                   {
686                      if(stipple & 0x8000)
687                         ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
688                      if(invert)
689                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
690                      else
691                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
692                   }
693                   break;
694             }
695          }
696          else
697          {
698             if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
699             {
700                switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
701                {
702                   case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
703                   case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
704                   case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
705                }
706             }
707             else
708             {
709                int x;
710                for(x = x1; x <= x2; x++, offset++)
711                {
712                   ((uint16 *)lfbSurface.bitmap.picture)[offset] =
713                      (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
714                }
715             }
716          }
717       }
718       else if(x1 == x2)
719       {
720          int y;
721
722          if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
723
724          if((x1>surface.box.right)||(x1<surface.box.left))return;
725          if((y1>surface.box.bottom)||(y2<surface.box.top))return;
726          if(y1<surface.box.top)y1=surface.box.top;
727          if(y2>surface.box.bottom)y2=surface.box.bottom;
728
729          offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
730          switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
731          {
732             case 0:
733                for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
734                {
735                   if(stipple & 0x8000)
736                      ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
737                   if(invert)
738                      stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
739                   else
740                      stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
741                }
742                break;
743             case 1:
744                for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
745                {
746                   if(stipple & 0x8000)
747                   {
748                      if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
749                         ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
750                      else
751                      {
752                         ((uint16 *)lfbSurface.bitmap.picture)[offset] =
753                            (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
754                      }
755                   }
756                   if(invert)
757                      stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
758                   else
759                      stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
760                }
761                break;
762             case 2:
763                if(stipple != 0xFFFF)
764                {
765                   for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
766                   {
767                      if(stipple & 0x8000)
768                         ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
769                      if(invert)
770                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
771                      else
772                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
773                   }
774                }
775                else
776                {
777                   for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
778                      ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
779                }
780                break;
781          }
782       }
783       else
784       {
785          if(x2 >= x1)
786          {
787             if(x1 < surface.box.left)
788             {
789                if(x2 < surface.box.left)
790                   return;
791                y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
792                x1 = surface.box.left;
793             }
794             if(x2 > surface.box.right)
795             {
796                if(x1 > surface.box.right)
797                   return;
798                y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
799                x2 = surface.box.right;
800             }
801             if(y2 >= y1)
802             {
803                if(y1 < surface.box.top)
804                {
805                   if(y2 < surface.box.top)
806                      return;
807                   x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
808                   y1 = surface.box.top;
809                }
810                if(y2 > surface.box.bottom)
811                {
812                   if(y1 > surface.box.bottom)
813                      return;
814                   x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
815                   y2 = surface.box.bottom;
816                }
817             }
818             else
819             {
820                if(y1 > surface.box.bottom)
821                {
822                   if(y2 > surface.box.bottom)
823                      return;
824                   x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
825                   y1 = surface.box.bottom;
826                }
827                if(y2 < surface.box.top)
828                {
829                   if(y1 < surface.box.top)
830                      return;
831                   x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
832                   y2 = surface.box.top;
833                }
834             }
835          }
836          else
837          {
838             if(x1 > surface.box.right)
839             {
840                if(x2 > surface.box.right)
841                   return;
842                y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
843                x1 = surface.box.right;
844             }
845             if(x2 < surface.box.left)
846             {
847                if(x1 < surface.box.left)
848                   return;
849                y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
850                x2 = surface.box.left;
851             }
852             if(y2 >= y1)
853             {
854                if(y1 < surface.box.top)
855                {
856                   if(y2 < surface.box.top)
857                      return;
858                   x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
859                   y1 = surface.box.top;
860                }
861                if(y2 > surface.box.bottom)
862                {
863                   if(y1 > surface.box.bottom)
864                      return;
865                   x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
866                   y2 = surface.box.bottom;
867                }
868             }
869             else
870             {
871                if(y1 > surface.box.bottom)
872                {
873                   if(y2 > surface.box.bottom)
874                      return;
875                   x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
876                   y1 = surface.box.bottom;
877                }
878                if(y2 < surface.box.top)
879                {
880                   if(y1 < surface.box.top)
881                      return;
882                   x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
883                   y2 = surface.box.top;
884                }
885             }
886          }
887
888          xd=x2-x1;
889          yd=y2-y1;
890
891          if(xd<0)
892          {
893             xd=-xd;
894             xu=-1;
895          }
896          else
897             xu=1;
898          if(yd<0)
899          {
900             yd=-yd;
901             yu=-(int)lfbSurface.bitmap.stride;
902          }
903          else
904             yu=lfbSurface.bitmap.stride;
905
906          offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
907          errorterm=0;
908
909          if(xd>yd)
910          {
911             int i, length=xd;
912             for(i=0; i<=length; i++)
913             {
914                if(stipple & 0x8000)
915                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
916                   {
917                      case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
918                      case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
919                      case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
920                   }
921                offset+=xu;
922                errorterm+=yd;
923                if(errorterm>=xd)
924                {
925                   errorterm-=xd;
926                   offset+=yu;
927                }
928                stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
929             }
930          }
931          else
932          {
933             int i, length=yd;
934             for(i=0; i<=length; i++)
935             {
936                if(stipple & 0x8000)
937                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
938                   {
939                      case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
940                      case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
941                      case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
942                   }
943                offset+=yu;
944                errorterm+=xd;
945                if(errorterm>=yd)
946                {
947                   errorterm-=yd;
948                   offset+=xu;
949                }
950             }
951          }
952       }
953    }
954
955    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
956    {
957       DrawLine(display, surface,x1,y1,x2,y1);
958       DrawLine(display, surface,x2,y1,x2,y2);
959       DrawLine(display, surface,x2,y2,x1,y2);
960       DrawLine(display, surface,x1,y2,x1,y1);
961    }
962
963    #if !defined(__GNUC__)
964    /*
965    void memset_32_aligned(void *buf, int val, int dwords)
966    {
967             // Qword align
968             if ((int)(buf) & 4)
969             {
970                     *((uint32 *)(buf)) = val;
971                     buf = ((uint32 *)(buf))+1;
972                     dwords--;
973             }
974
975             if (dwords > 1)
976             {
977                     __asm {
978                             cld
979                             mov   edi,  buf
980                             mov   ecx,  dwords
981                             shr       ecx,  1
982                             mov   eax,  val
983                             movd  mm0,  eax
984                             movd  mm1,  eax
985                             psllq mm1,  32
986                             por   mm0,  mm1
987                             align 16
988             repeat:
989                             movq [edi], mm0
990                             add   edi,  8
991                             loop  repeat
992                             emms
993                     };
994             }
995
996             // Final dword
997             if (dwords & 1) *((int*)(buf)) = val;
998    }*/
999
1000    //#define USE_SSE
1001
1002 /*
1003    void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1004    {
1005       dwords <<= 2;
1006    #ifdef USE_SSE
1007       if(((uint32)buf) & 0x7F)
1008       {
1009          for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1010          {
1011             *buf = val;
1012             dwords--;
1013          }
1014       }
1015       if(dwords)
1016    #endif
1017       __asm
1018       {
1019          mov edi, buf
1020          mov eax, val
1021          mov ecx, dwords
1022
1023          mov edx,ecx
1024    #ifdef USE_SSE
1025          shr ecx,7
1026    #else
1027          shr ecx,6
1028    #endif
1029          mov ebx,ecx
1030    #ifdef USE_SSE
1031          shl ebx,7
1032    #else
1033          shl ebx,6
1034    #endif
1035          sub edx,ebx                            ; edx holds # of overflow bytes
1036
1037    #ifdef USE_SSE
1038            mov [edi],eax
1039            mov [edi+4],eax
1040          mov [edi+8],eax
1041          mov [edi+12],eax
1042          movdqa xmm0, [edi]
1043    #else
1044          mov [edi],eax
1045            mov [edi+4],eax
1046          movq mm0, [edi]
1047    #endif
1048            cmp ecx,0
1049            je doneloop
1050    setloop:
1051
1052    #ifdef USE_SSE
1053          movdqa [edi],xmm0
1054          movdqa [edi+16],xmm0
1055          movdqa [edi+32],xmm0
1056          movdqa [edi+48],xmm0
1057          movdqa [edi+64],xmm0
1058          movdqa [edi+80],xmm0
1059          movdqa [edi+96],xmm0
1060          movdqa [edi+112],xmm0
1061          add edi,8*16
1062    #else
1063          movq [edi],mm0
1064          movq [edi+8],mm0
1065          movq [edi+16],mm0
1066          movq [edi+24],mm0
1067          movq [edi+32],mm0
1068          movq [edi+40],mm0
1069          movq [edi+48],mm0
1070          movq [edi+56],mm0
1071          add edi,8*8
1072    #endif
1073          dec ecx
1074            jnz setloop
1075
1076    doneloop:
1077            mov ecx,edx
1078            shr ecx,2
1079            rep stosd
1080
1081            emms
1082       };
1083    }
1084    void memset_32(void *buf, uint32 val, uint32 dwords)
1085    {
1086       int align = 0;
1087       if ((uint32)(buf) & 3)
1088       {
1089          align = 4;
1090          dwords--;
1091
1092          if (((uint32)(buf) & 1))
1093          {
1094             *(byte *)(buf) = (byte)(val&0xFF);
1095             buf = ((byte *)(buf))+1;
1096             val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1097             align --;
1098          }
1099          if (((uint32)(buf) & 2))
1100          {
1101             *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1102             buf = ((uint16 *)(buf))+1;
1103             val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1104             align-=2;
1105          }
1106       }
1107       memset_32_aligned(buf,val,dwords);
1108       if (align)
1109       {
1110          if (align == 1)
1111          {
1112             *(byte *)(buf) = (byte)(val&0xFF);
1113          }
1114          else
1115          {
1116             *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1117             if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1118          }
1119       }
1120    }
1121    */
1122    #endif
1123
1124    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1125    {
1126       LFBSurface lfbSurface = surface.driverData;
1127       uint32 color = lfbSurface.background;
1128
1129       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1130       {
1131          color |= lfbSurface.foreground | lfbSurface.drawingChar;
1132          x1 /= textCellW;
1133          x2 /= textCellW;
1134          y1 /= textCellH;
1135          y2 /= textCellH;
1136       }
1137       if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1138
1139       if(x1<surface.box.left)  x1=surface.box.left;
1140       if(x2>surface.box.right) x2=surface.box.right;
1141       if(y1<surface.box.top)   y1=surface.box.top;
1142       if(y2>surface.box.bottom)  y2=surface.box.bottom;
1143
1144       if(x2>=x1 && y2>=y1)
1145       {
1146          int w,y;
1147          byte * theOffset;
1148
1149          w = x2-x1+1;
1150          if(w<1) return;
1151
1152          x1 += surface.offset.x;
1153          x2 += surface.offset.x;
1154          y1 += surface.offset.y;
1155          y2 += surface.offset.y;
1156          if(lfbSurface.bitmap.picture)
1157          {
1158             if(!surface.writeColor)
1159             {
1160                ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1161                for(y = y1; y<= y2; y++)
1162                {
1163                   int c;
1164                   for(c = 0; c < w; c++, picture++)
1165                      if(!picture->a)
1166                         picture->a = (byte)((color & 0xFF000000) >> 24);
1167                   picture += lfbSurface.bitmap.stride - w;
1168                }
1169             }
1170             else
1171             {
1172                if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
1173                {
1174                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1175                   {
1176                      case 0:
1177                         theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1178                         for(y = y1; y<= y2; y++)
1179                         {
1180                            FillBytes(theOffset,(byte)color,w);
1181                            theOffset += lfbSurface.bitmap.stride;
1182                         }
1183                         break;
1184                      case 1:
1185                         theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1186                         for(y = y1; y<= y2; y++)
1187                         {
1188                            FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1189                            theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1190                         }
1191                         break;
1192                      case 2:
1193                         theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1194                         for(y = y1; y<= y2; y++)
1195                         {
1196          #if defined(__GNUC__)
1197                            FillBytesBy4((uint32 *) theOffset,color,w);
1198          #else
1199                            memset_32((uint32 *) theOffset,color,w);
1200          #endif
1201                            theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1202
1203                         }
1204                         /*
1205                         y = y2-y1+1;
1206                         {
1207                            int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1208                            //memset_32((uint32 *) theOffset,color,w);
1209                            /-*_asm
1210                            {
1211                               push edi
1212                               push ecx
1213                               push eax
1214                               push ebx
1215                               push edx
1216
1217                               mov ebx,bla
1218
1219                               mov edi,theOffset
1220                               mov eax,color
1221                               mov edx,y
1222                               mov ecx,w
1223
1224                               start:
1225                                  push ecx
1226
1227                                  rep stosd
1228                                  add edi,ebx
1229                                  pop ecx
1230                                  dec edx
1231                                  jnz start
1232                               pop edx
1233                               pop ebx
1234                               pop eax
1235                               pop ecx
1236                               pop edi
1237                            };
1238                         break;
1239                         }*/
1240                   }
1241                }
1242                else
1243                {
1244                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1245                   {
1246                      case 0:
1247                         theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1248                         for(y = y1; y<= y2; y++)
1249                         {
1250                            // TODO: IMPLEMENT THIS
1251                            FillBytes(theOffset,(byte)color,w);
1252                            theOffset += lfbSurface.bitmap.stride;
1253                         }
1254                         break;
1255                      case 1:
1256                      {
1257                         uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1258                         ColorAlpha c = surface.background;
1259                         int a = c.a;
1260                         int cr = c.color.r;
1261                         int cg = c.color.g;
1262                         int cb = c.color.b;
1263                         PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1264
1265                         for(y = y1; y <= y2; y++)
1266                         {
1267                            int c;
1268                            for(c = 0; c < w; c++, dest++)
1269                            {
1270                               Color destColor = 0;
1271                               if(pixelFormat == pixelFormat565)      { destColor = (Color)*(Color565 *)dest; }
1272                               else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
1273                               else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
1274                               {
1275                                  int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
1276                                  int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
1277                                  int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
1278
1279                                  if(r > 255) r = 255;
1280                                  if(g > 255) g = 255;
1281                                  if(b > 255) b = 255;
1282
1283                                  destColor = { (byte)r, (byte)g, (byte)b };
1284
1285                                  if(pixelFormat == pixelFormat565)      { *dest = (Color565)destColor; }
1286                                  else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
1287                                  else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
1288                               }
1289                            }
1290                            dest += (lfbSurface.bitmap.stride - w);
1291                         }
1292                         break;
1293                      }
1294                      case 2:
1295                      {
1296                         ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1297                         AlphaWriteMode alphaWrite = surface.alphaWrite;
1298                         ColorAlpha c = surface.background;
1299                         int a = c.a;
1300                         int cr = c.color.r;
1301                         int cg = c.color.g;
1302                         int cb = c.color.b;
1303                         for(y = y1; y <= y2; y++)
1304                         {
1305                            int c;
1306                            for(c = 0; c < w; c++, dest++)
1307                            {
1308                               int dr = dest->color.r;
1309                               int dg = dest->color.g;
1310                               int db = dest->color.b;
1311                               int r = a * cr / 255 + ((255 - a) * dr / 255);
1312                               int g = a * cg / 255 + ((255 - a) * dg / 255);
1313                               int b = a * cb / 255 + ((255 - a) * db / 255);
1314
1315                               if(r > 255) r = 255;
1316                               if(g > 255) g = 255;
1317                               if(b > 255) b = 255;
1318                               dest->color = { (byte)r, (byte)g, (byte)b };
1319
1320                               if(alphaWrite == blend)
1321                               {
1322                                  int ca = (int)(a + ((255 - a) * dest->a / 255));
1323                                  if(ca > 255) ca = 255;
1324                                  dest->a = (byte)ca;
1325                               }
1326                               else if(alphaWrite)
1327                                  dest->a = (byte)a;
1328                            }
1329                            dest += (lfbSurface.bitmap.stride - w);
1330                         }
1331                      }
1332                   }
1333                }
1334             }
1335          }
1336       }
1337    }
1338    void Clear(Display display, Surface surface, ClearType type)
1339    {
1340       LFBSurface lfbSurface = surface.driverData;
1341
1342       lfbSurface.clearing = true;
1343       if(surface.offset.x == 0 && surface.offset.y == 0 &&
1344          surface.box.left == 0 && surface.box.top  == 0 &&
1345          surface.box.right == surface.width-1 &&
1346          surface.box.bottom  == surface.height-1)
1347       {
1348          uint32 color = /*0xFF000000 | */lfbSurface.background;
1349          if(type != depthBuffer)
1350          {
1351             if(lfbSurface.bitmap.stride != surface.width)
1352                Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1353             else
1354             {
1355                switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1356                {
1357                   case 0:
1358                      FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
1359                      break;
1360                   case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
1361                   case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
1362                }
1363             }
1364          }
1365    /*
1366          if((flags & CLEAR_Z) && zbuffer)
1367             FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
1368    */
1369       }
1370       else
1371       {
1372          if(type != depthBuffer)
1373             Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1374    /*
1375          if((flags & CLEAR_Z))
1376          {
1377             int y;
1378             uint32 w = surface.box.right-surface.box.left+1;
1379             float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
1380                              +   surface.box.left+surface.offset.x;
1381             for(y = surface.box.top; y<= surface.box.bottom; y++)
1382             {
1383                FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
1384                offset += DISPLAY.Width;
1385             }
1386          }
1387    */
1388       }
1389       lfbSurface.clearing = false;
1390    }
1391
1392    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
1393    {
1394       LFBSurface lfbSurface = surface.driverData;
1395       bool flip = false;
1396
1397       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
1398
1399       if(w < 0) { w = -w; flip = true; }
1400
1401       //Clip against the edges of the source
1402       if(sx<0)
1403       {
1404          dx+=-sx;
1405          w-=-sx;
1406          sx=0;
1407       }
1408       if(sy<0)
1409       {
1410          dy+=0-sy;
1411          h-=0-sy;
1412          sy=0;
1413       }
1414       if(sx+w>src.width-1)
1415          w-=sx+w-(src.width-1)-1;
1416       if(sy+h>src.height-1)
1417          h-=sy+h-(src.height-1)-1;
1418       //Clip against the edges of the destination
1419       if(dx<surface.box.left)
1420       {
1421          if(!flip) sx+=surface.box.left-dx;
1422          w-=surface.box.left-dx;
1423          dx=surface.box.left;
1424       }
1425       if(dy<surface.box.top)
1426       {
1427          sy+=surface.box.top-dy;
1428          h-=surface.box.top-dy;
1429          dy=surface.box.top;
1430       }
1431       if((dx+w)>surface.box.right)
1432       {
1433          if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
1434          w-=((uint32)(dx+w)-surface.box.right-1);
1435       }
1436       if((dy+h)>surface.box.bottom)
1437          h-=((dy+h)-surface.box.bottom-1);
1438       if((w<=0)||(h<=0))
1439          return;
1440
1441       dx += surface.offset.x;
1442       dy += surface.offset.y;
1443
1444       if(lfbSurface.bitmap.picture)
1445       {
1446          AlphaWriteMode alphaWrite = surface.alphaWrite;
1447          if(src.alphaBlend && surface.blend)
1448          {
1449             int x, y;
1450             if(src.pixelFormat == pixelFormatAlpha)
1451             {
1452                if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
1453                {
1454                   ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
1455                   byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
1456                   ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
1457                   for(y = 0; y < h; y++)
1458                   {
1459                      for(x = 0; x < w; x++, picture++, source++)
1460                      {
1461                         int a = *source * color.a;
1462                         ColorAlpha dest = *picture;
1463                         int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
1464                         int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
1465                         int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
1466                         if(r > 255) r = 255;
1467                         if(g > 255) g = 255;
1468                         if(b > 255) b = 255;
1469                         picture->color = { (byte)r, (byte)g, (byte)b };
1470                         if(alphaWrite == blend)
1471                         {
1472                            int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
1473                            if(ca > 255) ca = 255;
1474                            picture->a = (byte)ca;
1475                         }
1476                         else if(alphaWrite)
1477                            picture->a = (byte)(a / 255);
1478                      }
1479                      picture += lfbSurface.bitmap.stride - w;
1480                      source += src.stride - w;
1481                   }
1482                }
1483                else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
1484                {
1485                   Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
1486                   byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
1487                   ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
1488                   for(y = 0; y < h; y++)
1489                   {
1490                      for(x = 0; x < w; x++, picture++, source++)
1491                      {
1492                         int a = *source * color.a;
1493                         Color dest = *picture;
1494                         int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
1495                         int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
1496                         int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
1497                         if(r > 255) r = 255;
1498                         if(g > 255) g = 255;
1499                         if(b > 255) b = 255;
1500                         *picture = Color { (byte)r, (byte)g, (byte)b };
1501                      }
1502                      picture += lfbSurface.bitmap.stride - w;
1503                      source += src.stride - w;
1504                   }
1505                }
1506                else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
1507                {
1508                   Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
1509                   byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
1510                   ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
1511                   for(y = 0; y < h; y++)
1512                   {
1513                      for(x = 0; x < w; x++, picture++, source++)
1514                      {
1515                         int a = *source * color.a;
1516                         Color dest = *picture;
1517                         int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
1518                         int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
1519                         int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
1520                         if(r > 255) r = 255;
1521                         if(g > 255) g = 255;
1522                         if(b > 255) b = 255;
1523                         *picture = Color { (byte)r, (byte)g, (byte)b };
1524                      }
1525                      picture += lfbSurface.bitmap.stride - w;
1526                      source += src.stride - w;
1527                   }
1528                }
1529             }
1530             else
1531             {
1532                ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
1533                if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
1534                {
1535                   ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
1536                   for(y = 0; y < h; y++)
1537                   {
1538                      for(x = 0; x < w; x++, picture++, source++)
1539                      {
1540                         ColorAlpha src = *source;
1541                         ColorAlpha dest = *picture;
1542                         int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
1543                         int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
1544                         int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
1545                         if(r > 255) r = 255;
1546                         if(g > 255) g = 255;
1547                         if(b > 255) b = 255;
1548                         picture->color = { (byte)r, (byte)g, (byte)b };
1549                         if(alphaWrite == blend)
1550                         {
1551                            int a = src.a + ((255 - src.a) * dest.a / 255);
1552                            if(a > 255) a = 255;
1553                            picture->a = (byte)a;
1554                         }
1555                         else if(alphaWrite)
1556                            picture->a = src.a;
1557                      }
1558                      picture += lfbSurface.bitmap.stride - w;
1559                      source += src.stride - w;
1560                   }
1561                }
1562                else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
1563                {
1564                   Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
1565                   for(y = 0; y < h; y++)
1566                   {
1567                      for(x = 0; x < w; x++, picture++, source++)
1568                      {
1569                         ColorAlpha src = *source;
1570                         Color565 dest = *picture;
1571                         int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
1572                         int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
1573                         int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
1574                         if(r > 255 * 31) r = 255 * 31;
1575                         if(g > 255 * 63) g = 255 * 63;
1576                         if(b > 255 * 31) b = 255 * 31;
1577                         *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
1578                      }
1579                      picture += lfbSurface.bitmap.stride - w;
1580                      source += src.stride - w;
1581                   }
1582                }
1583                else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
1584                {
1585                   Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
1586                   for(y = 0; y < h; y++)
1587                   {
1588                      for(x = 0; x < w; x++, picture++, source++)
1589                      {
1590                         ColorAlpha psrc = *source;
1591                         Color555 dest = *picture;
1592                         int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
1593                         int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
1594                         int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
1595                         if(r > 255 * 31) r = 255 * 31;
1596                         if(g > 255 * 31) g = 255 * 31;
1597                         if(b > 255 * 31) b = 255 * 31;
1598                         *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
1599                      }
1600                      picture += lfbSurface.bitmap.stride - w;
1601                      source += src.stride - w;
1602                   }
1603                }
1604             }
1605          }
1606          else if(src.paletteShades)
1607             shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
1608          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
1609             blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
1610          else if(src.pixelFormat == pixelFormat8)
1611             blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
1612       }
1613    }
1614
1615    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
1616    {
1617       bool result = false;
1618       LFBDisplay lfbDisplay = display.driverData;
1619
1620       if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
1621       {
1622          bitmap.Free();
1623          bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
1624             (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
1625       }
1626       if(bitmap)
1627       {
1628          Surface surface = bitmap.GetSurface(0,0,null);
1629          if(surface)
1630          {
1631             Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
1632             if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
1633                CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
1634             delete surface;
1635          }
1636          result = true;
1637       }
1638       return result;
1639    }
1640
1641    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1642    {
1643       LFBSurface lfbSurface = surface.driverData;
1644       bool flip = false;
1645
1646       float s2dw,s2dh,d2sw,d2sh;
1647
1648       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
1649
1650       if(Sgn(w) != Sgn(sw))
1651       {
1652          w = Abs(w);
1653          sw = Abs(sw);
1654          flip = true;
1655       }
1656
1657       s2dw=(float)w / sw;
1658       s2dh=(float)h / sh;
1659       d2sw=(float)sw / w;
1660       d2sh=(float)sh / h;
1661
1662       //Clip against the edges of the source
1663       if(sx<0)
1664       {
1665          dx+=(int)((0-sx) * s2dw);
1666          w-=(int)((0-sx) * s2dw);
1667          sw-=0-sx;
1668          sx=0;
1669       }
1670       if(sy<0)
1671       {
1672          dy+=(int)((0-sy) * s2dh);
1673          h-=(int)((0-sy) * s2dh);
1674
1675          sh-=0-sy;
1676          sy=0;
1677       }
1678       if(sx+sw>src.width-1)
1679       {
1680          w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
1681          sw-=sx+sw-(src.width-1)-1;
1682       }
1683       if(sy+sh>(src.height-1))
1684       {
1685          h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
1686          sh-=sy+sh-(src.height-1)-1;
1687       }
1688       //Clip against the edges of the destination
1689       if(dx<surface.box.left)
1690       {
1691          if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
1692          sw-=(int)((surface.box.left-dx)*d2sw);
1693          w-=surface.box.left-dx;
1694          dx=surface.box.left;
1695       }
1696       if(dy<surface.box.top)
1697       {
1698          sy+=(int)((surface.box.top-dy)*d2sh);
1699          sh-=(int)((surface.box.top-dy)*d2sh);
1700          h-=surface.box.top-dy;
1701          dy=surface.box.top;
1702       }
1703       if((dx+w)>surface.box.right)
1704       {
1705          if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
1706          sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
1707          w-=((dx+w)-surface.box.right-1);
1708       }
1709       if((dy+h)>surface.box.bottom)
1710       {
1711          sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
1712          h-=((dy+h)-surface.box.bottom-1);
1713       }
1714       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
1715
1716       dx+=surface.offset.x;
1717       dy+=surface.offset.y;
1718
1719       if(lfbSurface.bitmap.picture)
1720       {
1721          AlphaWriteMode alphaWrite = surface.alphaWrite;
1722          if(src.alphaBlend && surface.blend)
1723          {
1724             int x, y;
1725             uint xerr,yerr;
1726             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
1727             ColorAlpha * backsrc;
1728             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
1729             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
1730             if(flip) source += sw-1;
1731             adddest -= w;
1732             yerr = 0;
1733             for(y=0; y<sh; y++)
1734             {
1735                yerr+=h;
1736                backsrc = source;
1737                while(yerr >= sh)
1738                {
1739                   yerr-=sh;
1740                   xerr = 0;
1741                   for(x=0; x<sw; x++)
1742                   {
1743                      xerr+=w;
1744                      while(xerr>=sw)
1745                      {
1746                         xerr-=sw;
1747                         {
1748                            ColorAlpha src = *source;
1749                            ColorAlpha dst = *dest;
1750                            int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
1751                            int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
1752                            int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
1753                            if(r > 255) r = 255;
1754                            if(g > 255) g = 255;
1755                            if(b > 255) b = 255;
1756                            dest->color = { (byte)r, (byte)g, (byte)b };
1757                            if(alphaWrite == blend)
1758                            {
1759                               int a = src.a + ((255 - src.a) * dst.a / 255);
1760                               if(a > 255) a = 255;
1761                               dest->a = (byte)a;
1762                            }
1763                            else if(alphaWrite)
1764                               dest->a = src.a;
1765                         }
1766                         dest++;
1767                      }
1768                      source ++;
1769                   }
1770                   dest+=adddest;
1771                   source = backsrc;
1772                }
1773                source += addsource;
1774             }
1775          }
1776          else if(src.paletteShades)
1777             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1778          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
1779             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1780          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
1781             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1782       }
1783    }
1784
1785    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
1786    {
1787       LFBSurface lfbSurface = surface.driverData;
1788       bool flip = false;
1789
1790       float s2dw,s2dh,d2sw,d2sh;
1791
1792       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
1793
1794       if(Sgn(w) != Sgn(sw))
1795       {
1796          w = Abs(w);
1797          sw = Abs(sw);
1798          flip = true;
1799       }
1800
1801       s2dw=(float)w / sw;
1802       s2dh=(float)h / sh;
1803       d2sw=(float)sw / w;
1804       d2sh=(float)sh / h;
1805
1806       //Clip against the edges of the source
1807       if(sx<0)
1808       {
1809          dx+=(int)((0-sx) * s2dw);
1810          w-=(int)((0-sx) * s2dw);
1811          sw-=0-sx;
1812          sx=0;
1813       }
1814       if(sy<0)
1815       {
1816          dy+=(int)((0-sy) * s2dh);
1817          h-=(int)((0-sy) * s2dh);
1818
1819          sh-=0-sy;
1820          sy=0;
1821       }
1822       if(sx+sw>src.width-1)
1823       {
1824          w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
1825          sw-=sx+sw-(src.width-1)-1;
1826       }
1827       if(sy+sh>(src.height-1))
1828       {
1829          h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
1830          sh-=sy+sh-(src.height-1)-1;
1831       }
1832       //Clip against the edges of the destination
1833       if(dx<surface.box.left)
1834       {
1835          if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
1836          sw-=(int)((surface.box.left-dx)*d2sw);
1837          w-=surface.box.left-dx;
1838          dx=surface.box.left;
1839       }
1840       if(dy<surface.box.top)
1841       {
1842          sy+=(int)((surface.box.top-dy)*d2sh);
1843          sh-=(int)((surface.box.top-dy)*d2sh);
1844          h-=surface.box.top-dy;
1845          dy=surface.box.top;
1846       }
1847       if((dx+w)>surface.box.right)
1848       {
1849          if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
1850          sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
1851          w-=((dx+w)-surface.box.right-1);
1852       }
1853       if((dy+h)>surface.box.bottom)
1854       {
1855          sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
1856          h-=((dy+h)-surface.box.bottom-1);
1857       }
1858       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
1859
1860       dx+=surface.offset.x;
1861       dy+=surface.offset.y;
1862
1863       if(lfbSurface.bitmap.picture)
1864       {
1865          AlphaWriteMode alphaWrite = surface.alphaWrite;
1866          if(src.alphaBlend && surface.blend)
1867          {
1868             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
1869             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
1870             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
1871             float scaleX = (float)sw / w;
1872             float scaleY = (float)sh / h;
1873             /*if(flip < 0)
1874             {
1875                dest += w-1;
1876                adddest += w;
1877             }
1878             else*/
1879                adddest -= w;
1880             if (w > sw && h > sh)
1881             {
1882                int y;
1883                for (y = 0; y < h; y++)
1884                {
1885                   int y0 = y * sh / h;
1886                   int y1 = Min(y0 + 1, sh - 1);
1887                   float alpha = y * scaleY - y0;
1888                   int x;
1889                   for(x = 0; x < w; x++, dest += 1)
1890                   {
1891                      int x0 = x * sw / w;
1892                      int x1 = Min(x0 + 1, sw - 1);
1893                      float beta = x * scaleX - x0;
1894                      ColorAlpha src00, src01, src10, src11;
1895                      float a1,r1,g1,b1,a2,r2,g2,b2;
1896                      float a,r,g,b;
1897                      src00 = source[y0 * src.stride + x0];
1898                      src01 = source[y0 * src.stride + x1];
1899                      src10 = source[y1 * src.stride + x0];
1900                      src11 = source[y1 * src.stride + x1];
1901                      a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
1902                      r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
1903                      g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
1904                      b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
1905                      a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
1906                      r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
1907                      g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
1908                      b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
1909                      a = a1 * (1.0f - alpha) + a2 * alpha;
1910                      r = r1 * (1.0f - alpha) + r2 * alpha;
1911                      g = g1 * (1.0f - alpha) + g2 * alpha;
1912                      b = b1 * (1.0f - alpha) + b2 * alpha;
1913                      {
1914                         ColorAlpha dst = *dest;
1915                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
1916                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
1917                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
1918                         if(cr > 255) cr = 255;
1919                         if(cg > 255) cg = 255;
1920                         if(cb > 255) cb = 255;
1921                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
1922
1923                         if(alphaWrite == blend)
1924                         {
1925                            int ca = (int)(a + ((255 - a) * dst.a / 255));
1926                            if(ca > 255) ca = 255;
1927                            dest->a = (byte)ca;
1928                         }
1929                         else if(alphaWrite)
1930                            dest->a = (byte)a;
1931                      }
1932                   }
1933                   dest += adddest;
1934                }
1935             }
1936             else
1937             {
1938                int y;
1939                for (y = 0; y < h; y++)
1940                {
1941                   int y0 = Min((int)((y + 1) * scaleY), sh - 1);
1942                   int y1 = Min(y0 + 1, sh - 1);
1943                   int x;
1944                   for (x = 0; x < w; x++, dest += 1)
1945                   {
1946                      int x0 = Min((int)((x + 1) * scaleX), sw - 1);
1947                      int x1 = Min(x0 + 1, sw - 1);
1948                      float a = 0, r = 0, g = 0, b = 0;
1949                      int numPixels = 0;
1950                      int i, j;
1951                      for (i = y0; i <= y1; i++)
1952                         for (j = x0; j <= x1; j++)
1953                         {
1954                            ColorAlpha pixel = source[i * src.stride + j];
1955                            a += pixel.a;
1956                            r += pixel.color.r;
1957                            g += pixel.color.g;
1958                            b += pixel.color.b;
1959                            numPixels++;
1960                         }
1961                      a /= numPixels;
1962                      r /= numPixels;
1963                      g /= numPixels;
1964                      b /= numPixels;
1965                      {
1966                         ColorAlpha dst = *dest;
1967                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
1968                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
1969                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
1970                         if(cr > 255) cr = 255;
1971                         if(cg > 255) cg = 255;
1972                         if(cb > 255) cb = 255;
1973                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
1974                         if(alphaWrite == blend)
1975                         {
1976                            int ca = (int)(a + ((255 - a) * dst.a / 255));
1977                            if(ca > 255) ca = 255;
1978                            dest->a = (byte)ca;
1979                         }
1980                         else if(alphaWrite)
1981                            dest->a = (byte)a;
1982                      }
1983                   }
1984                   dest += adddest;
1985                }
1986             }
1987          }
1988          else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
1989             filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1990          // Fail back on Stretch
1991          else if(src.paletteShades)
1992             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1993          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
1994             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1995          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
1996             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
1997       }
1998    }
1999
2000    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2001    {
2002       Blit(display, surface, src, dx, dy, sx, sy, w, h);
2003    }
2004
2005    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2006    {
2007       Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2008    }
2009
2010    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2011    {
2012       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2013    }
2014
2015    void UnloadFont(DisplaySystem displaySystem, Font font)
2016    {
2017       delete font;
2018    }
2019
2020    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
2021    {
2022 #ifndef ECERE_NOTRUETYPE
2023       return Font::Load(displaySystem, faceName, size, flags, outlineSize, outlineFade);
2024 #else
2025       return { };
2026 #endif
2027    }
2028
2029    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2030    {
2031       if(displaySystem && displaySystem.flags.text && len)
2032       {
2033          if(width)
2034          {
2035             int num = len;
2036             *width = num * textCellW;
2037          }
2038          if(height) *height = textCellH;
2039       }
2040 #if !defined(ECERE_NOTRUETYPE)
2041       else if(font && len)
2042       {
2043          if(width)
2044          {
2045             int w = 0, advance = 0;
2046             font.ProcessString(displaySystem, (const byte *)text, len, false, null, null, &w, 0, prevGlyph, rPrevGlyph, &advance);
2047             if(adv) *adv = advance >> 6;
2048             //*width = (w + 64 - w % 64) >> 6;
2049             *width = w >> 6;
2050          }
2051          if(height)
2052             *height = font.height;
2053       }
2054 #endif
2055       else
2056       {
2057          if(width) *width = 0;
2058          if(height) *height = 0;
2059       }
2060    }
2061
2062    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
2063    {
2064       LFBSurface lfbSurface = surface.driverData;
2065       if(display && display.displaySystem.flags.text)
2066       {
2067          LFBDisplay lfbDisplay = display.driverData;
2068          uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
2069          int c;
2070
2071          x /= textCellW;
2072          y /= textCellH;
2073
2074          if(y > surface.box.bottom || y < surface.box.top)
2075             return;
2076          coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
2077          for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
2078          for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
2079          {
2080             if(surface.textOpacity)
2081                *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
2082             else
2083                *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
2084          }
2085       }
2086       else
2087       {
2088          lfbSurface.writingText = true;
2089 #if !defined(ECERE_NOTRUETYPE)
2090          x <<= 6;
2091
2092          if(surface.font.outlineSize)
2093          {
2094             ColorAlpha backForeground = surface.foreground;
2095             int fx = x;
2096             lfbSurface.writingOutline = true;
2097             surface.foreground = surface.outlineColor;
2098             lfbSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &fx, y, prevGlyph, rPrevGlyph, null);
2099             lfbSurface.writingOutline = false;
2100             surface.foreground = backForeground;
2101          }
2102
2103          lfbSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &x, y, prevGlyph, rPrevGlyph, null);
2104 #endif
2105          lfbSurface.writingText = false;
2106       }
2107    }
2108
2109    void TextFont(Display display, Surface surface, Font font)
2110    {
2111       LFBSurface lfbSurface = surface.driverData;
2112       lfbSurface.font = font;
2113    }
2114
2115    void TextOpacity(Display display, Surface surface, bool opaque)
2116    {
2117
2118    }
2119
2120    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * advance)
2121    {
2122       LFBSurface lfbSurface = surface.driverData;
2123       FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, advance);
2124    }
2125
2126    void DrawingChar(Display display, Surface surface, byte character)
2127    {
2128       LFBSurface lfbSurface = surface.driverData;
2129       lfbSurface.drawingChar = character;
2130    }
2131
2132    void LineStipple(Display display, Surface surface, uint32 stipple)
2133    {
2134       LFBSurface lfbSurface = surface.driverData;
2135       lfbSurface.stipple = (uint16)stipple;
2136    }
2137
2138 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
2139    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
2140    {
2141       if(mesh.vertices && !mesh.flags.vertices)
2142          delete mesh.vertices;
2143       if(mesh.normals && !mesh.flags.normals)
2144          delete mesh.normals;
2145       if(mesh.texCoords && !mesh.flags.texCoords1)
2146          delete mesh.texCoords;
2147       if(mesh.tangents && !mesh.flags.tangents)
2148          delete mesh.tangents;
2149       if(mesh.colors && !mesh.flags.colors)
2150          delete mesh.colors;
2151       if(mesh.lightVectors && !mesh.flags.lightVectors)
2152          delete mesh.lightVectors;
2153    }
2154
2155    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
2156    {
2157       bool result = false;
2158       if(mesh.nVertices == nVertices)
2159       {
2160          result = true;
2161          // Same number of vertices, adding features (Leaves the other features pointers alone)
2162          if(mesh.flags != flags)
2163          {
2164             if(!mesh.flags.vertices && flags.vertices)
2165             {
2166                if(flags.doubleVertices)
2167                {
2168                   mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
2169                }
2170                else
2171                   mesh.vertices = new Vector3Df[nVertices];
2172             }
2173             if(!mesh.flags.normals && flags.normals)
2174             {
2175                if(flags.doubleNormals)
2176                {
2177                   mesh.normals = (Vector3Df *)new Vector3D[nVertices];
2178                }
2179                else
2180                   mesh.normals = new Vector3Df[nVertices];
2181             }
2182             if(!mesh.flags.texCoords1 && flags.texCoords1)
2183                mesh.texCoords = new Pointf[nVertices];
2184             if(!mesh.flags.colors && flags.colors)
2185                mesh.colors = new ColorRGBAf[nVertices];
2186          }
2187       }
2188       else
2189       {
2190          result = true;
2191          // New number of vertices, reallocate all current and new features
2192          flags |= mesh.flags;
2193          if(flags.vertices)
2194          {
2195             if(flags.doubleVertices)
2196             {
2197                mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
2198             }
2199             else
2200                mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
2201          }
2202          if(flags.normals)
2203          {
2204             if(flags.doubleNormals)
2205             {
2206                mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
2207             }
2208             else
2209                mesh.normals = renew mesh.normals Vector3Df[nVertices];
2210          }
2211          if(flags.texCoords1)
2212             mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
2213          if(flags.colors)
2214             mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
2215       }
2216       return result;
2217    }
2218
2219    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
2220    {
2221       return true;
2222    }
2223
2224    void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
2225    {
2226       delete indices;
2227    }
2228
2229    uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
2230    {
2231       return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
2232    }
2233    uint16 * LockIndices(DisplaySystem displaySystem, void * indices)
2234    {
2235       return indices;
2236    }
2237 #endif
2238 }