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