sdk: const correctness
[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 FT_UNPATENTED_HINTING_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(const 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, const 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, const 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 = (uint)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 = (int)face->glyph->outline.points[point].x;
187     *ypos = (int)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, long offset, byte * buffer, long count)
250 {
251     File f = stream->descriptor.pointer;
252     f.Seek((int)offset, start);
253     return count ? f.Read(buffer, 1, (uint)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       delete (char *)key;
288       delete buffer;
289       if(hbFace)
290          HB_FreeFace(hbFace);
291       if(face)
292       {
293          FT_Done_Face(face);
294          numFonts--;
295          if(!numFonts)
296          {
297             FT_Done_FreeType(ftLibrary);
298             ftLibrary = null;
299          }
300       }
301    }
302 }
303
304 static float FaceSetCharSize(FT_Face face, float size)
305 {
306    float scale = 1;
307    if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
308    {
309       if(face->num_fixed_sizes)
310       {
311          int c;
312          int bestDiff = MAXINT, best = 0;
313          FT_Bitmap_Size * sizes = face->available_sizes;
314          int wishedHeight = (int)(size * 96 / 72);
315          for(c = 0; c < face->num_fixed_sizes; c++)
316          {
317             int diff = abs(sizes[c].height - wishedHeight);
318             if(diff < bestDiff)
319             {
320                best = c;
321                bestDiff = diff;
322             }
323          }
324          FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
325
326          if(!face->ascender)
327             face->ascender = sizes[best].height;
328          scale = (float)wishedHeight / sizes[best].height;
329       }
330    }
331    return scale;
332 }
333
334 #endif
335
336 struct GlyphInfo
337 {
338    int ax, ay;
339    int x, y;
340    int w, h;
341    int left, top;
342    int bx, by;
343    int glyphNo;
344    float scale;
345 };
346
347 class GlyphPack : BTNode
348 {
349    GlyphInfo glyphs[256];
350    Bitmap bitmap { };
351
352    void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
353    {
354 #if !defined(ECERE_NOTRUETYPE)
355       unichar c;
356       int maxWidth, maxHeight;
357       int cellWidth, cellHeight;
358       int width, height;
359       FontEntry fontEntry = null;
360       FT_Face faces[128];
361       float scales[128];
362       bool isGlyph = ((uint)key & 0x80000000) != 0;
363       //int curScript = ((uint)key & 0x7F000000) >> 24;
364       unichar testChar = 0;
365       /*
366       if(isGlyph)
367       {
368          switch(curScript)
369          {
370             case HB_Script_Arabic:
371                testChar = 0x621;
372                // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
373                break;
374             case HB_Script_Devanagari:
375                testChar = 0x905;
376                break;
377             case 60: testChar = 'あ'; break;
378             case 61: testChar = 0x3400; break;
379          }
380       }
381       */
382       /*
383       FT_GlyphSlot slot;
384       FT_Matrix matrix;
385       FT_Vector pen = { 0, 0 };
386       if(font.fakeItalic)
387       {
388          matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
389          matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
390          matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
391          matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
392          FT_Set_Transform( fontEntry.face, &matrix, &pen );
393       }
394       FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
395       */
396
397       maxWidth = 0;
398       maxHeight = 0;
399
400       for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
401       {
402          fontEntry = font.fontEntries[c];
403          if(fontEntry)
404          {
405             FT_Matrix matrix;
406             FT_Vector pen = { 0, 0 };
407
408             if(font.fakeItalic)
409             {
410                matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
411                matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
412                matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
413                matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
414                FT_Set_Transform(fontEntry.face, &matrix, &pen);
415             }
416             //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
417             fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
418             if(!c)
419             {
420                if(!fontEntry.face->units_per_EM)
421                   font.ascent = (int)((double)fontEntry.face->ascender);
422                else
423                   font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
424             }
425
426             fontEntry.hbFont.x_ppem  = fontEntry.face->size->metrics.x_ppem;
427             fontEntry.hbFont.y_ppem  = fontEntry.face->size->metrics.y_ppem;
428             fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
429             fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
430          }
431       }
432
433       fontEntry = null;
434       for(c = 0; c < 128; c++)
435       {
436          int entry = 0;
437          if(isGlyph)
438          {
439             uint glyph = ((uint)key | c) & 0xFFFFFF;
440             for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
441             {
442                fontEntry = font.fontEntries[entry];
443                if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
444                {
445                   if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
446                   {
447                      //printf("%s: Accepted entry %d ", font.faceName, entry);
448                      break;
449                   }
450                }
451             }
452          }
453          else
454          {
455             for(entry = startFontEntry; ; entry++)
456             {
457                uint glyph;
458                fontEntry = font.fontEntries[entry];
459                if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
460                {
461                   if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
462                      break;
463                }
464             }
465          }
466          scales[c] = fontEntry.scale;
467          faces[c] = fontEntry.face;
468          maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
469          maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
470          //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
471       }
472       cellWidth = maxWidth;
473       cellHeight = maxHeight;
474
475       width = pow2i(maxWidth * 16);
476       height = pow2i(maxHeight * 8);
477
478       if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
479       {
480          Bitmap bitmap = this.bitmap;
481
482          bitmap.transparent = true;
483
484          for(c = 0; c < 128; c++)
485          {
486             FT_Int i, j, p, q;
487             FT_Int xMax, yMax;
488             int sx = (c % 16) * cellWidth;
489             int sy = (c / 16) * cellHeight;
490             int x, y;
491             byte * picture = (byte *)bitmap.picture;
492             GlyphInfo * glyph = &glyphs[c];
493             FT_GlyphSlot slot = faces[c]->glyph;
494             double em_size = 1.0 * faces[c]->units_per_EM;
495             //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
496             double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
497             double ascender = faces[c]->ascender * y_scale;
498             int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
499
500             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
501
502             FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
503
504             x = sx;
505             y = sy;
506             //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
507
508             glyph->left = slot->bitmap_left;
509             // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
510             // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
511             //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
512             //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
513
514             //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0  + 0.5) - slot->bitmap_top;
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
517             //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
518
519             //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));
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
522             //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
523             glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
524
525             // 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);
526             xMax = x + slot->bitmap.width;
527             yMax = y + slot->bitmap.rows;
528
529             {
530                int total = 0;
531                int numPixels = 0;
532                //int max;
533                if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
534                {
535                   for(j = y, q = 0; j<yMax; j++)
536                   {
537                      for(p = 0, i = x; i<xMax; i++)
538                      {
539                         byte value = ((byte *)slot->bitmap.buffer)[q + p++];
540                         if(value > 32)
541                         {
542                            total += value;
543                            numPixels++;
544                         }
545                      }
546                      q += slot->bitmap.pitch;
547                   }
548                }
549                //max = numPixels ? (total / numPixels) : 1;
550
551                for(j = y, q = 0; j<yMax; j++)
552                {
553                   int bit = 0x80;
554                   for(p = 0, i = x; i<xMax; i++)
555                   {
556                      if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
557                      {
558                         picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
559                         bit >>= 1;
560                         if(!bit) { bit = 0x80; p++; }
561                      }
562                      else
563                      {
564                         byte value = ((byte *)slot->bitmap.buffer)[q + p++];
565                         picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
566                      }
567                   }
568                   q += slot->bitmap.pitch;
569                }
570             }
571             glyph->x = sx;
572             glyph->y = sy;
573             glyph->w = slot->bitmap.width;
574             glyph->h = slot->bitmap.rows;
575             glyph->glyphNo = glyphNo;
576             glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
577             glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
578             glyph->scale = scales[c];
579
580             glyph->ax = (int)slot->advance.x;
581             glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
582          }
583          #if 0
584          {
585             int c;
586             char fileName[256];
587             static int fid = 0;
588             for(c = 0; c<256; c++)
589                bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
590             bitmap.pixelFormat = pixelFormat8;
591
592             /*
593             //strcpy(fileName, faceName);
594             if(flags)
595                strcat(fileName, "Bold");
596             */
597             sprintf(fileName, "font%d", fid++);
598             ChangeExtension(fileName, "pcx", fileName);
599
600             bitmap.Save(fileName, null, 0);
601             bitmap.pixelFormat = pixelFormatAlpha;
602          }
603          #endif
604
605          if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
606          {
607             displaySystem.Lock();
608 #if defined(__WIN32__)
609             // Is this check still required?
610             if(displaySystem.driver == class(OpenGLDisplayDriver) ||
611                displaySystem.driver == class(Direct3D8DisplayDriver) ||
612                displaySystem.driver == class(Direct3D9DisplayDriver))
613 #endif
614                bitmap.MakeDD(displaySystem);
615             displaySystem.Unlock();
616          }
617       }
618 #endif
619    }
620 }
621
622 #if !defined(ECERE_NOTRUETYPE)
623 static HB_ShaperItem shaper_item;
624
625 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
626 {
627    static uint maxGlyphs = 0;
628    HB_Glyph * glyphs = shaper_item.glyphs;
629
630    shaper_item.kerning_applied = 0;
631    shaper_item.string = string;
632    shaper_item.stringLength = len;
633    shaper_item.item.script = script;
634    shaper_item.item.pos = 0;
635    shaper_item.item.length = shaper_item.stringLength;
636    if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
637       shaper_item.item.bidiLevel = 1;
638    else
639       shaper_item.item.bidiLevel = 0;
640    shaper_item.shaperFlags = 0;
641    shaper_item.font = &entry.hbFont;
642    shaper_item.face = entry.hbFace;
643    shaper_item.num_glyphs = shaper_item.item.length;
644    shaper_item.glyphIndicesPresent = 0;
645    shaper_item.initialGlyphCount = 0;
646    shaper_item.num_glyphs = 0;
647    shaper_item.glyphs = null;
648
649    while(!HB_ShapeItem(&shaper_item))
650    {
651       if(shaper_item.num_glyphs > maxGlyphs)
652       {
653          maxGlyphs = shaper_item.num_glyphs;
654          glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
655          shaper_item.attributes   = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
656          shaper_item.advances     = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
657          shaper_item.offsets      = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
658          shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
659       }
660       else
661       {
662          shaper_item.glyphs = glyphs;
663          shaper_item.num_glyphs = maxGlyphs;
664       }
665   }
666
667    *numGlyphs = shaper_item.num_glyphs;
668    *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
669    return shaper_item.glyphs;
670 }
671
672 /*
673    delete shaper_item.glyphs;
674    delete shaper_item.attributes;
675    delete shaper_item.advances;
676    delete shaper_item.offsets;
677    delete shaper_item.log_clusters;
678 */
679 #endif
680
681 public class Font : struct
682 {
683    BinaryTree glyphPacks { };
684    GlyphPack asciiPack { };
685 #if !defined(ECERE_NOTRUETYPE)
686    FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
687 #endif
688    float size;
689    bool fakeItalic;
690    int height;
691    FontFlags flags;
692    char faceName[512];
693    DisplaySystem displaySystem;
694    int ascent;
695    float scale;
696
697    ~Font()
698    {
699 #if !defined(ECERE_NOTRUETYPE)
700       GlyphPack pack;
701       while((pack = (GlyphPack)glyphPacks.root))
702       {
703          glyphPacks.Remove(pack);
704          delete pack;
705       }
706 #endif
707    }
708 };
709
710 public class LFBDisplay : struct
711 {
712 public:
713    Bitmap bitmap { };
714    byte rgbLookup[32768];
715    byte lightTable[256][LIGHTSTEPS];
716    OldList updateBoxes;
717    int x,y;
718    bool selfManaged;
719    void (* displayCallback)(Display display, Box updateBox);
720 };
721
722 public class LFBSystem : struct
723 {
724 public:
725    int format;
726    ColorAlpha * palette;
727    byte rgbLookup[32768];
728
729    LFBSystem()
730    {
731       if(!rgbLookupSet)
732       {
733          int c, r, g, b;
734          ColorAlpha * palette = GetDefaultPalette();
735          for(c = 16; c < 232; c++)
736          {
737             Color555 color = palette[c].color;
738             for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
739                for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
740                   for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
741                      defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
742          }
743          for(c = 232; c < 246; c++)
744          {
745             Color555 color = palette[c].color;
746             defaultRGBLookup[color] = (byte)c;
747          }
748          /*
749          for(c = 246; c < 256; c++)
750          {
751             Color555 color = palette[c].color;
752             defaultRGBLookup[color] = (byte)c;
753          }
754          for(c = 0; c < 16; c++)
755          {
756             Color555 color = palette[c].color;
757             defaultRGBLookup[color] = (byte)c;
758          }*/
759          /*
760          for(c = 0; c<32768; c++)
761          {
762             Color color = (Color)(Color555)c;
763             defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
764             // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
765          }
766          */
767          rgbLookupSet = true;
768       }
769    }
770 };
771
772 public class LFBSurface : struct
773 {
774 public:
775    // For compatibility with 3D drivers as well
776    Font font;
777    bool opaqueText;
778    int xOffset;
779    bool writingText;
780
781    Bitmap bitmap;
782
783    // Drawing attributes
784    uint foreground, background;
785    ColorAlpha foregroundRgb;
786    uint16 stipple;
787    byte drawingChar;
788    byte * paletteShades;
789    bool clearing;
790 };
791
792 /*
793 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
794 {
795    if(recordA->zMin > recordB->zMin)
796       return  1;
797    else if(recordA->zMin < recordB->zMin)
798       return -1;
799    else if(recordA > recordB)
800       return 1;
801    else if(recordA < recordB)
802       return -1;
803    else
804       return  0;
805 }
806 */
807
808 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
809 struct FontData
810 {
811    char fileName[MAX_FILENAME];
812    FontFlags flags;
813    bool forgive;
814 };
815
816 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
817 {
818    //if(fontType == TRUETYPE_FONTTYPE)
819    {
820       FontData * fontData = (FontData *) lParam;
821       char * fileName = (char *)lParam;
822       HKEY key;
823       int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
824       int italic = (fontData->flags.italic) ? 1 : 0;
825       if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
826       {
827          if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
828             !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
829          {
830             int value = 0;
831             while(true)
832             {
833                char entryName[1024];
834                char fontFileName[1024];
835                DWORD type;
836                DWORD size = 1024;
837                DWORD sizeFileName = 1024;
838                char * occurence;
839                if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
840                   break;
841                if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
842                {
843                   int c;
844                   for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
845                   {
846                      char ch = entryName[c];
847                      if(ch == '&') { c = -1; break; }
848                      else if(ch != ' ') break;
849                   }
850                   if(c >= 0) continue;
851                   for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
852                   {
853                      char ch = entryName[c];
854                      if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
855                      else if(ch != ' ') break;
856                   }
857
858                   if(atoi(entryName + c))
859                      c = -1;
860                   if(c >= 0) continue;
861
862                   strcpy(fileName, fontFileName);
863                   RegCloseKey(key);
864                   return 0;
865                }
866             }
867             RegCloseKey(key);
868             return 1;
869          }
870       }
871    }
872    return 1;
873 }
874 #endif
875
876 static int utf16BufferSize = 0;
877 static uint16 * utf16 = null;
878
879 public class LFBDisplayDriver : DisplayDriver
880 {
881    class_property(name) = "LFB";
882
883    bool CreateDisplaySystem(DisplaySystem displaySystem)
884    {
885       displaySystem.flags.memBackBuffer = true;
886       // displaySystem.pixelFormat = pixelFormat888;
887       return true;
888    }
889
890    void DestroyDisplaySystem(DisplaySystem displaySystem)
891    {
892    }
893
894    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
895    {
896       delete bitmap.picture;
897       if(bitmap.allocatePalette)
898          delete bitmap.palette;
899    }
900
901    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
902    {
903       bool result = false;
904       if(!stride)
905       {
906          switch(GetColorDepthShifts(format))
907          {
908             case 0: stride = (width + 3) & 0xFFFFFFFC; break;
909             case 1: stride = (width + 1) & 0xFFFFFFFE; break;
910             case 2: stride = width;                    break;
911          }
912       }
913       bitmap.stride = stride;
914       bitmap.width = width;
915       bitmap.height = height;
916       bitmap.size = (uint32) stride * (uint32)height;
917       bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
918       bitmap.pixelFormat = format;
919       bitmap.transparent = false;
920    /*
921       surface.box.left = surface.box.top = 0;
922       surface.box.right = width - 1;
923       surface.box.bottom = height - 1;
924    */
925       bitmap.picture = new0 byte[bitmap.sizeBytes];
926       if(bitmap.picture)
927       {
928          bitmap.allocatePalette = allocatePalette;
929          if(allocatePalette)
930          {
931             bitmap.palette = new ColorAlpha[256];
932             if(bitmap.palette)
933             {
934                CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
935                result = true;
936             }
937          }
938          else
939          {
940             bitmap.palette = GetDefaultPalette();
941             result = true;
942          }
943       }
944       if(!result)
945          FreeBitmap(displaySystem, bitmap);
946       return result;
947    }
948
949    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
950    {
951       bool result = false;
952       LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
953
954       if(src)
955       {
956          if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
957          {
958             if(src.transparent && src.pixelFormat == pixelFormat888)
959             {
960                /*
961                DWORD c;
962                DWORD * picture = (DWORD *)src.picture;
963
964                for(c = 0; c<src.size; c++, picture++)
965                {
966                   if(*picture & 0xFFFFFF)
967                      *picture =  *picture | 0xFF000000;
968                   else
969                      *picture = *picture & 0xFFFFFF;
970                }
971                */
972             }
973             result = true;
974          }
975          else
976          {
977             Bitmap bitmap { };
978             if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
979             {
980                if(format == pixelFormat8)
981                {
982                   if(palette)
983                      bitmap.palette = palette;
984                   else if(lfbSystem && lfbSystem.palette)
985                      bitmap.palette = lfbSystem.palette;
986                   else
987                      bitmap.palette = src.palette;
988                }
989
990                if(converters_table[src.pixelFormat][bitmap.pixelFormat])
991                {
992                   converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
993                   bitmap.transparent = src.transparent;
994                   bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
995                   delete src.picture;
996                   if(src.palette != bitmap.palette)
997                   {
998                      if(src.allocatePalette)
999                         delete src.palette;
1000                      src.allocatePalette = false;
1001                   }
1002                   src.picture = bitmap.picture;
1003                   src.palette = bitmap.palette;
1004                   src.stride = bitmap.stride;
1005                   src.size = bitmap.size;
1006                   src.sizeBytes = bitmap.sizeBytes;
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.blend || 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             uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2601             ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2602             ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest   + dx;
2603             float scaleX = (float)sw / w;
2604             float scaleY = (float)sh / h;
2605             /*if(flip < 0)
2606             {
2607                dest += w-1;
2608                adddest += w;
2609             }
2610             else*/
2611                adddest -= w;
2612             if (w > sw && h > sh)
2613             {
2614                int y;
2615                for (y = 0; y < h; y++)
2616                {
2617                   int y0 = y * sh / h;
2618                   int y1 = Min(y0 + 1, sh - 1);
2619                   float alpha = y * scaleY - y0;
2620                   int x;
2621                   for(x = 0; x < w; x++, dest += 1)
2622                   {
2623                      int x0 = x * sw / w;
2624                      int x1 = Min(x0 + 1, sw - 1);
2625                      float beta = x * scaleX - x0;
2626                      ColorAlpha src00, src01, src10, src11;
2627                      float a1,r1,g1,b1,a2,r2,g2,b2;
2628                      float a,r,g,b;
2629                      src00 = source[y0 * src.stride + x0];
2630                      src01 = source[y0 * src.stride + x1];
2631                      src10 = source[y1 * src.stride + x0];
2632                      src11 = source[y1 * src.stride + x1];
2633                      a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2634                      r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2635                      g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2636                      b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2637                      a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2638                      r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2639                      g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2640                      b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2641                      a = a1 * (1.0f - alpha) + a2 * alpha;
2642                      r = r1 * (1.0f - alpha) + r2 * alpha;
2643                      g = g1 * (1.0f - alpha) + g2 * alpha;
2644                      b = b1 * (1.0f - alpha) + b2 * alpha;
2645                      {
2646                         ColorAlpha dst = *dest;
2647                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2648                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2649                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2650                         if(cr > 255) cr = 255;
2651                         if(cg > 255) cg = 255;
2652                         if(cb > 255) cb = 255;
2653                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
2654
2655                         if(alphaWrite == blend)
2656                         {
2657                            int ca = (int)(a + ((255 - a) * dst.a / 255));
2658                            if(ca > 255) ca = 255;
2659                            dest->a = (byte)ca;
2660                         }
2661                         else if(alphaWrite)
2662                            dest->a = (byte)a;
2663                      }
2664                   }
2665                   dest += adddest;
2666                }
2667             }
2668             else
2669             {
2670                int y;
2671                for (y = 0; y < h; y++)
2672                {
2673                   int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2674                   int y1 = Min(y0 + 1, sh - 1);
2675                   int x;
2676                   for (x = 0; x < w; x++, dest += 1)
2677                   {
2678                      int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2679                      int x1 = Min(x0 + 1, sw - 1);
2680                      float a = 0, r = 0, g = 0, b = 0;
2681                      int numPixels = 0;
2682                      int i, j;
2683                      for (i = y0; i <= y1; i++)
2684                         for (j = x0; j <= x1; j++)
2685                         {
2686                            ColorAlpha pixel = source[i * src.stride + j];
2687                            a += pixel.a;
2688                            r += pixel.color.r;
2689                            g += pixel.color.g;
2690                            b += pixel.color.b;
2691                            numPixels++;
2692                         }
2693                      a /= numPixels;
2694                      r /= numPixels;
2695                      g /= numPixels;
2696                      b /= numPixels;
2697                      {
2698                         ColorAlpha dst = *dest;
2699                         int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2700                         int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2701                         int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2702                         if(cr > 255) cr = 255;
2703                         if(cg > 255) cg = 255;
2704                         if(cb > 255) cb = 255;
2705                         dest->color = { (byte)cr, (byte)cg, (byte)cb };
2706                         if(alphaWrite == blend)
2707                         {
2708                            int ca = (int)(a + ((255 - a) * dst.a / 255));
2709                            if(ca > 255) ca = 255;
2710                            dest->a = (byte)ca;
2711                         }
2712                         else if(alphaWrite)
2713                            dest->a = (byte)a;
2714                      }
2715                   }
2716                   dest += adddest;
2717                }
2718             }
2719          }
2720          else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2721             filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2722          // Fail back on Stretch
2723          else if(src.paletteShades)
2724             shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2725          else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2726             stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2727          else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2728             stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2729       }
2730    }
2731
2732    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2733    {
2734       Blit(display, surface, src, dx, dy, sx, sy, w, h);
2735    }
2736
2737    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2738    {
2739       Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2740    }
2741
2742    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2743    {
2744       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2745    }
2746
2747    void UnloadFont(DisplaySystem displaySystem, Font font)
2748    {
2749       if(font)
2750       {
2751 #if !defined(ECERE_NOTRUETYPE)
2752          int entry;
2753          for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2754          {
2755             FontEntry fontEntry = font.fontEntries[entry];
2756             if(fontEntry)
2757             {
2758                fontEntry.used--;
2759                if(!fontEntry.used)
2760                {
2761                   loadedFonts.Remove(fontEntry);
2762                   delete fontEntry;
2763                }
2764             }
2765          }
2766 #endif
2767          delete font;
2768       }
2769    }
2770
2771    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
2772    {
2773       void * result = null;
2774
2775 #if !defined(ECERE_NOTRUETYPE)
2776       Font font = Font { };
2777       if(font)
2778       {
2779          char fileName[MAX_LOCATION];
2780          bool fakeItalic = flags.italic;
2781          int fontID = 0;
2782 #if !defined(__WIN32__)
2783          File linkCfg;
2784 #endif
2785          const char * ecereFonts = getenv("ECERE_FONTS");
2786          if(!ecereFonts) ecereFonts = "<:ecere>";
2787 #if !defined(__WIN32__)
2788          {
2789             char linkCfgPath[MAX_LOCATION];
2790
2791             strcpy(linkCfgPath, ecereFonts);
2792             PathCat(linkCfgPath, "linking.cfg");
2793             linkCfg = FileOpen(linkCfgPath, read);
2794          }
2795 #endif
2796          strcpy(fileName, faceName);
2797          strcpy(font.faceName, faceName);
2798          font.flags = flags;
2799          font.displaySystem = displaySystem;
2800
2801          if(!FileExists(fileName))
2802          {
2803             strcpy(fileName, ecereFonts);
2804             PathCat(fileName, faceName);
2805             if(flags.bold && flags.italic) strcat(fileName, "bi");
2806             else if(flags.bold) strcat(fileName, "bd");
2807             else if(flags.italic) strcat(fileName, "i");
2808             strcat(fileName, ".ttf");
2809             strlwr(fileName);
2810             fakeItalic = false;
2811
2812             if(flags.italic && !FileExists(fileName))
2813             {
2814                strcpy(fileName, ecereFonts);
2815                PathCat(fileName, faceName);
2816                if(flags.bold) strcat(fileName, "bd");
2817                strcat(fileName, ".ttf");
2818                strlwr(fileName);
2819                fakeItalic = true;
2820             }
2821
2822             // Search in current working directory
2823             if(!FileExists(fileName))
2824             {
2825                strcpy(fileName, faceName);
2826                if(flags.bold && flags.italic) strcat(fileName, "bi");
2827                else if(flags.bold) strcat(fileName, "bd");
2828                else if(flags.italic) strcat(fileName, "i");
2829                strcat(fileName, ".ttf");
2830                strlwr(fileName);
2831                fakeItalic = false;
2832
2833                if(flags.italic && !FileExists(fileName))
2834                {
2835                   strcpy(fileName, faceName);
2836                   if(flags.bold) strcat(fileName, "bd");
2837                   strcat(fileName, ".ttf");
2838                   strlwr(fileName);
2839                   fakeItalic = true;
2840                }
2841             }
2842
2843    #if defined(__WIN32__)
2844             if(!FileExists(fileName))
2845             {
2846                FontData fontData = { { 0 } };
2847                LOGFONT logFont = { 0 };
2848                HDC hdc = GetDC(0);
2849
2850                fakeItalic = false;
2851
2852                logFont.lfCharSet = DEFAULT_CHARSET;
2853                strcpy(logFont.lfFaceName, faceName);
2854                fontData.flags = flags;
2855
2856                EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2857                if(!fontData.fileName[0] && flags.bold)
2858                {
2859                   fontData.forgive = true;
2860                   EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2861                }
2862                if(!fontData.fileName[0])
2863                {
2864                   // Fake italic
2865                   fontData.flags.italic = false;
2866                   EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2867                   fakeItalic = true;
2868                }
2869
2870                if(fontData.fileName[0])
2871                {
2872                   GetWindowsDirectory(fileName, MAX_LOCATION);
2873                   PathCat(fileName, "fonts");
2874                   PathCat(fileName, fontData.fileName);
2875                }
2876                ReleaseDC(0, hdc);
2877             }
2878    #elif !defined(ECERE_NOFONTCONFIG)
2879             {
2880                char * fileName2;
2881                FcResult result = 0;
2882                FcPattern * pattern;
2883                FcPattern * matched;
2884                char * family;
2885                unichar testChar = 0;
2886                FcCharSet * charSet;
2887                if(!fcConfig)
2888                   fcConfig = FcInitLoadConfigAndFonts();
2889
2890                charSet = FcCharSetCreate();
2891
2892                if(!strcmpi(faceName, "Mangal"))
2893                {
2894                   testChar = 0x905;
2895                }
2896
2897                if(testChar)
2898                   FcCharSetAddChar(charSet, testChar);
2899
2900                pattern = FcPatternBuild(null,
2901                                //FC_SOURCE, FcTypeString, "freetype",
2902                                FC_FAMILY, FcTypeString, faceName,
2903                                //FC_SCALABLE, FcTypeBool, 1,
2904                                FC_SIZE, FcTypeDouble, (double)size,
2905                                FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2906                                FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2907                                testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2908                                null);
2909                FcDefaultSubstitute(pattern);
2910                FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2911
2912                matched = FcFontMatch (0, pattern, &result);
2913                // printf("Locating %s\n", faceName);
2914                if(matched)
2915                {
2916                   FcPatternGetString(matched, FC_FAMILY, 0, &family);
2917                   //printf("Fontconfig returned %s\n", family);
2918                }
2919                if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2920                {
2921                   double fontSize;
2922                   FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2923                   FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2924                   FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2925                   strcpy(fileName, fileName2);
2926                   // size = (float)fontSize;
2927
2928                   //printf("Matched to %s, %f\n", fileName, size);
2929                }
2930                else
2931                {
2932                   //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2933                }
2934                if(pattern) FcPatternDestroy(pattern);
2935                if(matched) FcPatternDestroy(matched);
2936                if(charSet) FcCharSetDestroy(charSet);
2937             }
2938    #endif
2939          }
2940
2941          if(!FileExists(fileName))
2942             ChangeExtension(fileName, "otf", fileName);
2943          if(!FileExists(fileName))
2944             ChangeExtension(fileName, "ttc", fileName);
2945
2946          //if(FileExists(fileName))
2947          {
2948             int entry = 0;
2949             char links[1024] = "";
2950             int linksPos = 0;
2951 #if defined(__WIN32__)
2952             HKEY key;
2953             links[0] = 0;
2954             if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2955                !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2956             {
2957                // int value = 0;
2958                DWORD type;
2959                DWORD size = 1024;
2960                RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
2961                memset(links + size, 0, 1024 - size);
2962                RegCloseKey(key);
2963             }
2964 #else
2965             links[0] = 0;
2966             if(linkCfg)
2967             {
2968                char line[512];
2969                while(linkCfg.GetLine(line, sizeof(line)))
2970                {
2971                   int len = strlen(faceName);
2972                   if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2973                   {
2974                      while(linkCfg.GetLine(line, sizeof(line)))
2975                      {
2976                         TrimLSpaces(line, line);
2977                         if(!line[0] || line[0] == '[')
2978                            break;
2979                         len = strlen(line);
2980                         memcpy(links + linksPos, line, len);
2981                         linksPos += len;
2982                         links[linksPos] = 0;
2983                         linksPos++;
2984                      }
2985                   }
2986                }
2987                linksPos = 0;
2988             }
2989 #endif
2990             while(entry < MAX_FONT_LINK_ENTRIES)
2991             {
2992                FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2993                if(!fontEntry)
2994                {
2995                   File file = FileOpen/*Buffered*/(fileName, read);
2996                   if(file)
2997                   {
2998                      FileSize fileSize = file.GetSize();
2999                      FT_Open_Args args = { 0 };
3000                      FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3001                      FT_Stream stream = new0 FT_StreamRec[1];
3002
3003                      if(!ftLibrary)
3004                         FT_Init_FreeType( &ftLibrary );
3005
3006                      fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3007                      fontEntry.stream = stream;
3008
3009                      /*
3010                      fontEntry.buffer = new byte[fileSize];
3011                      file.Read(fontEntry.buffer, 1, fileSize);
3012                      */
3013
3014                      //args.num_params = 1;
3015                      args.params = &param;
3016
3017                      stream->size = fileSize;
3018                      stream->descriptor.pointer = file;
3019                      stream->read = FT_stream_load;
3020                      stream->close = FT_stream_close;
3021
3022                      args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3023                      args.stream = stream;
3024                      //args.pathname = fileName;
3025                      //args.memory_base = fontEntry.buffer;
3026                      //args.memory_size = fileSize;
3027
3028                      // printf("Opening: %s\n", fileName);
3029                      FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3030
3031                      // delete file;
3032                      if(fontEntry.face)
3033                      {
3034                         fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3035                         fontEntry.hbFont.klass = &hb_fontClass;
3036                         fontEntry.hbFont.userData = fontEntry; //.face;
3037
3038                         numFonts++;
3039                         loadedFonts.Add(fontEntry);
3040                      }
3041                      else
3042                      {
3043                         delete fontEntry;
3044                         // printf("Error opening font %s\n", fileName);
3045                      }
3046                   }
3047                }
3048                if(fontEntry)
3049                {
3050                   if(!entry)
3051                   {
3052                      FT_Matrix matrix;
3053                      FT_Vector pen = { 0, 0 };
3054                      if(fakeItalic)
3055                      {
3056                         matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3057                         matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3058                         matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3059                         matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3060                      }
3061                      else
3062                      {
3063                         matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3064                         matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3065                         matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3066                         matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3067                      }
3068                      FT_Set_Transform(fontEntry.face, &matrix, &pen );
3069                      FaceSetCharSize(fontEntry.face, size);
3070                      font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3071                      // printf("Font height is %d\n", font.height);
3072                      font.fakeItalic = fakeItalic;
3073                      font.size = size;
3074                      result = font;
3075                   }
3076                   font.fontEntries[entry++] = fontEntry;
3077                   fontEntry.used++;
3078                }
3079
3080                {
3081                   int c;
3082                   char ch;
3083                   char fontName[1024];
3084                   if(!links[linksPos]) break;
3085                   for(c = 0; (ch = links[linksPos + c]); c++)
3086                   {
3087                      fontName[c] = ch;
3088                      if(ch == ',') break;
3089                   }
3090                   fontName[c] = 0;
3091                   if(fontName[0] || ch == ',')
3092                   {
3093 #if defined(__WIN32__)
3094                      GetWindowsDirectory(fileName, MAX_LOCATION);
3095                      PathCat(fileName, "fonts");
3096                      PathCat(fileName, fontName);
3097 #elif !defined(ECERE_NOFONTCONFIG)
3098                      if(getenv("ECERE_FONTS"))
3099                      {
3100                         strcpy(fileName, ecereFonts);
3101                         PathCat(fileName, fontName);
3102                      }
3103                      else
3104                      {
3105                         {
3106                            char * fileName2;
3107                            FcResult result = 0;
3108                            FcPattern * pattern;
3109                            FcPattern * matched;
3110                            char * family;
3111                             pattern = FcPatternBuild(null,
3112                                            //FC_SOURCE, FcTypeString, "freetype",
3113                                            //FC_SCALABLE, FcTypeBool, 1,
3114                                            FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3115                                            FC_SIZE, FcTypeDouble, (double)size,
3116                                            FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3117                                            FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3118                                            null);
3119                            FcDefaultSubstitute(pattern);
3120                            FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3121
3122                            //printf("Locating %s\n", links + linksPos + c + 1);
3123                            matched = FcFontMatch (0, pattern, &result);
3124                            if(matched)
3125                            {
3126                               FcPatternGetString(matched, FC_FAMILY, 0, &family);
3127                               // printf("Fontconfig returned %s\n", family);
3128                            }
3129                            if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3130                               FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3131                            {
3132                               double fontSize;
3133                               FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3134                               FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3135                               FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3136                               strcpy(fileName, fileName2);
3137                               //size = (float)fontSize;
3138                               // printf("Matched to %s, %f\n", fileName, size);
3139                            }
3140                            else
3141                            {
3142                               // 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);
3143                            }
3144                            if(pattern) FcPatternDestroy(pattern);
3145                            if(matched) FcPatternDestroy(matched);
3146                         }
3147                      }
3148 #endif
3149
3150                   }
3151                   linksPos += c;
3152                   while(links[linksPos] && links[linksPos] != ',') linksPos++;
3153                   linksPos++;
3154                }
3155             }
3156          }
3157
3158          if(!result)
3159             UnloadFont(displaySystem, font);
3160          else
3161          {
3162             font.asciiPack.Render(font, 0, displaySystem);
3163          }
3164 #if !defined(__WIN32__)
3165          delete linkCfg;
3166 #endif
3167       }
3168    #endif
3169       return result;
3170    }
3171
3172 #if !defined(ECERE_NOTRUETYPE)
3173    void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
3174                         void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3175                         Surface surface, Display display, int * x, int y)
3176    {
3177       if(font && font.fontEntries && font.fontEntries[0])
3178       {
3179          int previousGlyph = 0;
3180          FT_Face previousFace = 0;
3181          int c, nb, glyphIndex = 0;
3182          unichar lastPack = 0;
3183          GlyphPack pack = font.asciiPack;
3184          int wc;
3185          uint * glyphs;
3186          int numGlyphs = 0;
3187          bool rightToLeft = false;
3188          int fontEntryNum = 0;
3189          int glyphScript = 0;
3190          FontEntry curFontEntry;
3191
3192          pack.bitmap.alphaBlend = true;
3193
3194          for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3195          {
3196             uint glyphNo;
3197             uint packNo;
3198             if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3199             {
3200                glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3201                rightToLeft ? glyphIndex-- : glyphIndex++;
3202             }
3203             else
3204             {
3205                HB_Script curScript = HB_Script_Common;
3206                const byte * scriptStart = text + c;
3207                //unichar nonASCIIch = 0;
3208                unichar ch;
3209                unichar ahead = 0;
3210                unichar testChar = 0;
3211 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3212                const char * testLang = null;
3213 #endif
3214
3215                while(true)
3216                {
3217                   HB_Script script = HB_Script_Common;
3218                   ch = UTF8GetChar((const char *)text + c, &nb);
3219                   //if(ch > 127) nonASCIIch = ch;
3220                   if(!nb) break;
3221                   if(ch == 32 && curScript)
3222                   {
3223                      if(ahead)
3224                         script = curScript;
3225                      else
3226                      {
3227                         int a;
3228                         for(a = c + 1; a < c + len; a++)
3229                         {
3230                            if(text[a] != 32)
3231                               break;
3232                         }
3233                         if(a < c + len)
3234                         {
3235                            int nb;
3236                            unichar ahead = UTF8GetChar((const char *)text + a, &nb);
3237                            if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3238                               script = curScript;
3239                         }
3240                         else
3241                            script = curScript;
3242                      }
3243                   }
3244                   else if(ch < 0x370)
3245                      script = HB_Script_Common;
3246                   else if(ch <= 0x11FF)
3247                   {
3248                      switch(ch & 0xFF00)
3249                      {
3250                         case 0x300: script = HB_Script_Greek; break;
3251                         case 0x400: script = HB_Script_Cyrillic; break;
3252                         case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3253                         case 0x600: script = HB_Script_Arabic; break;
3254                         case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3255                         case 0x800: script = HB_Script_Common; break;   // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3256                         case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3257                         case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3258                         case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3259                         case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3260                         case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3261                         case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3262                         case 0xF00: script = HB_Script_Tibetan; break;
3263                         case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3264                         case 0x1100: script = HB_Script_Hangul; break;
3265                      }
3266                   }
3267                   else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3268                   else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3269                      script = HB_Script_Hangul;
3270                   else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3271                   else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3272                   else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3273                   else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3274                   else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3275                   //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3276                   else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3277                   else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3278                   else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3279                   if(curScript)
3280                   {
3281                      if(!script || (script != curScript))
3282                         break;
3283                      c += nb;
3284                      if(c >= len)
3285                         break;
3286                   }
3287                   else
3288                   {
3289                      if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3290                      if(!script) { c += nb; break; }
3291                      curScript = script;
3292                   }
3293                }
3294                if(!nb) break;
3295                fontEntryNum = 0;
3296
3297                if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3298                {
3299                   rightToLeft = false;
3300                   glyphNo = ch;
3301                   theCurrentScript = 0;
3302                }
3303                else
3304                {
3305                   int len = c - (int)(scriptStart - text);
3306                   int max = len * 2 + 1;
3307                   if(max > utf16BufferSize)
3308                   {
3309                      utf16 = renew utf16 uint16[max];
3310                      utf16BufferSize = max;
3311                   }
3312                   wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
3313                   theCurrentScript = glyphScript = curScript;
3314                }
3315                switch(curScript)
3316                {
3317                   case HB_Script_Arabic:        testChar = 0x621; /*testLang = "ar"; */
3318                      //printf("Arabic ");
3319                      break;
3320                   case HB_Script_Devanagari:    testChar = 0x905;
3321 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3322                      testLang = "sa";
3323 #endif
3324                      //printf("Devanagari ");
3325                      break;
3326                   case HB_Script_Hebrew:        testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3327                      //printf("Hebrew ");
3328                      break;
3329                   default:
3330                      testChar = (ch == '\t') ? ' ' : ch;
3331                   /*
3332                   case 60: testChar = 'あ'; break;
3333                   case 61: testChar = 0x3400; break; //'愛'; break;
3334                   */
3335                }
3336
3337                if(testChar)
3338                {
3339                   // printf("Testing for char %x\n", testChar);
3340                   for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3341                   {
3342                      if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3343                         break;
3344                      /*if(font.fontEntries[fontEntryNum])
3345                         printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3346                   }
3347                }
3348
3349                if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3350                {
3351 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3352                   int fontID = 0;
3353                   double fontSize = font.size;
3354                   FcResult result = 0;
3355                   FcPattern * pattern;
3356                   FcPattern * matched;
3357                   FcCharSet * charSet;
3358                   char * family;
3359                   FontEntry fontEntry;
3360                   char * fileName = null;
3361                   bool fakeItalic = false;
3362                   for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3363                      if(!font.fontEntries[fontEntryNum])
3364                         break;
3365                   if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3366 #endif
3367                      continue;
3368
3369 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3370                   {
3371                      charSet = FcCharSetCreate();
3372                      FcCharSetAddChar(charSet, testChar);
3373                      //printf("Loading with char %x\n", testChar);
3374
3375                      pattern = FcPatternBuild(null,
3376                                      //FC_SOURCE, FcTypeString, "freetype",
3377                                      //FC_SCALABLE, FcTypeBool, 1,
3378                                      FC_FAMILY, FcTypeString, font.faceName,
3379                                      FC_SIZE, FcTypeDouble, (double)font.size,
3380                                      FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3381                                      FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3382                                      FC_CHARSET,FcTypeCharSet, charSet,
3383                                      testLang ? FC_LANG : 0, FcTypeString,testLang,
3384                                      null);
3385                      FcDefaultSubstitute(pattern);
3386                      FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3387
3388                      //printf("Locating %s for script %d\n", font.faceName, curScript);
3389                      matched = FcFontMatch (0, pattern, &result);
3390                      if(matched)
3391                      {
3392                         FcPatternGetString(matched, FC_FAMILY, 0, &family);
3393                         //printf("Fontconfig returned %s\n", family);
3394                      }
3395                      if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3396                      {
3397                         FcPatternGetString (matched, FC_FILE, 0, &fileName);
3398                         FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3399                         FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3400                         // printf("\nMatched to %s, %f\n", fileName, fontSize);
3401                      }
3402                      else
3403                      {
3404                         //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);
3405                      }
3406                   }
3407                   if(fileName)
3408                   {
3409                      fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3410                      if(!fontEntry)
3411                      {
3412                         File file = FileOpen(fileName, read);
3413                         if(file)
3414                         {
3415                            FileSize fileSize = file.GetSize();
3416                            FT_Open_Args args = { 0 };
3417                            FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3418                            FT_Stream stream = new0 FT_StreamRec[1];
3419
3420                            if(!ftLibrary)
3421                               FT_Init_FreeType( &ftLibrary );
3422
3423                            fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3424                            fontEntry.stream = stream;
3425
3426                            //args.num_params = 1;
3427                            args.params = &param;
3428
3429                            stream->size = fileSize;
3430                            stream->descriptor.pointer = file;
3431                            stream->read = FT_stream_load;
3432                            stream->close = FT_stream_close;
3433
3434                            args.flags = FT_OPEN_STREAM;
3435                            args.stream = stream;
3436                            //args.pathname = fileName;
3437                            //args.memory_base = fontEntry.buffer;
3438                            //args.memory_size = fileSize;
3439
3440                            // printf("Opening: %s\n", fileName);
3441                            FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3442
3443                            // delete file;
3444                            if(fontEntry.face)
3445                            {
3446                               fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3447                               fontEntry.hbFont.klass = &hb_fontClass;
3448                               fontEntry.hbFont.userData = fontEntry; //.face;
3449
3450                               numFonts++;
3451                               loadedFonts.Add(fontEntry);
3452                            }
3453                            else
3454                            {
3455                               delete fontEntry;
3456                               // printf("Error opening font %s\n", fileName);
3457                            }
3458                         }
3459                      }
3460                      if(fontEntry)
3461                      {
3462                         FaceSetCharSize(fontEntry.face, font.size);
3463
3464                         font.fontEntries[fontEntryNum] = fontEntry;
3465                         fontEntry.used++;
3466                      }
3467                   }
3468                   if(pattern) FcPatternDestroy(pattern);
3469                   if(matched) FcPatternDestroy(matched);
3470                   if(charSet) FcCharSetDestroy(charSet);
3471 #endif
3472                }
3473                if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3474                if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3475                {
3476                   font.fontEntries[fontEntryNum].font = font;
3477                   glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3478                   if(!numGlyphs)
3479                      continue;
3480
3481                   glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3482                   glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3483                   rightToLeft ? glyphIndex-- : glyphIndex++;
3484                }
3485             }
3486
3487             curFontEntry = font.fontEntries[fontEntryNum];
3488
3489             packNo = glyphNo & 0xFFFFFF80;
3490
3491             if(packNo != lastPack)
3492             {
3493                if(glyphNo < 128)
3494                   pack = font.asciiPack;
3495                else
3496                {
3497                   pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3498                   if(!pack)
3499                   {
3500                      pack = GlyphPack { key = (uintptr)packNo };
3501                      font.glyphPacks.Add(pack);
3502                      pack.Render(font, fontEntryNum, displaySystem);
3503                   }
3504                }
3505                pack.bitmap.alphaBlend = true;
3506                lastPack = packNo;
3507             }
3508             if(pack)
3509             {
3510                int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3511                GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3512
3513                int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3514                int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3515                int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3516
3517                ax += offset;
3518
3519                if(previousGlyph && curFontEntry.face == previousFace)
3520                {
3521                   FT_Vector delta = { 0, 0 };
3522                   FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3523                   if(delta.x < 0)  delta.x += (-delta.x) % 64;
3524                   else if(delta.x) delta.x += 64 - (delta.x % 64);
3525                   *x += delta.x * glyph->scale;
3526                }
3527                else
3528                   FaceSetCharSize(curFontEntry.face, font.size);
3529
3530                previousGlyph = glyph->glyphNo;
3531                previousFace = curFontEntry.face;
3532
3533                if(callback)
3534                   callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3535                *x += ax;
3536             }
3537             if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3538                numGlyphs = 0;
3539          }
3540       }
3541       if(surface)
3542       {
3543          LFBSurface lfbSurface = surface.driverData;
3544          lfbSurface.xOffset = 0;
3545       }
3546    }
3547
3548 #endif
3549    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3550    {
3551       if(displaySystem && displaySystem.flags.text && len)
3552       {
3553          if(width)
3554          {
3555             int num = len;
3556             *width = num * textCellW;
3557          }
3558          if(height) *height = textCellH;
3559       }
3560       else if(font && len)
3561       {
3562          if(width)
3563          {
3564             int w = 0;
3565 #if !defined(ECERE_NOTRUETYPE)
3566             ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
3567 #endif
3568             //*width = (w + 64 - w % 64) >> 6;
3569             *width = w >> 6;
3570          }
3571          if(height)
3572             *height = font.height;
3573       }
3574       else
3575       {
3576          if(width) *width = 0;
3577          if(height) *height = 0;
3578       }
3579    }
3580
3581 #if !defined(ECERE_NOTRUETYPE)
3582    void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3583    {
3584       surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3585    }
3586 #endif
3587
3588    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3589    {
3590       LFBSurface lfbSurface = surface.driverData;
3591       if(display && display.displaySystem.flags.text)
3592       {
3593          LFBDisplay lfbDisplay = display.driverData;
3594          uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3595          int c;
3596
3597          x /= textCellW;
3598          y /= textCellH;
3599
3600          if(y > surface.box.bottom || y < surface.box.top)
3601             return;
3602          coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3603          for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3604          for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3605          {
3606             if(surface.textOpacity)
3607                *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3608             else
3609                *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3610          }
3611       }
3612       else
3613       {
3614          lfbSurface.writingText = true;
3615 #if !defined(ECERE_NOTRUETYPE)
3616          x <<= 6;
3617          ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
3618 #endif
3619          lfbSurface.writingText = false;
3620       }
3621    }
3622
3623    void TextFont(Display display, Surface surface, Font font)
3624    {
3625       LFBSurface lfbSurface = surface.driverData;
3626       lfbSurface.font = font;
3627    }
3628
3629    void TextOpacity(Display display, Surface surface, bool opaque)
3630    {
3631
3632    }
3633
3634    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3635    {
3636       LFBSurface lfbSurface = surface.driverData;
3637       FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3638    }
3639
3640    void DrawingChar(Display display, Surface surface, byte character)
3641    {
3642       LFBSurface lfbSurface = surface.driverData;
3643       lfbSurface.drawingChar = character;
3644    }
3645
3646    void LineStipple(Display display, Surface surface, uint32 stipple)
3647    {
3648       LFBSurface lfbSurface = surface.driverData;
3649       lfbSurface.stipple = (uint16)stipple;
3650    }
3651
3652 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3653    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3654    {
3655       if(mesh.vertices && !mesh.flags.vertices)
3656          delete mesh.vertices;
3657       if(mesh.normals && !mesh.flags.normals)
3658          delete mesh.normals;
3659       if(mesh.texCoords && !mesh.flags.texCoords1)
3660          delete mesh.texCoords;
3661    }
3662
3663    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3664    {
3665       bool result = false;
3666
3667       if((!mesh.flags.vertices   || mesh.vertices  || (mesh.vertices  = new Vector3Df[mesh.nVertices])) &&
3668          (!mesh.flags.normals    || mesh.normals   || (mesh.normals   = new Vector3Df[mesh.nVertices])) &&
3669          (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf  [mesh.nVertices])))
3670          result = true;
3671       return result;
3672    }
3673
3674    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3675    {
3676       return true;
3677    }
3678
3679    void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3680    {
3681       delete indices;
3682    }
3683
3684    uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3685    {
3686       return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3687    }
3688    uint16 * LockIndices(DisplaySystem displaySystem, void * indices)
3689    {
3690       return indices;
3691    }
3692 #endif
3693 }