1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
8 #if !defined(ECERE_NOTRUETYPE)
10 #include FT_FREETYPE_H
11 #include FT_TRUETYPE_TABLES_H
12 #include <freetype/ttunpat.h>
13 #define property _property
17 #if defined(__WIN32__)
18 #define WIN32_LEAN_AND_MEAN
20 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
22 #include <fontconfig/fontconfig.h>
23 static FcConfig * fcConfig;
31 #pragma warning(disable:4244)
32 #pragma warning(disable:4018)
38 public define LIGHTSHIFT = 5;
39 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
41 /*#ifndef ECERE_VANILLA
43 static bool rgbLookupSet = true;
45 /*static */byte defaultRGBLookup[32768];
46 /*static */bool rgbLookupSet = false;
52 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
53 import "OpenGLDisplayDriver"
54 import "Direct3D8DisplayDriver"
55 import "Direct3D9DisplayDriver"
58 #if !defined(ECERE_NOTRUETYPE)
60 #define MAX_FONT_LINK_ENTRIES 10
62 static HB_Script theCurrentScript;
64 static unichar UTF16GetChar(uint16 *string, int * nw)
67 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
69 ch = HB_SurrogateToUcs4(string[0], string[1]);
80 static HB_Bool hb_stringToGlyphs(HB_Font font, uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
82 FT_Face face = ((FontEntry)font->userData).face;
86 if (length > *numGlyphs)
89 for (c = 0; c < length; c += nw)
91 unichar ch = UTF16GetChar(string + c, &nw);
92 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
94 *numGlyphs = glyph_pos;
98 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
100 FontEntry entry = font->userData;
101 Font glFont = entry.font;
104 GlyphPack pack = glFont.asciiPack;
106 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
108 if(glFont.fontEntries[fontEntryNum] == entry)
112 for(c = 0; c < numGlyphs; c++)
115 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
116 uint packNo = glyphNo & 0xFFFFFF80;
117 if(packNo != lastPack)
119 pack = (GlyphPack)glFont.glyphPacks.Find(packNo);
122 glFont.glyphPacks.Add((pack = GlyphPack { key = packNo }));
123 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
124 pack.bitmap.alphaBlend = true;
128 glyph = &pack.glyphs[glyphNo & 0x7F];
129 advances[c] = glyph->ax;
133 static HB_Bool hb_canRender(HB_Font font, uint16 * string, uint length)
135 FT_Face face = ((FontEntry)font->userData).face;
138 for (c = 0; c < length; c += nw)
140 unichar ch = UTF16GetChar(string + c, &nw);
141 if(!FT_Get_Char_Index(face, ch))
147 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
149 FT_Face face = (FT_Face)font;
150 FT_ULong ftlen = *length;
153 if (!FT_IS_SFNT(face))
154 return HB_Err_Invalid_Argument;
156 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
158 return (HB_Error)error;
161 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)
163 HB_Error error = HB_Err_Ok;
164 FT_Face face = (FT_Face)font->userData;
166 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
168 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
171 if (face->glyph->format != ft_glyph_format_outline)
172 return (HB_Error)HB_Err_Invalid_SubTable;
174 *nPoints = face->glyph->outline.n_points;
178 if (point > *nPoints)
179 return (HB_Error)HB_Err_Invalid_SubTable;
181 *xpos = face->glyph->outline.points[point].x;
182 *ypos = face->glyph->outline.points[point].y;
187 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
189 FontEntry entry = font->userData;
190 Font glFont = entry.font;
192 GlyphPack pack = glFont.asciiPack;
194 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
196 if(glFont.fontEntries[fontEntryNum] == entry)
201 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
202 uint packNo = glyphNo & 0xFFFFFF80;
203 if(packNo != lastPack)
205 pack = (GlyphPack)glFont.glyphPacks.Find(packNo);
208 pack = { key = packNo };
209 glFont.glyphPacks.Add(pack);
210 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
211 pack.bitmap.alphaBlend = true;
215 glyph = &pack.glyphs[glyphNo & 0x7F];
217 metrics->x = glyph->ax;
219 metrics->width = glyph->w;
220 metrics->height = glyph->h;
221 metrics->xOffset = glyph->bx;
222 metrics->yOffset = glyph->by;
226 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
228 FontEntry entry = font->userData;
229 FT_Face face = entry.face;
231 // Note that we aren't scanning the VDMX table which we probably would in
233 if(metric == HB_FontAscent)
234 return face->ascender;
238 static HB_FontClass hb_fontClass =
240 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
241 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
244 static uint FT_stream_load(FT_Stream stream, uint offset, byte * buffer, uint count)
246 File f = stream->descriptor.pointer;
247 f.Seek(offset, start);
248 return count ? f.Read(buffer, 1, count) : 0;
251 static void FT_stream_close(FT_Stream stream)
253 File f = stream->descriptor.pointer;
258 static FT_Library ftLibrary;
261 static BinaryTree loadedFonts
263 CompareKey = (void *)BinaryTree::CompareString
266 class FontEntry : BTNode
275 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
282 char * fileName = (char *)key;
293 FT_Done_FreeType(ftLibrary);
300 static float FaceSetCharSize(FT_Face face, float size)
303 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
305 if(face->num_fixed_sizes)
308 int bestDiff = MAXINT, best = 0;
309 FT_Bitmap_Size * sizes = face->available_sizes;
310 int wishedHeight = (int)(size * 96 / 72);
311 for(c = 0; c < face->num_fixed_sizes; c++)
313 int diff = abs(sizes[c].height - wishedHeight);
320 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
323 face->ascender = sizes[best].height;
324 scale = (float)wishedHeight / sizes[best].height;
343 class GlyphPack : BTNode
345 GlyphInfo glyphs[256];
348 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
350 #if !defined(ECERE_NOTRUETYPE)
352 int maxWidth, maxHeight;
353 int cellWidth, cellHeight;
355 FontEntry fontEntry = null;
358 bool isGlyph = key & 0x80000000;
359 int curScript = (key & 0x7F000000) >> 24;
360 unichar testChar = 0;
366 case HB_Script_Arabic:
368 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
370 case HB_Script_Devanagari:
373 case 60: testChar = 'あ'; break;
374 case 61: testChar = 0x3400; break;
381 FT_Vector pen = { 0, 0 };
384 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
385 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
386 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
387 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
388 FT_Set_Transform( fontEntry.face, &matrix, &pen );
390 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
396 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
398 fontEntry = font.fontEntries[c];
402 FT_Vector pen = { 0, 0 };
406 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
407 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
408 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
409 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
410 FT_Set_Transform(fontEntry.face, &matrix, &pen);
412 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
413 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
416 if(!fontEntry.face->units_per_EM)
417 font.ascent = (int)((double)fontEntry.face->ascender);
419 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
422 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
423 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
424 fontEntry.hbFont.x_scale = fontEntry.face->size->metrics.x_scale;
425 fontEntry.hbFont.y_scale = fontEntry.face->size->metrics.y_scale;
430 for(c = 0; c < 128; c++)
435 uint glyph = (key | c) & 0xFFFFFF;
436 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
438 fontEntry = font.fontEntries[entry];
439 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
441 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
443 //printf("%s: Accepted entry %d ", font.faceName, entry);
451 for(entry = startFontEntry; ; entry++)
454 fontEntry = font.fontEntries[entry];
455 if((glyph = FT_Get_Char_Index(fontEntry.face, (key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
457 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
462 scales[c] = fontEntry.scale;
463 faces[c] = fontEntry.face;
464 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
465 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
466 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
468 cellWidth = maxWidth;
469 cellHeight = maxHeight;
471 width = pow2i(maxWidth * 16);
472 height = pow2i(maxHeight * 8);
474 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
476 Bitmap bitmap = this.bitmap;
478 bitmap.transparent = true;
480 for(c = 0; c < 128; c++)
484 int sx = (c % 16) * cellWidth;
485 int sy = (c / 16) * cellHeight;
487 byte * picture = (byte *)bitmap.picture;
488 GlyphInfo * glyph = &glyphs[c];
489 FT_GlyphSlot slot = faces[c]->glyph;
490 double em_size = 1.0 * faces[c]->units_per_EM;
491 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
492 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
493 double ascender = faces[c]->ascender * y_scale;
494 int glyphNo = isGlyph ? ((key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], key | c);
496 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
498 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
502 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
504 glyph->left = slot->bitmap_left;
505 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
506 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
507 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
508 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
510 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
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;
513 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
515 //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));
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));
518 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
519 glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6)) / 2;
521 // 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);
522 xMax = x + slot->bitmap.width;
523 yMax = y + slot->bitmap.rows;
529 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
531 for(j = y, q = 0; j<yMax; j++)
533 for(p = 0, i = x; i<xMax; i++)
535 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
542 q += slot->bitmap.pitch;
545 max = numPixels ? (total / numPixels) : 1;
547 for(j = y, q = 0; j<yMax; j++)
550 for(p = 0, i = x; i<xMax; i++)
552 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
554 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
556 if(!bit) { bit = 0x80; p++; }
560 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
561 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
564 q += slot->bitmap.pitch;
569 glyph->w = slot->bitmap.width;
570 glyph->h = slot->bitmap.rows;
571 glyph->glyphNo = glyphNo;
572 glyph->bx = faces[c]->glyph->metrics.horiBearingX;
573 glyph->by = faces[c]->glyph->metrics.horiBearingY;
574 glyph->scale = scales[c];
576 glyph->ax = slot->advance.x;
577 glyph->ay = slot->advance.y + (64 - slot->advance.y % 64);
584 for(c = 0; c<256; c++)
585 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
586 bitmap.pixelFormat = pixelFormat8;
589 //strcpy(fileName, faceName);
591 strcat(fileName, "Bold");
593 sprintf(fileName, "font%d", fid++);
594 ChangeExtension(fileName, "pcx", fileName);
596 bitmap.Save(fileName, null, 0);
597 bitmap.pixelFormat = pixelFormatAlpha;
601 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
603 displaySystem.Lock();
604 #if defined(__WIN32__)
605 // Is this check still required?
606 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
607 displaySystem.driver == class(Direct3D8DisplayDriver) ||
608 displaySystem.driver == class(Direct3D9DisplayDriver))
610 bitmap.MakeDD(displaySystem);
611 displaySystem.Unlock();
618 #if !defined(ECERE_NOTRUETYPE)
619 static HB_ShaperItem shaper_item;
621 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
623 static uint maxGlyphs = 0;
624 HB_Glyph * glyphs = shaper_item.glyphs;
626 shaper_item.kerning_applied = 0;
627 shaper_item.string = string;
628 shaper_item.stringLength = len;
629 shaper_item.item.script = script;
630 shaper_item.item.pos = 0;
631 shaper_item.item.length = shaper_item.stringLength;
632 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
633 shaper_item.item.bidiLevel = 1;
635 shaper_item.item.bidiLevel = 0;
636 shaper_item.shaperFlags = 0;
637 shaper_item.font = &entry.hbFont;
638 shaper_item.face = entry.hbFace;
639 shaper_item.num_glyphs = shaper_item.item.length;
640 shaper_item.glyphIndicesPresent = 0;
641 shaper_item.initialGlyphCount = 0;
642 shaper_item.num_glyphs = 0;
643 shaper_item.glyphs = null;
645 while(!HB_ShapeItem(&shaper_item))
647 if(shaper_item.num_glyphs > maxGlyphs)
649 maxGlyphs = shaper_item.num_glyphs;
650 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
651 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
652 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
653 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
654 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
658 shaper_item.glyphs = glyphs;
659 shaper_item.num_glyphs = maxGlyphs;
663 *numGlyphs = shaper_item.num_glyphs;
664 *rightToLeft = shaper_item.item.bidiLevel % 2;
665 return shaper_item.glyphs;
669 delete shaper_item.glyphs;
670 delete shaper_item.attributes;
671 delete shaper_item.advances;
672 delete shaper_item.offsets;
673 delete shaper_item.log_clusters;
677 public class Font : struct
679 BinaryTree glyphPacks { };
680 GlyphPack asciiPack { };
681 #if !defined(ECERE_NOTRUETYPE)
682 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
689 DisplaySystem displaySystem;
695 #if !defined(ECERE_NOTRUETYPE)
697 while((pack = (GlyphPack)glyphPacks.root))
699 glyphPacks.Remove(pack);
706 public class LFBDisplay : struct
710 byte rgbLookup[32768];
711 byte lightTable[256][LIGHTSTEPS];
715 void (* displayCallback)(Display display, Box updateBox);
718 public class LFBSystem : struct
722 ColorAlpha * palette;
723 byte rgbLookup[32768];
730 ColorAlpha * palette = GetDefaultPalette();
731 for(c = 16; c < 232; c++)
733 Color555 color = palette[c].color;
734 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
735 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
736 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
737 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
739 for(c = 232; c < 246; c++)
741 Color555 color = palette[c].color;
742 defaultRGBLookup[color] = (byte)c;
745 for(c = 246; c < 256; c++)
747 Color555 color = palette[c].color;
748 defaultRGBLookup[color] = (byte)c;
750 for(c = 0; c < 16; c++)
752 Color555 color = palette[c].color;
753 defaultRGBLookup[color] = (byte)c;
756 for(c = 0; c<32768; c++)
758 Color color = (Color)(Color555)c;
759 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
760 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
768 public class LFBSurface : struct
771 // For compatibility with 3D drivers as well
779 // Drawing attributes
780 uint foreground, background;
781 ColorAlpha foregroundRgb;
784 byte * paletteShades;
789 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
791 if(recordA->zMin > recordB->zMin)
793 else if(recordA->zMin < recordB->zMin)
795 else if(recordA > recordB)
797 else if(recordA < recordB)
804 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
807 char fileName[MAX_FILENAME];
812 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
814 //if(fontType == TRUETYPE_FONTTYPE)
816 FontData * fontData = (FontData *) lParam;
817 char * fileName = (char *)lParam;
819 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
820 int italic = (fontData->flags.italic) ? 1 : 0;
821 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
823 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
824 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
829 char entryName[1024];
830 char fontFileName[1024];
833 int sizeFileName = 1024;
835 if(RegEnumValue(key, value++, entryName, (PDWORD)&size, null, (PDWORD)&type, (LPBYTE)fontFileName, (PDWORD)&sizeFileName) != ERROR_SUCCESS)
837 if((occurence = SearchString((char *)entryName, 0, (char *)font->elfFullName, false, false)))
840 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
842 char ch = entryName[c];
843 if(ch == '&') { c = -1; break; }
844 else if(ch != ' ') break;
847 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
849 char ch = entryName[c];
850 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
851 else if(ch != ' ') break;
854 if(atoi(entryName + c))
858 strcpy(fileName, fontFileName);
872 static int utf16BufferSize = 0;
873 static uint16 * utf16 = null;
875 public class LFBDisplayDriver : DisplayDriver
877 class_property(name) = "LFB";
879 bool CreateDisplaySystem(DisplaySystem displaySystem)
881 displaySystem.flags.memBackBuffer = true;
882 // displaySystem.pixelFormat = pixelFormat888;
886 void DestroyDisplaySystem(DisplaySystem displaySystem)
890 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
892 delete bitmap.picture;
893 if(bitmap.allocatePalette)
894 delete bitmap.palette;
897 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
902 switch(GetColorDepthShifts(format))
904 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
905 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
906 case 2: stride = width; break;
909 bitmap.stride = stride;
910 bitmap.width = width;
911 bitmap.height = height;
912 bitmap.size = (uint32) stride * (uint32)height;
913 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
914 bitmap.pixelFormat = format;
915 bitmap.transparent = false;
917 surface.box.left = surface.box.top = 0;
918 surface.box.right = width - 1;
919 surface.box.bottom = height - 1;
921 bitmap.picture = new0 byte[bitmap.sizeBytes];
924 bitmap.allocatePalette = allocatePalette;
927 bitmap.palette = new ColorAlpha[256];
930 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
936 bitmap.palette = GetDefaultPalette();
941 FreeBitmap(displaySystem, bitmap);
945 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
948 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
952 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
954 if(src.transparent && src.pixelFormat == pixelFormat888)
958 DWORD * picture = (DWORD *)src.picture;
960 for(c = 0; c<src.size; c++, picture++)
962 if(*picture & 0xFFFFFF)
963 *picture = *picture | 0xFF000000;
965 *picture = *picture & 0xFFFFFF;
974 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
976 if(format == pixelFormat8)
979 bitmap.palette = palette;
980 else if(lfbSystem && lfbSystem.palette)
981 bitmap.palette = lfbSystem.palette;
983 bitmap.palette = src.palette;
986 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
988 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
989 bitmap.transparent = src.transparent;
990 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
992 if(src.palette != bitmap.palette)
994 if(src.allocatePalette)
996 src.allocatePalette = false;
998 src.picture = bitmap.picture;
999 src.palette = bitmap.palette;
1000 src.stride = bitmap.stride;
1001 src.size = bitmap.size;
1002 src.pixelFormat = bitmap.pixelFormat;
1007 bitmap.palette = null;
1008 bitmap.picture = null;
1016 void DestroyDisplay(Display display)
1018 LFBDisplay lfbDisplay = display.driverData;
1019 delete lfbDisplay.bitmap.palette;
1022 bool CreateDisplay(Display display)
1024 bool result = false;
1025 LFBDisplay lfbDisplay = display.driverData;
1028 lfbDisplay = display.driverData = LFBDisplay { };
1029 lfbDisplay.selfManaged = true;
1030 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1033 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1035 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1041 bool DisplaySize(Display display, int width, int height)
1043 LFBDisplay lfbDisplay = display.driverData;
1044 //display.width = width;
1045 //display.height = height;
1046 lfbDisplay.bitmap.width = width;
1047 lfbDisplay.bitmap.height = height;
1049 lfbDisplay.updateBox.left = display.width;
1050 lfbDisplay.updateBox.top = display.height;
1051 lfbDisplay.updateBox.right = 0;
1052 lfbDisplay.updateBox.bottom = 0;
1055 if(lfbDisplay.selfManaged)
1057 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1058 lfbDisplay.bitmap.stride = width;
1060 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1064 void DisplayPosition(Display display, int x, int y)
1066 LFBDisplay lfbDisplay = display.driverData;
1071 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1073 LFBDisplay lfbDisplay = display.driverData;
1080 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1081 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1082 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1085 for(c = 0; c<32768; c++)
1086 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1088 for(c=0; c<256; c++)
1091 for(i=0; i<LIGHTSTEPS; i++)
1093 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1094 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1095 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1096 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1100 if(lfbDisplay.bitmap.palette)
1101 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1104 void Update(Display display, Box updateBox)
1106 LFBDisplay lfbDisplay = display.driverData;
1107 if(lfbDisplay.displayCallback)
1109 if(updateBox == null)
1111 Box box { 0,0, display.width,display.height };
1112 lfbDisplay.displayCallback(display, box);
1115 lfbDisplay.displayCallback(display, updateBox);
1119 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1121 if(bitmap.pixelFormat != pixelFormatAlpha)
1123 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1125 FreeBitmap(displaySystem, bitmap);
1132 void ReleaseSurface(Display display, Surface surface)
1134 LFBSurface lfbSurface = surface.driverData;
1136 surface.driverData = null;
1139 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1141 LFBDisplay lfbDisplay = display.driverData;
1142 LFBSurface lfbSurface = surface.driverData;
1145 lfbSurface = surface.driverData = LFBSurface { };
1148 lfbSurface.bitmap = lfbDisplay.bitmap;
1150 surface.offset.x = x;
1151 surface.offset.y = y;
1153 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1155 surface.offset.x /= textCellW;
1156 surface.offset.y /= textCellH;
1157 surface.box.left /= textCellW;
1158 surface.box.top /= textCellH;
1159 surface.box.right /= textCellW;
1160 surface.box.bottom /= textCellH;
1164 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1165 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1166 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1167 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1170 surface.unclippedBox = surface.box;
1171 lfbSurface.drawingChar = 219;
1175 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1177 bool result = false;
1178 LFBSurface lfbSurface = surface.driverData;
1179 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1181 lfbSurface.bitmap = bitmap;
1183 surface.offset.x = x;
1184 surface.offset.y = y;
1186 if(bitmap.pixelFormat == pixelFormatText)
1188 surface.offset.x /= textCellW;
1189 surface.offset.y /= textCellH;
1190 surface.box.left /= textCellW;
1191 surface.box.top /= textCellH;
1192 surface.box.right /= textCellW;
1193 surface.box.bottom /= textCellH;
1196 surface.unclippedBox = *&surface.box;
1197 lfbSurface.drawingChar = 219;
1204 void Clip(Display display, Surface surface, Box clip)
1206 LFBSurface lfbSurface = surface.driverData;
1211 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1213 box.left /= textCellW;
1214 box.top /= textCellH;
1215 box.right /= textCellW;
1216 box.bottom /= textCellH;
1218 box.Clip(surface.unclippedBox);
1222 surface.box = surface.unclippedBox;
1225 void SetForeground(Display display, Surface surface, ColorAlpha color)
1227 LFBDisplay lfbDisplay = display ? display.driverData : null;
1228 LFBSurface lfbSurface = surface.driverData;
1230 if(display) color = color /*& 0xFFFFFF*/;
1231 lfbSurface.foregroundRgb = color;
1233 if(lfbSurface.font && lfbDisplay)
1235 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1236 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1239 switch(lfbSurface.bitmap.pixelFormat)
1243 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1245 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1247 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1248 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1249 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1250 case pixelFormat888: lfbSurface.foreground = color; break;
1251 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1252 case pixelFormatText:
1254 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1256 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1261 void SetBackground(Display display, Surface surface, ColorAlpha color)
1263 LFBDisplay lfbDisplay = display ? display.driverData : null;
1264 LFBSurface lfbSurface = surface.driverData;
1265 color = color /*& 0xFFFFFF*/;
1266 switch(lfbSurface.bitmap.pixelFormat)
1270 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1272 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1274 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1275 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1276 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1277 case pixelFormat888: lfbSurface.background = color; break;
1278 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1279 case pixelFormatText:
1281 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1283 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1288 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1290 LFBSurface lfbSurface = surface.driverData;
1291 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1296 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1298 x += surface.offset.x;
1299 y += surface.offset.y;
1300 if(lfbSurface.bitmap.picture)
1302 switch(lfbSurface.bitmap.pixelFormat)
1304 case pixelFormatText:
1306 if(!lfbSurface.bitmap.palette) return 0;
1307 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1308 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1309 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1310 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1311 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1318 void PutPixel(Display display, Surface surface,int x,int y)
1320 LFBSurface lfbSurface = surface.driverData;
1321 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1326 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1328 x += surface.offset.x;
1329 y += surface.offset.y;
1330 if(lfbSurface.bitmap.picture)
1332 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1335 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1338 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1341 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1342 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1349 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1351 LFBSurface lfbSurface = surface.driverData;
1357 uint color = lfbSurface.foreground;
1358 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1359 bool invert = false;
1360 if(!lfbSurface.bitmap.picture) return;
1361 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1367 if(surface.textOpacity)
1368 color |= lfbSurface.background;
1369 color |= lfbSurface.drawingChar;
1373 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1375 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1376 if((x1>surface.box.right)||(x2<surface.box.left))return;
1377 if(x1<surface.box.left)x1=surface.box.left;
1378 if(x2>surface.box.right)x2=surface.box.right;
1382 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1383 if(stipple != 0xFFFF)
1386 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1389 for(x=x1; x<=x2; x++, offset++)
1391 if(stipple & 0x8000)
1392 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1394 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1396 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1400 for(x=x1; x<=x2; x++, offset++)
1402 if(stipple & 0x8000)
1403 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1405 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1407 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1411 for(x=x1; x<=x2; x++, offset++)
1413 if(stipple & 0x8000)
1414 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1416 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1418 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1425 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1427 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1429 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1430 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1431 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1437 for(x = x1; x <= x2; x++, offset++)
1439 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1440 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1449 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1451 if((x1>surface.box.right)||(x1<surface.box.left))return;
1452 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1453 if(y1<surface.box.top)y1=surface.box.top;
1454 if(y2>surface.box.bottom)y2=surface.box.bottom;
1456 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1457 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1460 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1462 if(stipple & 0x8000)
1463 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1465 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1467 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1471 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1473 if(stipple & 0x8000)
1475 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1476 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1479 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1480 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1484 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1486 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1490 if(stipple != 0xFFFF)
1492 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1494 if(stipple & 0x8000)
1495 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1497 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1499 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1504 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1505 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1514 if(x1 < surface.box.left)
1516 if(x2 < surface.box.left)
1518 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1519 x1 = surface.box.left;
1521 if(x2 > surface.box.right)
1523 if(x1 > surface.box.right)
1525 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1526 x2 = surface.box.right;
1530 if(y1 < surface.box.top)
1532 if(y2 < surface.box.top)
1534 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1535 y1 = surface.box.top;
1537 if(y2 > surface.box.bottom)
1539 if(y1 > surface.box.bottom)
1541 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1542 y2 = surface.box.bottom;
1547 if(y1 > surface.box.bottom)
1549 if(y2 > surface.box.bottom)
1551 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1552 y1 = surface.box.bottom;
1554 if(y2 < surface.box.top)
1556 if(y1 < surface.box.top)
1558 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1559 y2 = surface.box.top;
1565 if(x1 > surface.box.right)
1567 if(x2 > surface.box.right)
1569 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1570 x1 = surface.box.right;
1572 if(x2 < surface.box.left)
1574 if(x1 < surface.box.left)
1576 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1577 x2 = surface.box.left;
1581 if(y1 < surface.box.top)
1583 if(y2 < surface.box.top)
1585 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1586 y1 = surface.box.top;
1588 if(y2 > surface.box.bottom)
1590 if(y1 > surface.box.bottom)
1592 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1593 y2 = surface.box.bottom;
1598 if(y1 > surface.box.bottom)
1600 if(y2 > surface.box.bottom)
1602 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1603 y1 = surface.box.bottom;
1605 if(y2 < surface.box.top)
1607 if(y1 < surface.box.top)
1609 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1610 y2 = surface.box.top;
1628 yu=-(int)lfbSurface.bitmap.stride;
1631 yu=lfbSurface.bitmap.stride;
1633 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1639 for(i=0; i<=length; i++)
1641 if(stipple & 0x8000)
1642 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1644 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1645 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1646 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1655 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1661 for(i=0; i<=length; i++)
1663 if(stipple & 0x8000)
1664 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1666 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1667 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1668 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1682 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1684 DrawLine(display, surface,x1,y1,x2,y1);
1685 DrawLine(display, surface,x2,y1,x2,y2);
1686 DrawLine(display, surface,x2,y2,x1,y2);
1687 DrawLine(display, surface,x1,y2,x1,y1);
1690 #if !defined(__GNUC__)
1692 void memset_32_aligned(void *buf, int val, int dwords)
1697 *((uint32 *)(buf)) = val;
1698 buf = ((uint32 *)(buf))+1;
1724 if (dwords & 1) *((int*)(buf)) = val;
1730 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1734 if(((uint32)buf) & 0x7F)
1736 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1762 sub edx,ebx ; edx holds # of overflow bytes
1781 movdqa [edi+16],xmm0
1782 movdqa [edi+32],xmm0
1783 movdqa [edi+48],xmm0
1784 movdqa [edi+64],xmm0
1785 movdqa [edi+80],xmm0
1786 movdqa [edi+96],xmm0
1787 movdqa [edi+112],xmm0
1811 void memset_32(void *buf, uint32 val, uint32 dwords)
1814 if ((uint32)(buf) & 3)
1819 if (((uint32)(buf) & 1))
1821 *(byte *)(buf) = (byte)(val&0xFF);
1822 buf = ((byte *)(buf))+1;
1823 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1826 if (((uint32)(buf) & 2))
1828 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1829 buf = ((uint16 *)(buf))+1;
1830 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1834 memset_32_aligned(buf,val,dwords);
1839 *(byte *)(buf) = (byte)(val&0xFF);
1843 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1844 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1851 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1853 LFBSurface lfbSurface = surface.driverData;
1854 uint32 color = lfbSurface.background;
1856 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1858 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1864 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1866 if(x1<surface.box.left) x1=surface.box.left;
1867 if(x2>surface.box.right) x2=surface.box.right;
1868 if(y1<surface.box.top) y1=surface.box.top;
1869 if(y2>surface.box.bottom) y2=surface.box.bottom;
1871 if(x2>=x1 && y2>=y1)
1879 x1 += surface.offset.x;
1880 x2 += surface.offset.x;
1881 y1 += surface.offset.y;
1882 y2 += surface.offset.y;
1883 if(lfbSurface.bitmap.picture)
1885 if(!surface.writeColor)
1887 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1888 for(y = y1; y<= y2; y++)
1891 for(c = 0; c < w; c++, picture++)
1893 picture->a = (byte)((color & 0xFF000000) >> 24);
1894 picture += lfbSurface.bitmap.stride - w;
1899 if(surface.background.a == 255 || lfbSurface.clearing)
1901 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1904 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1905 for(y = y1; y<= y2; y++)
1907 FillBytes(theOffset,(byte)color,w);
1908 theOffset += lfbSurface.bitmap.stride;
1912 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1913 for(y = y1; y<= y2; y++)
1915 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1916 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1920 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1921 for(y = y1; y<= y2; y++)
1923 #if defined(__GNUC__)
1924 FillBytesBy4((uint32 *) theOffset,color,w);
1926 memset_32((uint32 *) theOffset,color,w);
1928 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1934 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1935 //memset_32((uint32 *) theOffset,color,w);
1971 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1974 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1975 for(y = y1; y<= y2; y++)
1977 // TODO: IMPLEMENT THIS
1978 FillBytes(theOffset,(byte)color,w);
1979 theOffset += lfbSurface.bitmap.stride;
1984 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1985 ColorAlpha c = surface.background;
1990 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1992 for(y = y1; y <= y2; y++)
1995 for(c = 0; c < w; c++, dest++)
1998 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
1999 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2000 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2002 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2003 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2004 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2006 if(r > 255) r = 255;
2007 if(g > 255) g = 255;
2008 if(b > 255) b = 255;
2010 destColor = { (byte)r, (byte)g, (byte)b };
2012 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2013 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2014 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2017 dest += (lfbSurface.bitmap.stride - w);
2023 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2024 AlphaWriteMode alphaWrite = surface.alphaWrite;
2025 ColorAlpha c = surface.background;
2030 for(y = y1; y <= y2; y++)
2033 for(c = 0; c < w; c++, dest++)
2035 int dr = dest->color.r;
2036 int dg = dest->color.g;
2037 int db = dest->color.b;
2038 int r = a * cr / 255 + ((255 - a) * dr / 255);
2039 int g = a * cg / 255 + ((255 - a) * dg / 255);
2040 int b = a * cb / 255 + ((255 - a) * db / 255);
2042 if(r > 255) r = 255;
2043 if(g > 255) g = 255;
2044 if(b > 255) b = 255;
2045 dest->color = { (byte)r, (byte)g, (byte)b };
2047 if(alphaWrite == blend)
2049 int ca = (int)(a + ((255 - a) * dest->a / 255));
2050 if(ca > 255) ca = 255;
2056 dest += (lfbSurface.bitmap.stride - w);
2065 void Clear(Display display, Surface surface, ClearType type)
2067 LFBSurface lfbSurface = surface.driverData;
2069 lfbSurface.clearing = true;
2070 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2071 surface.box.left == 0 && surface.box.top == 0 &&
2072 surface.box.right == surface.width-1 &&
2073 surface.box.bottom == surface.height-1)
2075 uint32 color = /*0xFF000000 | */lfbSurface.background;
2076 if(type != depthBuffer)
2078 if(lfbSurface.bitmap.stride != surface.width)
2079 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2082 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2085 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2087 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2088 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2093 if((flags & CLEAR_Z) && zbuffer)
2094 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2099 if(type != depthBuffer)
2100 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2102 if((flags & CLEAR_Z))
2105 uint32 w = surface.box.right-surface.box.left+1;
2106 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2107 + surface.box.left+surface.offset.x;
2108 for(y = surface.box.top; y<= surface.box.bottom; y++)
2110 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2111 offset += DISPLAY.Width;
2116 lfbSurface.clearing = false;
2119 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2121 LFBSurface lfbSurface = surface.driverData;
2124 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2126 if(w < 0) { w = -w; flip = true; }
2128 //Clip against the edges of the source
2141 if(sx+w>src.width-1)
2142 w-=sx+w-(src.width-1)-1;
2143 if(sy+h>src.height-1)
2144 h-=sy+h-(src.height-1)-1;
2145 //Clip against the edges of the destination
2146 if(dx<surface.box.left)
2148 if(!flip) sx+=surface.box.left-dx;
2149 w-=surface.box.left-dx;
2150 dx=surface.box.left;
2152 if(dy<surface.box.top)
2154 sy+=surface.box.top-dy;
2155 h-=surface.box.top-dy;
2158 if((dx+w)>surface.box.right)
2160 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2161 w-=((uint32)(dx+w)-surface.box.right-1);
2163 if((dy+h)>surface.box.bottom)
2164 h-=((dy+h)-surface.box.bottom-1);
2168 dx += surface.offset.x;
2169 dy += surface.offset.y;
2171 if(lfbSurface.bitmap.picture)
2173 AlphaWriteMode alphaWrite = surface.alphaWrite;
2174 if(src.alphaBlend && surface.blend)
2177 if(src.pixelFormat == pixelFormatAlpha)
2179 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2181 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2182 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2183 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2184 for(y = 0; y < h; y++)
2186 for(x = 0; x < w; x++, picture++, source++)
2188 int a = *source * color.a;
2189 ColorAlpha dest = *picture;
2190 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2191 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2192 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2193 if(r > 255) r = 255;
2194 if(g > 255) g = 255;
2195 if(b > 255) b = 255;
2196 picture->color = { (byte)r, (byte)g, (byte)b };
2197 if(alphaWrite == blend)
2199 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2200 if(ca > 255) ca = 255;
2201 picture->a = (byte)ca;
2204 picture->a = (byte)(a / 255);
2206 picture += lfbSurface.bitmap.stride - w;
2207 source += src.stride - w;
2210 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2212 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2213 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2214 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2215 for(y = 0; y < h; y++)
2217 for(x = 0; x < w; x++, picture++, source++)
2219 int a = *source * color.a;
2220 Color dest = *picture;
2221 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2222 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2223 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2224 if(r > 255) r = 255;
2225 if(g > 255) g = 255;
2226 if(b > 255) b = 255;
2227 *picture = Color { (byte)r, (byte)g, (byte)b };
2229 picture += lfbSurface.bitmap.stride - w;
2230 source += src.stride - w;
2233 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2235 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2236 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2237 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2238 for(y = 0; y < h; y++)
2240 for(x = 0; x < w; x++, picture++, source++)
2242 int a = *source * color.a;
2243 Color dest = *picture;
2244 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2245 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2246 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2247 if(r > 255) r = 255;
2248 if(g > 255) g = 255;
2249 if(b > 255) b = 255;
2250 *picture = Color { (byte)r, (byte)g, (byte)b };
2252 picture += lfbSurface.bitmap.stride - w;
2253 source += src.stride - w;
2259 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2260 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2262 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2263 for(y = 0; y < h; y++)
2265 for(x = 0; x < w; x++, picture++, source++)
2267 ColorAlpha src = *source;
2268 ColorAlpha dest = *picture;
2269 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2270 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2271 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2272 if(r > 255) r = 255;
2273 if(g > 255) g = 255;
2274 if(b > 255) b = 255;
2275 picture->color = { (byte)r, (byte)g, (byte)b };
2276 if(alphaWrite == blend)
2278 int a = src.a + ((255 - src.a) * dest.a / 255);
2279 if(a > 255) a = 255;
2280 picture->a = (byte)a;
2285 picture += lfbSurface.bitmap.stride - w;
2286 source += src.stride - w;
2289 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2291 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2292 for(y = 0; y < h; y++)
2294 for(x = 0; x < w; x++, picture++, source++)
2296 ColorAlpha src = *source;
2297 Color565 dest = *picture;
2298 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2299 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2300 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2301 if(r > 255 * 31) r = 255 * 31;
2302 if(g > 255 * 63) g = 255 * 63;
2303 if(b > 255 * 31) b = 255 * 31;
2304 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2306 picture += lfbSurface.bitmap.stride - w;
2307 source += src.stride - w;
2310 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2312 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2313 for(y = 0; y < h; y++)
2315 for(x = 0; x < w; x++, picture++, source++)
2317 ColorAlpha psrc = *source;
2318 Color555 dest = *picture;
2319 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2320 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2321 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2322 if(r > 255 * 31) r = 255 * 31;
2323 if(g > 255 * 31) g = 255 * 31;
2324 if(b > 255 * 31) b = 255 * 31;
2325 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2327 picture += lfbSurface.bitmap.stride - w;
2328 source += src.stride - w;
2333 else if(src.paletteShades)
2334 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2335 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2336 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2337 else if(src.pixelFormat == pixelFormat8)
2338 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2342 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2344 bool result = false;
2345 LFBDisplay lfbDisplay = display.driverData;
2347 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2350 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2351 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2355 Surface surface = bitmap.GetSurface(0,0,null);
2358 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2359 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2360 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2368 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2370 LFBSurface lfbSurface = surface.driverData;
2373 float s2dw,s2dh,d2sw,d2sh;
2375 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2377 if(Sgn(w) != Sgn(sw))
2389 //Clip against the edges of the source
2392 dx+=(int)((0-sx) * s2dw);
2393 w-=(int)((0-sx) * s2dw);
2399 dy+=(int)((0-sy) * s2dh);
2400 h-=(int)((0-sy) * s2dh);
2405 if(sx+sw>src.width-1)
2407 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2408 sw-=sx+sw-(src.width-1)-1;
2410 if(sy+sh>(src.height-1))
2412 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2413 sh-=sy+sh-(src.height-1)-1;
2415 //Clip against the edges of the destination
2416 if(dx<surface.box.left)
2418 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2419 sw-=(int)((surface.box.left-dx)*d2sw);
2420 w-=surface.box.left-dx;
2421 dx=surface.box.left;
2423 if(dy<surface.box.top)
2425 sy+=(int)((surface.box.top-dy)*d2sh);
2426 sh-=(int)((surface.box.top-dy)*d2sh);
2427 h-=surface.box.top-dy;
2430 if((dx+w)>surface.box.right)
2432 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2433 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2434 w-=((dx+w)-surface.box.right-1);
2436 if((dy+h)>surface.box.bottom)
2438 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2439 h-=((dy+h)-surface.box.bottom-1);
2441 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2443 dx+=surface.offset.x;
2444 dy+=surface.offset.y;
2446 if(lfbSurface.bitmap.picture)
2448 AlphaWriteMode alphaWrite = surface.alphaWrite;
2449 if(src.alphaBlend && surface.blend)
2453 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2454 ColorAlpha * backsrc;
2455 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2456 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2457 if(flip < 0) source += sw-1;
2475 ColorAlpha src = *source;
2476 ColorAlpha dst = *dest;
2477 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2478 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2479 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2480 if(r > 255) r = 255;
2481 if(g > 255) g = 255;
2482 if(b > 255) b = 255;
2483 dest->color = { (byte)r, (byte)g, (byte)b };
2484 if(alphaWrite == blend)
2486 int a = src.a + ((255 - src.a) * dst.a / 255);
2487 if(a > 255) a = 255;
2500 source += addsource;
2503 else if(src.paletteShades)
2504 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2505 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2506 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2507 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2508 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2512 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2514 LFBSurface lfbSurface = surface.driverData;
2517 float s2dw,s2dh,d2sw,d2sh;
2519 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2521 if(Sgn(w) != Sgn(sw))
2533 //Clip against the edges of the source
2536 dx+=(int)((0-sx) * s2dw);
2537 w-=(int)((0-sx) * s2dw);
2543 dy+=(int)((0-sy) * s2dh);
2544 h-=(int)((0-sy) * s2dh);
2549 if(sx+sw>src.width-1)
2551 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2552 sw-=sx+sw-(src.width-1)-1;
2554 if(sy+sh>(src.height-1))
2556 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2557 sh-=sy+sh-(src.height-1)-1;
2559 //Clip against the edges of the destination
2560 if(dx<surface.box.left)
2562 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2563 sw-=(int)((surface.box.left-dx)*d2sw);
2564 w-=surface.box.left-dx;
2565 dx=surface.box.left;
2567 if(dy<surface.box.top)
2569 sy+=(int)((surface.box.top-dy)*d2sh);
2570 sh-=(int)((surface.box.top-dy)*d2sh);
2571 h-=surface.box.top-dy;
2574 if((dx+w)>surface.box.right)
2576 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2577 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2578 w-=((dx+w)-surface.box.right-1);
2580 if((dy+h)>surface.box.bottom)
2582 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2583 h-=((dy+h)-surface.box.bottom-1);
2585 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2587 dx+=surface.offset.x;
2588 dy+=surface.offset.y;
2590 if(lfbSurface.bitmap.picture)
2592 AlphaWriteMode alphaWrite = surface.alphaWrite;
2593 if(src.alphaBlend && surface.blend)
2597 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2598 ColorAlpha * backsrc;
2599 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2600 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2601 float scaleX = (float)sw / w;
2602 float scaleY = (float)sh / h;
2610 if (w > sw && h > sh)
2613 for (y = 0; y < h; y++)
2615 int y0 = y * sh / h;
2616 int y1 = Min(y0 + 1, sh - 1);
2617 float alpha = y * scaleY - y0;
2619 for(x = 0; x < w; x++, dest += 1)
2621 int x0 = x * sw / w;
2622 int x1 = Min(x0 + 1, sw - 1);
2623 float beta = x * scaleX - x0;
2625 ColorAlpha src00, src01, src10, src11;
2626 float a1,r1,g1,b1,a2,r2,g2,b2;
2628 src00 = source[y0 * src.stride + x0];
2629 src01 = source[y0 * src.stride + x1];
2630 src10 = source[y1 * src.stride + x0];
2631 src11 = source[y1 * src.stride + x1];
2632 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2633 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2634 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2635 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2636 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2637 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2638 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2639 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2640 a = a1 * (1.0f - alpha) + a2 * alpha;
2641 r = r1 * (1.0f - alpha) + r2 * alpha;
2642 g = g1 * (1.0f - alpha) + g2 * alpha;
2643 b = b1 * (1.0f - alpha) + b2 * alpha;
2645 ColorAlpha dst = *dest;
2646 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2647 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2648 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2649 if(cr > 255) cr = 255;
2650 if(cg > 255) cg = 255;
2651 if(cb > 255) cb = 255;
2652 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2654 if(alphaWrite == blend)
2656 int ca = (int)(a + ((255 - a) * dst.a / 255));
2657 if(ca > 255) ca = 255;
2670 for (y = 0; y < h; y++)
2672 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2673 int y1 = Min(y0 + 1, sh - 1);
2675 for (x = 0; x < w; x++, dest += 1)
2677 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2678 int x1 = Min(x0 + 1, sw - 1);
2679 float a = 0, r = 0, g = 0, b = 0;
2683 for (i = y0; i <= y1; i++)
2684 for (j = x0; j <= x1; j++)
2686 ColorAlpha pixel = source[i * src.stride + j];
2698 ColorAlpha src = *source;
2699 ColorAlpha dst = *dest;
2700 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2701 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2702 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2703 if(cr > 255) cr = 255;
2704 if(cg > 255) cg = 255;
2705 if(cb > 255) cb = 255;
2706 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2707 if(alphaWrite == blend)
2709 int ca = (int)(a + ((255 - a) * dst.a / 255));
2710 if(ca > 255) ca = 255;
2721 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2722 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2723 // Fail back on Stretch
2724 else if(src.paletteShades)
2725 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2726 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2727 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2728 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2729 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2733 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2735 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2738 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2740 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2743 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2745 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2748 void UnloadFont(DisplaySystem displaySystem, Font font)
2752 #if !defined(ECERE_NOTRUETYPE)
2754 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2756 FontEntry fontEntry = font.fontEntries[entry];
2762 loadedFonts.Remove(fontEntry);
2772 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2774 void * result = null;
2776 #if !defined(ECERE_NOTRUETYPE)
2777 Font font = Font { };
2780 char fileName[MAX_LOCATION];
2781 bool fakeItalic = flags.italic;
2782 char linkCfgPath[MAX_LOCATION];
2784 #if !defined(__WIN32__)
2787 char * ecereFonts = getenv("ECERE_FONTS");
2788 if(!ecereFonts) ecereFonts = "<:ecere>";
2789 #if !defined(__WIN32__)
2790 strcpy(linkCfgPath, ecereFonts);
2791 PathCat(linkCfgPath, "linking.cfg");
2792 linkCfg = FileOpen(linkCfgPath, read);
2794 strcpy(fileName, faceName);
2795 strcpy(font.faceName, faceName);
2797 font.displaySystem = displaySystem;
2799 if(!FileExists(fileName))
2801 strcpy(fileName, ecereFonts);
2802 PathCat(fileName, faceName);
2803 if(flags.bold && flags.italic) strcat(fileName, "bi");
2804 else if(flags.bold) strcat(fileName, "bd");
2805 else if(flags.italic) strcat(fileName, "i");
2806 strcat(fileName, ".ttf");
2810 if(flags.italic && !FileExists(fileName))
2812 strcpy(fileName, ecereFonts);
2813 PathCat(fileName, faceName);
2814 if(flags.bold) strcat(fileName, "bd");
2815 strcat(fileName, ".ttf");
2820 #if defined(__WIN32__)
2821 if(!FileExists(fileName))
2823 FontData fontData = { { 0 } };
2824 LOGFONT logFont = { 0 };
2829 logFont.lfCharSet = DEFAULT_CHARSET;
2830 strcpy(logFont.lfFaceName, faceName);
2831 fontData.flags = flags;
2833 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2834 if(!fontData.fileName[0] && flags.bold)
2836 fontData.forgive = true;
2837 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2839 if(!fontData.fileName[0])
2842 fontData.flags.italic = false;
2843 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2847 if(fontData.fileName[0])
2849 GetWindowsDirectory(fileName, MAX_LOCATION);
2850 PathCat(fileName, "fonts");
2851 PathCat(fileName, fontData.fileName);
2858 FcResult result = 0;
2859 FcPattern * pattern;
2860 FcPattern * matched;
2862 unichar testChar = 0;
2863 FcCharSet * charSet;
2865 fcConfig = FcInitLoadConfigAndFonts();
2867 charSet = FcCharSetCreate();
2869 if(!strcmpi(faceName, "Mangal"))
2875 FcCharSetAddChar(charSet, testChar);
2877 pattern = FcPatternBuild(null,
2878 //FC_SOURCE, FcTypeString, "freetype",
2879 FC_FAMILY, FcTypeString, faceName,
2880 //FC_SCALABLE, FcTypeBool, 1,
2881 FC_SIZE, FcTypeDouble, (double)size,
2882 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2883 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2884 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2886 FcDefaultSubstitute(pattern);
2887 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2889 matched = FcFontMatch (0, pattern, &result);
2890 // printf("Locating %s\n", faceName);
2893 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2894 //printf("Fontconfig returned %s\n", family);
2896 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2899 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2900 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2901 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2902 strcpy(fileName, fileName2);
2903 // size = (float)fontSize;
2905 //printf("Matched to %s, %f\n", fileName, size);
2909 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2911 if(pattern) FcPatternDestroy(pattern);
2912 if(matched) FcPatternDestroy(matched);
2913 if(charSet) FcCharSetDestroy(charSet);
2918 if(!FileExists(fileName))
2919 ChangeExtension(fileName, "otf", fileName);
2920 if(!FileExists(fileName))
2921 ChangeExtension(fileName, "ttc", fileName);
2923 //if(FileExists(fileName))
2926 char links[1024] = "";
2928 #if defined(__WIN32__)
2931 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2932 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2937 RegQueryValueEx(key, faceName, null, (LPDWORD)&type, (LPBYTE)links, (LPDWORD)&size);
2938 memset(links + size, 0, 1024 - size);
2946 while(linkCfg.GetLine(line, sizeof(line)))
2948 int len = strlen(faceName);
2949 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2951 while(linkCfg.GetLine(line, sizeof(line)))
2953 TrimLSpaces(line, line);
2954 if(!line[0] || line[0] == '[')
2957 memcpy(links + linksPos, line, len);
2959 links[linksPos] = 0;
2967 while(entry < MAX_FONT_LINK_ENTRIES)
2969 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2972 File file = FileOpen/*Buffered*/(fileName, read);
2975 FileSize fileSize = file.GetSize();
2976 FT_Open_Args args = { 0 };
2977 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
2978 FT_Stream stream = new0 FT_StreamRec[1];
2981 FT_Init_FreeType( &ftLibrary );
2983 fontEntry = FontEntry { key = (uint)CopyString(fileName) };
2984 fontEntry.stream = stream;
2987 fontEntry.buffer = new byte[fileSize];
2988 file.Read(fontEntry.buffer, 1, fileSize);
2991 //args.num_params = 1;
2992 args.params = ¶m;
2994 stream->size = fileSize;
2995 stream->descriptor.pointer = file;
2996 stream->read = FT_stream_load;
2997 stream->close = FT_stream_close;
2999 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3000 args.stream = stream;
3001 //args.pathname = fileName;
3002 //args.memory_base = fontEntry.buffer;
3003 //args.memory_size = fileSize;
3005 // printf("Opening: %s\n", fileName);
3006 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3011 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3012 fontEntry.hbFont.klass = &hb_fontClass;
3013 fontEntry.hbFont.userData = fontEntry; //.face;
3016 loadedFonts.Add(fontEntry);
3021 // printf("Error opening font %s\n", fileName);
3030 FT_Vector pen = { 0, 0 };
3033 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3034 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3035 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3036 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3037 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3039 FaceSetCharSize(fontEntry.face, size);
3040 font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3041 // printf("Font height is %d\n", font.height);
3042 font.fakeItalic = fakeItalic;
3046 font.fontEntries[entry++] = fontEntry;
3053 char fontName[1024];
3054 if(!links[linksPos]) break;
3055 for(c = 0; (ch = links[linksPos + c]); c++)
3058 if(ch == ',') break;
3061 if(fontName[0] || ch == ',')
3063 #if defined(__WIN32__)
3064 GetWindowsDirectory(fileName, MAX_LOCATION);
3065 PathCat(fileName, "fonts");
3066 PathCat(fileName, fontName);
3067 #elif defined(ECERE_NOFONTCONFIG)
3068 if(getenv("ECERE_FONTS"))
3070 strcpy(fileName, ecereFonts);
3071 PathCat(fileName, fontName);
3077 FcResult result = 0;
3078 FcPattern * pattern;
3079 FcPattern * matched;
3081 pattern = FcPatternBuild(null,
3082 //FC_SOURCE, FcTypeString, "freetype",
3083 //FC_SCALABLE, FcTypeBool, 1,
3084 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3085 FC_SIZE, FcTypeDouble, (double)size,
3086 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3087 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3089 FcDefaultSubstitute(pattern);
3090 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3092 //printf("Locating %s\n", links + linksPos + c + 1);
3093 matched = FcFontMatch (0, pattern, &result);
3096 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3097 // printf("Fontconfig returned %s\n", family);
3099 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3100 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3103 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3104 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3105 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3106 strcpy(fileName, fileName2);
3107 //size = (float)fontSize;
3108 // printf("Matched to %s, %f\n", fileName, size);
3112 // 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);
3114 if(pattern) FcPatternDestroy(pattern);
3115 if(matched) FcPatternDestroy(matched);
3122 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3129 UnloadFont(displaySystem, font);
3132 font.asciiPack.Render(font, 0, displaySystem);
3134 #if !defined(__WIN32__)
3142 #if !defined(ECERE_NOTRUETYPE)
3143 void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
3144 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3145 Surface surface, Display display, int * x, int y)
3147 if(font && font.fontEntries && font.fontEntries[0])
3149 int previousGlyph = 0;
3150 FT_Face previousFace = 0;
3151 int c, nb, glyphIndex = 0;
3152 unichar lastPack = 0;
3153 GlyphPack pack = font.asciiPack;
3157 bool rightToLeft = false;
3158 int fontEntryNum = 0;
3159 int glyphScript = 0;
3160 FontEntry curFontEntry;
3162 pack.bitmap.alphaBlend = true;
3164 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3168 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3170 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3171 rightToLeft ? glyphIndex-- : glyphIndex++;
3175 HB_Script curScript = HB_Script_Common;
3176 byte * scriptStart = text + c;
3177 unichar nonASCIIch = 0;
3180 unichar testChar = 0;
3181 char * testLang = null;
3185 HB_Script script = HB_Script_Common;
3186 ch = UTF8GetChar((char *)text + c, &nb);
3187 if(ch > 127) nonASCIIch = ch;
3189 if(ch == 32 && curScript)
3196 for(a = c + 1; a < c + len; a++)
3204 unichar ahead = UTF8GetChar((char *)text + a, &nb);
3205 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3213 script = HB_Script_Common;
3214 else if(ch <= 0x11FF)
3218 case 0x300: script = HB_Script_Greek; break;
3219 case 0x400: script = HB_Script_Cyrillic; break;
3220 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3221 case 0x600: script = HB_Script_Arabic; break;
3222 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3223 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3224 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3225 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3226 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3227 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3228 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3229 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3230 case 0xF00: script = HB_Script_Tibetan; break;
3231 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3232 case 0x1100: script = HB_Script_Hangul; break;
3235 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3236 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3237 script = HB_Script_Hangul;
3238 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3239 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3240 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3241 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3242 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3243 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3244 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3245 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3246 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3249 if(!script || (script != curScript))
3257 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3258 if(!script) { c += nb; break; }
3265 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3267 rightToLeft = false;
3269 theCurrentScript = 0;
3273 int len = c - (int)(scriptStart - text);
3274 int max = len * 2 + 1;
3275 if(max > utf16BufferSize)
3277 utf16 = renew utf16 uint16[max];
3278 utf16BufferSize = max;
3280 wc = UTF8toUTF16BufferLen((char *)scriptStart, utf16, max, len);
3281 theCurrentScript = glyphScript = curScript;
3285 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3286 //printf("Arabic ");
3288 case HB_Script_Devanagari: testChar = 0x905; testLang = "sa";
3289 //printf("Devanagari ");
3291 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3292 //printf("Hebrew ");
3297 case 60: testChar = 'あ'; break;
3298 case 61: testChar = 0x3400; break; //'愛'; break;
3304 // printf("Testing for char %x\n", testChar);
3305 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3307 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3309 /*if(font.fontEntries[fontEntryNum])
3310 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3314 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3316 #if !defined(__WIN32__)
3318 double fontSize = font.size;
3319 FcResult result = 0;
3320 FcPattern * pattern;
3321 FcPattern * matched;
3322 FcCharSet * charSet;
3324 FontEntry fontEntry;
3325 char * fileName = null;
3326 bool fakeItalic = false;
3327 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3328 if(!font.fontEntries[fontEntryNum])
3330 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3334 #if !defined(__WIN32__)
3336 charSet = FcCharSetCreate();
3337 FcCharSetAddChar(charSet, testChar);
3338 //printf("Loading with char %x\n", testChar);
3340 pattern = FcPatternBuild(null,
3341 //FC_SOURCE, FcTypeString, "freetype",
3342 //FC_SCALABLE, FcTypeBool, 1,
3343 FC_FAMILY, FcTypeString, font.faceName,
3344 FC_SIZE, FcTypeDouble, (double)font.size,
3345 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3346 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3347 FC_CHARSET,FcTypeCharSet, charSet,
3348 testLang ? FC_LANG : 0, FcTypeString,testLang,
3350 FcDefaultSubstitute(pattern);
3351 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3353 //printf("Locating %s for script %d\n", font.faceName, curScript);
3354 matched = FcFontMatch (0, pattern, &result);
3357 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3358 //printf("Fontconfig returned %s\n", family);
3360 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3362 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3363 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3364 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3365 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3369 //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);
3374 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3377 File file = FileOpen(fileName, read);
3380 FileSize fileSize = file.GetSize();
3381 FT_Open_Args args = { 0 };
3382 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3383 FT_Stream stream = new0 FT_StreamRec[1];
3386 FT_Init_FreeType( &ftLibrary );
3388 fontEntry = FontEntry { key = (uint)CopyString(fileName) };
3389 fontEntry.stream = stream;
3391 //args.num_params = 1;
3392 args.params = ¶m;
3394 stream->size = fileSize;
3395 stream->descriptor.pointer = file;
3396 stream->read = FT_stream_load;
3397 stream->close = FT_stream_close;
3399 args.flags = FT_OPEN_STREAM;
3400 args.stream = stream;
3401 //args.pathname = fileName;
3402 //args.memory_base = fontEntry.buffer;
3403 //args.memory_size = fileSize;
3405 // printf("Opening: %s\n", fileName);
3406 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3411 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3412 fontEntry.hbFont.klass = &hb_fontClass;
3413 fontEntry.hbFont.userData = fontEntry; //.face;
3416 loadedFonts.Add(fontEntry);
3421 // printf("Error opening font %s\n", fileName);
3427 FaceSetCharSize(fontEntry.face, font.size);
3429 font.fontEntries[fontEntryNum] = fontEntry;
3433 if(pattern) FcPatternDestroy(pattern);
3434 if(matched) FcPatternDestroy(matched);
3435 if(charSet) FcCharSetDestroy(charSet);
3438 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3439 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3441 font.fontEntries[fontEntryNum].font = font;
3442 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3446 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3447 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3448 rightToLeft ? glyphIndex-- : glyphIndex++;
3452 curFontEntry = font.fontEntries[fontEntryNum];
3454 packNo = glyphNo & 0xFFFFFF80;
3456 if(packNo != lastPack)
3459 pack = font.asciiPack;
3462 pack = (GlyphPack)font.glyphPacks.Find(packNo);
3465 pack = GlyphPack { key = packNo };
3466 font.glyphPacks.Add(pack);
3467 pack.Render(font, fontEntryNum, displaySystem);
3470 pack.bitmap.alphaBlend = true;
3475 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3476 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3478 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3479 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3480 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3484 if(previousGlyph && curFontEntry.face == previousFace)
3486 FT_Vector delta = { 0, 0 };
3487 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3488 if(delta.x < 0) delta.x += (-delta.x) % 64;
3489 else if(delta.x) delta.x += 64 - (delta.x % 64);
3490 *x += delta.x * glyph->scale;
3492 previousGlyph = glyph->glyphNo;
3493 previousFace = curFontEntry.face;
3496 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3499 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3505 LFBSurface lfbSurface = surface.driverData;
3506 lfbSurface.xOffset = 0;
3511 void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3513 if(displaySystem && displaySystem.flags.text && len)
3518 *width = num * textCellW;
3520 if(height) *height = textCellH;
3522 else if(font && len)
3527 #if !defined(ECERE_NOTRUETYPE)
3528 ProcessString(font, displaySystem, text, len, null, null, null, &w, 0);
3530 //*width = (w + 64 - w % 64) >> 6;
3534 *height = font.height;
3538 if(width) *width = 0;
3539 if(height) *height = 0;
3543 #if !defined(ECERE_NOTRUETYPE)
3544 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3546 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3550 void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3552 LFBSurface lfbSurface = surface.driverData;
3553 if(display && display.displaySystem.flags.text)
3555 LFBDisplay lfbDisplay = display.driverData;
3556 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3562 if(y > surface.box.bottom || y < surface.box.top)
3564 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3565 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3566 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3568 if(surface.textOpacity)
3569 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3571 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3576 lfbSurface.writingText = true;
3577 #if !defined(ECERE_NOTRUETYPE)
3579 ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3581 lfbSurface.writingText = false;
3585 void TextFont(Display display, Surface surface, Font font)
3587 LFBSurface lfbSurface = surface.driverData;
3588 lfbSurface.font = font;
3591 void TextOpacity(Display display, Surface surface, bool opaque)
3593 LFBSurface lfbSurface = surface.driverData;
3597 void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3599 LFBSurface lfbSurface = surface.driverData;
3600 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3603 void DrawingChar(Display display, Surface surface, byte character)
3605 LFBSurface lfbSurface = surface.driverData;
3606 lfbSurface.drawingChar = character;
3609 void LineStipple(Display display, Surface surface, uint32 stipple)
3611 LFBSurface lfbSurface = surface.driverData;
3612 lfbSurface.stipple = (uint16)stipple;
3615 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3616 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3618 if(mesh.vertices && !mesh.flags.vertices)
3619 delete mesh.vertices;
3620 if(mesh.normals && !mesh.flags.normals)
3621 delete mesh.normals;
3622 if(mesh.texCoords && !mesh.flags.texCoords1)
3623 delete mesh.texCoords;
3626 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3628 bool result = false;
3630 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3631 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3632 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3637 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3642 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3647 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3649 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3651 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)