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