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