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