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