Initial git commit -- Transition from CodeGuard repository
[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                ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2083                byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2084                ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2085                for(y = 0; y < h; y++)
2086                {
2087                   for(x = 0; x < w; x++, picture++, source++)
2088                   {
2089                      int a = *source * color.a;
2090                      ColorAlpha dest = *picture;
2091                      int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2092                      int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2093                      int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2094                      if(r > 255) r = 255;
2095                      if(g > 255) g = 255;
2096                      if(b > 255) b = 255;
2097                      picture->color = { (byte)r, (byte)g, (byte)b };
2098                      if(alphaWrite == blend)
2099                      {
2100                         int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2101                         if(ca > 255) ca = 255;
2102                         picture->a = (byte)ca;
2103                      }
2104                      else if(alphaWrite)
2105                         picture->a = (byte)(a / 255);
2106                   }
2107                   picture += lfbSurface.bitmap.stride - w;
2108                   source += src.stride - w;
2109                }
2110             }
2111             else
2112             {
2113                ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2114                if(lfbSurface.bitmap.pixelFormat == pixelFormat888)               
2115                {
2116                   ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2117                   for(y = 0; y < h; y++)
2118                   {
2119                      for(x = 0; x < w; x++, picture++, source++)
2120                      {
2121                         ColorAlpha src = *source;
2122                         ColorAlpha dest = *picture;
2123                         int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2124                         int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2125                         int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2126                         if(r > 255) r = 255;
2127                         if(g > 255) g = 255;
2128                         if(b > 255) b = 255;
2129                         picture->color = { (byte)r, (byte)g, (byte)b };
2130                         if(alphaWrite == blend)
2131                         {
2132                            int a = src.a + ((255 - src.a) * dest.a / 255);
2133                            if(a > 255) a = 255;
2134                            picture->a = (byte)a;
2135                         }
2136                         else if(alphaWrite)
2137                            picture->a = src.a;
2138                      }
2139                      picture += lfbSurface.bitmap.stride - w;
2140                      source += src.stride - w;
2141                   }
2142                }
2143                else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2144                {
2145                   Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2146                   for(y = 0; y < h; y++)
2147                   {
2148                      for(x = 0; x < w; x++, picture++, source++)
2149                      {
2150                         ColorAlpha src = *source;
2151                         Color565 dest = *picture;
2152                         int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2153                         int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2154                         int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2155                         if(r > 255 * 31) r = 255 * 31;
2156                         if(g > 255 * 63) g = 255 * 63;
2157                         if(b > 255 * 31) b = 255 * 31;
2158                         *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2159                      }
2160                      picture += lfbSurface.bitmap.stride - w;
2161                      source += src.stride - w;
2162                   }
2163                }
2164                else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2165                {
2166                   Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2167                   for(y = 0; y < h; y++)
2168                   {
2169                      for(x = 0; x < w; x++, picture++, source++)
2170                      {
2171                         ColorAlpha src = *source;
2172                         Color555 dest = *picture;
2173                         int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2174                         int g = src.a * src.color.g * 31 / 255 + ((255 - src.a) * dest.g);
2175                         int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2176                         if(r > 255 * 31) r = 255 * 31;
2177                         if(g > 255 * 31) g = 255 * 31;
2178                         if(b > 255 * 31) b = 255 * 31;
2179                         *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2180                      }
2181                      picture += lfbSurface.bitmap.stride - w;
2182                      source += src.stride - w;
2183                   }
2184                }
2185             }
2186          }
2187          else if(src.paletteShades)
2188             shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2189          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2190             blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2191          else if(src.pixelFormat == pixelFormat8)
2192             blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2193       }
2194    }
2195
2196    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2197    {
2198       bool result = false;
2199       LFBDisplay lfbDisplay = display.driverData;
2200
2201       if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2202       {
2203          bitmap.Free();
2204          bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat, 
2205             (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2206       }
2207       if(bitmap)
2208       {
2209          Surface surface = bitmap.GetSurface(0,0,null);
2210          if(surface)
2211          {
2212             Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2213             if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2214                CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2215             delete surface;
2216          }
2217          result = true;
2218       }
2219       return result;
2220    }
2221
2222    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2223    {
2224       LFBSurface lfbSurface = surface.driverData;
2225       bool flip = false;
2226
2227       float s2dw,s2dh,d2sw,d2sh;
2228
2229       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2230
2231       if(Sgn(w) != Sgn(sw))
2232       {
2233          w = Abs(w);
2234          sw = Abs(sw);
2235          flip = true; 
2236       }
2237
2238       s2dw=(float)w / sw;
2239       s2dh=(float)h / sh;
2240       d2sw=(float)sw / w;
2241       d2sh=(float)sh / h;
2242
2243       //Clip against the edges of the source
2244       if(sx<0)
2245       {
2246          dx+=(int)((0-sx) * s2dw);
2247          w-=(int)((0-sx) * s2dw);
2248          sw-=0-sx;
2249          sx=0;
2250       }
2251       if(sy<0)
2252       {
2253          dy+=(int)((0-sy) * s2dh);
2254          h-=(int)((0-sy) * s2dh);
2255
2256          sh-=0-sy;
2257          sy=0;
2258       }
2259       if(sx+sw>src.width-1)
2260       {
2261          w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2262          sw-=sx+sw-(src.width-1)-1;
2263       }
2264       if(sy+sh>(src.height-1))
2265       {
2266          h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2267          sh-=sy+sh-(src.height-1)-1;
2268       }
2269       //Clip against the edges of the destination
2270       if(dx<surface.box.left)
2271       {
2272          if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2273          sw-=(int)((surface.box.left-dx)*d2sw);
2274          w-=surface.box.left-dx;
2275          dx=surface.box.left;
2276       }
2277       if(dy<surface.box.top)
2278       {
2279          sy+=(int)((surface.box.top-dy)*d2sh);
2280          sh-=(int)((surface.box.top-dy)*d2sh);
2281          h-=surface.box.top-dy;
2282          dy=surface.box.top;
2283       }
2284       if((dx+w)>surface.box.right)
2285       {
2286          if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2287          sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2288          w-=((dx+w)-surface.box.right-1);
2289       }
2290       if((dy+h)>surface.box.bottom)
2291       {
2292          sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2293          h-=((dy+h)-surface.box.bottom-1);
2294       }
2295       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2296
2297       dx+=surface.offset.x;
2298       dy+=surface.offset.y;
2299
2300       if(lfbSurface.bitmap.picture)
2301       {
2302          AlphaWriteMode alphaWrite = surface.alphaWrite;
2303          if(src.alphaBlend && surface.blend)
2304          {
2305             int x, y;
2306             uint xerr,yerr;
2307             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2308             ColorAlpha * backsrc;
2309             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2310             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
2311             if(flip < 0) source += sw-1;
2312             adddest -= w;
2313             yerr = 0;
2314             for(y=0; y<sh; y++)
2315             {
2316                yerr+=h;
2317                backsrc = source;
2318                while(yerr >= sh)
2319                {
2320                   yerr-=sh;
2321                   xerr = 0;
2322                   for(x=0; x<sw; x++)
2323                   {
2324                      xerr+=w;
2325                      while(xerr>=sw)
2326                      {
2327                         xerr-=sw;
2328                         {
2329                            ColorAlpha src = *source;
2330                            ColorAlpha dst = *dest;
2331                            int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2332                            int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2333                            int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2334                            if(r > 255) r = 255;
2335                            if(g > 255) g = 255;
2336                            if(b > 255) b = 255;
2337                            dest->color = { (byte)r, (byte)g, (byte)b };
2338                            if(alphaWrite == blend)
2339                            {
2340                               int a = src.a + ((255 - src.a) * dst.a / 255);
2341                               if(a > 255) a = 255;
2342                               dest->a = (byte)a;
2343                            }
2344                            else if(alphaWrite)
2345                               dest->a = src.a;
2346                         }
2347                         dest++;
2348                      }
2349                      source ++;
2350                   }
2351                   dest+=adddest;
2352                   source = backsrc;
2353                }
2354                source += addsource;
2355             }
2356          }
2357          else if(src.paletteShades)
2358             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2359          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2360             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2361          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2362             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2363       }
2364    }
2365
2366    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2367    {
2368       LFBSurface lfbSurface = surface.driverData;
2369       bool flip = false;
2370
2371       float s2dw,s2dh,d2sw,d2sh;
2372
2373       if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2374
2375       if(Sgn(w) != Sgn(sw))
2376       {
2377          w = Abs(w);
2378          sw = Abs(sw);
2379          flip = true; 
2380       }
2381
2382       s2dw=(float)w / sw;
2383       s2dh=(float)h / sh;
2384       d2sw=(float)sw / w;
2385       d2sh=(float)sh / h;
2386
2387       //Clip against the edges of the source
2388       if(sx<0)
2389       {
2390          dx+=(int)((0-sx) * s2dw);
2391          w-=(int)((0-sx) * s2dw);
2392          sw-=0-sx;
2393          sx=0;
2394       }
2395       if(sy<0)
2396       {
2397          dy+=(int)((0-sy) * s2dh);
2398          h-=(int)((0-sy) * s2dh);
2399
2400          sh-=0-sy;
2401          sy=0;
2402       }
2403       if(sx+sw>src.width-1)
2404       {
2405          w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2406          sw-=sx+sw-(src.width-1)-1;
2407       }
2408       if(sy+sh>(src.height-1))
2409       {
2410          h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2411          sh-=sy+sh-(src.height-1)-1;
2412       }
2413       //Clip against the edges of the destination
2414       if(dx<surface.box.left)
2415       {
2416          if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2417          sw-=(int)((surface.box.left-dx)*d2sw);
2418          w-=surface.box.left-dx;
2419          dx=surface.box.left;
2420       }
2421       if(dy<surface.box.top)
2422       {
2423          sy+=(int)((surface.box.top-dy)*d2sh);
2424          sh-=(int)((surface.box.top-dy)*d2sh);
2425          h-=surface.box.top-dy;
2426          dy=surface.box.top;
2427       }
2428       if((dx+w)>surface.box.right)
2429       {
2430          if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2431          sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2432          w-=((dx+w)-surface.box.right-1);
2433       }
2434       if((dy+h)>surface.box.bottom)
2435       {
2436          sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2437          h-=((dy+h)-surface.box.bottom-1);
2438       }
2439       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2440
2441       dx+=surface.offset.x;
2442       dy+=surface.offset.y;
2443
2444       if(lfbSurface.bitmap.picture)
2445       {
2446          AlphaWriteMode alphaWrite = surface.alphaWrite;
2447          if(src.alphaBlend && surface.blend)
2448          {
2449             int x, y;
2450             uint xerr,yerr;
2451             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2452             ColorAlpha * backsrc;
2453             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2454             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
2455             float scaleX = (float)sw / w;
2456             float scaleY = (float)sh / h;
2457             /*if(flip < 0)
2458             {
2459                dest += w-1;
2460                adddest += w;
2461             }
2462             else*/
2463                adddest -= w;
2464             if (w > sw && h > sh)
2465             {
2466                int y;
2467                for (y = 0; y < h; y++)
2468                {
2469                   int y0 = y * sh / h;
2470                   int y1 = Min(y0 + 1, sh - 1);
2471                   float alpha = y * scaleY - y0;
2472                   int x;
2473                   for(x = 0; x < w; x++, dest += 1)
2474                   {
2475                      int x0 = x * sw / w;
2476                      int x1 = Min(x0 + 1, sw - 1);
2477                      float beta = x * scaleX - x0;
2478                      ColorAlpha color;
2479                      ColorAlpha src00, src01, src10, src11;
2480                      float a1,r1,g1,b1,a2,r2,g2,b2;
2481                      float a,r,g,b;
2482                      src00 = source[y0 * src.stride + x0];
2483                      src01 = source[y0 * src.stride + x1];
2484                      src10 = source[y1 * src.stride + x0];
2485                      src11 = source[y1 * src.stride + x1];
2486                      a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2487                      r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2488                      g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2489                      b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2490                      a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2491                      r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2492                      g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2493                      b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2494                      a = a1 * (1.0f - alpha) + a2 * alpha;
2495                      r = r1 * (1.0f - alpha) + r2 * alpha;
2496                      g = g1 * (1.0f - alpha) + g2 * alpha;
2497                      b = b1 * (1.0f - alpha) + b2 * alpha;
2498                      {
2499                         ColorAlpha dst = *dest;
2500                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2501                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2502                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2503                         if(cr > 255) cr = 255;
2504                         if(cg > 255) cg = 255;
2505                         if(cb > 255) cb = 255;
2506                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
2507
2508                         if(alphaWrite == blend)
2509                         {
2510                            int ca = (int)(a + ((255 - a) * dst.a / 255));
2511                            if(ca > 255) ca = 255;
2512                            dest->a = (byte)ca;
2513                         }
2514                         else if(alphaWrite)
2515                            dest->a = (byte)a;
2516                      }
2517                   } 
2518                   dest += adddest;
2519                }
2520             }
2521             else 
2522             { 
2523                int y;
2524                for (y = 0; y < h; y++)
2525                {
2526                   int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2527                   int y1 = Min(y0 + 1, sh - 1);
2528                   int x;
2529                   for (x = 0; x < w; x++, dest += 1)
2530                   {
2531                      int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2532                      int x1 = Min(x0 + 1, sw - 1);
2533                      float a = 0, r = 0, g = 0, b = 0;
2534                      int numPixels = 0;
2535                      int i, j;
2536                      ColorAlpha color;
2537                      for (i = y0; i <= y1; i++)
2538                         for (j = x0; j <= x1; j++)
2539                         {
2540                            ColorAlpha pixel = source[i * src.stride + j];
2541                            a += pixel.a;
2542                            r += pixel.color.r;
2543                            g += pixel.color.g;
2544                            b += pixel.color.b;
2545                            numPixels++;
2546                         } 
2547                      a /= numPixels;
2548                      r /= numPixels;
2549                      g /= numPixels;
2550                      b /= numPixels;
2551                      {
2552                         ColorAlpha src = *source;
2553                         ColorAlpha dst = *dest;
2554                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2555                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2556                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2557                         if(cr > 255) cr = 255;
2558                         if(cg > 255) cg = 255;
2559                         if(cb > 255) cb = 255;
2560                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
2561                         if(alphaWrite == blend)
2562                         {
2563                            int ca = (int)(a + ((255 - a) * dst.a / 255));
2564                            if(ca > 255) ca = 255;
2565                            dest->a = (byte)ca;
2566                         }
2567                         else if(alphaWrite)
2568                            dest->a = (byte)a;
2569                      }
2570                   }
2571                   dest += adddest;
2572                } 
2573             }
2574          }
2575          else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2576             filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2577          // Fail back on Stretch
2578          else if(src.paletteShades)
2579             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2580          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2581             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2582          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2583             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2584       }
2585    }
2586
2587    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2588    {
2589       Blit(display, surface, src, dx, dy, sx, sy, w, h);
2590    }
2591
2592    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2593    {
2594       Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2595    }
2596
2597    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2598    {
2599       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2600    }
2601
2602    void UnloadFont(DisplaySystem displaySystem, Font font)
2603    {
2604       if(font)
2605       {
2606 #if !defined(ECERE_NOTRUETYPE)
2607          int entry;
2608          for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2609          {
2610             FontEntry fontEntry = font.fontEntries[entry];
2611             if(fontEntry)
2612             {
2613                fontEntry.used--;
2614                if(!fontEntry.used)
2615                {
2616                   loadedFonts.Remove(fontEntry);
2617                   delete fontEntry;
2618                }
2619             }
2620          } 
2621 #endif
2622          delete font;
2623       }
2624    }
2625
2626    Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2627    {
2628       void * result = null;
2629
2630 #if !defined(ECERE_NOTRUETYPE)
2631       Font font = Font { };
2632       if(font)
2633       {
2634          char fileName[MAX_LOCATION];
2635          bool fakeItalic = flags.italic;
2636          char linkCfgPath[MAX_LOCATION];
2637          int fontID = 0;
2638 #if !defined(__WIN32__)
2639          File linkCfg;
2640 #endif
2641          char * ecereFonts = getenv("ECERE_FONTS");
2642          if(!ecereFonts) ecereFonts = "<:ecere>";
2643 #if !defined(__WIN32__)
2644          strcpy(linkCfgPath, ecereFonts);
2645          PathCat(linkCfgPath, "linking.cfg");
2646          linkCfg = FileOpen(linkCfgPath, read);
2647 #endif
2648          strcpy(fileName, faceName);
2649          strcpy(font.faceName, faceName);
2650          font.flags = flags;
2651
2652          if(!FileExists(fileName))
2653          {
2654             strcpy(fileName, ecereFonts);
2655             PathCat(fileName, faceName);
2656             if(flags.bold && flags.italic) strcat(fileName, "bi");
2657             else if(flags.bold) strcat(fileName, "bd");
2658             else if(flags.italic) strcat(fileName, "i");
2659             strcat(fileName, ".ttf");
2660             strlwr(fileName);
2661             fakeItalic = false;
2662             
2663             if(flags.italic && !FileExists(fileName))
2664             {
2665                strcpy(fileName, ecereFonts);
2666                PathCat(fileName, faceName);
2667                if(flags.bold) strcat(fileName, "bd");
2668                strcat(fileName, ".ttf");
2669                strlwr(fileName);
2670                fakeItalic = true;
2671             }
2672
2673    #if defined(__WIN32__)
2674             if(!FileExists(fileName))
2675             {
2676                FontData fontData = { { 0 } };
2677                LOGFONT logFont = { 0 };
2678                HDC hdc = GetDC(0);
2679       
2680                fakeItalic = false;
2681       
2682                logFont.lfCharSet = DEFAULT_CHARSET;
2683                strcpy(logFont.lfFaceName, faceName);
2684                fontData.flags = flags;
2685                   
2686                EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2687                if(!fontData.fileName[0])
2688                {
2689                   // Fake italic
2690                   fontData.flags.italic = false;
2691                   EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2692                   fakeItalic = true;
2693                }
2694       
2695                if(fontData.fileName[0])
2696                {
2697                   GetWindowsDirectory(fileName, MAX_LOCATION);
2698                   PathCat(fileName, "fonts");
2699                   PathCat(fileName, fontData.fileName);
2700                }
2701                ReleaseDC(0, hdc);
2702             }  
2703    #else
2704             {
2705                char * fileName2;
2706                FcResult result = 0;
2707                FcPattern * pattern;
2708                FcPattern * matched;
2709                char * family;
2710                unichar testChar = 0;
2711                FcCharSet * charSet;
2712                if(!fcConfig)
2713                   fcConfig = FcInitLoadConfigAndFonts();
2714
2715                charSet = FcCharSetCreate();
2716
2717                if(!strcmpi(faceName, "Mangal"))
2718                {
2719                   testChar = 0x905;
2720                }
2721
2722                if(testChar)
2723                   FcCharSetAddChar(charSet, testChar);
2724    
2725                pattern = FcPatternBuild(null,
2726                                //FC_SOURCE, FcTypeString, "freetype",
2727                                FC_FAMILY, FcTypeString, faceName,
2728                                //FC_SCALABLE, FcTypeBool, 1,
2729                                FC_SIZE, FcTypeDouble, (double)size,
2730                                FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2731                                FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2732                                testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2733                                null);
2734                FcDefaultSubstitute(pattern);
2735                FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2736
2737                matched = FcFontMatch (0, pattern, &result);
2738                // printf("Locating %s\n", faceName);
2739                if(matched)
2740                {
2741                   FcPatternGetString(matched, FC_FAMILY, 0, &family);
2742                   //printf("Fontconfig returned %s\n", family);
2743                }
2744                if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2745                {
2746                   double fontSize;
2747                   FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2748                   FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2749                   FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2750                   strcpy(fileName, fileName2);
2751                   // size = (float)fontSize;
2752
2753                   //printf("Matched to %s, %f\n", fileName, size);
2754                }
2755                else
2756                {
2757                   //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2758                }
2759                if(pattern) FcPatternDestroy(pattern);
2760                if(matched) FcPatternDestroy(matched);
2761                if(charSet) FcCharSetDestroy(charSet);
2762             }
2763    #endif
2764          }
2765
2766          if(!FileExists(fileName))
2767             ChangeExtension(fileName, "otf", fileName);
2768          if(!FileExists(fileName))
2769             ChangeExtension(fileName, "ttc", fileName);
2770
2771          //if(FileExists(fileName))
2772          {
2773             int entry = 0;
2774             char links[1024] = "";
2775             int linksPos = 0;
2776 #if defined(__WIN32__)
2777             HKEY key;
2778             links[0] = 0;
2779             if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2780                !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2781             {  
2782                int value = 0;
2783                uint32 type;
2784                int size = 1024;
2785                RegQueryValueEx(key, faceName,null, &type, links, &size);
2786                RegCloseKey(key);
2787             }
2788 #else
2789             links[0] = 0;
2790             if(linkCfg)
2791             {
2792                char line[512];
2793                while(linkCfg.GetLine(line, sizeof(line)))
2794                {
2795                   int len = strlen(faceName);
2796                   if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2797                   {
2798                      while(linkCfg.GetLine(line, sizeof(line)))
2799                      {
2800                         TrimLSpaces(line, line);
2801                         if(!line[0] || line[0] == '[')
2802                            break;
2803                         len = strlen(line);
2804                         memcpy(links + linksPos, line, len);
2805                         linksPos += len;
2806                         links[linksPos] = 0;
2807                         linksPos++;
2808                      }
2809                   }
2810                }
2811                linksPos = 0;
2812             }
2813 #endif
2814             while(entry < MAX_FONT_LINK_ENTRIES)
2815             {
2816                FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2817                if(!fontEntry)
2818                {
2819                   File file = FileOpen/*Buffered*/(fileName, read);
2820                   if(file)
2821                   {
2822                      FileSize fileSize = file.GetSize();
2823                      FT_Open_Args args = { 0 };
2824                      FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
2825                      FT_Stream stream = new0 FT_StreamRec[1];
2826                      
2827                      if(!ftLibrary)
2828                         FT_Init_FreeType( &ftLibrary );
2829
2830                      fontEntry = FontEntry { key = (uint)CopyString(fileName) };
2831                      fontEntry.stream = stream;
2832
2833                      /*
2834                      fontEntry.buffer = new byte[fileSize];
2835                      file.Read(fontEntry.buffer, 1, fileSize);
2836                      */
2837
2838                      //args.num_params = 1;
2839                      args.params = &param;
2840
2841                      stream->size = fileSize;
2842                      stream->descriptor.pointer = file;
2843                      stream->read = FT_stream_load;
2844                      stream->close = FT_stream_close;
2845
2846                      args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
2847                      args.stream = stream;
2848                      //args.pathname = fileName;
2849                      //args.memory_base = fontEntry.buffer;
2850                      //args.memory_size = fileSize;
2851
2852                      // printf("Opening: %s\n", fileName);
2853                      FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
2854
2855                      // delete file;
2856                      if(fontEntry.face)
2857                      {
2858                         fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
2859                         fontEntry.hbFont.klass = &hb_fontClass;
2860                         fontEntry.hbFont.userData = fontEntry.face;
2861
2862                         numFonts++;
2863                         loadedFonts.Add(fontEntry);
2864                      }
2865                      else
2866                      {
2867                         delete fontEntry;
2868                         // printf("Error opening font %s\n", fileName);
2869                      }
2870                   }
2871                }
2872                if(fontEntry)
2873                {
2874                   if(!entry)
2875                   {
2876                      FT_Matrix matrix;
2877                      FT_Vector pen = { 0, 0 };
2878                      if(fakeItalic)
2879                      {
2880                         matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
2881                         matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
2882                         matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
2883                         matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
2884                         FT_Set_Transform(fontEntry.face, &matrix, &pen );
2885                      }
2886                      FT_Set_Char_Size( fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
2887                      font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
2888                      // printf("Font height is %d\n", font.height);
2889                      font.fakeItalic = fakeItalic;
2890                      font.size = size;
2891                      result = font;
2892                   }
2893                   font.fontEntries[entry++] = fontEntry;
2894                   fontEntry.used++;
2895                }
2896
2897                {
2898                   int c;
2899                   char ch;
2900                   char fontName[1024];
2901                   if(!links[linksPos]) break;
2902                   for(c = 0; (ch = links[linksPos + c]); c++)
2903                   {
2904                      fontName[c] = ch;
2905                      if(ch == ',') break;
2906                   }
2907                   fontName[c] = 0;
2908                   if(fontName[0] || ch == ',')
2909                   {
2910 #if defined(__WIN32__)
2911                      GetWindowsDirectory(fileName, MAX_LOCATION);
2912                      PathCat(fileName, "fonts");
2913                      PathCat(fileName, fontName);
2914 #elif defined(ECERE_NOFONTCONFIG)
2915                      if(getenv("ECERE_FONTS"))
2916                      {
2917                         strcpy(fileName, ecereFonts);
2918                         PathCat(fileName, fontName);
2919                      }
2920                      else
2921                      {
2922                         {
2923                            char * fileName2;
2924                            FcResult result = 0;
2925                            FcPattern * pattern;
2926                            FcPattern * matched;
2927                            char * family;
2928                             pattern = FcPatternBuild(null,
2929                                            //FC_SOURCE, FcTypeString, "freetype",
2930                                            //FC_SCALABLE, FcTypeBool, 1,
2931                                            FC_FAMILY, FcTypeString, links + linksPos + c + 1,
2932                                            FC_SIZE, FcTypeDouble, (double)size,
2933                                            FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2934                                            FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2935                                            null);
2936                            FcDefaultSubstitute(pattern);
2937                            FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2938
2939                            //printf("Locating %s\n", links + linksPos + c + 1);
2940                            matched = FcFontMatch (0, pattern, &result);
2941                            if(matched)
2942                            {
2943                               FcPatternGetString(matched, FC_FAMILY, 0, &family);
2944                               // printf("Fontconfig returned %s\n", family);
2945                            }
2946                            if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
2947                               FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
2948                            {
2949                               double fontSize;
2950                               FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2951                               FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2952                               FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2953                               strcpy(fileName, fileName2);
2954                               //size = (float)fontSize;
2955                               // printf("Matched to %s, %f\n", fileName, size);
2956                            }
2957                            else
2958                            {
2959                               // 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);
2960                            }
2961                            if(pattern) FcPatternDestroy(pattern);
2962                            if(matched) FcPatternDestroy(matched);
2963                         }
2964                      }
2965 #endif
2966                      
2967                   }
2968                   linksPos += c;
2969                   while(links[linksPos]) linksPos++;
2970                   linksPos++;
2971                }
2972             }
2973          }
2974             
2975          if(!result)
2976             UnloadFont(displaySystem, font);
2977          else
2978          {
2979             font.asciiPack.Render(font, 0, displaySystem);
2980          }
2981 #if !defined(__WIN32__)
2982          delete linkCfg;
2983 #endif
2984       }
2985    #endif
2986       return result;
2987    }
2988
2989 #if !defined(ECERE_NOTRUETYPE)
2990    void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len, 
2991                         void (* callback)(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft),
2992                         Surface surface, Display display, int * x, int y)
2993    {
2994       if(font && font.fontEntries && font.fontEntries[0])
2995       {
2996          int previousGlyph = 0;
2997          int c, nb, glyphIndex = 0;
2998          unichar lastPack = 0;
2999          GlyphPack pack = font.asciiPack;
3000          int wc;
3001          uint * glyphs;
3002          int numGlyphs = 0;
3003          bool rightToLeft = false;
3004          int rightToLeftOffset = 0;
3005          int fontEntryNum = 0;
3006          bool foundArabic = false;
3007          int glyphScript = 0;
3008          
3009          pack.bitmap.alphaBlend = true;
3010
3011          for(c = 0; c < len || glyphIndex < numGlyphs;)
3012          {
3013             uint glyphNo;
3014             uint packNo;
3015             if(glyphIndex < numGlyphs)
3016             {
3017                glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3018             }
3019             else
3020             {
3021                HB_Script curScript = HB_Script_Common;
3022                byte * scriptStart = text + c;
3023                unichar ch;
3024                unichar ahead = 0;
3025                unichar testChar = 0;
3026                char * testLang = null;
3027                
3028                while(true)
3029                {
3030                   HB_Script script = HB_Script_Common;
3031                   ch = UTF8GetChar(text + c, &nb);
3032                   if(!nb) break;
3033                   if(ch == 32 && curScript)
3034                   {
3035                      if(ahead)
3036                         script = curScript;
3037                      else
3038                      {
3039                         int a;
3040                         for(a = c + 1; a < c + len; a++)
3041                         {
3042                            if(text[a] != 32)
3043                               break;
3044                         }
3045                         if(a < c + len)
3046                         {
3047                            int nb;
3048                            unichar ahead = UTF8GetChar(text + a, &nb);
3049                            if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3050                               script = curScript;                           
3051                         }
3052                         else
3053                            script = curScript;
3054                      }
3055                   }
3056                   else if(ch < 0x370)
3057                      script = HB_Script_Common;
3058                   else if(ch <= 0x11FF)
3059                   {
3060                      switch(ch & 0xFF00)
3061                      {
3062                         case 0x300: script = HB_Script_Greek; break;
3063                         case 0x400: script = HB_Script_Cyrillic; break;
3064                         case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3065                         case 0x600: script = HB_Script_Arabic; break;
3066                         case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3067                         case 0x800: script = HB_Script_Common; break;   // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3068                         case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3069                         case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3070                         case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3071                         case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3072                         case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3073                         case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3074                         case 0xF00: script = HB_Script_Tibetan; break;
3075                         case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3076                         case 0x1100: script = HB_Script_Hangul; break;
3077                      }
3078                   }
3079                   else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3080                   else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3081                      script = HB_Script_Hangul;
3082                   else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3083                   else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3084                   else if(ch >= 0x1780 && ch <= 0x17FF || ch >= 0x19E0 && ch <= 0x19FF) script = HB_Script_Khmer;
3085                   else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3086                   else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3087                   //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3088                   else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3089                   else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3090                   else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3091                   if(curScript)
3092                   {
3093                      if(!script || (script != curScript))
3094                         break;
3095                      c += nb;
3096                      if(c >= len)
3097                         break;
3098                   }
3099                   else 
3100                   {
3101                      if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3102                      if(!script) { c += nb; break; }
3103                      curScript = script;
3104                   }
3105                }
3106                if(!nb) break;
3107                fontEntryNum = 0;
3108
3109                if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3110                {
3111                   rightToLeft = false;
3112                   glyphNo = ch;
3113                }
3114                else
3115                {
3116                   int len = c - (int)(scriptStart - text);
3117                   int max = len * 2 + 1;
3118                   if(max > utf16BufferSize)
3119                   {
3120                      utf16 = renew utf16 uint16[max];
3121                      utf16BufferSize = max;
3122                   }
3123                   wc = UTF8toUTF16BufferLen(scriptStart, utf16, max, len);
3124                   glyphScript = curScript;
3125                }
3126                switch(curScript)
3127                {
3128                   case HB_Script_Arabic:        testChar = 0x621; /*testLang = "ar"; */
3129                      //printf("Arabic ");
3130                      break;
3131                   case HB_Script_Devanagari:    testChar = 0x905; testLang = "sa"; 
3132                      //printf("Devanagari ");
3133                      break;
3134                   default:
3135                      testChar = ch;
3136                   /*
3137                   case 60: testChar = 'あ'; break;
3138                   case 61: testChar = 0x3400; break; //'愛'; break;
3139                   */
3140                }
3141
3142                if(testChar)
3143                {
3144                   // printf("Testing for char %x\n", testChar);
3145                   for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3146                   {
3147                      if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3148                         break;
3149                      /*if(font.fontEntries[fontEntryNum])
3150                         printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3151                   }
3152                }
3153                
3154                if(fontEntryNum == MAX_FONT_LINK_ENTRIES) 
3155                {
3156 #if !defined(__WIN32__)
3157                   int fontID = 0;
3158                   double fontSize = font.size;
3159                   FcResult result = 0;
3160                   FcPattern * pattern;
3161                   FcPattern * matched;
3162                   FcCharSet * charSet;
3163                   char * family;
3164                   FontEntry fontEntry;
3165                   char * fileName = null;
3166                   bool fakeItalic = false;
3167                   for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3168                      if(!font.fontEntries[fontEntryNum])
3169                         break;
3170                   if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3171 #endif
3172                      continue;
3173             
3174 #if !defined(__WIN32__)
3175                   {
3176                      charSet = FcCharSetCreate();
3177                      FcCharSetAddChar(charSet, testChar);
3178                      //printf("Loading with char %x\n", testChar);
3179
3180                      pattern = FcPatternBuild(null,
3181                                      //FC_SOURCE, FcTypeString, "freetype",
3182                                      //FC_SCALABLE, FcTypeBool, 1,
3183                                      FC_FAMILY, FcTypeString, font.faceName,
3184                                      FC_SIZE, FcTypeDouble, (double)font.size,
3185                                      FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3186                                      FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3187                                      FC_CHARSET,FcTypeCharSet, charSet,
3188                                      testLang ? FC_LANG : 0, FcTypeString,testLang,
3189                                      null);
3190                      FcDefaultSubstitute(pattern);
3191                      FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3192
3193                      //printf("Locating %s for script %d\n", font.faceName, curScript);
3194                      matched = FcFontMatch (0, pattern, &result);
3195                      if(matched)
3196                      {
3197                         FcPatternGetString(matched, FC_FAMILY, 0, &family);
3198                         //printf("Fontconfig returned %s\n", family);
3199                      }
3200                      if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3201                      {
3202                         FcPatternGetString (matched, FC_FILE, 0, &fileName);
3203                         FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3204                         FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3205                         // printf("\nMatched to %s, %f\n", fileName, fontSize);
3206                      }
3207                      else
3208                      {
3209                         //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);
3210                      }
3211                   }
3212                   if(fileName)
3213                   {
3214                      fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3215                      if(!fontEntry)
3216                      {
3217                         File file = FileOpen(fileName, read);
3218                         if(file)
3219                         {
3220                            FileSize fileSize = file.GetSize();
3221                            FT_Open_Args args = { 0 };                            
3222                            FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3223                            FT_Stream stream = new0 FT_StreamRec[1];
3224                            
3225                            if(!ftLibrary)
3226                               FT_Init_FreeType( &ftLibrary );
3227
3228                            fontEntry = FontEntry { key = (uint)CopyString(fileName) };
3229                            fontEntry.stream = stream;
3230                                                 
3231                            //args.num_params = 1;
3232                            args.params = &param;
3233
3234                            stream->size = fileSize;
3235                            stream->descriptor.pointer = file;
3236                            stream->read = FT_stream_load;
3237                            stream->close = FT_stream_close;
3238
3239                            args.flags = FT_OPEN_STREAM;
3240                            args.stream = stream;
3241                            //args.pathname = fileName;
3242                            //args.memory_base = fontEntry.buffer;
3243                            //args.memory_size = fileSize;
3244
3245                            // printf("Opening: %s\n", fileName);
3246                            FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3247
3248                            // delete file;
3249                            if(fontEntry.face)
3250                            {
3251                               fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);            
3252                               fontEntry.hbFont.klass = &hb_fontClass;
3253                               fontEntry.hbFont.userData = fontEntry.face;
3254
3255                               numFonts++;
3256                               loadedFonts.Add(fontEntry);
3257                            }
3258                            else
3259                            {
3260                               delete fontEntry;
3261                               // printf("Error opening font %s\n", fileName);
3262                            }
3263                         }
3264                      }
3265                      if(fontEntry)
3266                      {
3267                         FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
3268
3269                         font.fontEntries[fontEntryNum] = fontEntry;
3270                         fontEntry.used++;
3271                      }
3272                   }
3273                   if(pattern) FcPatternDestroy(pattern);          
3274                   if(matched) FcPatternDestroy(matched);
3275                   if(charSet) FcCharSetDestroy(charSet);
3276 #endif
3277                }
3278                if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3279                if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3280                {
3281                   int c;
3282                   glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3283                   if(!numGlyphs)
3284                      continue;
3285                   if(rightToLeft /*&& surface*/)
3286                   {
3287                      int c;
3288                      rightToLeftOffset = 0;
3289                      for(c = 0; c<numGlyphs; c++)
3290                      {
3291                         GlyphInfo * glyph;
3292                         glyphNo = glyphs[c] | 0x80000000 | (glyphScript << 24);
3293                         packNo = glyphNo & 0xFFFFFF80;
3294                         if(packNo != lastPack)
3295                         {
3296                            pack = (GlyphPack)font.glyphPacks.Find(packNo);
3297                            if(!pack)
3298                            {
3299                               pack = GlyphPack { key = packNo };
3300                               font.glyphPacks.Add(pack);
3301                               pack.Render(font, fontEntryNum, displaySystem);
3302                            }
3303                            pack.bitmap.alphaBlend = true;
3304                            lastPack = packNo;
3305                         }
3306                         glyph = &pack.glyphs[glyphNo & 0x7F];
3307
3308                         rightToLeftOffset += (int)glyph->ax - glyph->left;
3309                      }
3310                      *x += rightToLeftOffset;
3311                   }
3312
3313                   glyphIndex = 0;
3314                   glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3315                }
3316             }
3317             packNo = glyphNo & 0xFFFFFF80;
3318
3319             if(packNo != lastPack)
3320             {
3321                if(glyphNo < 128) 
3322                   pack = font.asciiPack;
3323                else
3324                {
3325                   pack = (GlyphPack)font.glyphPacks.Find(packNo);
3326                   if(!pack)
3327                   {
3328                      pack = GlyphPack { key = packNo };
3329                      font.glyphPacks.Add(pack);
3330                      pack.Render(font, fontEntryNum, displaySystem);
3331                   }
3332                }
3333                pack.bitmap.alphaBlend = true;
3334                lastPack = packNo;
3335             }
3336             if(pack)
3337             {
3338                GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3339
3340                /*if(previousGlyph)
3341                {
3342                   FT_Vector delta;
3343                   FT_Get_Kerning(font.fontEntries[fontEntryNum].face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3344                   *x += delta.x;
3345                }
3346                previousGlyph = glyph->glyphNo;*/
3347                callback(surface, display, x, y, glyph, pack.bitmap, rightToLeft);
3348             }
3349             if(numGlyphs && glyphIndex == numGlyphs)
3350             {
3351                *x += rightToLeftOffset;
3352                numGlyphs = 0;
3353             }
3354          }
3355       }
3356       if(surface)
3357       {
3358          LFBSurface lfbSurface = surface.driverData;
3359          lfbSurface.xOffset = 0;
3360       }
3361    }
3362
3363    void ::AddWidth(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3364    {
3365       if(rightToLeft)
3366       {
3367          *x -= (int)glyph->ax - glyph->left;
3368       }
3369       else
3370       {
3371          *x += glyph->ax;
3372       }
3373    }
3374 #endif
3375    void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3376    {
3377       if(displaySystem && displaySystem.flags.text && len)
3378       {
3379          if(width) 
3380          {
3381             int num = len;
3382             *width = num * textCellW;
3383          }
3384          if(height) *height = textCellH;
3385       }
3386       else if(font && len)
3387       {
3388          if(width)
3389          {
3390             int w = 0;
3391 #if !defined(ECERE_NOTRUETYPE)
3392             ProcessString(font, displaySystem, text, len, AddWidth, null, null, &w, 0);
3393 #endif
3394             //*width = (w + 64 - w % 64) >> 6;
3395             *width = w >> 6;
3396          }
3397          if(height)
3398             *height = font.height;
3399       }
3400       else
3401       {
3402          if(width) *width = 0;
3403          if(height) *height = 0;
3404       }
3405    }
3406
3407 #if !defined(ECERE_NOTRUETYPE)
3408    void ::OutputGlyph(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3409    {
3410       LFBSurface lfbSurface = surface.driverData;
3411       //lfbSurface.xOffset = (*x & 0x3F);
3412       if(rightToLeft)
3413       {
3414          surface.driver.Blit(display, surface, bitmap, (*x >> 6) - glyph->w, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3415          *x -= (int)glyph->ax - glyph->left;
3416       }
3417       else
3418       {
3419          surface.driver.Blit(display, surface, bitmap, (*x >> 6) + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3420          *x += glyph->ax;
3421       }
3422    }
3423 #endif
3424
3425    void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3426    {
3427       LFBSurface lfbSurface = surface.driverData;
3428       if(display && display.displaySystem.flags.text)
3429       {
3430          LFBDisplay lfbDisplay = display.driverData;
3431          uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3432          int c;
3433
3434          x /= textCellW;
3435          y /= textCellH;
3436
3437          if(y > surface.box.bottom || y < surface.box.top) 
3438             return;
3439          coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3440          for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3441          for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3442          {
3443             if(surface.textOpacity)
3444                *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3445             else
3446                *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3447          }
3448       }
3449       else 
3450       {
3451          lfbSurface.writingText = true;
3452 #if !defined(ECERE_NOTRUETYPE)
3453          x <<= 6;
3454          ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3455 #endif
3456          lfbSurface.writingText = false;
3457       }
3458    }
3459    
3460    void TextFont(Display display, Surface surface, Font font)
3461    {
3462       LFBSurface lfbSurface = surface.driverData;
3463       lfbSurface.font = font;
3464    }
3465
3466    void TextOpacity(Display display, Surface surface, bool opaque)
3467    {
3468       LFBSurface lfbSurface = surface.driverData;
3469
3470    }
3471
3472    void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3473    {
3474       LFBSurface lfbSurface = surface.driverData;
3475       FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3476    }
3477
3478    void DrawingChar(Display display, Surface surface, byte character)
3479    {
3480       LFBSurface lfbSurface = surface.driverData;
3481       lfbSurface.drawingChar = character;
3482    }
3483
3484    void LineStipple(Display display, Surface surface, uint32 stipple)
3485    {
3486       LFBSurface lfbSurface = surface.driverData;
3487       lfbSurface.stipple = (uint16)stipple;
3488    }
3489
3490 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3491    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3492    {
3493       if(mesh.vertices && !mesh.flags.vertices)
3494          delete mesh.vertices;
3495       if(mesh.normals && !mesh.flags.normals)
3496          delete mesh.normals;
3497       if(mesh.texCoords && !mesh.flags.texCoords1)
3498          delete mesh.texCoords;
3499    }
3500
3501    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3502    {
3503       bool result = false;
3504
3505       if((!mesh.flags.vertices   || mesh.vertices  || (mesh.vertices  = new Vector3Df[mesh.nVertices])) &&
3506          (!mesh.flags.normals    || mesh.normals   || (mesh.normals   = new Vector3Df[mesh.nVertices])) &&
3507          (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf  [mesh.nVertices])))
3508          result = true;
3509       return result;
3510    }
3511
3512    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3513    {
3514       return true;
3515    }
3516
3517    void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3518    {
3519       delete indices;
3520    }
3521
3522    uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3523    {
3524       return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3525    }
3526    uint16 * LockIndices(DisplaySystem displaySystem, void * indices)
3527    {
3528       return indices;
3529    }
3530 #endif
3531 }