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