Modifications to fix crashes on Window with alphaBlend = true on 16 bit display
[sdk] / ecere / src / gfx / drivers / LFBDisplayDriver.ec
1 namespace gfx::drivers;
2
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
5 #endif
6
7 #define uint _uint
8 #if !defined(ECERE_NOTRUETYPE)
9 #include <ft2build.h>
10 #include FT_FREETYPE_H
11 #include FT_TRUETYPE_TABLES_H
12 #include <freetype/ttunpat.h>
13 #define property  _property
14 #include "harfbuzz.h"
15 #undef property
16
17 #if defined(__WIN32__)
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
21 #define set _set
22 #include <fontconfig/fontconfig.h>
23 static FcConfig * fcConfig;
24 #undef set
25 #endif
26
27 #endif
28 #undef uint
29
30 #ifdef __MSC__
31 #pragma warning(disable:4244)
32 #pragma warning(disable:4018)
33 #endif
34
35 import "File"
36 import "Display"
37
38 public define LIGHTSHIFT = 5;
39 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
40
41 /*#ifndef ECERE_VANILLA
42 import "lfbRGBLookup"
43 static bool rgbLookupSet = true;
44 #else*/
45 /*static */byte defaultRGBLookup[32768];
46 /*static */bool rgbLookupSet = false;
47 //#endif
48
49 import "lfbBlit"
50 import "lfbConvert"
51
52 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
53 import "OpenGLDisplayDriver"
54 import "Direct3D8DisplayDriver"
55 import "Direct3D9DisplayDriver"
56 #endif
57
58 #if !defined(ECERE_NOTRUETYPE)
59
60 static unichar UTF16GetChar(uint16 *string, int * nw)
61 {
62    unichar ch;
63    if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
64    {
65       ch = HB_SurrogateToUcs4(string[0], string[1]);
66       *nw = 2;
67    }
68    else
69    {
70       ch = *string;
71       *nw = 1;
72    }
73    return ch;
74 }
75
76 static HB_Bool hb_stringToGlyphs(HB_Font font, uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
77 {
78    FT_Face face = (FT_Face)font->userData;
79    int glyph_pos = 0;
80    int c, nw;
81
82    if (length > *numGlyphs)
83       return 0;
84
85    for (c = 0; c < length; c += nw)
86    {
87       unichar ch = UTF16GetChar(string + c, &nw);
88       glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
89    }
90    *numGlyphs = glyph_pos;
91    return 1;
92 }
93
94 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
95 {
96    int c;
97    for(c = 0; c < numGlyphs; c++)
98       advances[c] = 0; // ### not tested right now
99 }
100
101 static HB_Bool hb_canRender(HB_Font font, uint16 * string, uint length)
102 {
103    FT_Face face = (FT_Face)font->userData;
104    int c, nw;
105
106    for (c = 0; c < length; c += nw)
107    {
108       unichar ch = UTF16GetChar(string + c, &nw);
109       if(!FT_Get_Char_Index(face, ch))
110          return 0;
111    }
112    return 1;
113 }
114
115 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
116 {
117     FT_Face face = (FT_Face)font;
118     FT_ULong ftlen = *length;
119     FT_Error error = 0;
120
121     if (!FT_IS_SFNT(face))
122         return HB_Err_Invalid_Argument;
123
124     error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
125     *length = ftlen;
126     return (HB_Error)error;
127 }
128
129 static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
130 {
131     HB_Error error = HB_Err_Ok;
132     FT_Face face = (FT_Face)font->userData;
133
134     int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
135
136     if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
137         return error;
138
139     if (face->glyph->format != ft_glyph_format_outline)
140         return (HB_Error)HB_Err_Invalid_GPOS_SubTable;
141
142     *nPoints = face->glyph->outline.n_points;
143     if (!(*nPoints))
144         return HB_Err_Ok;
145
146     if (point > *nPoints)
147         return (HB_Error)HB_Err_Invalid_GPOS_SubTable;
148
149     *xpos = face->glyph->outline.points[point].x;
150     *ypos = face->glyph->outline.points[point].y;
151
152     return HB_Err_Ok;
153 }
154
155 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)
156 {
157     // ###
158     metrics->x = metrics->y = metrics->width = metrics->height = metrics->xOffset = metrics->yOffset = 0;
159 }
160
161 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
162 {
163     return 0; // ####
164 }
165
166 static HB_FontClass hb_fontClass =
167 {
168    hb_stringToGlyphs, hb_getAdvances, hb_canRender,
169    hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
170 };
171
172 static uint FT_stream_load(FT_Stream stream, uint offset, byte * buffer, uint count)
173 {
174     File f = stream->descriptor.pointer;
175     f.Seek(offset, start);
176     return count ? f.Read(buffer, 1, count) : 0;
177 }
178
179 static void FT_stream_close(FT_Stream stream)
180 {
181    File f = stream->descriptor.pointer;
182    delete f;
183    delete stream;
184 }
185
186 static FT_Library ftLibrary;
187 static int numFonts;
188 #undef CompareString
189 static BinaryTree loadedFonts
190 {
191    CompareKey = (void *)BinaryTree::CompareString 
192 };
193
194 class FontEntry : BTNode
195 {
196    FT_Face face;
197    HB_FontRec hbFont;
198    HB_Face hbFace;
199
200    int used;
201    byte * buffer;
202    
203    //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
204    FT_Stream stream;
205
206    ~FontEntry()
207    {
208       char * fileName = (char *)key;
209       delete fileName;
210       delete buffer;
211       if(hbFace)
212          HB_FreeFace(hbFace);
213       if(face)
214       {
215          FT_Done_Face(face);
216          numFonts--;
217          if(!numFonts)
218          {
219             FT_Done_FreeType(ftLibrary);
220             ftLibrary = null;
221          }
222       }
223    }
224 }
225 #endif
226
227 struct GlyphInfo
228 {
229    int ax, ay;
230    int x, y;
231    int w, h;
232    int left, top;
233    int glyphNo;
234 };
235
236 #define MAX_FONT_LINK_ENTRIES   10
237
238 class GlyphPack : BTNode
239 {
240    GlyphInfo glyphs[256];
241    Bitmap bitmap { };
242
243    void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
244    {
245 #if !defined(ECERE_NOTRUETYPE)
246       unichar c;
247       int maxWidth, maxHeight;
248       int cellWidth, cellHeight;
249       int width, height;
250       FontEntry fontEntry = null;
251       FT_Face faces[128];
252       bool isGlyph = key & 0x80000000;
253       int curScript = (key & 0x7F000000) >> 24;
254       unichar testChar = 0;
255       /*
256       if(isGlyph)
257       {
258          switch(curScript)
259          {
260             case HB_Script_Arabic:
261                testChar = 0x621;
262                // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
263                break;
264             case HB_Script_Devanagari:
265                testChar = 0x905; 
266                break;
267             case 60: testChar = 'あ'; break;
268             case 61: testChar = 0x3400; break;
269          }
270       }
271       */
272       /*
273       FT_GlyphSlot slot;
274       FT_Matrix matrix;
275       FT_Vector pen = { 0, 0 };
276       if(font.fakeItalic)
277       {
278          matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
279          matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
280          matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
281          matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
282          FT_Set_Transform( fontEntry.face, &matrix, &pen );
283       }
284       FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
285       */
286
287       maxWidth = 0; 
288       maxHeight = 0;
289
290       for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
291       {
292          fontEntry = font.fontEntries[c];
293          if(fontEntry)
294          {
295             FT_Matrix matrix;
296             FT_Vector pen = { 0, 0 };
297             
298             if(font.fakeItalic)
299             {
300                matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
301                matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
302                matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
303                matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
304                FT_Set_Transform(fontEntry.face, &matrix, &pen);
305             }
306             FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
307
308             fontEntry.hbFont.x_ppem  = fontEntry.face->size->metrics.x_ppem;
309             fontEntry.hbFont.y_ppem  = fontEntry.face->size->metrics.y_ppem;
310             fontEntry.hbFont.x_scale = fontEntry.face->size->metrics.x_scale;
311             fontEntry.hbFont.y_scale = fontEntry.face->size->metrics.y_scale;
312          }
313       }
314
315       fontEntry = null;
316       for(c = 0; c < 128; c++)
317       {
318          int entry = 0;
319          if(isGlyph)
320          {
321             uint glyph = (key | c) & 0xFFFFFF;
322             for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
323             {
324                fontEntry = font.fontEntries[entry];
325                if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
326                {
327                   if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
328                   {
329                      
330                      //printf("%s: Accepted entry %d ", font.faceName, entry);
331                      break;
332                   }
333                }
334             }
335          }
336          else
337          {
338             for(entry = startFontEntry; ; entry++)
339             {
340                uint glyph;
341                fontEntry = font.fontEntries[entry];
342                if((glyph = FT_Get_Char_Index(fontEntry.face, (key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
343                {
344                   if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
345                      break;
346                }
347             }
348          }
349          faces[c] = fontEntry.face;
350          maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - faces[c]->glyph->metrics.width & 0x3F)) >> 6));
351          maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6));
352          //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
353       }
354       cellWidth = maxWidth;
355       cellHeight = maxHeight;
356
357       width = pow2i(maxWidth * 16);
358       height = pow2i(maxHeight * 8);
359
360       if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
361       {
362          Bitmap bitmap = this.bitmap;
363
364          bitmap.transparent = true;
365
366          for(c = 0; c < 128; c++)
367          {
368             FT_Int i, j, p, q;
369             FT_Int xMax, yMax;
370             int sx = (c % 16) * cellWidth;
371             int sy = (c / 16) * cellHeight;
372             int x, y;
373             byte * picture = (byte *)bitmap.picture;
374             GlyphInfo * glyph = &glyphs[c];
375             FT_GlyphSlot slot = faces[c]->glyph;
376             double em_size = 1.0 * faces[c]->units_per_EM;
377             double x_scale = faces[c]->size->metrics.x_ppem / em_size;
378             double y_scale = faces[c]->size->metrics.y_ppem / em_size;
379             double ascender = faces[c]->ascender * y_scale;
380             int glyphNo = isGlyph ? ((key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], key | c);
381
382             FT_Load_Glyph(faces[c], glyphNo, /*FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT*/ FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/); // FT_LOAD_RENDER // FT_LOAD_NO_HINTING
383             
384             FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
385
386             x = sx;
387             y = sy;
388             //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
389             
390             glyph->left = slot->bitmap_left;
391             // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
392             // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
393             //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
394             //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
395
396             //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0  + 0.5) - slot->bitmap_top;
397             //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0  + 0.5) - slot->bitmap_top;
398
399             //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
400
401             //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
402             //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
403             
404             //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
405             glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6)) / 2;
406
407             // printf("[char: %d] mode: %d, width: %d, height: %d, pitch: %d\n", key + c, slot->bitmap.pixel_mode, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
408             xMax = x + slot->bitmap.width;
409             yMax = y + slot->bitmap.rows;
410
411             {
412                int total = 0;
413                int numPixels = 0;
414                int max;
415                if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
416                {
417                   for(j = y, q = 0; j<yMax; j++)
418                   {
419                      for(p = 0, i = x; i<xMax; i++)
420                      {
421                         byte value = ((byte *)slot->bitmap.buffer)[q + p++];
422                         if(value > 32)
423                         {
424                            total += value;
425                            numPixels++;
426                         }
427                      }
428                      q += slot->bitmap.pitch;
429                   }
430                }
431                max = numPixels ? (total / numPixels) : 1;
432
433                for(j = y, q = 0; j<yMax; j++)
434                {
435                   int bit = 0x80;
436                   for(p = 0, i = x; i<xMax; i++)
437                   {
438                      if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
439                      {
440                         picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
441                         bit >>= 1;
442                         if(!bit) { bit = 0x80; p++; }                     
443                      }
444                      else
445                      {
446                         byte value = ((byte *)slot->bitmap.buffer)[q + p++];
447                         picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
448                      }
449                   }
450                   q += slot->bitmap.pitch;
451                }
452             }
453             glyph->x = sx;
454             glyph->y = sy;
455             glyph->w = slot->bitmap.width;
456             glyph->h = slot->bitmap.rows;
457             glyph->glyphNo = glyphNo;
458
459             glyph->ax = slot->advance.x;
460             glyph->ay = slot->advance.y + (64 - slot->advance.y % 64);
461          }
462          #if 0
463          {
464             int c;
465             char fileName[256];
466             static int fid = 0;
467             for(c = 0; c<256; c++)
468                bitmap.palette[c] = ColorAlpha { 255, { c,c,c } };
469             bitmap.pixelFormat = pixelFormat8;
470             
471             /*
472             //strcpy(fileName, faceName);
473             if(flags)
474                strcat(fileName, "Bold");
475             */
476             sprintf(fileName, "font%d", fid++);
477             ChangeExtension(fileName, "pcx", fileName);
478
479             bitmap.Save(fileName, null, 0);
480             bitmap.pixelFormat = pixelFormatAlpha;
481          }
482          #endif
483
484          if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
485          {
486             displaySystem.Lock();
487 #if defined(__WIN32__)
488             // Is this check still required?
489             if(displaySystem.driver == class(OpenGLDisplayDriver) ||
490                displaySystem.driver == class(Direct3D8DisplayDriver) ||
491                displaySystem.driver == class(Direct3D9DisplayDriver))
492 #endif
493                bitmap.MakeDD(displaySystem);
494             displaySystem.Unlock();
495          }
496       }
497 #endif
498    }
499 }
500
501 #if !defined(ECERE_NOTRUETYPE)
502 default:
503 HB_LineBreakClass HB_GetLineBreakClass(unichar ch)
504 {
505    return 0; //(HB_LineBreakClass)QUnicodeTables::lineBreakClass(ch);
506 }
507
508 void HB_GetUnicodeCharProperties(unichar ch, HB_CharCategory *category, int *combiningClass)
509 {
510    *category = GetCharCategory(ch); //(HB_CharCategory)QChar::category(ch);
511    *combiningClass = 0; //QChar::combiningClass(ch);
512 }
513
514 HB_CharCategory HB_GetUnicodeCharCategory(unichar ch)
515 {
516   return GetCharCategory(ch);
517 }
518
519 int HB_GetUnicodeCharCombiningClass(unichar ch)
520 {
521    return 0; // QChar::combiningClass(ch);
522 }
523
524 uint16 HB_GetMirroredChar(uint16 ch)
525 {
526    return 0; //QChar::mirroredChar(ch);
527 }
528 private:
529
530 static HB_ShaperItem shaper_item;
531
532 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
533 {
534    static uint maxGlyphs = 0;
535    HB_Glyph * glyphs = shaper_item.glyphs;
536
537    shaper_item.kerning_applied = 0;
538    shaper_item.string = string;
539    shaper_item.stringLength = len;
540    shaper_item.item.script = script;
541    shaper_item.item.pos = 0;
542    shaper_item.item.length = shaper_item.stringLength;
543    if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
544       shaper_item.item.bidiLevel = 1;
545    else
546       shaper_item.item.bidiLevel = 0;
547    shaper_item.shaperFlags = 0;
548    shaper_item.font = &entry.hbFont;
549    shaper_item.face = entry.hbFace;
550    shaper_item.num_glyphs = shaper_item.item.length;
551    shaper_item.glyphIndicesPresent = 0;
552    shaper_item.initialGlyphCount = 0;
553    shaper_item.num_glyphs = 0;   
554    shaper_item.glyphs = null;   
555
556    while(!HB_ShapeItem(&shaper_item))
557    {
558       if(shaper_item.num_glyphs > maxGlyphs)
559       {
560          maxGlyphs = shaper_item.num_glyphs;                                                                                                            
561          glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
562          shaper_item.attributes   = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
563          shaper_item.advances     = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
564          shaper_item.offsets      = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
565          shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
566       }
567       else
568       {
569          shaper_item.glyphs = glyphs;
570          shaper_item.num_glyphs = maxGlyphs;
571       } 
572   }
573
574    *numGlyphs = shaper_item.num_glyphs;
575    *rightToLeft = shaper_item.item.bidiLevel % 2;
576    return shaper_item.glyphs;
577 }
578
579 /*
580    delete shaper_item.glyphs;
581    delete shaper_item.attributes;
582    delete shaper_item.advances;
583    delete shaper_item.offsets;
584    delete shaper_item.log_clusters;
585 */
586 #endif
587
588 public class Font : struct
589 {
590    BinaryTree glyphPacks { };
591    GlyphPack asciiPack { };
592 #if !defined(ECERE_NOTRUETYPE)
593    FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
594 #endif
595    float size;
596    bool fakeItalic;
597    int height;
598    FontFlags flags;
599    char faceName[512];
600
601    ~Font()
602    {
603 #if !defined(ECERE_NOTRUETYPE)
604       GlyphPack pack;
605       while((pack = (GlyphPack)glyphPacks.root))
606       {
607          glyphPacks.Remove(pack);
608          delete pack;
609       }
610 #endif
611    }
612 };
613
614 public class LFBDisplay : struct
615 {
616 public:
617    Bitmap bitmap { };
618    byte rgbLookup[32768];
619    byte lightTable[256][LIGHTSTEPS];
620    OldList updateBoxes;
621    int x,y;
622    bool selfManaged;
623    void (* displayCallback)(Display display, Box updateBox);
624 };
625
626 public class LFBSystem : struct
627 {
628 public:
629    int format;
630    ColorAlpha * palette;
631    byte rgbLookup[32768];
632
633    LFBSystem()
634    {
635       if(!rgbLookupSet)
636       {
637          int c, r, g, b;
638          ColorAlpha * palette = GetDefaultPalette();
639          for(c = 16; c < 232; c++)
640          {
641             Color555 color = palette[c].color;
642             for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
643                for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
644                   for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
645                      defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
646          }
647          for(c = 232; c < 246; c++)
648          {
649             Color555 color = palette[c].color;
650             defaultRGBLookup[color] = (byte)c;
651          }
652          /*
653          for(c = 246; c < 256; c++)
654          {
655             Color555 color = palette[c].color;
656             defaultRGBLookup[color] = (byte)c;
657          }
658          for(c = 0; c < 16; c++)
659          {
660             Color555 color = palette[c].color;
661             defaultRGBLookup[color] = (byte)c;
662          }*/
663          /*
664          for(c = 0; c<32768; c++)
665          {
666             Color color = (Color)(Color555)c;
667             defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
668             // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
669          }
670          */
671          rgbLookupSet = true;
672       }
673    }
674 };
675
676 public class LFBSurface : struct
677 {
678 public:
679    // For compatibility with 3D drivers as well
680    Font font;
681    bool opaqueText;
682    int xOffset;
683    bool writingText;
684
685    Bitmap bitmap;
686
687    // Drawing attributes
688    uint foreground, background;
689    ColorAlpha foregroundRgb;
690    uint16 stipple;
691    byte drawingChar;
692    byte * paletteShades;
693    bool clearing;
694 };
695
696 /*
697 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
698 {
699    if(recordA->zMin > recordB->zMin)
700       return  1;
701    else if(recordA->zMin < recordB->zMin)
702       return -1;
703    else if(recordA > recordB)
704       return 1;
705    else if(recordA < recordB)
706       return -1;
707    else
708       return  0;
709 }
710 */
711
712 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
713 struct FontData
714 {
715    char fileName[MAX_FILENAME];
716    FontFlags flags;
717 };
718
719 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
720 {
721    if(fontType == TRUETYPE_FONTTYPE)
722    {
723       FontData * fontData = (FontData *) lParam;
724       char * fileName = (char *)lParam;
725       HKEY key;
726       int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
727       int italic = (fontData->flags.italic) ? 1 : 0;
728       if(weight == font->elfLogFont.lfWeight && italic == (font->elfLogFont.lfItalic != 0))
729       {
730          if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
731             !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
732          {  
733             int value = 0;
734             while(true)
735             {
736                char entryName[1024];
737                char fontFileName[1024];
738                uint32 type;
739                int size = 1024;
740                int sizeFileName = 1024;
741                char * occurence;
742                if(RegEnumValue(key, value++, entryName, &size, null, &type, fontFileName, &sizeFileName) != ERROR_SUCCESS)
743                   break;
744                if((occurence = SearchString(entryName, 0, font->elfFullName, false, false)))
745                {
746                   int c;
747                   for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
748                   {
749                      char ch = entryName[c];
750                      if(ch == '&') { c = -1; break; }
751                      else if(ch != ' ') break;
752                   }
753                   if(c >= 0) continue;
754                   for(c = (int)(occurence - entryName) + strlen(font->elfFullName); ; c++)
755                   {
756                      char ch = entryName[c];
757                      if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
758                      else if(ch != ' ') break;
759                   }
760                   if(c >= 0) continue;
761
762                   strcpy(fileName, fontFileName);
763                   RegCloseKey(key);
764                   return 0;
765                }               
766             }
767             RegCloseKey(key);
768             return 1;
769          }
770       }
771    }
772    return 1;   
773 }
774 #endif
775
776 static int utf16BufferSize = 0;
777 static uint16 * utf16 = null;
778
779 public class LFBDisplayDriver : DisplayDriver
780 {
781    class_property(name) = "LFB";
782
783    bool CreateDisplaySystem(DisplaySystem displaySystem)
784    {
785       displaySystem.flags.memBackBuffer = true;
786       // displaySystem.pixelFormat = pixelFormat888;
787       return true;
788    }
789
790    void DestroyDisplaySystem(DisplaySystem displaySystem)
791    {
792    }
793
794    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
795    {
796       delete bitmap.picture;
797       if(bitmap.allocatePalette)
798          delete bitmap.palette;
799    }
800
801    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
802    {
803       bool result = false;
804       if(!stride)
805       {
806          switch(GetColorDepthShifts(format))
807          {
808             case 0: stride = (width + 3) & 0xFFFFFFFC; break;
809             case 1: stride = (width + 1) & 0xFFFFFFFE; break;
810             case 2: stride = width;                    break;
811          }
812       }
813       bitmap.stride = stride;   
814       bitmap.width = width;
815       bitmap.height = height;
816       bitmap.size = (uint32) stride * (uint32)height;
817       bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
818       bitmap.pixelFormat = format;
819       bitmap.transparent = false;
820    /*
821       surface.box.left = surface.box.top = 0;
822       surface.box.right = width - 1;
823       surface.box.bottom = height - 1;
824    */
825       bitmap.picture = new0 byte[bitmap.sizeBytes];
826       if(bitmap.picture)
827       {
828          bitmap.allocatePalette = allocatePalette;
829          if(allocatePalette)
830          {
831             bitmap.palette = new ColorAlpha[256];
832             if(bitmap.palette)
833             {
834                CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
835                result = true;
836             }
837          }
838          else
839          {
840             bitmap.palette = GetDefaultPalette();
841             result = true;
842          }
843       }
844       if(!result)
845          FreeBitmap(displaySystem, bitmap);
846       return result;
847    }
848
849    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
850    {  
851       bool result = false;
852       LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
853
854       if(src)
855       {
856          if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
857          {
858             if(src.transparent && src.pixelFormat == pixelFormat888)
859             {
860                /*
861                DWORD c;
862                DWORD * picture = (DWORD *)src.picture;
863                
864                for(c = 0; c<src.size; c++, picture++)
865                {
866                   if(*picture & 0xFFFFFF)
867                      *picture =  *picture | 0xFF000000;
868                   else
869                      *picture = *picture & 0xFFFFFF;
870                }
871                */
872             }
873             result = true;
874          }
875          else
876          {
877             Bitmap bitmap { };
878             if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
879             {
880                if(format == pixelFormat8)
881                {
882                   if(palette)
883                      bitmap.palette = palette;
884                   else if(lfbSystem && lfbSystem.palette)
885                      bitmap.palette = lfbSystem.palette;
886                   else
887                      bitmap.palette = src.palette;
888                }
889
890                if(converters_table[src.pixelFormat][bitmap.pixelFormat])
891                {
892                   converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
893                   bitmap.transparent = src.transparent;
894                   bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
895                   delete src.picture;
896                   if(src.palette != bitmap.palette)
897                   {
898                      if(src.allocatePalette)
899                         delete src.palette;
900                      src.allocatePalette = false;
901                   }
902                   src.picture = bitmap.picture;
903                   src.palette = bitmap.palette;
904                   src.stride = bitmap.stride;
905                   src.pixelFormat = bitmap.pixelFormat;
906
907                   result = true;
908                }
909
910                bitmap.palette = null;
911                bitmap.picture = null;
912             }
913             delete bitmap;
914          }
915       }
916       return result;
917    }
918
919    void DestroyDisplay(Display display)
920    {
921       LFBDisplay lfbDisplay = display.driverData;
922       delete lfbDisplay.bitmap.palette;
923    }
924
925    bool CreateDisplay(Display display)
926    {
927       bool result = false;
928       LFBDisplay lfbDisplay = display.driverData;
929       if(!lfbDisplay)
930       {
931          lfbDisplay = display.driverData = LFBDisplay { };
932          lfbDisplay.selfManaged = true;
933          lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
934       }
935
936       if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
937       {
938          CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
939          result = true;
940       }
941       return result;
942    }
943
944    bool DisplaySize(Display display, int width, int height)
945    {
946       LFBDisplay lfbDisplay = display.driverData;
947       //display.width = width;
948       //display.height = height;
949       lfbDisplay.bitmap.width = width;
950       lfbDisplay.bitmap.height = height;
951       /*
952       lfbDisplay.updateBox.left = display.width;
953       lfbDisplay.updateBox.top = display.height;
954       lfbDisplay.updateBox.right = 0;
955       lfbDisplay.updateBox.bottom = 0;
956       */
957
958       if(lfbDisplay.selfManaged)
959       {
960          lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
961          lfbDisplay.bitmap.stride = width;
962       }
963       lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
964       return true;
965    }
966
967    void DisplayPosition(Display display, int x, int y)
968    {
969       LFBDisplay lfbDisplay = display.driverData;
970       lfbDisplay.x = x;
971       lfbDisplay.y = y;
972    }
973
974    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
975    {
976       LFBDisplay lfbDisplay = display.driverData;
977       if(colorMatch)
978       {
979          int c;
980
981          if(!palette)
982          {
983             LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
984             palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
985             CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
986          }
987          else
988             for(c = 0; c<32768; c++)
989                lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
990
991          for(c=0; c<256; c++)
992          {
993             int i;
994             for(i=0; i<LIGHTSTEPS; i++)
995             {
996                lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
997                           (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
998                           (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
999                           (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1000             }
1001          }
1002       }
1003       if(lfbDisplay.bitmap.palette)
1004          CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1005    }
1006
1007    void Update(Display display, Box updateBox)
1008    {
1009       LFBDisplay lfbDisplay = display.driverData;
1010       if(lfbDisplay.displayCallback)
1011       {
1012          if(updateBox == null)
1013          {
1014             Box box { 0,0, display.width,display.height };
1015             lfbDisplay.displayCallback(display, box);
1016          }
1017          else
1018             lfbDisplay.displayCallback(display, updateBox);
1019       }
1020    }
1021
1022    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1023    {
1024       if(bitmap.pixelFormat != pixelFormatAlpha)
1025       {
1026          if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1027          {
1028             FreeBitmap(displaySystem, bitmap);
1029             return false;
1030          }
1031       }
1032       return true;
1033    }
1034
1035    void ReleaseSurface(Display display, Surface surface)
1036    {
1037       LFBSurface lfbSurface = surface.driverData;
1038       delete lfbSurface;
1039       surface.driverData = null;
1040    }
1041
1042    bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1043    {
1044       LFBDisplay lfbDisplay = display.driverData;
1045       LFBSurface lfbSurface = surface.driverData;
1046       if(!lfbSurface)
1047       {
1048          lfbSurface = surface.driverData = LFBSurface { };
1049       }
1050
1051       lfbSurface.bitmap = lfbDisplay.bitmap;
1052
1053       surface.offset.x = x;
1054       surface.offset.y = y;
1055       surface.box = clip;
1056       if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1057       {
1058          surface.offset.x /= textCellW;
1059          surface.offset.y /= textCellH;
1060          surface.box.left /= textCellW;
1061          surface.box.top /= textCellH;
1062          surface.box.right /= textCellW;
1063          surface.box.bottom /= textCellH;
1064       }
1065
1066       /*
1067       lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1068       lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1069       lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1070       lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1071       */
1072
1073       surface.unclippedBox = surface.box;
1074       lfbSurface.drawingChar = 219;
1075       return true;
1076    }
1077
1078    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1079    {
1080       bool result = false;
1081       LFBSurface lfbSurface = surface.driverData;
1082       if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1083       {
1084          lfbSurface.bitmap = bitmap;
1085
1086          surface.offset.x = x;
1087          surface.offset.y = y;
1088          surface.box = clip;
1089          if(bitmap.pixelFormat == pixelFormatText)
1090          {
1091             surface.offset.x /= textCellW;
1092             surface.offset.y /= textCellH;
1093             surface.box.left /= textCellW;
1094             surface.box.top /= textCellH;
1095             surface.box.right /= textCellW;
1096             surface.box.bottom /= textCellH;
1097          }
1098
1099          surface.unclippedBox = *&surface.box;
1100          lfbSurface.drawingChar = 219;
1101
1102          result = true;
1103       }
1104       return result;
1105    }
1106
1107    void Clip(Display display, Surface surface, Box clip)
1108    {
1109       LFBSurface lfbSurface = surface.driverData;
1110       if(clip != null)
1111       {
1112          Box box = clip;
1113
1114          if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1115          {
1116             box.left /= textCellW;
1117             box.top /= textCellH;
1118             box.right /= textCellW;
1119             box.bottom /= textCellH;
1120          }
1121          box.Clip(surface.unclippedBox);
1122          surface.box = box;
1123       }
1124       else
1125          surface.box = surface.unclippedBox;
1126    }
1127
1128    void SetForeground(Display display, Surface surface, ColorAlpha color)
1129    {
1130       LFBDisplay lfbDisplay = display ? display.driverData : null;
1131       LFBSurface lfbSurface = surface.driverData;
1132       uint index;
1133       if(display) color = color /*& 0xFFFFFF*/;
1134       lfbSurface.foregroundRgb = color;
1135
1136       if(lfbSurface.font && lfbDisplay)
1137       {
1138          index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1139          lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1140       }
1141
1142       switch(lfbSurface.bitmap.pixelFormat)
1143       {
1144          case pixelFormat8:
1145             if(display)
1146                lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1147             else
1148                lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1149             break;
1150          case pixelFormat444:  lfbSurface.foreground = (Color444)color; break;
1151          case pixelFormat555:  lfbSurface.foreground = (Color555)color; break;
1152          case pixelFormat565:  lfbSurface.foreground = (Color565)color; break;
1153          case pixelFormat888:  lfbSurface.foreground = color; break;
1154          case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1155          case pixelFormatText: 
1156             if(display)
1157                lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1158             else
1159                lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1160             break;
1161       }
1162    }
1163
1164    void SetBackground(Display display, Surface surface, ColorAlpha color)
1165    {
1166       LFBDisplay lfbDisplay = display ? display.driverData : null;
1167       LFBSurface lfbSurface = surface.driverData;
1168       color = color /*& 0xFFFFFF*/;
1169       switch(lfbSurface.bitmap.pixelFormat)
1170       {
1171          case pixelFormat8:
1172             if(display)
1173                lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1174             else
1175                lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1176             break;
1177          case pixelFormat444:  lfbSurface.background = (Color444)color; break;
1178          case pixelFormat555:  lfbSurface.background = (Color555)color; break;
1179          case pixelFormat565:  lfbSurface.background = (Color565)color; break;
1180          case pixelFormat888:  lfbSurface.background = color; break;
1181          case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1182          case pixelFormatText: 
1183             if(display)
1184                lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1185             else
1186                lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1187             break;
1188       }
1189    }
1190
1191    ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1192    {
1193       LFBSurface lfbSurface = surface.driverData;
1194       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1195       {
1196          x /= textCellW;
1197          y /= textCellH;
1198       }
1199       if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1200       {
1201          x += surface.offset.x;
1202          y += surface.offset.y;
1203          if(lfbSurface.bitmap.picture)
1204          {
1205             switch(lfbSurface.bitmap.pixelFormat)
1206             {
1207                case pixelFormatText:
1208                case pixelFormat8:
1209                   if(!lfbSurface.bitmap.palette) return 0;
1210                   return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1211                case pixelFormat444:  return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1212                case pixelFormat555:  return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1213                case pixelFormat565:  return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1214                case pixelFormat888:  return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1215             }
1216          }
1217       }
1218       return 0;
1219    }
1220
1221    void PutPixel(Display display, Surface surface,int x,int y)
1222    {
1223       LFBSurface lfbSurface = surface.driverData;
1224       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1225       {
1226          x /= textCellW;
1227          y /= textCellH;
1228       }
1229       if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1230       {
1231          x += surface.offset.x;
1232          y += surface.offset.y;
1233          if(lfbSurface.bitmap.picture)
1234          {
1235             switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1236             {
1237                case 0:
1238                   ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1239                   break;
1240                case 1:
1241                   ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1242                   break;
1243                case 2:
1244                   if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1245                      ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1246                   break;
1247             }
1248          }
1249       }
1250    }
1251
1252    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1253    {
1254       LFBSurface lfbSurface = surface.driverData;
1255
1256       int xd, yd;
1257       int xu,yu;
1258       int errorterm;
1259       uint offset;
1260       uint color = lfbSurface.foreground;
1261       uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1262       bool invert = false;
1263       if(!lfbSurface.bitmap.picture) return;
1264       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1265       {
1266          x1 /= textCellW;
1267          x2 /= textCellW;
1268          y1 /= textCellH;
1269          y2 /= textCellH;
1270          if(surface.textOpacity)
1271             color |= lfbSurface.background;
1272          color |= lfbSurface.drawingChar;
1273       }
1274       if(y1 == y2)
1275       {
1276          if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1277
1278          if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1279          if((x1>surface.box.right)||(x2<surface.box.left))return;
1280          if(x1<surface.box.left)x1=surface.box.left;
1281          if(x2>surface.box.right)x2=surface.box.right;
1282
1283          if(x2 < x1) return;
1284
1285          offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1286          if(stipple != 0xFFFF)
1287          {
1288             int x;
1289             switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1290             {
1291                case 0:
1292                   for(x=x1; x<=x2; x++, offset++)
1293                   {
1294                      if(stipple & 0x8000)
1295                         ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1296                      if(invert)
1297                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1298                      else
1299                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1300                   }
1301                   break;
1302                case 1:
1303                   for(x=x1; x<=x2; x++, offset++)
1304                   {
1305                      if(stipple & 0x8000)
1306                         ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1307                      if(invert)
1308                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1309                      else
1310                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1311                   }
1312                   break;
1313                case 2:
1314                   for(x=x1; x<=x2; x++, offset++)
1315                   {
1316                      if(stipple & 0x8000)
1317                         ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1318                      if(invert)
1319                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1320                      else
1321                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1322                   }
1323                   break;
1324             }
1325          }
1326          else
1327          {
1328             if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1329             {
1330                switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1331                {
1332                   case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1333                   case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1334                   case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1335                }
1336             }
1337             else
1338             {
1339                int x;
1340                for(x = x1; x <= x2; x++, offset++)
1341                {
1342                   ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1343                      (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1344                }
1345             }
1346          }
1347       }
1348       else if(x1 == x2)
1349       {
1350          int y;
1351
1352          if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1353
1354          if((x1>surface.box.right)||(x1<surface.box.left))return;
1355          if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1356          if(y1<surface.box.top)y1=surface.box.top;
1357          if(y2>surface.box.bottom)y2=surface.box.bottom;
1358
1359          offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1360          switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1361          {
1362             case 0:
1363                for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1364                {
1365                   if(stipple & 0x8000)
1366                      ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1367                   if(invert)
1368                      stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1369                   else
1370                      stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1371                }
1372                break;
1373             case 1:
1374                for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1375                {
1376                   if(stipple & 0x8000)
1377                   {
1378                      if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1379                         ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1380                      else
1381                      {
1382                         ((uint16 *)lfbSurface.bitmap.picture)[offset] = 
1383                            (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1384                      }
1385                   }
1386                   if(invert)
1387                      stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1388                   else
1389                      stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1390                }
1391                break;
1392             case 2:
1393                if(stipple != 0xFFFF)
1394                {
1395                   for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1396                   {
1397                      if(stipple & 0x8000)
1398                         ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1399                      if(invert)
1400                         stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1401                      else
1402                         stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1403                   }
1404                }
1405                else
1406                {
1407                   for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1408                      ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1409                }
1410                break;
1411          }
1412       }
1413       else 
1414       {
1415          if(x2 >= x1)
1416          {
1417             if(x1 < surface.box.left)
1418             {
1419                if(x2 < surface.box.left)
1420                   return;
1421                y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1422                x1 = surface.box.left;
1423             }
1424             if(x2 > surface.box.right)
1425             {
1426                if(x1 > surface.box.right)
1427                   return;
1428                y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1429                x2 = surface.box.right;
1430             }
1431             if(y2 >= y1)
1432             {
1433                if(y1 < surface.box.top)
1434                {
1435                   if(y2 < surface.box.top)
1436                      return;
1437                   x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1438                   y1 = surface.box.top;
1439                }
1440                if(y2 > surface.box.bottom)
1441                {
1442                   if(y1 > surface.box.bottom)
1443                      return;
1444                   x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1445                   y2 = surface.box.bottom;
1446                }
1447             }
1448             else
1449             {
1450                if(y1 > surface.box.bottom)
1451                {
1452                   if(y2 > surface.box.bottom)
1453                      return;
1454                   x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1455                   y1 = surface.box.bottom;
1456                }
1457                if(y2 < surface.box.top)
1458                {
1459                   if(y1 < surface.box.top)
1460                      return;
1461                   x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1462                   y2 = surface.box.top;
1463                }
1464             }
1465          }
1466          else
1467          {
1468             if(x1 > surface.box.right)
1469             {
1470                if(x2 > surface.box.right)
1471                   return;
1472                y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1473                x1 = surface.box.right;
1474             }
1475             if(x2 < surface.box.left)
1476             {
1477                if(x1 < surface.box.left)
1478                   return;
1479                y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1480                x2 = surface.box.left;
1481             }
1482             if(y2 >= y1)
1483             {
1484                if(y1 < surface.box.top)
1485                {
1486                   if(y2 < surface.box.top)
1487                      return;
1488                   x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1489                   y1 = surface.box.top;
1490                }
1491                if(y2 > surface.box.bottom)
1492                {
1493                   if(y1 > surface.box.bottom)
1494                      return;
1495                   x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1496                   y2 = surface.box.bottom;
1497                }
1498             }
1499             else
1500             {
1501                if(y1 > surface.box.bottom)
1502                {
1503                   if(y2 > surface.box.bottom)
1504                      return;
1505                   x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1506                   y1 = surface.box.bottom;
1507                }
1508                if(y2 < surface.box.top)
1509                {
1510                   if(y1 < surface.box.top)
1511                      return;
1512                   x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1513                   y2 = surface.box.top;
1514                }
1515             }
1516          }
1517
1518          xd=x2-x1;
1519          yd=y2-y1;
1520
1521          if(xd<0)
1522          {
1523             xd=-xd;
1524             xu=-1;
1525          }
1526          else
1527             xu=1;
1528          if(yd<0)
1529          {
1530             yd=-yd;
1531             yu=-(int)lfbSurface.bitmap.stride;
1532          }
1533          else
1534             yu=lfbSurface.bitmap.stride;
1535
1536          offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1537          errorterm=0;
1538
1539          if(xd>yd)
1540          {
1541             int i, length=xd;
1542             for(i=0; i<=length; i++)
1543             {
1544                if(stipple & 0x8000)
1545                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1546                   {
1547                      case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1548                      case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1549                      case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1550                   }
1551                offset+=xu;
1552                errorterm+=yd;
1553                if(errorterm>=xd)
1554                {
1555                   errorterm-=xd;
1556                   offset+=yu;
1557                }
1558                stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1559             }
1560          }
1561          else
1562          {
1563             int i, length=yd;
1564             for(i=0; i<=length; i++)
1565             {
1566                if(stipple & 0x8000)
1567                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1568                   {
1569                      case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1570                      case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1571                      case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1572                   }
1573                offset+=yu;
1574                errorterm+=xd;
1575                if(errorterm>=yd)
1576                {
1577                   errorterm-=yd;
1578                   offset+=xu;
1579                }
1580             }
1581          }
1582       }
1583    }
1584
1585    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1586    {
1587       DrawLine(display, surface,x1,y1,x2,y1);
1588       DrawLine(display, surface,x2,y1,x2,y2);
1589       DrawLine(display, surface,x2,y2,x1,y2);
1590       DrawLine(display, surface,x1,y2,x1,y1);
1591    }
1592
1593    #if !defined(__GNUC__)
1594    /*
1595    void memset_32_aligned(void *buf, int val, int dwords)
1596    {
1597             // Qword align
1598             if ((int)(buf) & 4) 
1599             {
1600                     *((uint32 *)(buf)) = val;
1601                     buf = ((uint32 *)(buf))+1;
1602                     dwords--;
1603             }
1604     
1605             if (dwords > 1) 
1606             {
1607                     __asm {
1608                             cld
1609                             mov   edi,  buf
1610                             mov   ecx,  dwords
1611                             shr       ecx,  1
1612                             mov   eax,  val
1613                             movd  mm0,  eax
1614                             movd  mm1,  eax
1615                             psllq mm1,  32
1616                             por   mm0,  mm1
1617                             align 16
1618             repeat:
1619                             movq [edi], mm0
1620                             add   edi,  8
1621                             loop  repeat
1622                             emms
1623                     };
1624             }
1625     
1626             // Final dword
1627             if (dwords & 1) *((int*)(buf)) = val;
1628    }*/
1629
1630    //#define USE_SSE
1631
1632 /*
1633    void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1634    {
1635       dwords <<= 2;
1636    #ifdef USE_SSE
1637       if(((uint32)buf) & 0x7F)
1638       {
1639          for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1640          {
1641             *buf = val;
1642             dwords--;
1643          }
1644       }
1645       if(dwords)
1646    #endif
1647       __asm
1648       {
1649          mov edi, buf
1650          mov eax, val
1651          mov ecx, dwords
1652
1653          mov edx,ecx
1654    #ifdef USE_SSE
1655          shr ecx,7
1656    #else
1657          shr ecx,6
1658    #endif
1659          mov ebx,ecx
1660    #ifdef USE_SSE
1661          shl ebx,7
1662    #else
1663          shl ebx,6
1664    #endif
1665          sub edx,ebx                            ; edx holds # of overflow bytes
1666
1667    #ifdef USE_SSE
1668            mov [edi],eax
1669            mov [edi+4],eax
1670          mov [edi+8],eax
1671          mov [edi+12],eax
1672          movdqa xmm0, [edi]
1673    #else
1674          mov [edi],eax
1675            mov [edi+4],eax
1676          movq mm0, [edi]
1677    #endif
1678            cmp ecx,0
1679            je doneloop
1680    setloop:
1681
1682    #ifdef USE_SSE
1683          movdqa [edi],xmm0
1684          movdqa [edi+16],xmm0
1685          movdqa [edi+32],xmm0
1686          movdqa [edi+48],xmm0
1687          movdqa [edi+64],xmm0
1688          movdqa [edi+80],xmm0
1689          movdqa [edi+96],xmm0
1690          movdqa [edi+112],xmm0
1691          add edi,8*16
1692    #else
1693          movq [edi],mm0
1694          movq [edi+8],mm0
1695          movq [edi+16],mm0
1696          movq [edi+24],mm0
1697          movq [edi+32],mm0
1698          movq [edi+40],mm0
1699          movq [edi+48],mm0
1700          movq [edi+56],mm0
1701          add edi,8*8
1702    #endif
1703          dec ecx
1704            jnz setloop
1705
1706    doneloop:
1707            mov ecx,edx
1708            shr ecx,2
1709            rep stosd
1710
1711            emms
1712       };
1713    }
1714    void memset_32(void *buf, uint32 val, uint32 dwords)
1715    {
1716       int align = 0;
1717       if ((uint32)(buf) & 3) 
1718       {
1719          align = 4;
1720          dwords--;
1721          
1722          if (((uint32)(buf) & 1))
1723          {
1724             *(byte *)(buf) = (byte)(val&0xFF); 
1725             buf = ((byte *)(buf))+1;
1726             val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1727             align --;
1728          }
1729          if (((uint32)(buf) & 2))
1730          {
1731             *(uint16 *)(buf) = (uint16)(val&0xFFFF); 
1732             buf = ((uint16 *)(buf))+1;
1733             val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1734             align-=2;
1735          }
1736       }
1737       memset_32_aligned(buf,val,dwords);
1738       if (align)
1739       {
1740          if (align == 1)
1741          {
1742             *(byte *)(buf) = (byte)(val&0xFF); 
1743          }
1744          else
1745          {
1746             *(uint16 *)(buf) = (uint16)(val&0xFFFF); 
1747             if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF); 
1748          }
1749       }
1750    }
1751    */
1752    #endif
1753
1754    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1755    {
1756       LFBSurface lfbSurface = surface.driverData;
1757       uint32 color = lfbSurface.background;
1758
1759       if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1760       {
1761          color |= lfbSurface.foreground | lfbSurface.drawingChar;
1762          x1 /= textCellW;
1763          x2 /= textCellW;
1764          y1 /= textCellH;
1765          y2 /= textCellH;
1766       }
1767       if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1768
1769       if(x1<surface.box.left)  x1=surface.box.left;
1770       if(x2>surface.box.right) x2=surface.box.right;
1771       if(y1<surface.box.top)   y1=surface.box.top;
1772       if(y2>surface.box.bottom)  y2=surface.box.bottom;
1773
1774       if(x2>=x1 && y2>=y1)
1775       {
1776          int w,y;
1777          byte * theOffset;
1778          
1779          w = x2-x1+1;
1780          if(w<1) return;
1781
1782          x1 += surface.offset.x;
1783          x2 += surface.offset.x;
1784          y1 += surface.offset.y;
1785          y2 += surface.offset.y;
1786          if(lfbSurface.bitmap.picture)
1787          {
1788             if(!surface.writeColor)
1789             {
1790                ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1791                for(y = y1; y<= y2; y++)
1792                {
1793                   int c;
1794                   for(c = 0; c < w; c++, picture++)
1795                      if(!picture->a)
1796                         picture->a = (byte)((color & 0xFF000000) >> 24);
1797                   picture += lfbSurface.bitmap.stride - w;
1798                }
1799             }
1800             else
1801             {
1802                if(surface.background.a == 255 || lfbSurface.clearing)
1803                {
1804                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1805                   {
1806                      case 0:
1807                         theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1808                         for(y = y1; y<= y2; y++)
1809                         {
1810                            FillBytes(theOffset,(byte)color,w);
1811                            theOffset += lfbSurface.bitmap.stride;
1812                         }
1813                         break;
1814                      case 1:
1815                         theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1816                         for(y = y1; y<= y2; y++)
1817                         {
1818                            FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1819                            theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1820                         }
1821                         break;
1822                      case 2:
1823                         theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1824                         for(y = y1; y<= y2; y++)
1825                         {
1826          #if defined(__GNUC__)
1827                            FillBytesBy4((uint32 *) theOffset,color,w);
1828          #else
1829                            memset_32((uint32 *) theOffset,color,w);
1830          #endif
1831                            theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1832
1833                         }
1834                         /*
1835                         y = y2-y1+1;
1836                         {
1837                            int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1838                            //memset_32((uint32 *) theOffset,color,w);
1839                            /*_asm
1840                            {
1841                               push edi
1842                               push ecx
1843                               push eax
1844                               push ebx
1845                               push edx
1846
1847                               mov ebx,bla
1848
1849                               mov edi,theOffset
1850                               mov eax,color
1851                               mov edx,y
1852                               mov ecx,w
1853                               
1854                               start:
1855                                  push ecx
1856                                  
1857                                  rep stosd
1858                                  add edi,ebx
1859                                  pop ecx
1860                                  dec edx                        
1861                                  jnz start
1862                               pop edx
1863                               pop ebx
1864                               pop eax
1865                               pop ecx
1866                               pop edi
1867                            };
1868                         break;
1869                         }*/
1870                   }
1871                }
1872                else
1873                {
1874                   switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1875                   {
1876                      case 0:
1877                         theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1878                         for(y = y1; y<= y2; y++)
1879                         {
1880                            // TODO: IMPLEMENT THIS
1881                            FillBytes(theOffset,(byte)color,w);
1882                            theOffset += lfbSurface.bitmap.stride;
1883                         }
1884                         break;
1885                      case 1:
1886                      {
1887                         uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1888                         ColorAlpha c = surface.background;
1889                         int a = c.a;
1890                         int cr = c.color.r;
1891                         int cg = c.color.g;
1892                         int cb = c.color.b;
1893                         PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1894
1895                         for(y = y1; y <= y2; y++)
1896                         {
1897                            int c;
1898                            for(c = 0; c < w; c++, dest++)
1899                            {                              
1900                               Color destColor;
1901                               if(pixelFormat == pixelFormat565)      { destColor = (Color)*(Color565 *)dest; }
1902                               else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
1903                               else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
1904                               {
1905                                  int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
1906                                  int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
1907                                  int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
1908
1909                                  if(r > 255) r = 255;
1910                                  if(g > 255) g = 255;
1911                                  if(b > 255) b = 255;
1912
1913                                  destColor = { (byte)r, (byte)g, (byte)b };
1914
1915                                  if(pixelFormat == pixelFormat565)      { *dest = (Color565)destColor; }
1916                                  else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
1917                                  else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
1918                               }
1919                            }
1920                            dest += (lfbSurface.bitmap.stride - w);
1921                         }
1922                         break;
1923                      }
1924                      case 2:
1925                      {
1926                         ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1927                         AlphaWriteMode alphaWrite = surface.alphaWrite;
1928                         ColorAlpha c = surface.background;
1929                         int a = c.a;
1930                         int cr = c.color.r;
1931                         int cg = c.color.g;
1932                         int cb = c.color.b;
1933                         for(y = y1; y <= y2; y++)
1934                         {
1935                            int c;
1936                            for(c = 0; c < w; c++, dest++)
1937                            {                              
1938                               int dr = dest->color.r;
1939                               int dg = dest->color.g;
1940                               int db = dest->color.b;
1941                               int r = a * cr / 255 + ((255 - a) * dr / 255);
1942                               int g = a * cg / 255 + ((255 - a) * dg / 255);
1943                               int b = a * cb / 255 + ((255 - a) * db / 255);
1944
1945                               if(r > 255) r = 255;
1946                               if(g > 255) g = 255;
1947                               if(b > 255) b = 255;
1948                               dest->color = { (byte)r, (byte)g, (byte)b };
1949
1950                               if(alphaWrite == blend)
1951                               {
1952                                  int ca = (int)(a + ((255 - a) * dest->a / 255));
1953                                  if(ca > 255) ca = 255;
1954                                  dest->a = (byte)ca;
1955                               }
1956                               else if(alphaWrite)
1957                                  dest->a = (byte)a;
1958                            }
1959                            dest += (lfbSurface.bitmap.stride - w);
1960                         }
1961                      }
1962                   }
1963                }
1964             }
1965          }
1966       }
1967    }
1968    void Clear(Display display, Surface surface, ClearType type)
1969    {
1970       LFBSurface lfbSurface = surface.driverData;
1971
1972       lfbSurface.clearing = true;
1973       if(surface.offset.x == 0 && surface.offset.y == 0 &&
1974          surface.box.left == 0 && surface.box.top  == 0 &&
1975          surface.box.right == surface.width-1 &&
1976          surface.box.bottom  == surface.height-1)
1977       {
1978          uint32 color = /*0xFF000000 | */lfbSurface.background;
1979          if(type != depthBuffer)
1980          {
1981             if(lfbSurface.bitmap.stride != surface.width)
1982                Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1983             else
1984             {
1985                switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1986                {
1987                   case 0:
1988                      FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
1989                      break;
1990                   case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
1991                   case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
1992                }
1993             }
1994          }
1995    /*
1996          if((flags & CLEAR_Z) && zbuffer)
1997             FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
1998    */
1999       }
2000       else
2001       {
2002          if(type != depthBuffer)
2003             Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2004    /*
2005          if((flags & CLEAR_Z))
2006          {
2007             int y;
2008             uint32 w = surface.box.right-surface.box.left+1;
2009             float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2010                              +   surface.box.left+surface.offset.x;
2011             for(y = surface.box.top; y<= surface.box.bottom; y++)
2012             {
2013                FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2014                offset += DISPLAY.Width;
2015             }
2016          }
2017    */
2018       }
2019       lfbSurface.clearing = false;
2020    }
2021
2022    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2023    {
2024       LFBSurface lfbSurface = surface.driverData;
2025       bool flip = false;
2026
2027       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2028
2029       if(w < 0) { w = -w; flip = true; }
2030
2031       //Clip against the edges of the source
2032       if(sx<0)
2033       {
2034          dx+=-sx;
2035          w-=-sx;
2036          sx=0;
2037       }
2038       if(sy<0)
2039       {
2040          dy+=0-sy;
2041          h-=0-sy;
2042          sy=0;
2043       }
2044       if(sx+w>src.width-1)
2045          w-=sx+w-(src.width-1)-1;
2046       if(sy+h>src.height-1)
2047          h-=sy+h-(src.height-1)-1;
2048       //Clip against the edges of the destination
2049       if(dx<surface.box.left)
2050       {
2051          if(!flip) sx+=surface.box.left-dx;
2052          w-=surface.box.left-dx;
2053          dx=surface.box.left;
2054       }
2055       if(dy<surface.box.top)
2056       {
2057          sy+=surface.box.top-dy;
2058          h-=surface.box.top-dy;
2059          dy=surface.box.top;
2060       }
2061       if((dx+w)>surface.box.right)
2062       {
2063          if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2064          w-=((uint32)(dx+w)-surface.box.right-1);
2065       }
2066       if((dy+h)>surface.box.bottom)
2067          h-=((dy+h)-surface.box.bottom-1);
2068       if((w<=0)||(h<=0))
2069          return;
2070
2071       dx += surface.offset.x;
2072       dy += surface.offset.y;
2073
2074       if(lfbSurface.bitmap.picture)
2075       {
2076          AlphaWriteMode alphaWrite = surface.alphaWrite;
2077          if(src.alphaBlend && surface.blend)
2078          {
2079             int x, y;
2080             if(src.pixelFormat == pixelFormatAlpha)
2081             {
2082                if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2083                {
2084                   ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2085                   byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2086                   ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2087                   for(y = 0; y < h; y++)
2088                   {
2089                      for(x = 0; x < w; x++, picture++, source++)
2090                      {
2091                         int a = *source * color.a;
2092                         ColorAlpha dest = *picture;
2093                         int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2094                         int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2095                         int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2096                         if(r > 255) r = 255;
2097                         if(g > 255) g = 255;
2098                         if(b > 255) b = 255;
2099                         picture->color = { (byte)r, (byte)g, (byte)b };
2100                         if(alphaWrite == blend)
2101                         {
2102                            int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2103                            if(ca > 255) ca = 255;
2104                            picture->a = (byte)ca;
2105                         }
2106                         else if(alphaWrite)
2107                            picture->a = (byte)(a / 255);
2108                      }
2109                      picture += lfbSurface.bitmap.stride - w;
2110                      source += src.stride - w;
2111                   }
2112                }
2113                else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2114                {
2115                   Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2116                   byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2117                   ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2118                   for(y = 0; y < h; y++)
2119                   {
2120                      for(x = 0; x < w; x++, picture++, source++)
2121                      {
2122                         int a = *source * color.a;
2123                         Color dest = *picture;
2124                         int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2125                         int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2126                         int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2127                         if(r > 255) r = 255;
2128                         if(g > 255) g = 255;
2129                         if(b > 255) b = 255;
2130                         *picture = Color { (byte)r, (byte)g, (byte)b };
2131                      }
2132                      picture += lfbSurface.bitmap.stride - w;
2133                      source += src.stride - w;
2134                   }
2135                }
2136                else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2137                {
2138                   Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2139                   byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2140                   ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2141                   for(y = 0; y < h; y++)
2142                   {
2143                      for(x = 0; x < w; x++, picture++, source++)
2144                      {
2145                         int a = *source * color.a;
2146                         Color dest = *picture;
2147                         int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2148                         int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2149                         int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2150                         if(r > 255) r = 255;
2151                         if(g > 255) g = 255;
2152                         if(b > 255) b = 255;
2153                         *picture = Color { (byte)r, (byte)g, (byte)b };
2154                      }
2155                      picture += lfbSurface.bitmap.stride - w;
2156                      source += src.stride - w;
2157                   }
2158                }
2159             }
2160             else
2161             {
2162                ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2163                if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2164                {
2165                   ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2166                   for(y = 0; y < h; y++)
2167                   {
2168                      for(x = 0; x < w; x++, picture++, source++)
2169                      {
2170                         ColorAlpha src = *source;
2171                         ColorAlpha dest = *picture;
2172                         int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2173                         int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2174                         int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2175                         if(r > 255) r = 255;
2176                         if(g > 255) g = 255;
2177                         if(b > 255) b = 255;
2178                         picture->color = { (byte)r, (byte)g, (byte)b };
2179                         if(alphaWrite == blend)
2180                         {
2181                            int a = src.a + ((255 - src.a) * dest.a / 255);
2182                            if(a > 255) a = 255;
2183                            picture->a = (byte)a;
2184                         }
2185                         else if(alphaWrite)
2186                            picture->a = src.a;
2187                      }
2188                      picture += lfbSurface.bitmap.stride - w;
2189                      source += src.stride - w;
2190                   }
2191                }
2192                else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2193                {
2194                   Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2195                   for(y = 0; y < h; y++)
2196                   {
2197                      for(x = 0; x < w; x++, picture++, source++)
2198                      {
2199                         ColorAlpha src = *source;
2200                         Color565 dest = *picture;
2201                         int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2202                         int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2203                         int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2204                         if(r > 255 * 31) r = 255 * 31;
2205                         if(g > 255 * 63) g = 255 * 63;
2206                         if(b > 255 * 31) b = 255 * 31;
2207                         *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2208                      }
2209                      picture += lfbSurface.bitmap.stride - w;
2210                      source += src.stride - w;
2211                   }
2212                }
2213                else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2214                {
2215                   Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2216                   for(y = 0; y < h; y++)
2217                   {
2218                      for(x = 0; x < w; x++, picture++, source++)
2219                      {
2220                         ColorAlpha psrc = *source;
2221                         Color555 dest = *picture;
2222                         int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2223                         int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2224                         int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2225                         if(r > 255 * 31) r = 255 * 31;
2226                         if(g > 255 * 31) g = 255 * 31;
2227                         if(b > 255 * 31) b = 255 * 31;
2228                         *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2229                      }
2230                      picture += lfbSurface.bitmap.stride - w;
2231                      source += src.stride - w;
2232                   }
2233                }
2234             }
2235          }
2236          else if(src.paletteShades)
2237             shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2238          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2239             blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2240          else if(src.pixelFormat == pixelFormat8)
2241             blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2242       }
2243    }
2244
2245    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2246    {
2247       bool result = false;
2248       LFBDisplay lfbDisplay = display.driverData;
2249
2250       if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2251       {
2252          bitmap.Free();
2253          bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat, 
2254             (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2255       }
2256       if(bitmap)
2257       {
2258          Surface surface = bitmap.GetSurface(0,0,null);
2259          if(surface)
2260          {
2261             Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2262             if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2263                CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2264             delete surface;
2265          }
2266          result = true;
2267       }
2268       return result;
2269    }
2270
2271    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2272    {
2273       LFBSurface lfbSurface = surface.driverData;
2274       bool flip = false;
2275
2276       float s2dw,s2dh,d2sw,d2sh;
2277
2278       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2279
2280       if(Sgn(w) != Sgn(sw))
2281       {
2282          w = Abs(w);
2283          sw = Abs(sw);
2284          flip = true; 
2285       }
2286
2287       s2dw=(float)w / sw;
2288       s2dh=(float)h / sh;
2289       d2sw=(float)sw / w;
2290       d2sh=(float)sh / h;
2291
2292       //Clip against the edges of the source
2293       if(sx<0)
2294       {
2295          dx+=(int)((0-sx) * s2dw);
2296          w-=(int)((0-sx) * s2dw);
2297          sw-=0-sx;
2298          sx=0;
2299       }
2300       if(sy<0)
2301       {
2302          dy+=(int)((0-sy) * s2dh);
2303          h-=(int)((0-sy) * s2dh);
2304
2305          sh-=0-sy;
2306          sy=0;
2307       }
2308       if(sx+sw>src.width-1)
2309       {
2310          w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2311          sw-=sx+sw-(src.width-1)-1;
2312       }
2313       if(sy+sh>(src.height-1))
2314       {
2315          h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2316          sh-=sy+sh-(src.height-1)-1;
2317       }
2318       //Clip against the edges of the destination
2319       if(dx<surface.box.left)
2320       {
2321          if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2322          sw-=(int)((surface.box.left-dx)*d2sw);
2323          w-=surface.box.left-dx;
2324          dx=surface.box.left;
2325       }
2326       if(dy<surface.box.top)
2327       {
2328          sy+=(int)((surface.box.top-dy)*d2sh);
2329          sh-=(int)((surface.box.top-dy)*d2sh);
2330          h-=surface.box.top-dy;
2331          dy=surface.box.top;
2332       }
2333       if((dx+w)>surface.box.right)
2334       {
2335          if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2336          sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2337          w-=((dx+w)-surface.box.right-1);
2338       }
2339       if((dy+h)>surface.box.bottom)
2340       {
2341          sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2342          h-=((dy+h)-surface.box.bottom-1);
2343       }
2344       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2345
2346       dx+=surface.offset.x;
2347       dy+=surface.offset.y;
2348
2349       if(lfbSurface.bitmap.picture)
2350       {
2351          AlphaWriteMode alphaWrite = surface.alphaWrite;
2352          if(src.alphaBlend && surface.blend)
2353          {
2354             int x, y;
2355             uint xerr,yerr;
2356             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2357             ColorAlpha * backsrc;
2358             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2359             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
2360             if(flip < 0) source += sw-1;
2361             adddest -= w;
2362             yerr = 0;
2363             for(y=0; y<sh; y++)
2364             {
2365                yerr+=h;
2366                backsrc = source;
2367                while(yerr >= sh)
2368                {
2369                   yerr-=sh;
2370                   xerr = 0;
2371                   for(x=0; x<sw; x++)
2372                   {
2373                      xerr+=w;
2374                      while(xerr>=sw)
2375                      {
2376                         xerr-=sw;
2377                         {
2378                            ColorAlpha src = *source;
2379                            ColorAlpha dst = *dest;
2380                            int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2381                            int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2382                            int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2383                            if(r > 255) r = 255;
2384                            if(g > 255) g = 255;
2385                            if(b > 255) b = 255;
2386                            dest->color = { (byte)r, (byte)g, (byte)b };
2387                            if(alphaWrite == blend)
2388                            {
2389                               int a = src.a + ((255 - src.a) * dst.a / 255);
2390                               if(a > 255) a = 255;
2391                               dest->a = (byte)a;
2392                            }
2393                            else if(alphaWrite)
2394                               dest->a = src.a;
2395                         }
2396                         dest++;
2397                      }
2398                      source ++;
2399                   }
2400                   dest+=adddest;
2401                   source = backsrc;
2402                }
2403                source += addsource;
2404             }
2405          }
2406          else if(src.paletteShades)
2407             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2408          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2409             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2410          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2411             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2412       }
2413    }
2414
2415    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2416    {
2417       LFBSurface lfbSurface = surface.driverData;
2418       bool flip = false;
2419
2420       float s2dw,s2dh,d2sw,d2sh;
2421
2422       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2423
2424       if(Sgn(w) != Sgn(sw))
2425       {
2426          w = Abs(w);
2427          sw = Abs(sw);
2428          flip = true; 
2429       }
2430
2431       s2dw=(float)w / sw;
2432       s2dh=(float)h / sh;
2433       d2sw=(float)sw / w;
2434       d2sh=(float)sh / h;
2435
2436       //Clip against the edges of the source
2437       if(sx<0)
2438       {
2439          dx+=(int)((0-sx) * s2dw);
2440          w-=(int)((0-sx) * s2dw);
2441          sw-=0-sx;
2442          sx=0;
2443       }
2444       if(sy<0)
2445       {
2446          dy+=(int)((0-sy) * s2dh);
2447          h-=(int)((0-sy) * s2dh);
2448
2449          sh-=0-sy;
2450          sy=0;
2451       }
2452       if(sx+sw>src.width-1)
2453       {
2454          w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2455          sw-=sx+sw-(src.width-1)-1;
2456       }
2457       if(sy+sh>(src.height-1))
2458       {
2459          h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2460          sh-=sy+sh-(src.height-1)-1;
2461       }
2462       //Clip against the edges of the destination
2463       if(dx<surface.box.left)
2464       {
2465          if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2466          sw-=(int)((surface.box.left-dx)*d2sw);
2467          w-=surface.box.left-dx;
2468          dx=surface.box.left;
2469       }
2470       if(dy<surface.box.top)
2471       {
2472          sy+=(int)((surface.box.top-dy)*d2sh);
2473          sh-=(int)((surface.box.top-dy)*d2sh);
2474          h-=surface.box.top-dy;
2475          dy=surface.box.top;
2476       }
2477       if((dx+w)>surface.box.right)
2478       {
2479          if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2480          sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2481          w-=((dx+w)-surface.box.right-1);
2482       }
2483       if((dy+h)>surface.box.bottom)
2484       {
2485          sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2486          h-=((dy+h)-surface.box.bottom-1);
2487       }
2488       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2489
2490       dx+=surface.offset.x;
2491       dy+=surface.offset.y;
2492
2493       if(lfbSurface.bitmap.picture)
2494       {
2495          AlphaWriteMode alphaWrite = surface.alphaWrite;
2496          if(src.alphaBlend && surface.blend)
2497          {
2498             int x, y;
2499             uint xerr,yerr;
2500             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2501             ColorAlpha * backsrc;
2502             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2503             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
2504             float scaleX = (float)sw / w;
2505             float scaleY = (float)sh / h;
2506             /*if(flip < 0)
2507             {
2508                dest += w-1;
2509                adddest += w;
2510             }
2511             else*/
2512                adddest -= w;
2513             if (w > sw && h > sh)
2514             {
2515                int y;
2516                for (y = 0; y < h; y++)
2517                {
2518                   int y0 = y * sh / h;
2519                   int y1 = Min(y0 + 1, sh - 1);
2520                   float alpha = y * scaleY - y0;
2521                   int x;
2522                   for(x = 0; x < w; x++, dest += 1)
2523                   {
2524                      int x0 = x * sw / w;
2525                      int x1 = Min(x0 + 1, sw - 1);
2526                      float beta = x * scaleX - x0;
2527                      ColorAlpha color;
2528                      ColorAlpha src00, src01, src10, src11;
2529                      float a1,r1,g1,b1,a2,r2,g2,b2;
2530                      float a,r,g,b;
2531                      src00 = source[y0 * src.stride + x0];
2532                      src01 = source[y0 * src.stride + x1];
2533                      src10 = source[y1 * src.stride + x0];
2534                      src11 = source[y1 * src.stride + x1];
2535                      a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2536                      r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2537                      g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2538                      b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2539                      a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2540                      r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2541                      g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2542                      b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2543                      a = a1 * (1.0f - alpha) + a2 * alpha;
2544                      r = r1 * (1.0f - alpha) + r2 * alpha;
2545                      g = g1 * (1.0f - alpha) + g2 * alpha;
2546                      b = b1 * (1.0f - alpha) + b2 * alpha;
2547                      {
2548                         ColorAlpha dst = *dest;
2549                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2550                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2551                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2552                         if(cr > 255) cr = 255;
2553                         if(cg > 255) cg = 255;
2554                         if(cb > 255) cb = 255;
2555                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
2556
2557                         if(alphaWrite == blend)
2558                         {
2559                            int ca = (int)(a + ((255 - a) * dst.a / 255));
2560                            if(ca > 255) ca = 255;
2561                            dest->a = (byte)ca;
2562                         }
2563                         else if(alphaWrite)
2564                            dest->a = (byte)a;
2565                      }
2566                   } 
2567                   dest += adddest;
2568                }
2569             }
2570             else 
2571             { 
2572                int y;
2573                for (y = 0; y < h; y++)
2574                {
2575                   int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2576                   int y1 = Min(y0 + 1, sh - 1);
2577                   int x;
2578                   for (x = 0; x < w; x++, dest += 1)
2579                   {
2580                      int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2581                      int x1 = Min(x0 + 1, sw - 1);
2582                      float a = 0, r = 0, g = 0, b = 0;
2583                      int numPixels = 0;
2584                      int i, j;
2585                      ColorAlpha color;
2586                      for (i = y0; i <= y1; i++)
2587                         for (j = x0; j <= x1; j++)
2588                         {
2589                            ColorAlpha pixel = source[i * src.stride + j];
2590                            a += pixel.a;
2591                            r += pixel.color.r;
2592                            g += pixel.color.g;
2593                            b += pixel.color.b;
2594                            numPixels++;
2595                         } 
2596                      a /= numPixels;
2597                      r /= numPixels;
2598                      g /= numPixels;
2599                      b /= numPixels;
2600                      {
2601                         ColorAlpha src = *source;
2602                         ColorAlpha dst = *dest;
2603                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2604                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2605                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2606                         if(cr > 255) cr = 255;
2607                         if(cg > 255) cg = 255;
2608                         if(cb > 255) cb = 255;
2609                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
2610                         if(alphaWrite == blend)
2611                         {
2612                            int ca = (int)(a + ((255 - a) * dst.a / 255));
2613                            if(ca > 255) ca = 255;
2614                            dest->a = (byte)ca;
2615                         }
2616                         else if(alphaWrite)
2617                            dest->a = (byte)a;
2618                      }
2619                   }
2620                   dest += adddest;
2621                } 
2622             }
2623          }
2624          else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2625             filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2626          // Fail back on Stretch
2627          else if(src.paletteShades)
2628             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2629          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2630             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2631          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2632             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2633       }
2634    }
2635
2636    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2637    {
2638       Blit(display, surface, src, dx, dy, sx, sy, w, h);
2639    }
2640
2641    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2642    {
2643       Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2644    }
2645
2646    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2647    {
2648       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2649    }
2650
2651    void UnloadFont(DisplaySystem displaySystem, Font font)
2652    {
2653       if(font)
2654       {
2655 #if !defined(ECERE_NOTRUETYPE)
2656          int entry;
2657          for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2658          {
2659             FontEntry fontEntry = font.fontEntries[entry];
2660             if(fontEntry)
2661             {
2662                fontEntry.used--;
2663                if(!fontEntry.used)
2664                {
2665                   loadedFonts.Remove(fontEntry);
2666                   delete fontEntry;
2667                }
2668             }
2669          } 
2670 #endif
2671          delete font;
2672       }
2673    }
2674
2675    Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2676    {
2677       void * result = null;
2678
2679 #if !defined(ECERE_NOTRUETYPE)
2680       Font font = Font { };
2681       if(font)
2682       {
2683          char fileName[MAX_LOCATION];
2684          bool fakeItalic = flags.italic;
2685          char linkCfgPath[MAX_LOCATION];
2686          int fontID = 0;
2687 #if !defined(__WIN32__)
2688          File linkCfg;
2689 #endif
2690          char * ecereFonts = getenv("ECERE_FONTS");
2691          if(!ecereFonts) ecereFonts = "<:ecere>";
2692 #if !defined(__WIN32__)
2693          strcpy(linkCfgPath, ecereFonts);
2694          PathCat(linkCfgPath, "linking.cfg");
2695          linkCfg = FileOpen(linkCfgPath, read);
2696 #endif
2697          strcpy(fileName, faceName);
2698          strcpy(font.faceName, faceName);
2699          font.flags = flags;
2700
2701          if(!FileExists(fileName))
2702          {
2703             strcpy(fileName, ecereFonts);
2704             PathCat(fileName, faceName);
2705             if(flags.bold && flags.italic) strcat(fileName, "bi");
2706             else if(flags.bold) strcat(fileName, "bd");
2707             else if(flags.italic) strcat(fileName, "i");
2708             strcat(fileName, ".ttf");
2709             strlwr(fileName);
2710             fakeItalic = false;
2711             
2712             if(flags.italic && !FileExists(fileName))
2713             {
2714                strcpy(fileName, ecereFonts);
2715                PathCat(fileName, faceName);
2716                if(flags.bold) strcat(fileName, "bd");
2717                strcat(fileName, ".ttf");
2718                strlwr(fileName);
2719                fakeItalic = true;
2720             }
2721
2722    #if defined(__WIN32__)
2723             if(!FileExists(fileName))
2724             {
2725                FontData fontData = { { 0 } };
2726                LOGFONT logFont = { 0 };
2727                HDC hdc = GetDC(0);
2728       
2729                fakeItalic = false;
2730       
2731                logFont.lfCharSet = DEFAULT_CHARSET;
2732                strcpy(logFont.lfFaceName, faceName);
2733                fontData.flags = flags;
2734                   
2735                EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2736                if(!fontData.fileName[0])
2737                {
2738                   // Fake italic
2739                   fontData.flags.italic = false;
2740                   EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2741                   fakeItalic = true;
2742                }
2743       
2744                if(fontData.fileName[0])
2745                {
2746                   GetWindowsDirectory(fileName, MAX_LOCATION);
2747                   PathCat(fileName, "fonts");
2748                   PathCat(fileName, fontData.fileName);
2749                }
2750                ReleaseDC(0, hdc);
2751             }  
2752    #else
2753             {
2754                char * fileName2;
2755                FcResult result = 0;
2756                FcPattern * pattern;
2757                FcPattern * matched;
2758                char * family;
2759                unichar testChar = 0;
2760                FcCharSet * charSet;
2761                if(!fcConfig)
2762                   fcConfig = FcInitLoadConfigAndFonts();
2763
2764                charSet = FcCharSetCreate();
2765
2766                if(!strcmpi(faceName, "Mangal"))
2767                {
2768                   testChar = 0x905;
2769                }
2770
2771                if(testChar)
2772                   FcCharSetAddChar(charSet, testChar);
2773    
2774                pattern = FcPatternBuild(null,
2775                                //FC_SOURCE, FcTypeString, "freetype",
2776                                FC_FAMILY, FcTypeString, faceName,
2777                                //FC_SCALABLE, FcTypeBool, 1,
2778                                FC_SIZE, FcTypeDouble, (double)size,
2779                                FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2780                                FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2781                                testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2782                                null);
2783                FcDefaultSubstitute(pattern);
2784                FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2785
2786                matched = FcFontMatch (0, pattern, &result);
2787                // printf("Locating %s\n", faceName);
2788                if(matched)
2789                {
2790                   FcPatternGetString(matched, FC_FAMILY, 0, &family);
2791                   //printf("Fontconfig returned %s\n", family);
2792                }
2793                if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2794                {
2795                   double fontSize;
2796                   FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2797                   FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2798                   FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2799                   strcpy(fileName, fileName2);
2800                   // size = (float)fontSize;
2801
2802                   //printf("Matched to %s, %f\n", fileName, size);
2803                }
2804                else
2805                {
2806                   //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2807                }
2808                if(pattern) FcPatternDestroy(pattern);
2809                if(matched) FcPatternDestroy(matched);
2810                if(charSet) FcCharSetDestroy(charSet);
2811             }
2812    #endif
2813          }
2814
2815          if(!FileExists(fileName))
2816             ChangeExtension(fileName, "otf", fileName);
2817          if(!FileExists(fileName))
2818             ChangeExtension(fileName, "ttc", fileName);
2819
2820          //if(FileExists(fileName))
2821          {
2822             int entry = 0;
2823             char links[1024] = "";
2824             int linksPos = 0;
2825 #if defined(__WIN32__)
2826             HKEY key;
2827             links[0] = 0;
2828             if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2829                !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2830             {  
2831                int value = 0;
2832                uint32 type;
2833                int size = 1024;
2834                RegQueryValueEx(key, faceName,null, &type, links, &size);
2835                RegCloseKey(key);
2836             }
2837 #else
2838             links[0] = 0;
2839             if(linkCfg)
2840             {
2841                char line[512];
2842                while(linkCfg.GetLine(line, sizeof(line)))
2843                {
2844                   int len = strlen(faceName);
2845                   if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2846                   {
2847                      while(linkCfg.GetLine(line, sizeof(line)))
2848                      {
2849                         TrimLSpaces(line, line);
2850                         if(!line[0] || line[0] == '[')
2851                            break;
2852                         len = strlen(line);
2853                         memcpy(links + linksPos, line, len);
2854                         linksPos += len;
2855                         links[linksPos] = 0;
2856                         linksPos++;
2857                      }
2858                   }
2859                }
2860                linksPos = 0;
2861             }
2862 #endif
2863             while(entry < MAX_FONT_LINK_ENTRIES)
2864             {
2865                FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2866                if(!fontEntry)
2867                {
2868                   File file = FileOpen/*Buffered*/(fileName, read);
2869                   if(file)
2870                   {
2871                      FileSize fileSize = file.GetSize();
2872                      FT_Open_Args args = { 0 };
2873                      FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
2874                      FT_Stream stream = new0 FT_StreamRec[1];
2875                      
2876                      if(!ftLibrary)
2877                         FT_Init_FreeType( &ftLibrary );
2878
2879                      fontEntry = FontEntry { key = (uint)CopyString(fileName) };
2880                      fontEntry.stream = stream;
2881
2882                      /*
2883                      fontEntry.buffer = new byte[fileSize];
2884                      file.Read(fontEntry.buffer, 1, fileSize);
2885                      */
2886
2887                      //args.num_params = 1;
2888                      args.params = &param;
2889
2890                      stream->size = fileSize;
2891                      stream->descriptor.pointer = file;
2892                      stream->read = FT_stream_load;
2893                      stream->close = FT_stream_close;
2894
2895                      args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
2896                      args.stream = stream;
2897                      //args.pathname = fileName;
2898                      //args.memory_base = fontEntry.buffer;
2899                      //args.memory_size = fileSize;
2900
2901                      // printf("Opening: %s\n", fileName);
2902                      FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
2903
2904                      // delete file;
2905                      if(fontEntry.face)
2906                      {
2907                         fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
2908                         fontEntry.hbFont.klass = &hb_fontClass;
2909                         fontEntry.hbFont.userData = fontEntry.face;
2910
2911                         numFonts++;
2912                         loadedFonts.Add(fontEntry);
2913                      }
2914                      else
2915                      {
2916                         delete fontEntry;
2917                         // printf("Error opening font %s\n", fileName);
2918                      }
2919                   }
2920                }
2921                if(fontEntry)
2922                {
2923                   if(!entry)
2924                   {
2925                      FT_Matrix matrix;
2926                      FT_Vector pen = { 0, 0 };
2927                      if(fakeItalic)
2928                      {
2929                         matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
2930                         matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
2931                         matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
2932                         matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
2933                         FT_Set_Transform(fontEntry.face, &matrix, &pen );
2934                      }
2935                      FT_Set_Char_Size( fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
2936                      font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
2937                      // printf("Font height is %d\n", font.height);
2938                      font.fakeItalic = fakeItalic;
2939                      font.size = size;
2940                      result = font;
2941                   }
2942                   font.fontEntries[entry++] = fontEntry;
2943                   fontEntry.used++;
2944                }
2945
2946                {
2947                   int c;
2948                   char ch;
2949                   char fontName[1024];
2950                   if(!links[linksPos]) break;
2951                   for(c = 0; (ch = links[linksPos + c]); c++)
2952                   {
2953                      fontName[c] = ch;
2954                      if(ch == ',') break;
2955                   }
2956                   fontName[c] = 0;
2957                   if(fontName[0] || ch == ',')
2958                   {
2959 #if defined(__WIN32__)
2960                      GetWindowsDirectory(fileName, MAX_LOCATION);
2961                      PathCat(fileName, "fonts");
2962                      PathCat(fileName, fontName);
2963 #elif defined(ECERE_NOFONTCONFIG)
2964                      if(getenv("ECERE_FONTS"))
2965                      {
2966                         strcpy(fileName, ecereFonts);
2967                         PathCat(fileName, fontName);
2968                      }
2969                      else
2970                      {
2971                         {
2972                            char * fileName2;
2973                            FcResult result = 0;
2974                            FcPattern * pattern;
2975                            FcPattern * matched;
2976                            char * family;
2977                             pattern = FcPatternBuild(null,
2978                                            //FC_SOURCE, FcTypeString, "freetype",
2979                                            //FC_SCALABLE, FcTypeBool, 1,
2980                                            FC_FAMILY, FcTypeString, links + linksPos + c + 1,
2981                                            FC_SIZE, FcTypeDouble, (double)size,
2982                                            FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2983                                            FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2984                                            null);
2985                            FcDefaultSubstitute(pattern);
2986                            FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2987
2988                            //printf("Locating %s\n", links + linksPos + c + 1);
2989                            matched = FcFontMatch (0, pattern, &result);
2990                            if(matched)
2991                            {
2992                               FcPatternGetString(matched, FC_FAMILY, 0, &family);
2993                               // printf("Fontconfig returned %s\n", family);
2994                            }
2995                            if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
2996                               FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
2997                            {
2998                               double fontSize;
2999                               FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3000                               FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3001                               FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3002                               strcpy(fileName, fileName2);
3003                               //size = (float)fontSize;
3004                               // printf("Matched to %s, %f\n", fileName, size);
3005                            }
3006                            else
3007                            {
3008                               // printf("Could not find a match for %s, %f, %s %s (%d)\n", links + linksPos + c + 1, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
3009                            }
3010                            if(pattern) FcPatternDestroy(pattern);
3011                            if(matched) FcPatternDestroy(matched);
3012                         }
3013                      }
3014 #endif
3015                      
3016                   }
3017                   linksPos += c;
3018                   while(links[linksPos]) linksPos++;
3019                   linksPos++;
3020                }
3021             }
3022          }
3023             
3024          if(!result)
3025             UnloadFont(displaySystem, font);
3026          else
3027          {
3028             font.asciiPack.Render(font, 0, displaySystem);
3029          }
3030 #if !defined(__WIN32__)
3031          delete linkCfg;
3032 #endif
3033       }
3034    #endif
3035       return result;
3036    }
3037
3038 #if !defined(ECERE_NOTRUETYPE)
3039    void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len, 
3040                         void (* callback)(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft),
3041                         Surface surface, Display display, int * x, int y)
3042    {
3043       if(font && font.fontEntries && font.fontEntries[0])
3044       {
3045          int previousGlyph = 0;
3046          int c, nb, glyphIndex = 0;
3047          unichar lastPack = 0;
3048          GlyphPack pack = font.asciiPack;
3049          int wc;
3050          uint * glyphs;
3051          int numGlyphs = 0;
3052          bool rightToLeft = false;
3053          int rightToLeftOffset = 0;
3054          int fontEntryNum = 0;
3055          bool foundArabic = false;
3056          int glyphScript = 0;
3057          
3058          pack.bitmap.alphaBlend = true;
3059
3060          for(c = 0; c < len || glyphIndex < numGlyphs;)
3061          {
3062             uint glyphNo;
3063             uint packNo;
3064             if(glyphIndex < numGlyphs)
3065             {
3066                glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3067             }
3068             else
3069             {
3070                HB_Script curScript = HB_Script_Common;
3071                byte * scriptStart = text + c;
3072                unichar ch;
3073                unichar ahead = 0;
3074                unichar testChar = 0;
3075                char * testLang = null;
3076                
3077                while(true)
3078                {
3079                   HB_Script script = HB_Script_Common;
3080                   ch = UTF8GetChar(text + c, &nb);
3081                   if(!nb) break;
3082                   if(ch == 32 && curScript)
3083                   {
3084                      if(ahead)
3085                         script = curScript;
3086                      else
3087                      {
3088                         int a;
3089                         for(a = c + 1; a < c + len; a++)
3090                         {
3091                            if(text[a] != 32)
3092                               break;
3093                         }
3094                         if(a < c + len)
3095                         {
3096                            int nb;
3097                            unichar ahead = UTF8GetChar(text + a, &nb);
3098                            if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3099                               script = curScript;                           
3100                         }
3101                         else
3102                            script = curScript;
3103                      }
3104                   }
3105                   else if(ch < 0x370)
3106                      script = HB_Script_Common;
3107                   else if(ch <= 0x11FF)
3108                   {
3109                      switch(ch & 0xFF00)
3110                      {
3111                         case 0x300: script = HB_Script_Greek; break;
3112                         case 0x400: script = HB_Script_Cyrillic; break;
3113                         case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3114                         case 0x600: script = HB_Script_Arabic; break;
3115                         case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3116                         case 0x800: script = HB_Script_Common; break;   // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3117                         case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3118                         case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3119                         case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3120                         case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3121                         case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3122                         case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3123                         case 0xF00: script = HB_Script_Tibetan; break;
3124                         case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3125                         case 0x1100: script = HB_Script_Hangul; break;
3126                      }
3127                   }
3128                   else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3129                   else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3130                      script = HB_Script_Hangul;
3131                   else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3132                   else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3133                   else if(ch >= 0x1780 && ch <= 0x17FF || ch >= 0x19E0 && ch <= 0x19FF) script = HB_Script_Khmer;
3134                   else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3135                   else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3136                   //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3137                   else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3138                   else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3139                   else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3140                   if(curScript)
3141                   {
3142                      if(!script || (script != curScript))
3143                         break;
3144                      c += nb;
3145                      if(c >= len)
3146                         break;
3147                   }
3148                   else 
3149                   {
3150                      if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3151                      if(!script) { c += nb; break; }
3152                      curScript = script;
3153                   }
3154                }
3155                if(!nb) break;
3156                fontEntryNum = 0;
3157
3158                if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3159                {
3160                   rightToLeft = false;
3161                   glyphNo = ch;
3162                }
3163                else
3164                {
3165                   int len = c - (int)(scriptStart - text);
3166                   int max = len * 2 + 1;
3167                   if(max > utf16BufferSize)
3168                   {
3169                      utf16 = renew utf16 uint16[max];
3170                      utf16BufferSize = max;
3171                   }
3172                   wc = UTF8toUTF16BufferLen(scriptStart, utf16, max, len);
3173                   glyphScript = curScript;
3174                }
3175                switch(curScript)
3176                {
3177                   case HB_Script_Arabic:        testChar = 0x621; /*testLang = "ar"; */
3178                      //printf("Arabic ");
3179                      break;
3180                   case HB_Script_Devanagari:    testChar = 0x905; testLang = "sa"; 
3181                      //printf("Devanagari ");
3182                      break;
3183                   default:
3184                      testChar = ch;
3185                   /*
3186                   case 60: testChar = 'あ'; break;
3187                   case 61: testChar = 0x3400; break; //'愛'; break;
3188                   */
3189                }
3190
3191                if(testChar)
3192                {
3193                   // printf("Testing for char %x\n", testChar);
3194                   for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3195                   {
3196                      if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3197                         break;
3198                      /*if(font.fontEntries[fontEntryNum])
3199                         printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3200                   }
3201                }
3202                
3203                if(fontEntryNum == MAX_FONT_LINK_ENTRIES) 
3204                {
3205 #if !defined(__WIN32__)
3206                   int fontID = 0;
3207                   double fontSize = font.size;
3208                   FcResult result = 0;
3209                   FcPattern * pattern;
3210                   FcPattern * matched;
3211                   FcCharSet * charSet;
3212                   char * family;
3213                   FontEntry fontEntry;
3214                   char * fileName = null;
3215                   bool fakeItalic = false;
3216                   for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3217                      if(!font.fontEntries[fontEntryNum])
3218                         break;
3219                   if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3220 #endif
3221                      continue;
3222             
3223 #if !defined(__WIN32__)
3224                   {
3225                      charSet = FcCharSetCreate();
3226                      FcCharSetAddChar(charSet, testChar);
3227                      //printf("Loading with char %x\n", testChar);
3228
3229                      pattern = FcPatternBuild(null,
3230                                      //FC_SOURCE, FcTypeString, "freetype",
3231                                      //FC_SCALABLE, FcTypeBool, 1,
3232                                      FC_FAMILY, FcTypeString, font.faceName,
3233                                      FC_SIZE, FcTypeDouble, (double)font.size,
3234                                      FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3235                                      FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3236                                      FC_CHARSET,FcTypeCharSet, charSet,
3237                                      testLang ? FC_LANG : 0, FcTypeString,testLang,
3238                                      null);
3239                      FcDefaultSubstitute(pattern);
3240                      FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3241
3242                      //printf("Locating %s for script %d\n", font.faceName, curScript);
3243                      matched = FcFontMatch (0, pattern, &result);
3244                      if(matched)
3245                      {
3246                         FcPatternGetString(matched, FC_FAMILY, 0, &family);
3247                         //printf("Fontconfig returned %s\n", family);
3248                      }
3249                      if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3250                      {
3251                         FcPatternGetString (matched, FC_FILE, 0, &fileName);
3252                         FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3253                         FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3254                         // printf("\nMatched to %s, %f\n", fileName, fontSize);
3255                      }
3256                      else
3257                      {
3258                         //printf("Could not find a match for %s, %f, %s %s (%d)\n", font.faceName, font.size, font.flags.bold ? "bold" : "", font.flags.italic ? "italic" : "", (int)result);
3259                      }
3260                   }
3261                   if(fileName)
3262                   {
3263                      fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3264                      if(!fontEntry)
3265                      {
3266                         File file = FileOpen(fileName, read);
3267                         if(file)
3268                         {
3269                            FileSize fileSize = file.GetSize();
3270                            FT_Open_Args args = { 0 };                            
3271                            FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3272                            FT_Stream stream = new0 FT_StreamRec[1];
3273                            
3274                            if(!ftLibrary)
3275                               FT_Init_FreeType( &ftLibrary );
3276
3277                            fontEntry = FontEntry { key = (uint)CopyString(fileName) };
3278                            fontEntry.stream = stream;
3279                                                 
3280                            //args.num_params = 1;
3281                            args.params = &param;
3282
3283                            stream->size = fileSize;
3284                            stream->descriptor.pointer = file;
3285                            stream->read = FT_stream_load;
3286                            stream->close = FT_stream_close;
3287
3288                            args.flags = FT_OPEN_STREAM;
3289                            args.stream = stream;
3290                            //args.pathname = fileName;
3291                            //args.memory_base = fontEntry.buffer;
3292                            //args.memory_size = fileSize;
3293
3294                            // printf("Opening: %s\n", fileName);
3295                            FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3296
3297                            // delete file;
3298                            if(fontEntry.face)
3299                            {
3300                               fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);            
3301                               fontEntry.hbFont.klass = &hb_fontClass;
3302                               fontEntry.hbFont.userData = fontEntry.face;
3303
3304                               numFonts++;
3305                               loadedFonts.Add(fontEntry);
3306                            }
3307                            else
3308                            {
3309                               delete fontEntry;
3310                               // printf("Error opening font %s\n", fileName);
3311                            }
3312                         }
3313                      }
3314                      if(fontEntry)
3315                      {
3316                         FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
3317
3318                         font.fontEntries[fontEntryNum] = fontEntry;
3319                         fontEntry.used++;
3320                      }
3321                   }
3322                   if(pattern) FcPatternDestroy(pattern);          
3323                   if(matched) FcPatternDestroy(matched);
3324                   if(charSet) FcCharSetDestroy(charSet);
3325 #endif
3326                }
3327                if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3328                if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3329                {
3330                   int c;
3331                   glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3332                   if(!numGlyphs)
3333                      continue;
3334                   if(rightToLeft /*&& surface*/)
3335                   {
3336                      int c;
3337                      rightToLeftOffset = 0;
3338                      for(c = 0; c<numGlyphs; c++)
3339                      {
3340                         GlyphInfo * glyph;
3341                         glyphNo = glyphs[c] | 0x80000000 | (glyphScript << 24);
3342                         packNo = glyphNo & 0xFFFFFF80;
3343                         if(packNo != lastPack)
3344                         {
3345                            pack = (GlyphPack)font.glyphPacks.Find(packNo);
3346                            if(!pack)
3347                            {
3348                               pack = GlyphPack { key = packNo };
3349                               font.glyphPacks.Add(pack);
3350                               pack.Render(font, fontEntryNum, displaySystem);
3351                            }
3352                            pack.bitmap.alphaBlend = true;
3353                            lastPack = packNo;
3354                         }
3355                         glyph = &pack.glyphs[glyphNo & 0x7F];
3356
3357                         rightToLeftOffset += (int)glyph->ax - glyph->left;
3358                      }
3359                      *x += rightToLeftOffset;
3360                   }
3361
3362                   glyphIndex = 0;
3363                   glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3364                }
3365             }
3366             packNo = glyphNo & 0xFFFFFF80;
3367
3368             if(packNo != lastPack)
3369             {
3370                if(glyphNo < 128) 
3371                   pack = font.asciiPack;
3372                else
3373                {
3374                   pack = (GlyphPack)font.glyphPacks.Find(packNo);
3375                   if(!pack)
3376                   {
3377                      pack = GlyphPack { key = packNo };
3378                      font.glyphPacks.Add(pack);
3379                      pack.Render(font, fontEntryNum, displaySystem);
3380                   }
3381                }
3382                pack.bitmap.alphaBlend = true;
3383                lastPack = packNo;
3384             }
3385             if(pack)
3386             {
3387                GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3388
3389                /*if(previousGlyph)
3390                {
3391                   FT_Vector delta;
3392                   FT_Get_Kerning(font.fontEntries[fontEntryNum].face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3393                   *x += delta.x;
3394                }
3395                previousGlyph = glyph->glyphNo;*/
3396                callback(surface, display, x, y, glyph, pack.bitmap, rightToLeft);
3397             }
3398             if(numGlyphs && glyphIndex == numGlyphs)
3399             {
3400                *x += rightToLeftOffset;
3401                numGlyphs = 0;
3402             }
3403          }
3404       }
3405       if(surface)
3406       {
3407          LFBSurface lfbSurface = surface.driverData;
3408          lfbSurface.xOffset = 0;
3409       }
3410    }
3411
3412    void ::AddWidth(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3413    {
3414       if(rightToLeft)
3415       {
3416          *x -= (int)glyph->ax - glyph->left;
3417       }
3418       else
3419       {
3420          *x += glyph->ax;
3421       }
3422    }
3423 #endif
3424    void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3425    {
3426       if(displaySystem && displaySystem.flags.text && len)
3427       {
3428          if(width) 
3429          {
3430             int num = len;
3431             *width = num * textCellW;
3432          }
3433          if(height) *height = textCellH;
3434       }
3435       else if(font && len)
3436       {
3437          if(width)
3438          {
3439             int w = 0;
3440 #if !defined(ECERE_NOTRUETYPE)
3441             ProcessString(font, displaySystem, text, len, AddWidth, null, null, &w, 0);
3442 #endif
3443             //*width = (w + 64 - w % 64) >> 6;
3444             *width = w >> 6;
3445          }
3446          if(height)
3447             *height = font.height;
3448       }
3449       else
3450       {
3451          if(width) *width = 0;
3452          if(height) *height = 0;
3453       }
3454    }
3455
3456 #if !defined(ECERE_NOTRUETYPE)
3457    void ::OutputGlyph(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3458    {
3459       LFBSurface lfbSurface = surface.driverData;
3460       //lfbSurface.xOffset = (*x & 0x3F);
3461       if(rightToLeft)
3462       {
3463          surface.driver.Blit(display, surface, bitmap, (*x >> 6) - glyph->w, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3464          *x -= (int)glyph->ax - glyph->left;
3465       }
3466       else
3467       {
3468          surface.driver.Blit(display, surface, bitmap, (*x >> 6) + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3469          *x += glyph->ax;
3470       }
3471    }
3472 #endif
3473
3474    void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3475    {
3476       LFBSurface lfbSurface = surface.driverData;
3477       if(display && display.displaySystem.flags.text)
3478       {
3479          LFBDisplay lfbDisplay = display.driverData;
3480          uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3481          int c;
3482
3483          x /= textCellW;
3484          y /= textCellH;
3485
3486          if(y > surface.box.bottom || y < surface.box.top) 
3487             return;
3488          coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3489          for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3490          for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3491          {
3492             if(surface.textOpacity)
3493                *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3494             else
3495                *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3496          }
3497       }
3498       else 
3499       {
3500          lfbSurface.writingText = true;
3501 #if !defined(ECERE_NOTRUETYPE)
3502          x <<= 6;
3503          ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3504 #endif
3505          lfbSurface.writingText = false;
3506       }
3507    }
3508    
3509    void TextFont(Display display, Surface surface, Font font)
3510    {
3511       LFBSurface lfbSurface = surface.driverData;
3512       lfbSurface.font = font;
3513    }
3514
3515    void TextOpacity(Display display, Surface surface, bool opaque)
3516    {
3517       LFBSurface lfbSurface = surface.driverData;
3518
3519    }
3520
3521    void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3522    {
3523       LFBSurface lfbSurface = surface.driverData;
3524       FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3525    }
3526
3527    void DrawingChar(Display display, Surface surface, byte character)
3528    {
3529       LFBSurface lfbSurface = surface.driverData;
3530       lfbSurface.drawingChar = character;
3531    }
3532
3533    void LineStipple(Display display, Surface surface, uint32 stipple)
3534    {
3535       LFBSurface lfbSurface = surface.driverData;
3536       lfbSurface.stipple = (uint16)stipple;
3537    }
3538
3539 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3540    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3541    {
3542       if(mesh.vertices && !mesh.flags.vertices)
3543          delete mesh.vertices;
3544       if(mesh.normals && !mesh.flags.normals)
3545          delete mesh.normals;
3546       if(mesh.texCoords && !mesh.flags.texCoords1)
3547          delete mesh.texCoords;
3548    }
3549
3550    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3551    {
3552       bool result = false;
3553
3554       if((!mesh.flags.vertices   || mesh.vertices  || (mesh.vertices  = new Vector3Df[mesh.nVertices])) &&
3555          (!mesh.flags.normals    || mesh.normals   || (mesh.normals   = new Vector3Df[mesh.nVertices])) &&
3556          (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf  [mesh.nVertices])))
3557          result = true;
3558       return result;
3559    }
3560
3561    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3562    {
3563       return true;
3564    }
3565
3566    void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3567    {
3568       delete indices;
3569    }
3570
3571    uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3572    {
3573       return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3574    }
3575    uint16 * LockIndices(DisplaySystem displaySystem, void * indices)
3576    {
3577       return indices;
3578    }
3579 #endif
3580 }