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