1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
9 #if !defined(ECERE_NOTRUETYPE)
11 #include FT_FREETYPE_H
12 #include FT_TRUETYPE_TABLES_H
13 #include <freetype/ttunpat.h>
14 #define property _property
18 #if defined(__WIN32__)
19 #define WIN32_LEAN_AND_MEAN
21 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
23 #include <fontconfig/fontconfig.h>
24 static FcConfig * fcConfig;
32 #pragma warning(disable:4244)
33 #pragma warning(disable:4018)
39 public define LIGHTSHIFT = 5;
40 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
42 /*#ifndef ECERE_VANILLA
44 static bool rgbLookupSet = true;
46 /*static */byte defaultRGBLookup[32768];
47 /*static */bool rgbLookupSet = false;
53 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
54 import "OpenGLDisplayDriver"
55 import "Direct3D8DisplayDriver"
56 import "Direct3D9DisplayDriver"
59 #if !defined(ECERE_NOTRUETYPE)
61 #define MAX_FONT_LINK_ENTRIES 10
63 static HB_Script theCurrentScript;
65 static unichar UTF16GetChar(uint16 *string, int * nw)
68 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
70 ch = HB_SurrogateToUcs4(string[0], string[1]);
81 static HB_Bool hb_stringToGlyphs(HB_Font font, uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
83 FT_Face face = ((FontEntry)font->userData).face;
87 if (length > *numGlyphs)
90 for (c = 0; c < length; c += nw)
92 unichar ch = UTF16GetChar(string + c, &nw);
93 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
95 *numGlyphs = glyph_pos;
99 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
101 FontEntry entry = font->userData;
102 Font glFont = entry.font;
105 GlyphPack pack = glFont.asciiPack;
107 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
109 if(glFont.fontEntries[fontEntryNum] == entry)
113 for(c = 0; c < numGlyphs; c++)
116 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
117 uint packNo = glyphNo & 0xFFFFFF80;
118 if(packNo != lastPack)
120 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
123 glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
124 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
125 pack.bitmap.alphaBlend = true;
129 glyph = &pack.glyphs[glyphNo & 0x7F];
130 advances[c] = glyph->ax;
134 static HB_Bool hb_canRender(HB_Font font, uint16 * string, uint length)
136 FT_Face face = ((FontEntry)font->userData).face;
139 for (c = 0; c < length; c += nw)
141 unichar ch = UTF16GetChar(string + c, &nw);
142 if(!FT_Get_Char_Index(face, ch))
148 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
150 FT_Face face = (FT_Face)font;
151 FT_ULong ftlen = *length;
154 if (!FT_IS_SFNT(face))
155 return HB_Err_Invalid_Argument;
157 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
159 return (HB_Error)error;
162 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)
164 HB_Error error = HB_Err_Ok;
165 FT_Face face = (FT_Face)font->userData;
167 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
169 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
172 if (face->glyph->format != ft_glyph_format_outline)
173 return (HB_Error)HB_Err_Invalid_SubTable;
175 *nPoints = face->glyph->outline.n_points;
179 if (point > *nPoints)
180 return (HB_Error)HB_Err_Invalid_SubTable;
182 *xpos = face->glyph->outline.points[point].x;
183 *ypos = face->glyph->outline.points[point].y;
188 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
190 FontEntry entry = font->userData;
191 Font glFont = entry.font;
193 GlyphPack pack = glFont.asciiPack;
195 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
197 if(glFont.fontEntries[fontEntryNum] == entry)
202 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
203 uint packNo = glyphNo & 0xFFFFFF80;
204 if(packNo != lastPack)
206 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
209 pack = { key = (uintptr)packNo };
210 glFont.glyphPacks.Add(pack);
211 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
212 pack.bitmap.alphaBlend = true;
216 glyph = &pack.glyphs[glyphNo & 0x7F];
218 metrics->x = glyph->ax;
220 metrics->width = glyph->w;
221 metrics->height = glyph->h;
222 metrics->xOffset = glyph->bx;
223 metrics->yOffset = glyph->by;
227 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
229 FontEntry entry = font->userData;
230 FT_Face face = entry.face;
232 // Note that we aren't scanning the VDMX table which we probably would in
234 if(metric == HB_FontAscent)
235 return face->ascender;
239 static HB_FontClass hb_fontClass =
241 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
242 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
245 static uint FT_stream_load(FT_Stream stream, uint offset, byte * buffer, uint count)
247 File f = stream->descriptor.pointer;
248 f.Seek(offset, start);
249 return count ? f.Read(buffer, 1, count) : 0;
252 static void FT_stream_close(FT_Stream stream)
254 File f = stream->descriptor.pointer;
259 static FT_Library ftLibrary;
262 static BinaryTree loadedFonts
264 CompareKey = (void *)BinaryTree::CompareString
267 class FontEntry : BTNode
276 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
283 char * fileName = (char *)key;
294 FT_Done_FreeType(ftLibrary);
301 static float FaceSetCharSize(FT_Face face, float size)
304 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
306 if(face->num_fixed_sizes)
309 int bestDiff = MAXINT, best = 0;
310 FT_Bitmap_Size * sizes = face->available_sizes;
311 int wishedHeight = (int)(size * 96 / 72);
312 for(c = 0; c < face->num_fixed_sizes; c++)
314 int diff = abs(sizes[c].height - wishedHeight);
321 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
324 face->ascender = sizes[best].height;
325 scale = (float)wishedHeight / sizes[best].height;
344 class GlyphPack : BTNode
346 GlyphInfo glyphs[256];
349 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
351 #if !defined(ECERE_NOTRUETYPE)
353 int maxWidth, maxHeight;
354 int cellWidth, cellHeight;
356 FontEntry fontEntry = null;
359 bool isGlyph = (uint)key & 0x80000000;
360 int curScript = ((uint)key & 0x7F000000) >> 24;
361 unichar testChar = 0;
367 case HB_Script_Arabic:
369 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
371 case HB_Script_Devanagari:
374 case 60: testChar = 'あ'; break;
375 case 61: testChar = 0x3400; break;
382 FT_Vector pen = { 0, 0 };
385 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
386 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
387 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
388 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
389 FT_Set_Transform( fontEntry.face, &matrix, &pen );
391 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
397 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
399 fontEntry = font.fontEntries[c];
403 FT_Vector pen = { 0, 0 };
407 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
408 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
409 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
410 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
411 FT_Set_Transform(fontEntry.face, &matrix, &pen);
413 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
414 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
417 if(!fontEntry.face->units_per_EM)
418 font.ascent = (int)((double)fontEntry.face->ascender);
420 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
423 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
424 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
425 fontEntry.hbFont.x_scale = fontEntry.face->size->metrics.x_scale;
426 fontEntry.hbFont.y_scale = fontEntry.face->size->metrics.y_scale;
431 for(c = 0; c < 128; c++)
436 uint glyph = ((uint)key | c) & 0xFFFFFF;
437 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
439 fontEntry = font.fontEntries[entry];
440 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
442 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
444 //printf("%s: Accepted entry %d ", font.faceName, entry);
452 for(entry = startFontEntry; ; entry++)
455 fontEntry = font.fontEntries[entry];
456 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
458 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
463 scales[c] = fontEntry.scale;
464 faces[c] = fontEntry.face;
465 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
466 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
467 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
469 cellWidth = maxWidth;
470 cellHeight = maxHeight;
472 width = pow2i(maxWidth * 16);
473 height = pow2i(maxHeight * 8);
475 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
477 Bitmap bitmap = this.bitmap;
479 bitmap.transparent = true;
481 for(c = 0; c < 128; c++)
485 int sx = (c % 16) * cellWidth;
486 int sy = (c / 16) * cellHeight;
488 byte * picture = (byte *)bitmap.picture;
489 GlyphInfo * glyph = &glyphs[c];
490 FT_GlyphSlot slot = faces[c]->glyph;
491 double em_size = 1.0 * faces[c]->units_per_EM;
492 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
493 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
494 double ascender = faces[c]->ascender * y_scale;
495 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
497 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
499 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
503 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
505 glyph->left = slot->bitmap_left;
506 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
507 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
508 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
509 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
511 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
512 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
514 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
516 //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));
517 //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));
519 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
520 glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6)) / 2;
522 // 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);
523 xMax = x + slot->bitmap.width;
524 yMax = y + slot->bitmap.rows;
530 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
532 for(j = y, q = 0; j<yMax; j++)
534 for(p = 0, i = x; i<xMax; i++)
536 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
543 q += slot->bitmap.pitch;
546 max = numPixels ? (total / numPixels) : 1;
548 for(j = y, q = 0; j<yMax; j++)
551 for(p = 0, i = x; i<xMax; i++)
553 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
555 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
557 if(!bit) { bit = 0x80; p++; }
561 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
562 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
565 q += slot->bitmap.pitch;
570 glyph->w = slot->bitmap.width;
571 glyph->h = slot->bitmap.rows;
572 glyph->glyphNo = glyphNo;
573 glyph->bx = faces[c]->glyph->metrics.horiBearingX;
574 glyph->by = faces[c]->glyph->metrics.horiBearingY;
575 glyph->scale = scales[c];
577 glyph->ax = slot->advance.x;
578 glyph->ay = slot->advance.y + (64 - slot->advance.y % 64);
585 for(c = 0; c<256; c++)
586 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
587 bitmap.pixelFormat = pixelFormat8;
590 //strcpy(fileName, faceName);
592 strcat(fileName, "Bold");
594 sprintf(fileName, "font%d", fid++);
595 ChangeExtension(fileName, "pcx", fileName);
597 bitmap.Save(fileName, null, 0);
598 bitmap.pixelFormat = pixelFormatAlpha;
602 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
604 displaySystem.Lock();
605 #if defined(__WIN32__)
606 // Is this check still required?
607 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
608 displaySystem.driver == class(Direct3D8DisplayDriver) ||
609 displaySystem.driver == class(Direct3D9DisplayDriver))
611 bitmap.MakeDD(displaySystem);
612 displaySystem.Unlock();
619 #if !defined(ECERE_NOTRUETYPE)
620 static HB_ShaperItem shaper_item;
622 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
624 static uint maxGlyphs = 0;
625 HB_Glyph * glyphs = shaper_item.glyphs;
627 shaper_item.kerning_applied = 0;
628 shaper_item.string = string;
629 shaper_item.stringLength = len;
630 shaper_item.item.script = script;
631 shaper_item.item.pos = 0;
632 shaper_item.item.length = shaper_item.stringLength;
633 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
634 shaper_item.item.bidiLevel = 1;
636 shaper_item.item.bidiLevel = 0;
637 shaper_item.shaperFlags = 0;
638 shaper_item.font = &entry.hbFont;
639 shaper_item.face = entry.hbFace;
640 shaper_item.num_glyphs = shaper_item.item.length;
641 shaper_item.glyphIndicesPresent = 0;
642 shaper_item.initialGlyphCount = 0;
643 shaper_item.num_glyphs = 0;
644 shaper_item.glyphs = null;
646 while(!HB_ShapeItem(&shaper_item))
648 if(shaper_item.num_glyphs > maxGlyphs)
650 maxGlyphs = shaper_item.num_glyphs;
651 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
652 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
653 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
654 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
655 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
659 shaper_item.glyphs = glyphs;
660 shaper_item.num_glyphs = maxGlyphs;
664 *numGlyphs = shaper_item.num_glyphs;
665 *rightToLeft = shaper_item.item.bidiLevel % 2;
666 return shaper_item.glyphs;
670 delete shaper_item.glyphs;
671 delete shaper_item.attributes;
672 delete shaper_item.advances;
673 delete shaper_item.offsets;
674 delete shaper_item.log_clusters;
678 public class Font : struct
680 BinaryTree glyphPacks { };
681 GlyphPack asciiPack { };
682 #if !defined(ECERE_NOTRUETYPE)
683 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
690 DisplaySystem displaySystem;
696 #if !defined(ECERE_NOTRUETYPE)
698 while((pack = (GlyphPack)glyphPacks.root))
700 glyphPacks.Remove(pack);
707 public class LFBDisplay : struct
711 byte rgbLookup[32768];
712 byte lightTable[256][LIGHTSTEPS];
716 void (* displayCallback)(Display display, Box updateBox);
719 public class LFBSystem : struct
723 ColorAlpha * palette;
724 byte rgbLookup[32768];
731 ColorAlpha * palette = GetDefaultPalette();
732 for(c = 16; c < 232; c++)
734 Color555 color = palette[c].color;
735 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
736 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
737 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
738 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
740 for(c = 232; c < 246; c++)
742 Color555 color = palette[c].color;
743 defaultRGBLookup[color] = (byte)c;
746 for(c = 246; c < 256; c++)
748 Color555 color = palette[c].color;
749 defaultRGBLookup[color] = (byte)c;
751 for(c = 0; c < 16; c++)
753 Color555 color = palette[c].color;
754 defaultRGBLookup[color] = (byte)c;
757 for(c = 0; c<32768; c++)
759 Color color = (Color)(Color555)c;
760 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
761 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
769 public class LFBSurface : struct
772 // For compatibility with 3D drivers as well
780 // Drawing attributes
781 uint foreground, background;
782 ColorAlpha foregroundRgb;
785 byte * paletteShades;
790 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
792 if(recordA->zMin > recordB->zMin)
794 else if(recordA->zMin < recordB->zMin)
796 else if(recordA > recordB)
798 else if(recordA < recordB)
805 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
808 char fileName[MAX_FILENAME];
813 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
815 //if(fontType == TRUETYPE_FONTTYPE)
817 FontData * fontData = (FontData *) lParam;
818 char * fileName = (char *)lParam;
820 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
821 int italic = (fontData->flags.italic) ? 1 : 0;
822 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
824 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
825 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
830 char entryName[1024];
831 char fontFileName[1024];
834 int sizeFileName = 1024;
836 if(RegEnumValue(key, value++, entryName, (PDWORD)&size, null, (PDWORD)&type, (LPBYTE)fontFileName, (PDWORD)&sizeFileName) != ERROR_SUCCESS)
838 if((occurence = SearchString((char *)entryName, 0, (char *)font->elfFullName, false, false)))
841 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
843 char ch = entryName[c];
844 if(ch == '&') { c = -1; break; }
845 else if(ch != ' ') break;
848 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
850 char ch = entryName[c];
851 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
852 else if(ch != ' ') break;
855 if(atoi(entryName + c))
859 strcpy(fileName, fontFileName);
873 static int utf16BufferSize = 0;
874 static uint16 * utf16 = null;
876 public class LFBDisplayDriver : DisplayDriver
878 class_property(name) = "LFB";
880 bool CreateDisplaySystem(DisplaySystem displaySystem)
882 displaySystem.flags.memBackBuffer = true;
883 // displaySystem.pixelFormat = pixelFormat888;
887 void DestroyDisplaySystem(DisplaySystem displaySystem)
891 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
893 delete bitmap.picture;
894 if(bitmap.allocatePalette)
895 delete bitmap.palette;
898 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
903 switch(GetColorDepthShifts(format))
905 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
906 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
907 case 2: stride = width; break;
910 bitmap.stride = stride;
911 bitmap.width = width;
912 bitmap.height = height;
913 bitmap.size = (uint32) stride * (uint32)height;
914 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
915 bitmap.pixelFormat = format;
916 bitmap.transparent = false;
918 surface.box.left = surface.box.top = 0;
919 surface.box.right = width - 1;
920 surface.box.bottom = height - 1;
922 bitmap.picture = new0 byte[bitmap.sizeBytes];
925 bitmap.allocatePalette = allocatePalette;
928 bitmap.palette = new ColorAlpha[256];
931 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
937 bitmap.palette = GetDefaultPalette();
942 FreeBitmap(displaySystem, bitmap);
946 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
949 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
953 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
955 if(src.transparent && src.pixelFormat == pixelFormat888)
959 DWORD * picture = (DWORD *)src.picture;
961 for(c = 0; c<src.size; c++, picture++)
963 if(*picture & 0xFFFFFF)
964 *picture = *picture | 0xFF000000;
966 *picture = *picture & 0xFFFFFF;
975 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
977 if(format == pixelFormat8)
980 bitmap.palette = palette;
981 else if(lfbSystem && lfbSystem.palette)
982 bitmap.palette = lfbSystem.palette;
984 bitmap.palette = src.palette;
987 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
989 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
990 bitmap.transparent = src.transparent;
991 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
993 if(src.palette != bitmap.palette)
995 if(src.allocatePalette)
997 src.allocatePalette = false;
999 src.picture = bitmap.picture;
1000 src.palette = bitmap.palette;
1001 src.stride = bitmap.stride;
1002 src.size = bitmap.size;
1003 src.pixelFormat = bitmap.pixelFormat;
1008 bitmap.palette = null;
1009 bitmap.picture = null;
1017 void DestroyDisplay(Display display)
1019 LFBDisplay lfbDisplay = display.driverData;
1020 delete lfbDisplay.bitmap.palette;
1023 bool CreateDisplay(Display display)
1025 bool result = false;
1026 LFBDisplay lfbDisplay = display.driverData;
1029 lfbDisplay = display.driverData = LFBDisplay { };
1030 lfbDisplay.selfManaged = true;
1031 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1034 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1036 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1042 bool DisplaySize(Display display, int width, int height)
1044 LFBDisplay lfbDisplay = display.driverData;
1045 //display.width = width;
1046 //display.height = height;
1047 lfbDisplay.bitmap.width = width;
1048 lfbDisplay.bitmap.height = height;
1050 lfbDisplay.updateBox.left = display.width;
1051 lfbDisplay.updateBox.top = display.height;
1052 lfbDisplay.updateBox.right = 0;
1053 lfbDisplay.updateBox.bottom = 0;
1056 if(lfbDisplay.selfManaged)
1058 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1059 lfbDisplay.bitmap.stride = width;
1061 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1065 void DisplayPosition(Display display, int x, int y)
1067 LFBDisplay lfbDisplay = display.driverData;
1072 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1074 LFBDisplay lfbDisplay = display.driverData;
1081 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1082 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1083 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1086 for(c = 0; c<32768; c++)
1087 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1089 for(c=0; c<256; c++)
1092 for(i=0; i<LIGHTSTEPS; i++)
1094 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1095 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1096 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1097 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1101 if(lfbDisplay.bitmap.palette)
1102 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1105 void Update(Display display, Box updateBox)
1107 LFBDisplay lfbDisplay = display.driverData;
1108 if(lfbDisplay.displayCallback)
1110 if(updateBox == null)
1112 Box box { 0,0, display.width,display.height };
1113 lfbDisplay.displayCallback(display, box);
1116 lfbDisplay.displayCallback(display, updateBox);
1120 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1122 if(bitmap.pixelFormat != pixelFormatAlpha)
1124 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1126 FreeBitmap(displaySystem, bitmap);
1133 void ReleaseSurface(Display display, Surface surface)
1135 LFBSurface lfbSurface = surface.driverData;
1137 surface.driverData = null;
1140 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1142 LFBDisplay lfbDisplay = display.driverData;
1143 LFBSurface lfbSurface = surface.driverData;
1146 lfbSurface = surface.driverData = LFBSurface { };
1149 lfbSurface.bitmap = lfbDisplay.bitmap;
1151 surface.offset.x = x;
1152 surface.offset.y = y;
1154 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1156 surface.offset.x /= textCellW;
1157 surface.offset.y /= textCellH;
1158 surface.box.left /= textCellW;
1159 surface.box.top /= textCellH;
1160 surface.box.right /= textCellW;
1161 surface.box.bottom /= textCellH;
1165 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1166 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1167 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1168 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1171 surface.unclippedBox = surface.box;
1172 lfbSurface.drawingChar = 219;
1176 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1178 bool result = false;
1179 LFBSurface lfbSurface = surface.driverData;
1180 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1182 lfbSurface.bitmap = bitmap;
1184 surface.offset.x = x;
1185 surface.offset.y = y;
1187 if(bitmap.pixelFormat == pixelFormatText)
1189 surface.offset.x /= textCellW;
1190 surface.offset.y /= textCellH;
1191 surface.box.left /= textCellW;
1192 surface.box.top /= textCellH;
1193 surface.box.right /= textCellW;
1194 surface.box.bottom /= textCellH;
1197 surface.unclippedBox = *&surface.box;
1198 lfbSurface.drawingChar = 219;
1205 void Clip(Display display, Surface surface, Box clip)
1207 LFBSurface lfbSurface = surface.driverData;
1212 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1214 box.left /= textCellW;
1215 box.top /= textCellH;
1216 box.right /= textCellW;
1217 box.bottom /= textCellH;
1219 box.Clip(surface.unclippedBox);
1223 surface.box = surface.unclippedBox;
1226 void SetForeground(Display display, Surface surface, ColorAlpha color)
1228 LFBDisplay lfbDisplay = display ? display.driverData : null;
1229 LFBSurface lfbSurface = surface.driverData;
1231 if(display) color = color /*& 0xFFFFFF*/;
1232 lfbSurface.foregroundRgb = color;
1234 if(lfbSurface.font && lfbDisplay)
1236 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1237 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1240 switch(lfbSurface.bitmap.pixelFormat)
1244 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1246 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1248 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1249 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1250 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1251 case pixelFormat888: lfbSurface.foreground = color; break;
1252 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1253 case pixelFormatText:
1255 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1257 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1262 void SetBackground(Display display, Surface surface, ColorAlpha color)
1264 LFBDisplay lfbDisplay = display ? display.driverData : null;
1265 LFBSurface lfbSurface = surface.driverData;
1266 color = color /*& 0xFFFFFF*/;
1267 switch(lfbSurface.bitmap.pixelFormat)
1271 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1273 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1275 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1276 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1277 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1278 case pixelFormat888: lfbSurface.background = color; break;
1279 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1280 case pixelFormatText:
1282 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1284 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1289 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1291 LFBSurface lfbSurface = surface.driverData;
1292 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1297 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1299 x += surface.offset.x;
1300 y += surface.offset.y;
1301 if(lfbSurface.bitmap.picture)
1303 switch(lfbSurface.bitmap.pixelFormat)
1305 case pixelFormatText:
1307 if(!lfbSurface.bitmap.palette) return 0;
1308 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1309 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1310 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1311 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1312 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1319 void PutPixel(Display display, Surface surface,int x,int y)
1321 LFBSurface lfbSurface = surface.driverData;
1322 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1327 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1329 x += surface.offset.x;
1330 y += surface.offset.y;
1331 if(lfbSurface.bitmap.picture)
1333 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1336 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1339 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1342 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1343 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1350 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1352 LFBSurface lfbSurface = surface.driverData;
1358 uint color = lfbSurface.foreground;
1359 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1360 bool invert = false;
1361 if(!lfbSurface.bitmap.picture) return;
1362 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1368 if(surface.textOpacity)
1369 color |= lfbSurface.background;
1370 color |= lfbSurface.drawingChar;
1374 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1376 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1377 if((x1>surface.box.right)||(x2<surface.box.left))return;
1378 if(x1<surface.box.left)x1=surface.box.left;
1379 if(x2>surface.box.right)x2=surface.box.right;
1383 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1384 if(stipple != 0xFFFF)
1387 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1390 for(x=x1; x<=x2; x++, offset++)
1392 if(stipple & 0x8000)
1393 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1395 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1397 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1401 for(x=x1; x<=x2; x++, offset++)
1403 if(stipple & 0x8000)
1404 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1406 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1408 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1412 for(x=x1; x<=x2; x++, offset++)
1414 if(stipple & 0x8000)
1415 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1417 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1419 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1426 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1428 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1430 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1431 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1432 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1438 for(x = x1; x <= x2; x++, offset++)
1440 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1441 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1450 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1452 if((x1>surface.box.right)||(x1<surface.box.left))return;
1453 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1454 if(y1<surface.box.top)y1=surface.box.top;
1455 if(y2>surface.box.bottom)y2=surface.box.bottom;
1457 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1458 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1461 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1463 if(stipple & 0x8000)
1464 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1466 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1468 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1472 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1474 if(stipple & 0x8000)
1476 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1477 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1480 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1481 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1485 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1487 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1491 if(stipple != 0xFFFF)
1493 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1495 if(stipple & 0x8000)
1496 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1498 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1500 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1505 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1506 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1515 if(x1 < surface.box.left)
1517 if(x2 < surface.box.left)
1519 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1520 x1 = surface.box.left;
1522 if(x2 > surface.box.right)
1524 if(x1 > surface.box.right)
1526 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1527 x2 = surface.box.right;
1531 if(y1 < surface.box.top)
1533 if(y2 < surface.box.top)
1535 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1536 y1 = surface.box.top;
1538 if(y2 > surface.box.bottom)
1540 if(y1 > surface.box.bottom)
1542 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1543 y2 = surface.box.bottom;
1548 if(y1 > surface.box.bottom)
1550 if(y2 > surface.box.bottom)
1552 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1553 y1 = surface.box.bottom;
1555 if(y2 < surface.box.top)
1557 if(y1 < surface.box.top)
1559 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1560 y2 = surface.box.top;
1566 if(x1 > surface.box.right)
1568 if(x2 > surface.box.right)
1570 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1571 x1 = surface.box.right;
1573 if(x2 < surface.box.left)
1575 if(x1 < surface.box.left)
1577 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1578 x2 = surface.box.left;
1582 if(y1 < surface.box.top)
1584 if(y2 < surface.box.top)
1586 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1587 y1 = surface.box.top;
1589 if(y2 > surface.box.bottom)
1591 if(y1 > surface.box.bottom)
1593 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1594 y2 = surface.box.bottom;
1599 if(y1 > surface.box.bottom)
1601 if(y2 > surface.box.bottom)
1603 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1604 y1 = surface.box.bottom;
1606 if(y2 < surface.box.top)
1608 if(y1 < surface.box.top)
1610 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1611 y2 = surface.box.top;
1629 yu=-(int)lfbSurface.bitmap.stride;
1632 yu=lfbSurface.bitmap.stride;
1634 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1640 for(i=0; i<=length; i++)
1642 if(stipple & 0x8000)
1643 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1645 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1646 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1647 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1656 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1662 for(i=0; i<=length; i++)
1664 if(stipple & 0x8000)
1665 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1667 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1668 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1669 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1683 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1685 DrawLine(display, surface,x1,y1,x2,y1);
1686 DrawLine(display, surface,x2,y1,x2,y2);
1687 DrawLine(display, surface,x2,y2,x1,y2);
1688 DrawLine(display, surface,x1,y2,x1,y1);
1691 #if !defined(__GNUC__)
1693 void memset_32_aligned(void *buf, int val, int dwords)
1698 *((uint32 *)(buf)) = val;
1699 buf = ((uint32 *)(buf))+1;
1725 if (dwords & 1) *((int*)(buf)) = val;
1731 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1735 if(((uint32)buf) & 0x7F)
1737 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1763 sub edx,ebx ; edx holds # of overflow bytes
1782 movdqa [edi+16],xmm0
1783 movdqa [edi+32],xmm0
1784 movdqa [edi+48],xmm0
1785 movdqa [edi+64],xmm0
1786 movdqa [edi+80],xmm0
1787 movdqa [edi+96],xmm0
1788 movdqa [edi+112],xmm0
1812 void memset_32(void *buf, uint32 val, uint32 dwords)
1815 if ((uint32)(buf) & 3)
1820 if (((uint32)(buf) & 1))
1822 *(byte *)(buf) = (byte)(val&0xFF);
1823 buf = ((byte *)(buf))+1;
1824 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1827 if (((uint32)(buf) & 2))
1829 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1830 buf = ((uint16 *)(buf))+1;
1831 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1835 memset_32_aligned(buf,val,dwords);
1840 *(byte *)(buf) = (byte)(val&0xFF);
1844 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1845 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1852 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1854 LFBSurface lfbSurface = surface.driverData;
1855 uint32 color = lfbSurface.background;
1857 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1859 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1865 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1867 if(x1<surface.box.left) x1=surface.box.left;
1868 if(x2>surface.box.right) x2=surface.box.right;
1869 if(y1<surface.box.top) y1=surface.box.top;
1870 if(y2>surface.box.bottom) y2=surface.box.bottom;
1872 if(x2>=x1 && y2>=y1)
1880 x1 += surface.offset.x;
1881 x2 += surface.offset.x;
1882 y1 += surface.offset.y;
1883 y2 += surface.offset.y;
1884 if(lfbSurface.bitmap.picture)
1886 if(!surface.writeColor)
1888 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1889 for(y = y1; y<= y2; y++)
1892 for(c = 0; c < w; c++, picture++)
1894 picture->a = (byte)((color & 0xFF000000) >> 24);
1895 picture += lfbSurface.bitmap.stride - w;
1900 if(surface.background.a == 255 || lfbSurface.clearing)
1902 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1905 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1906 for(y = y1; y<= y2; y++)
1908 FillBytes(theOffset,(byte)color,w);
1909 theOffset += lfbSurface.bitmap.stride;
1913 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1914 for(y = y1; y<= y2; y++)
1916 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1917 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1921 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1922 for(y = y1; y<= y2; y++)
1924 #if defined(__GNUC__)
1925 FillBytesBy4((uint32 *) theOffset,color,w);
1927 memset_32((uint32 *) theOffset,color,w);
1929 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1935 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1936 //memset_32((uint32 *) theOffset,color,w);
1972 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1975 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1976 for(y = y1; y<= y2; y++)
1978 // TODO: IMPLEMENT THIS
1979 FillBytes(theOffset,(byte)color,w);
1980 theOffset += lfbSurface.bitmap.stride;
1985 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1986 ColorAlpha c = surface.background;
1991 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1993 for(y = y1; y <= y2; y++)
1996 for(c = 0; c < w; c++, dest++)
1999 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2000 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2001 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2003 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2004 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2005 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2007 if(r > 255) r = 255;
2008 if(g > 255) g = 255;
2009 if(b > 255) b = 255;
2011 destColor = { (byte)r, (byte)g, (byte)b };
2013 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2014 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2015 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2018 dest += (lfbSurface.bitmap.stride - w);
2024 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2025 AlphaWriteMode alphaWrite = surface.alphaWrite;
2026 ColorAlpha c = surface.background;
2031 for(y = y1; y <= y2; y++)
2034 for(c = 0; c < w; c++, dest++)
2036 int dr = dest->color.r;
2037 int dg = dest->color.g;
2038 int db = dest->color.b;
2039 int r = a * cr / 255 + ((255 - a) * dr / 255);
2040 int g = a * cg / 255 + ((255 - a) * dg / 255);
2041 int b = a * cb / 255 + ((255 - a) * db / 255);
2043 if(r > 255) r = 255;
2044 if(g > 255) g = 255;
2045 if(b > 255) b = 255;
2046 dest->color = { (byte)r, (byte)g, (byte)b };
2048 if(alphaWrite == blend)
2050 int ca = (int)(a + ((255 - a) * dest->a / 255));
2051 if(ca > 255) ca = 255;
2057 dest += (lfbSurface.bitmap.stride - w);
2066 void Clear(Display display, Surface surface, ClearType type)
2068 LFBSurface lfbSurface = surface.driverData;
2070 lfbSurface.clearing = true;
2071 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2072 surface.box.left == 0 && surface.box.top == 0 &&
2073 surface.box.right == surface.width-1 &&
2074 surface.box.bottom == surface.height-1)
2076 uint32 color = /*0xFF000000 | */lfbSurface.background;
2077 if(type != depthBuffer)
2079 if(lfbSurface.bitmap.stride != surface.width)
2080 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2083 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2086 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2088 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2089 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2094 if((flags & CLEAR_Z) && zbuffer)
2095 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2100 if(type != depthBuffer)
2101 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2103 if((flags & CLEAR_Z))
2106 uint32 w = surface.box.right-surface.box.left+1;
2107 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2108 + surface.box.left+surface.offset.x;
2109 for(y = surface.box.top; y<= surface.box.bottom; y++)
2111 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2112 offset += DISPLAY.Width;
2117 lfbSurface.clearing = false;
2120 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2122 LFBSurface lfbSurface = surface.driverData;
2125 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2127 if(w < 0) { w = -w; flip = true; }
2129 //Clip against the edges of the source
2142 if(sx+w>src.width-1)
2143 w-=sx+w-(src.width-1)-1;
2144 if(sy+h>src.height-1)
2145 h-=sy+h-(src.height-1)-1;
2146 //Clip against the edges of the destination
2147 if(dx<surface.box.left)
2149 if(!flip) sx+=surface.box.left-dx;
2150 w-=surface.box.left-dx;
2151 dx=surface.box.left;
2153 if(dy<surface.box.top)
2155 sy+=surface.box.top-dy;
2156 h-=surface.box.top-dy;
2159 if((dx+w)>surface.box.right)
2161 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2162 w-=((uint32)(dx+w)-surface.box.right-1);
2164 if((dy+h)>surface.box.bottom)
2165 h-=((dy+h)-surface.box.bottom-1);
2169 dx += surface.offset.x;
2170 dy += surface.offset.y;
2172 if(lfbSurface.bitmap.picture)
2174 AlphaWriteMode alphaWrite = surface.alphaWrite;
2175 if(src.alphaBlend && surface.blend)
2178 if(src.pixelFormat == pixelFormatAlpha)
2180 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2182 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2183 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2184 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2185 for(y = 0; y < h; y++)
2187 for(x = 0; x < w; x++, picture++, source++)
2189 int a = *source * color.a;
2190 ColorAlpha dest = *picture;
2191 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2192 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2193 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2194 if(r > 255) r = 255;
2195 if(g > 255) g = 255;
2196 if(b > 255) b = 255;
2197 picture->color = { (byte)r, (byte)g, (byte)b };
2198 if(alphaWrite == blend)
2200 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2201 if(ca > 255) ca = 255;
2202 picture->a = (byte)ca;
2205 picture->a = (byte)(a / 255);
2207 picture += lfbSurface.bitmap.stride - w;
2208 source += src.stride - w;
2211 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2213 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2214 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2215 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2216 for(y = 0; y < h; y++)
2218 for(x = 0; x < w; x++, picture++, source++)
2220 int a = *source * color.a;
2221 Color dest = *picture;
2222 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2223 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2224 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2225 if(r > 255) r = 255;
2226 if(g > 255) g = 255;
2227 if(b > 255) b = 255;
2228 *picture = Color { (byte)r, (byte)g, (byte)b };
2230 picture += lfbSurface.bitmap.stride - w;
2231 source += src.stride - w;
2234 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2236 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2237 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2238 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2239 for(y = 0; y < h; y++)
2241 for(x = 0; x < w; x++, picture++, source++)
2243 int a = *source * color.a;
2244 Color dest = *picture;
2245 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2246 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2247 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2248 if(r > 255) r = 255;
2249 if(g > 255) g = 255;
2250 if(b > 255) b = 255;
2251 *picture = Color { (byte)r, (byte)g, (byte)b };
2253 picture += lfbSurface.bitmap.stride - w;
2254 source += src.stride - w;
2260 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2261 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2263 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2264 for(y = 0; y < h; y++)
2266 for(x = 0; x < w; x++, picture++, source++)
2268 ColorAlpha src = *source;
2269 ColorAlpha dest = *picture;
2270 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2271 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2272 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2273 if(r > 255) r = 255;
2274 if(g > 255) g = 255;
2275 if(b > 255) b = 255;
2276 picture->color = { (byte)r, (byte)g, (byte)b };
2277 if(alphaWrite == blend)
2279 int a = src.a + ((255 - src.a) * dest.a / 255);
2280 if(a > 255) a = 255;
2281 picture->a = (byte)a;
2286 picture += lfbSurface.bitmap.stride - w;
2287 source += src.stride - w;
2290 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2292 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2293 for(y = 0; y < h; y++)
2295 for(x = 0; x < w; x++, picture++, source++)
2297 ColorAlpha src = *source;
2298 Color565 dest = *picture;
2299 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2300 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2301 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2302 if(r > 255 * 31) r = 255 * 31;
2303 if(g > 255 * 63) g = 255 * 63;
2304 if(b > 255 * 31) b = 255 * 31;
2305 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2307 picture += lfbSurface.bitmap.stride - w;
2308 source += src.stride - w;
2311 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2313 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2314 for(y = 0; y < h; y++)
2316 for(x = 0; x < w; x++, picture++, source++)
2318 ColorAlpha psrc = *source;
2319 Color555 dest = *picture;
2320 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2321 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2322 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2323 if(r > 255 * 31) r = 255 * 31;
2324 if(g > 255 * 31) g = 255 * 31;
2325 if(b > 255 * 31) b = 255 * 31;
2326 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2328 picture += lfbSurface.bitmap.stride - w;
2329 source += src.stride - w;
2334 else if(src.paletteShades)
2335 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2336 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2337 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2338 else if(src.pixelFormat == pixelFormat8)
2339 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2343 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2345 bool result = false;
2346 LFBDisplay lfbDisplay = display.driverData;
2348 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2351 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2352 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2356 Surface surface = bitmap.GetSurface(0,0,null);
2359 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2360 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2361 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2369 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2371 LFBSurface lfbSurface = surface.driverData;
2374 float s2dw,s2dh,d2sw,d2sh;
2376 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2378 if(Sgn(w) != Sgn(sw))
2390 //Clip against the edges of the source
2393 dx+=(int)((0-sx) * s2dw);
2394 w-=(int)((0-sx) * s2dw);
2400 dy+=(int)((0-sy) * s2dh);
2401 h-=(int)((0-sy) * s2dh);
2406 if(sx+sw>src.width-1)
2408 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2409 sw-=sx+sw-(src.width-1)-1;
2411 if(sy+sh>(src.height-1))
2413 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2414 sh-=sy+sh-(src.height-1)-1;
2416 //Clip against the edges of the destination
2417 if(dx<surface.box.left)
2419 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2420 sw-=(int)((surface.box.left-dx)*d2sw);
2421 w-=surface.box.left-dx;
2422 dx=surface.box.left;
2424 if(dy<surface.box.top)
2426 sy+=(int)((surface.box.top-dy)*d2sh);
2427 sh-=(int)((surface.box.top-dy)*d2sh);
2428 h-=surface.box.top-dy;
2431 if((dx+w)>surface.box.right)
2433 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2434 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2435 w-=((dx+w)-surface.box.right-1);
2437 if((dy+h)>surface.box.bottom)
2439 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2440 h-=((dy+h)-surface.box.bottom-1);
2442 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2444 dx+=surface.offset.x;
2445 dy+=surface.offset.y;
2447 if(lfbSurface.bitmap.picture)
2449 AlphaWriteMode alphaWrite = surface.alphaWrite;
2450 if(src.alphaBlend && surface.blend)
2454 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2455 ColorAlpha * backsrc;
2456 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2457 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2458 if(flip < 0) source += sw-1;
2476 ColorAlpha src = *source;
2477 ColorAlpha dst = *dest;
2478 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2479 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2480 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2481 if(r > 255) r = 255;
2482 if(g > 255) g = 255;
2483 if(b > 255) b = 255;
2484 dest->color = { (byte)r, (byte)g, (byte)b };
2485 if(alphaWrite == blend)
2487 int a = src.a + ((255 - src.a) * dst.a / 255);
2488 if(a > 255) a = 255;
2501 source += addsource;
2504 else if(src.paletteShades)
2505 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2506 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2507 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2508 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2509 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2513 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2515 LFBSurface lfbSurface = surface.driverData;
2518 float s2dw,s2dh,d2sw,d2sh;
2520 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2522 if(Sgn(w) != Sgn(sw))
2534 //Clip against the edges of the source
2537 dx+=(int)((0-sx) * s2dw);
2538 w-=(int)((0-sx) * s2dw);
2544 dy+=(int)((0-sy) * s2dh);
2545 h-=(int)((0-sy) * s2dh);
2550 if(sx+sw>src.width-1)
2552 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2553 sw-=sx+sw-(src.width-1)-1;
2555 if(sy+sh>(src.height-1))
2557 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2558 sh-=sy+sh-(src.height-1)-1;
2560 //Clip against the edges of the destination
2561 if(dx<surface.box.left)
2563 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2564 sw-=(int)((surface.box.left-dx)*d2sw);
2565 w-=surface.box.left-dx;
2566 dx=surface.box.left;
2568 if(dy<surface.box.top)
2570 sy+=(int)((surface.box.top-dy)*d2sh);
2571 sh-=(int)((surface.box.top-dy)*d2sh);
2572 h-=surface.box.top-dy;
2575 if((dx+w)>surface.box.right)
2577 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2578 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2579 w-=((dx+w)-surface.box.right-1);
2581 if((dy+h)>surface.box.bottom)
2583 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2584 h-=((dy+h)-surface.box.bottom-1);
2586 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2588 dx+=surface.offset.x;
2589 dy+=surface.offset.y;
2591 if(lfbSurface.bitmap.picture)
2593 AlphaWriteMode alphaWrite = surface.alphaWrite;
2594 if(src.alphaBlend && surface.blend)
2598 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2599 ColorAlpha * backsrc;
2600 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2601 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2602 float scaleX = (float)sw / w;
2603 float scaleY = (float)sh / h;
2611 if (w > sw && h > sh)
2614 for (y = 0; y < h; y++)
2616 int y0 = y * sh / h;
2617 int y1 = Min(y0 + 1, sh - 1);
2618 float alpha = y * scaleY - y0;
2620 for(x = 0; x < w; x++, dest += 1)
2622 int x0 = x * sw / w;
2623 int x1 = Min(x0 + 1, sw - 1);
2624 float beta = x * scaleX - x0;
2626 ColorAlpha src00, src01, src10, src11;
2627 float a1,r1,g1,b1,a2,r2,g2,b2;
2629 src00 = source[y0 * src.stride + x0];
2630 src01 = source[y0 * src.stride + x1];
2631 src10 = source[y1 * src.stride + x0];
2632 src11 = source[y1 * src.stride + x1];
2633 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2634 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2635 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2636 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2637 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2638 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2639 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2640 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2641 a = a1 * (1.0f - alpha) + a2 * alpha;
2642 r = r1 * (1.0f - alpha) + r2 * alpha;
2643 g = g1 * (1.0f - alpha) + g2 * alpha;
2644 b = b1 * (1.0f - alpha) + b2 * alpha;
2646 ColorAlpha dst = *dest;
2647 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2648 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2649 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2650 if(cr > 255) cr = 255;
2651 if(cg > 255) cg = 255;
2652 if(cb > 255) cb = 255;
2653 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2655 if(alphaWrite == blend)
2657 int ca = (int)(a + ((255 - a) * dst.a / 255));
2658 if(ca > 255) ca = 255;
2671 for (y = 0; y < h; y++)
2673 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2674 int y1 = Min(y0 + 1, sh - 1);
2676 for (x = 0; x < w; x++, dest += 1)
2678 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2679 int x1 = Min(x0 + 1, sw - 1);
2680 float a = 0, r = 0, g = 0, b = 0;
2684 for (i = y0; i <= y1; i++)
2685 for (j = x0; j <= x1; j++)
2687 ColorAlpha pixel = source[i * src.stride + j];
2699 ColorAlpha src = *source;
2700 ColorAlpha dst = *dest;
2701 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2702 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2703 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2704 if(cr > 255) cr = 255;
2705 if(cg > 255) cg = 255;
2706 if(cb > 255) cb = 255;
2707 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2708 if(alphaWrite == blend)
2710 int ca = (int)(a + ((255 - a) * dst.a / 255));
2711 if(ca > 255) ca = 255;
2722 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2723 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2724 // Fail back on Stretch
2725 else if(src.paletteShades)
2726 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2727 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2728 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2729 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2730 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2734 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2736 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2739 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2741 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2744 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2746 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2749 void UnloadFont(DisplaySystem displaySystem, Font font)
2753 #if !defined(ECERE_NOTRUETYPE)
2755 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2757 FontEntry fontEntry = font.fontEntries[entry];
2763 loadedFonts.Remove(fontEntry);
2773 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2775 void * result = null;
2777 #if !defined(ECERE_NOTRUETYPE)
2778 Font font = Font { };
2781 char fileName[MAX_LOCATION];
2782 bool fakeItalic = flags.italic;
2783 char linkCfgPath[MAX_LOCATION];
2785 #if !defined(__WIN32__)
2788 char * ecereFonts = getenv("ECERE_FONTS");
2789 if(!ecereFonts) ecereFonts = "<:ecere>";
2790 #if !defined(__WIN32__)
2791 strcpy(linkCfgPath, ecereFonts);
2792 PathCat(linkCfgPath, "linking.cfg");
2793 linkCfg = FileOpen(linkCfgPath, read);
2795 strcpy(fileName, faceName);
2796 strcpy(font.faceName, faceName);
2798 font.displaySystem = displaySystem;
2800 if(!FileExists(fileName))
2802 strcpy(fileName, ecereFonts);
2803 PathCat(fileName, faceName);
2804 if(flags.bold && flags.italic) strcat(fileName, "bi");
2805 else if(flags.bold) strcat(fileName, "bd");
2806 else if(flags.italic) strcat(fileName, "i");
2807 strcat(fileName, ".ttf");
2811 if(flags.italic && !FileExists(fileName))
2813 strcpy(fileName, ecereFonts);
2814 PathCat(fileName, faceName);
2815 if(flags.bold) strcat(fileName, "bd");
2816 strcat(fileName, ".ttf");
2821 // Search in current working directory
2822 if(!FileExists(fileName))
2824 strcpy(fileName, faceName);
2825 if(flags.bold && flags.italic) strcat(fileName, "bi");
2826 else if(flags.bold) strcat(fileName, "bd");
2827 else if(flags.italic) strcat(fileName, "i");
2828 strcat(fileName, ".ttf");
2832 if(flags.italic && !FileExists(fileName))
2834 strcpy(fileName, faceName);
2835 if(flags.bold) strcat(fileName, "bd");
2836 strcat(fileName, ".ttf");
2842 #if defined(__WIN32__)
2843 if(!FileExists(fileName))
2845 FontData fontData = { { 0 } };
2846 LOGFONT logFont = { 0 };
2851 logFont.lfCharSet = DEFAULT_CHARSET;
2852 strcpy(logFont.lfFaceName, faceName);
2853 fontData.flags = flags;
2855 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2856 if(!fontData.fileName[0] && flags.bold)
2858 fontData.forgive = true;
2859 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2861 if(!fontData.fileName[0])
2864 fontData.flags.italic = false;
2865 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2869 if(fontData.fileName[0])
2871 GetWindowsDirectory(fileName, MAX_LOCATION);
2872 PathCat(fileName, "fonts");
2873 PathCat(fileName, fontData.fileName);
2877 #elif !defined(ECERE_NOFONTCONFIG)
2880 FcResult result = 0;
2881 FcPattern * pattern;
2882 FcPattern * matched;
2884 unichar testChar = 0;
2885 FcCharSet * charSet;
2887 fcConfig = FcInitLoadConfigAndFonts();
2889 charSet = FcCharSetCreate();
2891 if(!strcmpi(faceName, "Mangal"))
2897 FcCharSetAddChar(charSet, testChar);
2899 pattern = FcPatternBuild(null,
2900 //FC_SOURCE, FcTypeString, "freetype",
2901 FC_FAMILY, FcTypeString, faceName,
2902 //FC_SCALABLE, FcTypeBool, 1,
2903 FC_SIZE, FcTypeDouble, (double)size,
2904 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2905 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2906 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2908 FcDefaultSubstitute(pattern);
2909 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2911 matched = FcFontMatch (0, pattern, &result);
2912 // printf("Locating %s\n", faceName);
2915 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2916 //printf("Fontconfig returned %s\n", family);
2918 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2921 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2922 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2923 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2924 strcpy(fileName, fileName2);
2925 // size = (float)fontSize;
2927 //printf("Matched to %s, %f\n", fileName, size);
2931 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2933 if(pattern) FcPatternDestroy(pattern);
2934 if(matched) FcPatternDestroy(matched);
2935 if(charSet) FcCharSetDestroy(charSet);
2940 if(!FileExists(fileName))
2941 ChangeExtension(fileName, "otf", fileName);
2942 if(!FileExists(fileName))
2943 ChangeExtension(fileName, "ttc", fileName);
2945 //if(FileExists(fileName))
2948 char links[1024] = "";
2950 #if defined(__WIN32__)
2953 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2954 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2959 RegQueryValueEx(key, faceName, null, (LPDWORD)&type, (LPBYTE)links, (LPDWORD)&size);
2960 memset(links + size, 0, 1024 - size);
2968 while(linkCfg.GetLine(line, sizeof(line)))
2970 int len = strlen(faceName);
2971 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2973 while(linkCfg.GetLine(line, sizeof(line)))
2975 TrimLSpaces(line, line);
2976 if(!line[0] || line[0] == '[')
2979 memcpy(links + linksPos, line, len);
2981 links[linksPos] = 0;
2989 while(entry < MAX_FONT_LINK_ENTRIES)
2991 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2994 File file = FileOpen/*Buffered*/(fileName, read);
2997 FileSize fileSize = file.GetSize();
2998 FT_Open_Args args = { 0 };
2999 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3000 FT_Stream stream = new0 FT_StreamRec[1];
3003 FT_Init_FreeType( &ftLibrary );
3005 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3006 fontEntry.stream = stream;
3009 fontEntry.buffer = new byte[fileSize];
3010 file.Read(fontEntry.buffer, 1, fileSize);
3013 //args.num_params = 1;
3014 args.params = ¶m;
3016 stream->size = fileSize;
3017 stream->descriptor.pointer = file;
3018 stream->read = FT_stream_load;
3019 stream->close = FT_stream_close;
3021 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3022 args.stream = stream;
3023 //args.pathname = fileName;
3024 //args.memory_base = fontEntry.buffer;
3025 //args.memory_size = fileSize;
3027 // printf("Opening: %s\n", fileName);
3028 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3033 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3034 fontEntry.hbFont.klass = &hb_fontClass;
3035 fontEntry.hbFont.userData = fontEntry; //.face;
3038 loadedFonts.Add(fontEntry);
3043 // printf("Error opening font %s\n", fileName);
3052 FT_Vector pen = { 0, 0 };
3055 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3056 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3057 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3058 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3062 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3063 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3064 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3065 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3067 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3068 FaceSetCharSize(fontEntry.face, size);
3069 font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3070 // printf("Font height is %d\n", font.height);
3071 font.fakeItalic = fakeItalic;
3075 font.fontEntries[entry++] = fontEntry;
3082 char fontName[1024];
3083 if(!links[linksPos]) break;
3084 for(c = 0; (ch = links[linksPos + c]); c++)
3087 if(ch == ',') break;
3090 if(fontName[0] || ch == ',')
3092 #if defined(__WIN32__)
3093 GetWindowsDirectory(fileName, MAX_LOCATION);
3094 PathCat(fileName, "fonts");
3095 PathCat(fileName, fontName);
3096 #elif !defined(ECERE_NOFONTCONFIG)
3097 if(getenv("ECERE_FONTS"))
3099 strcpy(fileName, ecereFonts);
3100 PathCat(fileName, fontName);
3106 FcResult result = 0;
3107 FcPattern * pattern;
3108 FcPattern * matched;
3110 pattern = FcPatternBuild(null,
3111 //FC_SOURCE, FcTypeString, "freetype",
3112 //FC_SCALABLE, FcTypeBool, 1,
3113 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3114 FC_SIZE, FcTypeDouble, (double)size,
3115 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3116 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3118 FcDefaultSubstitute(pattern);
3119 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3121 //printf("Locating %s\n", links + linksPos + c + 1);
3122 matched = FcFontMatch (0, pattern, &result);
3125 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3126 // printf("Fontconfig returned %s\n", family);
3128 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3129 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3132 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3133 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3134 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3135 strcpy(fileName, fileName2);
3136 //size = (float)fontSize;
3137 // printf("Matched to %s, %f\n", fileName, size);
3141 // printf("Could not find a match for %s, %f, %s %s (%d)\n", links + linksPos + c + 1, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
3143 if(pattern) FcPatternDestroy(pattern);
3144 if(matched) FcPatternDestroy(matched);
3151 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3158 UnloadFont(displaySystem, font);
3161 font.asciiPack.Render(font, 0, displaySystem);
3163 #if !defined(__WIN32__)
3171 #if !defined(ECERE_NOTRUETYPE)
3172 void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
3173 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3174 Surface surface, Display display, int * x, int y)
3176 if(font && font.fontEntries && font.fontEntries[0])
3178 int previousGlyph = 0;
3179 FT_Face previousFace = 0;
3180 int c, nb, glyphIndex = 0;
3181 unichar lastPack = 0;
3182 GlyphPack pack = font.asciiPack;
3186 bool rightToLeft = false;
3187 int fontEntryNum = 0;
3188 int glyphScript = 0;
3189 FontEntry curFontEntry;
3191 pack.bitmap.alphaBlend = true;
3193 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3197 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3199 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3200 rightToLeft ? glyphIndex-- : glyphIndex++;
3204 HB_Script curScript = HB_Script_Common;
3205 byte * scriptStart = text + c;
3206 unichar nonASCIIch = 0;
3209 unichar testChar = 0;
3210 char * testLang = null;
3214 HB_Script script = HB_Script_Common;
3215 ch = UTF8GetChar((char *)text + c, &nb);
3216 if(ch > 127) nonASCIIch = ch;
3218 if(ch == 32 && curScript)
3225 for(a = c + 1; a < c + len; a++)
3233 unichar ahead = UTF8GetChar((char *)text + a, &nb);
3234 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3242 script = HB_Script_Common;
3243 else if(ch <= 0x11FF)
3247 case 0x300: script = HB_Script_Greek; break;
3248 case 0x400: script = HB_Script_Cyrillic; break;
3249 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3250 case 0x600: script = HB_Script_Arabic; break;
3251 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3252 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3253 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3254 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3255 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3256 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3257 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3258 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3259 case 0xF00: script = HB_Script_Tibetan; break;
3260 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3261 case 0x1100: script = HB_Script_Hangul; break;
3264 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3265 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3266 script = HB_Script_Hangul;
3267 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3268 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3269 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3270 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3271 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3272 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3273 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3274 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3275 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3278 if(!script || (script != curScript))
3286 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3287 if(!script) { c += nb; break; }
3294 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3296 rightToLeft = false;
3298 theCurrentScript = 0;
3302 int len = c - (int)(scriptStart - text);
3303 int max = len * 2 + 1;
3304 if(max > utf16BufferSize)
3306 utf16 = renew utf16 uint16[max];
3307 utf16BufferSize = max;
3309 wc = UTF8toUTF16BufferLen((char *)scriptStart, utf16, max, len);
3310 theCurrentScript = glyphScript = curScript;
3314 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3315 //printf("Arabic ");
3317 case HB_Script_Devanagari: testChar = 0x905; testLang = "sa";
3318 //printf("Devanagari ");
3320 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3321 //printf("Hebrew ");
3324 testChar = (ch == '\t') ? ' ' : ch;
3326 case 60: testChar = 'あ'; break;
3327 case 61: testChar = 0x3400; break; //'愛'; break;
3333 // printf("Testing for char %x\n", testChar);
3334 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3336 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3338 /*if(font.fontEntries[fontEntryNum])
3339 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3343 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3345 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3347 double fontSize = font.size;
3348 FcResult result = 0;
3349 FcPattern * pattern;
3350 FcPattern * matched;
3351 FcCharSet * charSet;
3353 FontEntry fontEntry;
3354 char * fileName = null;
3355 bool fakeItalic = false;
3356 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3357 if(!font.fontEntries[fontEntryNum])
3359 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3363 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3365 charSet = FcCharSetCreate();
3366 FcCharSetAddChar(charSet, testChar);
3367 //printf("Loading with char %x\n", testChar);
3369 pattern = FcPatternBuild(null,
3370 //FC_SOURCE, FcTypeString, "freetype",
3371 //FC_SCALABLE, FcTypeBool, 1,
3372 FC_FAMILY, FcTypeString, font.faceName,
3373 FC_SIZE, FcTypeDouble, (double)font.size,
3374 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3375 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3376 FC_CHARSET,FcTypeCharSet, charSet,
3377 testLang ? FC_LANG : 0, FcTypeString,testLang,
3379 FcDefaultSubstitute(pattern);
3380 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3382 //printf("Locating %s for script %d\n", font.faceName, curScript);
3383 matched = FcFontMatch (0, pattern, &result);
3386 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3387 //printf("Fontconfig returned %s\n", family);
3389 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3391 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3392 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3393 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3394 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3398 //printf("Could not find a match for %s, %f, %s %s (%d)\n", font.faceName, font.size, font.flags.bold ? "bold" : "", font.flags.italic ? "italic" : "", (int)result);
3403 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3406 File file = FileOpen(fileName, read);
3409 FileSize fileSize = file.GetSize();
3410 FT_Open_Args args = { 0 };
3411 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3412 FT_Stream stream = new0 FT_StreamRec[1];
3415 FT_Init_FreeType( &ftLibrary );
3417 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3418 fontEntry.stream = stream;
3420 //args.num_params = 1;
3421 args.params = ¶m;
3423 stream->size = fileSize;
3424 stream->descriptor.pointer = file;
3425 stream->read = FT_stream_load;
3426 stream->close = FT_stream_close;
3428 args.flags = FT_OPEN_STREAM;
3429 args.stream = stream;
3430 //args.pathname = fileName;
3431 //args.memory_base = fontEntry.buffer;
3432 //args.memory_size = fileSize;
3434 // printf("Opening: %s\n", fileName);
3435 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3440 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3441 fontEntry.hbFont.klass = &hb_fontClass;
3442 fontEntry.hbFont.userData = fontEntry; //.face;
3445 loadedFonts.Add(fontEntry);
3450 // printf("Error opening font %s\n", fileName);
3456 FaceSetCharSize(fontEntry.face, font.size);
3458 font.fontEntries[fontEntryNum] = fontEntry;
3462 if(pattern) FcPatternDestroy(pattern);
3463 if(matched) FcPatternDestroy(matched);
3464 if(charSet) FcCharSetDestroy(charSet);
3467 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3468 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3470 font.fontEntries[fontEntryNum].font = font;
3471 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3475 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3476 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3477 rightToLeft ? glyphIndex-- : glyphIndex++;
3481 curFontEntry = font.fontEntries[fontEntryNum];
3483 packNo = glyphNo & 0xFFFFFF80;
3485 if(packNo != lastPack)
3488 pack = font.asciiPack;
3491 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3494 pack = GlyphPack { key = (uintptr)packNo };
3495 font.glyphPacks.Add(pack);
3496 pack.Render(font, fontEntryNum, displaySystem);
3499 pack.bitmap.alphaBlend = true;
3504 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3505 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3507 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3508 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3509 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3513 if(previousGlyph && curFontEntry.face == previousFace)
3515 FT_Vector delta = { 0, 0 };
3516 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3517 if(delta.x < 0) delta.x += (-delta.x) % 64;
3518 else if(delta.x) delta.x += 64 - (delta.x % 64);
3519 *x += delta.x * glyph->scale;
3522 FaceSetCharSize(curFontEntry.face, font.size);
3524 previousGlyph = glyph->glyphNo;
3525 previousFace = curFontEntry.face;
3528 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3531 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3537 LFBSurface lfbSurface = surface.driverData;
3538 lfbSurface.xOffset = 0;
3543 void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3545 if(displaySystem && displaySystem.flags.text && len)
3550 *width = num * textCellW;
3552 if(height) *height = textCellH;
3554 else if(font && len)
3559 #if !defined(ECERE_NOTRUETYPE)
3560 ProcessString(font, displaySystem, text, len, null, null, null, &w, 0);
3562 //*width = (w + 64 - w % 64) >> 6;
3566 *height = font.height;
3570 if(width) *width = 0;
3571 if(height) *height = 0;
3575 #if !defined(ECERE_NOTRUETYPE)
3576 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3578 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3582 void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3584 LFBSurface lfbSurface = surface.driverData;
3585 if(display && display.displaySystem.flags.text)
3587 LFBDisplay lfbDisplay = display.driverData;
3588 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3594 if(y > surface.box.bottom || y < surface.box.top)
3596 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3597 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3598 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3600 if(surface.textOpacity)
3601 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3603 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3608 lfbSurface.writingText = true;
3609 #if !defined(ECERE_NOTRUETYPE)
3611 ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3613 lfbSurface.writingText = false;
3617 void TextFont(Display display, Surface surface, Font font)
3619 LFBSurface lfbSurface = surface.driverData;
3620 lfbSurface.font = font;
3623 void TextOpacity(Display display, Surface surface, bool opaque)
3625 LFBSurface lfbSurface = surface.driverData;
3629 void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3631 LFBSurface lfbSurface = surface.driverData;
3632 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3635 void DrawingChar(Display display, Surface surface, byte character)
3637 LFBSurface lfbSurface = surface.driverData;
3638 lfbSurface.drawingChar = character;
3641 void LineStipple(Display display, Surface surface, uint32 stipple)
3643 LFBSurface lfbSurface = surface.driverData;
3644 lfbSurface.stipple = (uint16)stipple;
3647 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3648 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3650 if(mesh.vertices && !mesh.flags.vertices)
3651 delete mesh.vertices;
3652 if(mesh.normals && !mesh.flags.normals)
3653 delete mesh.normals;
3654 if(mesh.texCoords && !mesh.flags.texCoords1)
3655 delete mesh.texCoords;
3658 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3660 bool result = false;
3662 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3663 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3664 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3669 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3674 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3679 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3681 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3683 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)