1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
10 #if !defined(ECERE_NOTRUETYPE)
12 #include FT_FREETYPE_H
13 #include FT_TRUETYPE_TABLES_H
14 #include FT_UNPATENTED_HINTING_H
15 #define property _property
19 #if defined(__WIN32__)
20 #define WIN32_LEAN_AND_MEAN
21 #define String _String
24 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
26 #include <fontconfig/fontconfig.h>
27 static FcConfig * fcConfig;
36 #pragma warning(disable:4244)
37 #pragma warning(disable:4018)
43 public define LIGHTSHIFT = 5;
44 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
46 /*#ifndef ECERE_VANILLA
48 static bool rgbLookupSet = true;
50 /*static */byte defaultRGBLookup[32768];
51 /*static */bool rgbLookupSet = false;
57 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
58 import "OpenGLDisplayDriver"
59 import "Direct3D8DisplayDriver"
60 import "Direct3D9DisplayDriver"
63 #if !defined(ECERE_NOTRUETYPE)
65 #define MAX_FONT_LINK_ENTRIES 10
67 static HB_Script theCurrentScript;
69 static unichar UTF16GetChar(const uint16 *string, int * nw)
72 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
74 ch = HB_SurrogateToUcs4(string[0], string[1]);
85 static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
87 FT_Face face = ((FontEntry)font->userData).face;
91 if (length > *numGlyphs)
94 for (c = 0; c < length; c += nw)
96 unichar ch = UTF16GetChar(string + c, &nw);
97 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
99 *numGlyphs = glyph_pos;
103 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
105 FontEntry entry = font->userData;
106 Font glFont = entry.font;
109 GlyphPack pack = glFont.asciiPack;
111 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
113 if(glFont.fontEntries[fontEntryNum] == entry)
117 for(c = 0; c < numGlyphs; c++)
120 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
121 uint packNo = glyphNo & 0xFFFFFF80;
122 if(packNo != lastPack)
124 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
127 glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
128 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
129 pack.bitmap.alphaBlend = true;
133 glyph = &pack.glyphs[glyphNo & 0x7F];
134 advances[c] = glyph->ax;
138 static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
140 FT_Face face = ((FontEntry)font->userData).face;
143 for (c = 0; c < length; c += nw)
145 unichar ch = UTF16GetChar(string + c, &nw);
146 if(!FT_Get_Char_Index(face, ch))
152 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
154 FT_Face face = (FT_Face)font;
155 FT_ULong ftlen = *length;
158 if (!FT_IS_SFNT(face))
159 return HB_Err_Invalid_Argument;
161 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
162 *length = (uint)ftlen;
163 return (HB_Error)error;
166 static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
168 HB_Error error = HB_Err_Ok;
169 FT_Face face = (FT_Face)font->userData;
171 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
173 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
176 if (face->glyph->format != ft_glyph_format_outline)
177 return (HB_Error)HB_Err_Invalid_SubTable;
179 *nPoints = face->glyph->outline.n_points;
183 if (point > *nPoints)
184 return (HB_Error)HB_Err_Invalid_SubTable;
186 *xpos = (int)face->glyph->outline.points[point].x;
187 *ypos = (int)face->glyph->outline.points[point].y;
192 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
194 FontEntry entry = font->userData;
195 Font glFont = entry.font;
197 GlyphPack pack = glFont.asciiPack;
199 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
201 if(glFont.fontEntries[fontEntryNum] == entry)
206 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
207 uint packNo = glyphNo & 0xFFFFFF80;
208 if(packNo != lastPack)
210 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
213 pack = { key = (uintptr)packNo };
214 glFont.glyphPacks.Add(pack);
215 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
216 pack.bitmap.alphaBlend = true;
220 glyph = &pack.glyphs[glyphNo & 0x7F];
222 metrics->x = glyph->ax;
224 metrics->width = glyph->w;
225 metrics->height = glyph->h;
226 metrics->xOffset = glyph->bx;
227 metrics->yOffset = glyph->by;
231 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
233 FontEntry entry = font->userData;
234 FT_Face face = entry.face;
236 // Note that we aren't scanning the VDMX table which we probably would in
238 if(metric == HB_FontAscent)
239 return face->ascender;
243 static HB_FontClass hb_fontClass =
245 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
246 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
249 static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
251 File f = stream->descriptor.pointer;
252 f.Seek((int)offset, start);
253 return count ? f.Read(buffer, 1, (uint)count) : 0;
256 static void FT_stream_close(FT_Stream stream)
258 File f = stream->descriptor.pointer;
263 static FT_Library ftLibrary;
266 static BinaryTree loadedFonts
268 CompareKey = (void *)BinaryTree::CompareString
271 class FontEntry : BTNode
280 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
297 FT_Done_FreeType(ftLibrary);
304 static float FaceSetCharSize(FT_Face face, float size)
307 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
309 if(face->num_fixed_sizes)
312 int bestDiff = MAXINT, best = 0;
313 FT_Bitmap_Size * sizes = face->available_sizes;
314 int wishedHeight = (int)(size * 96 / 72);
315 for(c = 0; c < face->num_fixed_sizes; c++)
317 int diff = abs(sizes[c].height - wishedHeight);
324 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
327 face->ascender = sizes[best].height;
328 scale = (float)wishedHeight / sizes[best].height;
347 class GlyphPack : BTNode
349 GlyphInfo glyphs[256];
352 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
354 #if !defined(ECERE_NOTRUETYPE)
356 int maxWidth, maxHeight;
357 int cellWidth, cellHeight;
359 FontEntry fontEntry = null;
362 bool isGlyph = ((uint)key & 0x80000000) != 0;
363 //int curScript = ((uint)key & 0x7F000000) >> 24;
364 unichar testChar = 0;
370 case HB_Script_Arabic:
372 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
374 case HB_Script_Devanagari:
377 case 60: testChar = 'あ'; break;
378 case 61: testChar = 0x3400; break;
385 FT_Vector pen = { 0, 0 };
388 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
389 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
390 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
391 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
392 FT_Set_Transform( fontEntry.face, &matrix, &pen );
394 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
400 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
402 fontEntry = font.fontEntries[c];
406 FT_Vector pen = { 0, 0 };
410 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
411 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
412 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
413 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
414 FT_Set_Transform(fontEntry.face, &matrix, &pen);
416 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
417 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
420 if(!fontEntry.face->units_per_EM)
421 font.ascent = (int)((double)fontEntry.face->ascender);
423 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
426 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
427 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
428 fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
429 fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
434 for(c = 0; c < 128; c++)
439 uint glyph = ((uint)key | c) & 0xFFFFFF;
440 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
442 fontEntry = font.fontEntries[entry];
443 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
445 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
447 //printf("%s: Accepted entry %d ", font.faceName, entry);
455 for(entry = startFontEntry; ; entry++)
458 fontEntry = font.fontEntries[entry];
459 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
461 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
466 scales[c] = fontEntry.scale;
467 faces[c] = fontEntry.face;
468 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
469 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
470 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
472 cellWidth = maxWidth;
473 cellHeight = maxHeight;
475 width = pow2i(maxWidth * 16);
476 height = pow2i(maxHeight * 8);
478 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
480 Bitmap bitmap = this.bitmap;
482 bitmap.transparent = true;
484 for(c = 0; c < 128; c++)
488 int sx = (c % 16) * cellWidth;
489 int sy = (c / 16) * cellHeight;
491 byte * picture = (byte *)bitmap.picture;
492 GlyphInfo * glyph = &glyphs[c];
493 FT_GlyphSlot slot = faces[c]->glyph;
494 double em_size = 1.0 * faces[c]->units_per_EM;
495 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
496 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
497 double ascender = faces[c]->ascender * y_scale;
498 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
500 FT_Load_Glyph(faces[c], glyphNo, /*FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT*/ FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/); // FT_LOAD_RENDER // FT_LOAD_NO_HINTING
502 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
506 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
508 glyph->left = slot->bitmap_left;
509 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
510 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
511 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
512 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
514 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
515 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
517 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
519 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
520 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
522 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
523 glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
525 // printf("[char: %d] mode: %d, width: %d, height: %d, pitch: %d\n", key + c, slot->bitmap.pixel_mode, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
526 xMax = x + slot->bitmap.width;
527 yMax = y + slot->bitmap.rows;
533 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
535 for(j = y, q = 0; j<yMax; j++)
537 for(p = 0, i = x; i<xMax; i++)
539 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
546 q += slot->bitmap.pitch;
549 //max = numPixels ? (total / numPixels) : 1;
551 for(j = y, q = 0; j<yMax; j++)
554 for(p = 0, i = x; i<xMax; i++)
556 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
558 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
560 if(!bit) { bit = 0x80; p++; }
564 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
565 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
568 q += slot->bitmap.pitch;
573 glyph->w = slot->bitmap.width;
574 glyph->h = slot->bitmap.rows;
575 glyph->glyphNo = glyphNo;
576 glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
577 glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
578 glyph->scale = scales[c];
580 glyph->ax = (int)slot->advance.x;
581 glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
588 for(c = 0; c<256; c++)
589 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
590 bitmap.pixelFormat = pixelFormat8;
593 //strcpy(fileName, faceName);
595 strcat(fileName, "Bold");
597 sprintf(fileName, "font%d", fid++);
598 ChangeExtension(fileName, "pcx", fileName);
600 bitmap.Save(fileName, null, 0);
601 bitmap.pixelFormat = pixelFormatAlpha;
605 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
607 displaySystem.Lock();
608 #if defined(__WIN32__)
609 // Is this check still required?
610 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
611 displaySystem.driver == class(Direct3D8DisplayDriver) ||
612 displaySystem.driver == class(Direct3D9DisplayDriver))
614 bitmap.MakeDD(displaySystem);
615 displaySystem.Unlock();
622 #if !defined(ECERE_NOTRUETYPE)
623 static HB_ShaperItem shaper_item;
625 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
627 static uint maxGlyphs = 0;
628 HB_Glyph * glyphs = shaper_item.glyphs;
630 shaper_item.kerning_applied = 0;
631 shaper_item.string = string;
632 shaper_item.stringLength = len;
633 shaper_item.item.script = script;
634 shaper_item.item.pos = 0;
635 shaper_item.item.length = shaper_item.stringLength;
636 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
637 shaper_item.item.bidiLevel = 1;
639 shaper_item.item.bidiLevel = 0;
640 shaper_item.shaperFlags = 0;
641 shaper_item.font = &entry.hbFont;
642 shaper_item.face = entry.hbFace;
643 shaper_item.num_glyphs = shaper_item.item.length;
644 shaper_item.glyphIndicesPresent = 0;
645 shaper_item.initialGlyphCount = 0;
646 shaper_item.num_glyphs = 0;
647 shaper_item.glyphs = null;
649 while(!HB_ShapeItem(&shaper_item))
651 if(shaper_item.num_glyphs > maxGlyphs)
653 maxGlyphs = shaper_item.num_glyphs;
654 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
655 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
656 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
657 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
658 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
662 shaper_item.glyphs = glyphs;
663 shaper_item.num_glyphs = maxGlyphs;
667 *numGlyphs = shaper_item.num_glyphs;
668 *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
669 return shaper_item.glyphs;
673 delete shaper_item.glyphs;
674 delete shaper_item.attributes;
675 delete shaper_item.advances;
676 delete shaper_item.offsets;
677 delete shaper_item.log_clusters;
681 public class Font : struct
683 BinaryTree glyphPacks { };
684 GlyphPack asciiPack { };
685 #if !defined(ECERE_NOTRUETYPE)
686 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
693 DisplaySystem displaySystem;
699 #if !defined(ECERE_NOTRUETYPE)
701 while((pack = (GlyphPack)glyphPacks.root))
703 glyphPacks.Remove(pack);
710 public class LFBDisplay : struct
714 byte rgbLookup[32768];
715 byte lightTable[256][LIGHTSTEPS];
719 void (* displayCallback)(Display display, Box updateBox);
722 public class LFBSystem : struct
726 ColorAlpha * palette;
727 byte rgbLookup[32768];
734 ColorAlpha * palette = GetDefaultPalette();
735 for(c = 16; c < 232; c++)
737 Color555 color = palette[c].color;
738 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
739 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
740 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
741 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
743 for(c = 232; c < 246; c++)
745 Color555 color = palette[c].color;
746 defaultRGBLookup[color] = (byte)c;
749 for(c = 246; c < 256; c++)
751 Color555 color = palette[c].color;
752 defaultRGBLookup[color] = (byte)c;
754 for(c = 0; c < 16; c++)
756 Color555 color = palette[c].color;
757 defaultRGBLookup[color] = (byte)c;
760 for(c = 0; c<32768; c++)
762 Color color = (Color)(Color555)c;
763 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
764 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
772 public class LFBSurface : struct
775 // For compatibility with 3D drivers as well
783 // Drawing attributes
784 uint foreground, background;
785 ColorAlpha foregroundRgb;
788 byte * paletteShades;
793 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
795 if(recordA->zMin > recordB->zMin)
797 else if(recordA->zMin < recordB->zMin)
799 else if(recordA > recordB)
801 else if(recordA < recordB)
808 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
811 char fileName[MAX_FILENAME];
816 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
818 //if(fontType == TRUETYPE_FONTTYPE)
820 FontData * fontData = (FontData *) lParam;
821 char * fileName = (char *)lParam;
823 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
824 int italic = (fontData->flags.italic) ? 1 : 0;
825 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
827 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
828 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
833 char entryName[1024];
834 char fontFileName[1024];
837 DWORD sizeFileName = 1024;
839 if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
841 if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
844 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
846 char ch = entryName[c];
847 if(ch == '&') { c = -1; break; }
848 else if(ch != ' ') break;
851 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
853 char ch = entryName[c];
854 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
855 else if(ch != ' ') break;
858 if(atoi(entryName + c))
862 strcpy(fileName, fontFileName);
876 static int utf16BufferSize = 0;
877 static uint16 * utf16 = null;
879 public class LFBDisplayDriver : DisplayDriver
881 class_property(name) = "LFB";
883 bool CreateDisplaySystem(DisplaySystem displaySystem)
885 displaySystem.flags.memBackBuffer = true;
886 // displaySystem.pixelFormat = pixelFormat888;
890 void DestroyDisplaySystem(DisplaySystem displaySystem)
894 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
896 delete bitmap.picture;
897 if(bitmap.allocatePalette)
898 delete bitmap.palette;
901 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
906 switch(GetColorDepthShifts(format))
908 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
909 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
910 case 2: stride = width; break;
913 bitmap.stride = stride;
914 bitmap.width = width;
915 bitmap.height = height;
916 bitmap.size = (uint32) stride * (uint32)height;
917 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
918 bitmap.pixelFormat = format;
919 bitmap.transparent = false;
921 surface.box.left = surface.box.top = 0;
922 surface.box.right = width - 1;
923 surface.box.bottom = height - 1;
925 bitmap.picture = new0 byte[bitmap.sizeBytes];
928 bitmap.allocatePalette = allocatePalette;
931 bitmap.palette = new ColorAlpha[256];
934 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
940 bitmap.palette = GetDefaultPalette();
945 FreeBitmap(displaySystem, bitmap);
949 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
952 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
956 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
958 if(src.transparent && src.pixelFormat == pixelFormat888)
962 DWORD * picture = (DWORD *)src.picture;
964 for(c = 0; c<src.size; c++, picture++)
966 if(*picture & 0xFFFFFF)
967 *picture = *picture | 0xFF000000;
969 *picture = *picture & 0xFFFFFF;
978 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
980 if(format == pixelFormat8)
983 bitmap.palette = palette;
984 else if(lfbSystem && lfbSystem.palette)
985 bitmap.palette = lfbSystem.palette;
987 bitmap.palette = src.palette;
990 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
992 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
993 bitmap.transparent = src.transparent;
994 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
996 if(src.palette != bitmap.palette)
998 if(src.allocatePalette)
1000 src.allocatePalette = false;
1002 src.picture = bitmap.picture;
1003 src.palette = bitmap.palette;
1004 src.stride = bitmap.stride;
1005 src.size = bitmap.size;
1006 src.sizeBytes = bitmap.sizeBytes;
1007 src.pixelFormat = bitmap.pixelFormat;
1012 bitmap.palette = null;
1013 bitmap.picture = null;
1021 void DestroyDisplay(Display display)
1023 LFBDisplay lfbDisplay = display.driverData;
1024 delete lfbDisplay.bitmap.palette;
1027 bool CreateDisplay(Display display)
1029 bool result = false;
1030 LFBDisplay lfbDisplay = display.driverData;
1033 lfbDisplay = display.driverData = LFBDisplay { };
1034 lfbDisplay.selfManaged = true;
1035 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1038 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1040 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1046 bool DisplaySize(Display display, int width, int height)
1048 LFBDisplay lfbDisplay = display.driverData;
1049 //display.width = width;
1050 //display.height = height;
1051 lfbDisplay.bitmap.width = width;
1052 lfbDisplay.bitmap.height = height;
1054 lfbDisplay.updateBox.left = display.width;
1055 lfbDisplay.updateBox.top = display.height;
1056 lfbDisplay.updateBox.right = 0;
1057 lfbDisplay.updateBox.bottom = 0;
1060 if(lfbDisplay.selfManaged)
1062 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1063 lfbDisplay.bitmap.stride = width;
1065 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1069 void DisplayPosition(Display display, int x, int y)
1071 LFBDisplay lfbDisplay = display.driverData;
1076 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1078 LFBDisplay lfbDisplay = display.driverData;
1085 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1086 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1087 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1090 for(c = 0; c<32768; c++)
1091 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1093 for(c=0; c<256; c++)
1096 for(i=0; i<LIGHTSTEPS; i++)
1098 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1099 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1100 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1101 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1105 if(lfbDisplay.bitmap.palette)
1106 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1109 void Update(Display display, Box updateBox)
1111 LFBDisplay lfbDisplay = display.driverData;
1112 if(lfbDisplay.displayCallback)
1114 if(updateBox == null)
1116 Box box { 0,0, display.width,display.height };
1117 lfbDisplay.displayCallback(display, box);
1120 lfbDisplay.displayCallback(display, updateBox);
1124 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1126 if(bitmap.pixelFormat != pixelFormatAlpha)
1128 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1130 FreeBitmap(displaySystem, bitmap);
1137 void ReleaseSurface(Display display, Surface surface)
1139 LFBSurface lfbSurface = surface.driverData;
1141 surface.driverData = null;
1144 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1146 LFBDisplay lfbDisplay = display.driverData;
1147 LFBSurface lfbSurface = surface.driverData;
1150 lfbSurface = surface.driverData = LFBSurface { };
1153 lfbSurface.bitmap = lfbDisplay.bitmap;
1155 surface.offset.x = x;
1156 surface.offset.y = y;
1158 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1160 surface.offset.x /= textCellW;
1161 surface.offset.y /= textCellH;
1162 surface.box.left /= textCellW;
1163 surface.box.top /= textCellH;
1164 surface.box.right /= textCellW;
1165 surface.box.bottom /= textCellH;
1169 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1170 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1171 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1172 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1175 surface.unclippedBox = surface.box;
1176 lfbSurface.drawingChar = 219;
1180 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1182 bool result = false;
1183 LFBSurface lfbSurface = surface.driverData;
1184 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1186 lfbSurface.bitmap = bitmap;
1188 surface.offset.x = x;
1189 surface.offset.y = y;
1191 if(bitmap.pixelFormat == pixelFormatText)
1193 surface.offset.x /= textCellW;
1194 surface.offset.y /= textCellH;
1195 surface.box.left /= textCellW;
1196 surface.box.top /= textCellH;
1197 surface.box.right /= textCellW;
1198 surface.box.bottom /= textCellH;
1201 surface.unclippedBox = *&surface.box;
1202 lfbSurface.drawingChar = 219;
1209 void Clip(Display display, Surface surface, Box clip)
1211 LFBSurface lfbSurface = surface.driverData;
1216 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1218 box.left /= textCellW;
1219 box.top /= textCellH;
1220 box.right /= textCellW;
1221 box.bottom /= textCellH;
1223 box.Clip(surface.unclippedBox);
1227 surface.box = surface.unclippedBox;
1230 void SetForeground(Display display, Surface surface, ColorAlpha color)
1232 LFBDisplay lfbDisplay = display ? display.driverData : null;
1233 LFBSurface lfbSurface = surface.driverData;
1235 if(display) color = color /*& 0xFFFFFF*/;
1236 lfbSurface.foregroundRgb = color;
1238 if(lfbSurface.font && lfbDisplay)
1240 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1241 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1244 switch(lfbSurface.bitmap.pixelFormat)
1248 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1250 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1252 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1253 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1254 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1255 case pixelFormat888: lfbSurface.foreground = color; break;
1256 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1257 case pixelFormatText:
1259 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1261 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1266 void SetBackground(Display display, Surface surface, ColorAlpha color)
1268 LFBDisplay lfbDisplay = display ? display.driverData : null;
1269 LFBSurface lfbSurface = surface.driverData;
1270 color = color /*& 0xFFFFFF*/;
1271 switch(lfbSurface.bitmap.pixelFormat)
1275 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1277 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1279 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1280 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1281 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1282 case pixelFormat888: lfbSurface.background = color; break;
1283 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1284 case pixelFormatText:
1286 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1288 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1293 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1295 LFBSurface lfbSurface = surface.driverData;
1296 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1301 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1303 x += surface.offset.x;
1304 y += surface.offset.y;
1305 if(lfbSurface.bitmap.picture)
1307 switch(lfbSurface.bitmap.pixelFormat)
1309 case pixelFormatText:
1311 if(!lfbSurface.bitmap.palette) return 0;
1312 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1313 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1314 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1315 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1316 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1323 void PutPixel(Display display, Surface surface,int x,int y)
1325 LFBSurface lfbSurface = surface.driverData;
1326 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1331 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1333 x += surface.offset.x;
1334 y += surface.offset.y;
1335 if(lfbSurface.bitmap.picture)
1337 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1340 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1343 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1346 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1347 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1354 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1356 LFBSurface lfbSurface = surface.driverData;
1362 uint color = lfbSurface.foreground;
1363 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1364 bool invert = false;
1365 if(!lfbSurface.bitmap.picture) return;
1366 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1372 if(surface.textOpacity)
1373 color |= lfbSurface.background;
1374 color |= lfbSurface.drawingChar;
1378 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1380 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1381 if((x1>surface.box.right)||(x2<surface.box.left))return;
1382 if(x1<surface.box.left)x1=surface.box.left;
1383 if(x2>surface.box.right)x2=surface.box.right;
1387 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1388 if(stipple != 0xFFFF)
1391 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1394 for(x=x1; x<=x2; x++, offset++)
1396 if(stipple & 0x8000)
1397 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1399 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1401 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1405 for(x=x1; x<=x2; x++, offset++)
1407 if(stipple & 0x8000)
1408 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1410 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1412 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1416 for(x=x1; x<=x2; x++, offset++)
1418 if(stipple & 0x8000)
1419 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1421 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1423 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1430 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1432 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1434 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1435 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1436 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1442 for(x = x1; x <= x2; x++, offset++)
1444 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1445 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1454 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1456 if((x1>surface.box.right)||(x1<surface.box.left))return;
1457 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1458 if(y1<surface.box.top)y1=surface.box.top;
1459 if(y2>surface.box.bottom)y2=surface.box.bottom;
1461 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1462 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1465 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1467 if(stipple & 0x8000)
1468 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1470 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1472 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1476 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1478 if(stipple & 0x8000)
1480 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1481 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1484 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1485 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1489 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1491 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1495 if(stipple != 0xFFFF)
1497 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1499 if(stipple & 0x8000)
1500 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1502 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1504 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1509 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1510 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1519 if(x1 < surface.box.left)
1521 if(x2 < surface.box.left)
1523 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1524 x1 = surface.box.left;
1526 if(x2 > surface.box.right)
1528 if(x1 > surface.box.right)
1530 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1531 x2 = surface.box.right;
1535 if(y1 < surface.box.top)
1537 if(y2 < surface.box.top)
1539 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1540 y1 = surface.box.top;
1542 if(y2 > surface.box.bottom)
1544 if(y1 > surface.box.bottom)
1546 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1547 y2 = surface.box.bottom;
1552 if(y1 > surface.box.bottom)
1554 if(y2 > surface.box.bottom)
1556 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1557 y1 = surface.box.bottom;
1559 if(y2 < surface.box.top)
1561 if(y1 < surface.box.top)
1563 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1564 y2 = surface.box.top;
1570 if(x1 > surface.box.right)
1572 if(x2 > surface.box.right)
1574 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1575 x1 = surface.box.right;
1577 if(x2 < surface.box.left)
1579 if(x1 < surface.box.left)
1581 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1582 x2 = surface.box.left;
1586 if(y1 < surface.box.top)
1588 if(y2 < surface.box.top)
1590 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1591 y1 = surface.box.top;
1593 if(y2 > surface.box.bottom)
1595 if(y1 > surface.box.bottom)
1597 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1598 y2 = surface.box.bottom;
1603 if(y1 > surface.box.bottom)
1605 if(y2 > surface.box.bottom)
1607 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1608 y1 = surface.box.bottom;
1610 if(y2 < surface.box.top)
1612 if(y1 < surface.box.top)
1614 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1615 y2 = surface.box.top;
1633 yu=-(int)lfbSurface.bitmap.stride;
1636 yu=lfbSurface.bitmap.stride;
1638 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1644 for(i=0; i<=length; i++)
1646 if(stipple & 0x8000)
1647 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1649 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1650 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1651 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1660 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1666 for(i=0; i<=length; i++)
1668 if(stipple & 0x8000)
1669 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1671 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1672 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1673 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1687 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1689 DrawLine(display, surface,x1,y1,x2,y1);
1690 DrawLine(display, surface,x2,y1,x2,y2);
1691 DrawLine(display, surface,x2,y2,x1,y2);
1692 DrawLine(display, surface,x1,y2,x1,y1);
1695 #if !defined(__GNUC__)
1697 void memset_32_aligned(void *buf, int val, int dwords)
1702 *((uint32 *)(buf)) = val;
1703 buf = ((uint32 *)(buf))+1;
1729 if (dwords & 1) *((int*)(buf)) = val;
1735 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1739 if(((uint32)buf) & 0x7F)
1741 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1767 sub edx,ebx ; edx holds # of overflow bytes
1786 movdqa [edi+16],xmm0
1787 movdqa [edi+32],xmm0
1788 movdqa [edi+48],xmm0
1789 movdqa [edi+64],xmm0
1790 movdqa [edi+80],xmm0
1791 movdqa [edi+96],xmm0
1792 movdqa [edi+112],xmm0
1816 void memset_32(void *buf, uint32 val, uint32 dwords)
1819 if ((uint32)(buf) & 3)
1824 if (((uint32)(buf) & 1))
1826 *(byte *)(buf) = (byte)(val&0xFF);
1827 buf = ((byte *)(buf))+1;
1828 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1831 if (((uint32)(buf) & 2))
1833 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1834 buf = ((uint16 *)(buf))+1;
1835 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1839 memset_32_aligned(buf,val,dwords);
1844 *(byte *)(buf) = (byte)(val&0xFF);
1848 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1849 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1856 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1858 LFBSurface lfbSurface = surface.driverData;
1859 uint32 color = lfbSurface.background;
1861 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1863 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1869 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1871 if(x1<surface.box.left) x1=surface.box.left;
1872 if(x2>surface.box.right) x2=surface.box.right;
1873 if(y1<surface.box.top) y1=surface.box.top;
1874 if(y2>surface.box.bottom) y2=surface.box.bottom;
1876 if(x2>=x1 && y2>=y1)
1884 x1 += surface.offset.x;
1885 x2 += surface.offset.x;
1886 y1 += surface.offset.y;
1887 y2 += surface.offset.y;
1888 if(lfbSurface.bitmap.picture)
1890 if(!surface.writeColor)
1892 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1893 for(y = y1; y<= y2; y++)
1896 for(c = 0; c < w; c++, picture++)
1898 picture->a = (byte)((color & 0xFF000000) >> 24);
1899 picture += lfbSurface.bitmap.stride - w;
1904 if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
1906 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1909 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1910 for(y = y1; y<= y2; y++)
1912 FillBytes(theOffset,(byte)color,w);
1913 theOffset += lfbSurface.bitmap.stride;
1917 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1918 for(y = y1; y<= y2; y++)
1920 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1921 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1925 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1926 for(y = y1; y<= y2; y++)
1928 #if defined(__GNUC__)
1929 FillBytesBy4((uint32 *) theOffset,color,w);
1931 memset_32((uint32 *) theOffset,color,w);
1933 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1939 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1940 //memset_32((uint32 *) theOffset,color,w);
1976 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1979 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1980 for(y = y1; y<= y2; y++)
1982 // TODO: IMPLEMENT THIS
1983 FillBytes(theOffset,(byte)color,w);
1984 theOffset += lfbSurface.bitmap.stride;
1989 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1990 ColorAlpha c = surface.background;
1995 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1997 for(y = y1; y <= y2; y++)
2000 for(c = 0; c < w; c++, dest++)
2003 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2004 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2005 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2007 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2008 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2009 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2011 if(r > 255) r = 255;
2012 if(g > 255) g = 255;
2013 if(b > 255) b = 255;
2015 destColor = { (byte)r, (byte)g, (byte)b };
2017 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2018 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2019 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2022 dest += (lfbSurface.bitmap.stride - w);
2028 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2029 AlphaWriteMode alphaWrite = surface.alphaWrite;
2030 ColorAlpha c = surface.background;
2035 for(y = y1; y <= y2; y++)
2038 for(c = 0; c < w; c++, dest++)
2040 int dr = dest->color.r;
2041 int dg = dest->color.g;
2042 int db = dest->color.b;
2043 int r = a * cr / 255 + ((255 - a) * dr / 255);
2044 int g = a * cg / 255 + ((255 - a) * dg / 255);
2045 int b = a * cb / 255 + ((255 - a) * db / 255);
2047 if(r > 255) r = 255;
2048 if(g > 255) g = 255;
2049 if(b > 255) b = 255;
2050 dest->color = { (byte)r, (byte)g, (byte)b };
2052 if(alphaWrite == blend)
2054 int ca = (int)(a + ((255 - a) * dest->a / 255));
2055 if(ca > 255) ca = 255;
2061 dest += (lfbSurface.bitmap.stride - w);
2070 void Clear(Display display, Surface surface, ClearType type)
2072 LFBSurface lfbSurface = surface.driverData;
2074 lfbSurface.clearing = true;
2075 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2076 surface.box.left == 0 && surface.box.top == 0 &&
2077 surface.box.right == surface.width-1 &&
2078 surface.box.bottom == surface.height-1)
2080 uint32 color = /*0xFF000000 | */lfbSurface.background;
2081 if(type != depthBuffer)
2083 if(lfbSurface.bitmap.stride != surface.width)
2084 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2087 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2090 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2092 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2093 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2098 if((flags & CLEAR_Z) && zbuffer)
2099 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2104 if(type != depthBuffer)
2105 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2107 if((flags & CLEAR_Z))
2110 uint32 w = surface.box.right-surface.box.left+1;
2111 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2112 + surface.box.left+surface.offset.x;
2113 for(y = surface.box.top; y<= surface.box.bottom; y++)
2115 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2116 offset += DISPLAY.Width;
2121 lfbSurface.clearing = false;
2124 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2126 LFBSurface lfbSurface = surface.driverData;
2129 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2131 if(w < 0) { w = -w; flip = true; }
2133 //Clip against the edges of the source
2146 if(sx+w>src.width-1)
2147 w-=sx+w-(src.width-1)-1;
2148 if(sy+h>src.height-1)
2149 h-=sy+h-(src.height-1)-1;
2150 //Clip against the edges of the destination
2151 if(dx<surface.box.left)
2153 if(!flip) sx+=surface.box.left-dx;
2154 w-=surface.box.left-dx;
2155 dx=surface.box.left;
2157 if(dy<surface.box.top)
2159 sy+=surface.box.top-dy;
2160 h-=surface.box.top-dy;
2163 if((dx+w)>surface.box.right)
2165 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2166 w-=((uint32)(dx+w)-surface.box.right-1);
2168 if((dy+h)>surface.box.bottom)
2169 h-=((dy+h)-surface.box.bottom-1);
2173 dx += surface.offset.x;
2174 dy += surface.offset.y;
2176 if(lfbSurface.bitmap.picture)
2178 AlphaWriteMode alphaWrite = surface.alphaWrite;
2179 if(src.alphaBlend && surface.blend)
2182 if(src.pixelFormat == pixelFormatAlpha)
2184 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2186 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2187 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2188 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2189 for(y = 0; y < h; y++)
2191 for(x = 0; x < w; x++, picture++, source++)
2193 int a = *source * color.a;
2194 ColorAlpha dest = *picture;
2195 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2196 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2197 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2198 if(r > 255) r = 255;
2199 if(g > 255) g = 255;
2200 if(b > 255) b = 255;
2201 picture->color = { (byte)r, (byte)g, (byte)b };
2202 if(alphaWrite == blend)
2204 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2205 if(ca > 255) ca = 255;
2206 picture->a = (byte)ca;
2209 picture->a = (byte)(a / 255);
2211 picture += lfbSurface.bitmap.stride - w;
2212 source += src.stride - w;
2215 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2217 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2218 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2219 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2220 for(y = 0; y < h; y++)
2222 for(x = 0; x < w; x++, picture++, source++)
2224 int a = *source * color.a;
2225 Color dest = *picture;
2226 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2227 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2228 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2229 if(r > 255) r = 255;
2230 if(g > 255) g = 255;
2231 if(b > 255) b = 255;
2232 *picture = Color { (byte)r, (byte)g, (byte)b };
2234 picture += lfbSurface.bitmap.stride - w;
2235 source += src.stride - w;
2238 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2240 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2241 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2242 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2243 for(y = 0; y < h; y++)
2245 for(x = 0; x < w; x++, picture++, source++)
2247 int a = *source * color.a;
2248 Color dest = *picture;
2249 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2250 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2251 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2252 if(r > 255) r = 255;
2253 if(g > 255) g = 255;
2254 if(b > 255) b = 255;
2255 *picture = Color { (byte)r, (byte)g, (byte)b };
2257 picture += lfbSurface.bitmap.stride - w;
2258 source += src.stride - w;
2264 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2265 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2267 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2268 for(y = 0; y < h; y++)
2270 for(x = 0; x < w; x++, picture++, source++)
2272 ColorAlpha src = *source;
2273 ColorAlpha dest = *picture;
2274 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2275 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2276 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2277 if(r > 255) r = 255;
2278 if(g > 255) g = 255;
2279 if(b > 255) b = 255;
2280 picture->color = { (byte)r, (byte)g, (byte)b };
2281 if(alphaWrite == blend)
2283 int a = src.a + ((255 - src.a) * dest.a / 255);
2284 if(a > 255) a = 255;
2285 picture->a = (byte)a;
2290 picture += lfbSurface.bitmap.stride - w;
2291 source += src.stride - w;
2294 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2296 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2297 for(y = 0; y < h; y++)
2299 for(x = 0; x < w; x++, picture++, source++)
2301 ColorAlpha src = *source;
2302 Color565 dest = *picture;
2303 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2304 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2305 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2306 if(r > 255 * 31) r = 255 * 31;
2307 if(g > 255 * 63) g = 255 * 63;
2308 if(b > 255 * 31) b = 255 * 31;
2309 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2311 picture += lfbSurface.bitmap.stride - w;
2312 source += src.stride - w;
2315 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2317 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2318 for(y = 0; y < h; y++)
2320 for(x = 0; x < w; x++, picture++, source++)
2322 ColorAlpha psrc = *source;
2323 Color555 dest = *picture;
2324 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2325 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2326 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2327 if(r > 255 * 31) r = 255 * 31;
2328 if(g > 255 * 31) g = 255 * 31;
2329 if(b > 255 * 31) b = 255 * 31;
2330 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2332 picture += lfbSurface.bitmap.stride - w;
2333 source += src.stride - w;
2338 else if(src.paletteShades)
2339 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2340 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2341 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2342 else if(src.pixelFormat == pixelFormat8)
2343 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2347 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2349 bool result = false;
2350 LFBDisplay lfbDisplay = display.driverData;
2352 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2355 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2356 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2360 Surface surface = bitmap.GetSurface(0,0,null);
2363 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2364 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2365 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2373 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2375 LFBSurface lfbSurface = surface.driverData;
2378 float s2dw,s2dh,d2sw,d2sh;
2380 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2382 if(Sgn(w) != Sgn(sw))
2394 //Clip against the edges of the source
2397 dx+=(int)((0-sx) * s2dw);
2398 w-=(int)((0-sx) * s2dw);
2404 dy+=(int)((0-sy) * s2dh);
2405 h-=(int)((0-sy) * s2dh);
2410 if(sx+sw>src.width-1)
2412 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2413 sw-=sx+sw-(src.width-1)-1;
2415 if(sy+sh>(src.height-1))
2417 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2418 sh-=sy+sh-(src.height-1)-1;
2420 //Clip against the edges of the destination
2421 if(dx<surface.box.left)
2423 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2424 sw-=(int)((surface.box.left-dx)*d2sw);
2425 w-=surface.box.left-dx;
2426 dx=surface.box.left;
2428 if(dy<surface.box.top)
2430 sy+=(int)((surface.box.top-dy)*d2sh);
2431 sh-=(int)((surface.box.top-dy)*d2sh);
2432 h-=surface.box.top-dy;
2435 if((dx+w)>surface.box.right)
2437 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2438 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2439 w-=((dx+w)-surface.box.right-1);
2441 if((dy+h)>surface.box.bottom)
2443 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2444 h-=((dy+h)-surface.box.bottom-1);
2446 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2448 dx+=surface.offset.x;
2449 dy+=surface.offset.y;
2451 if(lfbSurface.bitmap.picture)
2453 AlphaWriteMode alphaWrite = surface.alphaWrite;
2454 if(src.alphaBlend && surface.blend)
2458 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2459 ColorAlpha * backsrc;
2460 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2461 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2462 if(flip < 0) source += sw-1;
2480 ColorAlpha src = *source;
2481 ColorAlpha dst = *dest;
2482 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2483 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2484 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2485 if(r > 255) r = 255;
2486 if(g > 255) g = 255;
2487 if(b > 255) b = 255;
2488 dest->color = { (byte)r, (byte)g, (byte)b };
2489 if(alphaWrite == blend)
2491 int a = src.a + ((255 - src.a) * dst.a / 255);
2492 if(a > 255) a = 255;
2505 source += addsource;
2508 else if(src.paletteShades)
2509 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2510 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2511 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2512 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2513 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2517 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2519 LFBSurface lfbSurface = surface.driverData;
2522 float s2dw,s2dh,d2sw,d2sh;
2524 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2526 if(Sgn(w) != Sgn(sw))
2538 //Clip against the edges of the source
2541 dx+=(int)((0-sx) * s2dw);
2542 w-=(int)((0-sx) * s2dw);
2548 dy+=(int)((0-sy) * s2dh);
2549 h-=(int)((0-sy) * s2dh);
2554 if(sx+sw>src.width-1)
2556 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2557 sw-=sx+sw-(src.width-1)-1;
2559 if(sy+sh>(src.height-1))
2561 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2562 sh-=sy+sh-(src.height-1)-1;
2564 //Clip against the edges of the destination
2565 if(dx<surface.box.left)
2567 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2568 sw-=(int)((surface.box.left-dx)*d2sw);
2569 w-=surface.box.left-dx;
2570 dx=surface.box.left;
2572 if(dy<surface.box.top)
2574 sy+=(int)((surface.box.top-dy)*d2sh);
2575 sh-=(int)((surface.box.top-dy)*d2sh);
2576 h-=surface.box.top-dy;
2579 if((dx+w)>surface.box.right)
2581 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2582 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2583 w-=((dx+w)-surface.box.right-1);
2585 if((dy+h)>surface.box.bottom)
2587 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2588 h-=((dy+h)-surface.box.bottom-1);
2590 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2592 dx+=surface.offset.x;
2593 dy+=surface.offset.y;
2595 if(lfbSurface.bitmap.picture)
2597 AlphaWriteMode alphaWrite = surface.alphaWrite;
2598 if(src.alphaBlend && surface.blend)
2600 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2601 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2602 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2603 float scaleX = (float)sw / w;
2604 float scaleY = (float)sh / h;
2612 if (w > sw && h > sh)
2615 for (y = 0; y < h; y++)
2617 int y0 = y * sh / h;
2618 int y1 = Min(y0 + 1, sh - 1);
2619 float alpha = y * scaleY - y0;
2621 for(x = 0; x < w; x++, dest += 1)
2623 int x0 = x * sw / w;
2624 int x1 = Min(x0 + 1, sw - 1);
2625 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;
2683 for (i = y0; i <= y1; i++)
2684 for (j = x0; j <= x1; j++)
2686 ColorAlpha pixel = source[i * src.stride + j];
2698 ColorAlpha dst = *dest;
2699 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2700 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2701 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2702 if(cr > 255) cr = 255;
2703 if(cg > 255) cg = 255;
2704 if(cb > 255) cb = 255;
2705 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2706 if(alphaWrite == blend)
2708 int ca = (int)(a + ((255 - a) * dst.a / 255));
2709 if(ca > 255) ca = 255;
2720 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2721 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2722 // Fail back on Stretch
2723 else if(src.paletteShades)
2724 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2725 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2726 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2727 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2728 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2732 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2734 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2737 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2739 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2742 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2744 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2747 void UnloadFont(DisplaySystem displaySystem, Font font)
2751 #if !defined(ECERE_NOTRUETYPE)
2753 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2755 FontEntry fontEntry = font.fontEntries[entry];
2761 loadedFonts.Remove(fontEntry);
2771 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
2773 void * result = null;
2775 #if !defined(ECERE_NOTRUETYPE)
2776 Font font = Font { };
2779 char fileName[MAX_LOCATION];
2780 bool fakeItalic = flags.italic;
2782 #if !defined(__WIN32__)
2785 const char * ecereFonts = getenv("ECERE_FONTS");
2786 if(!ecereFonts) ecereFonts = "<:ecere>";
2787 #if !defined(__WIN32__)
2789 char linkCfgPath[MAX_LOCATION];
2791 strcpy(linkCfgPath, ecereFonts);
2792 PathCat(linkCfgPath, "linking.cfg");
2793 linkCfg = FileOpen(linkCfgPath, read);
2796 strcpy(fileName, faceName);
2797 strcpy(font.faceName, faceName);
2799 font.displaySystem = displaySystem;
2801 if(!FileExists(fileName))
2803 strcpy(fileName, ecereFonts);
2804 PathCat(fileName, faceName);
2805 if(flags.bold && flags.italic) strcat(fileName, "bi");
2806 else if(flags.bold) strcat(fileName, "bd");
2807 else if(flags.italic) strcat(fileName, "i");
2808 strcat(fileName, ".ttf");
2812 if(flags.italic && !FileExists(fileName))
2814 strcpy(fileName, ecereFonts);
2815 PathCat(fileName, faceName);
2816 if(flags.bold) strcat(fileName, "bd");
2817 strcat(fileName, ".ttf");
2822 // Search in current working directory
2823 if(!FileExists(fileName))
2825 strcpy(fileName, faceName);
2826 if(flags.bold && flags.italic) strcat(fileName, "bi");
2827 else if(flags.bold) strcat(fileName, "bd");
2828 else if(flags.italic) strcat(fileName, "i");
2829 strcat(fileName, ".ttf");
2833 if(flags.italic && !FileExists(fileName))
2835 strcpy(fileName, faceName);
2836 if(flags.bold) strcat(fileName, "bd");
2837 strcat(fileName, ".ttf");
2843 #if defined(__WIN32__)
2844 if(!FileExists(fileName))
2846 FontData fontData = { { 0 } };
2847 LOGFONT logFont = { 0 };
2852 logFont.lfCharSet = DEFAULT_CHARSET;
2853 strcpy(logFont.lfFaceName, faceName);
2854 fontData.flags = flags;
2856 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2857 if(!fontData.fileName[0] && flags.bold)
2859 fontData.forgive = true;
2860 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2862 if(!fontData.fileName[0])
2865 fontData.flags.italic = false;
2866 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2870 if(fontData.fileName[0])
2872 GetWindowsDirectory(fileName, MAX_LOCATION);
2873 PathCat(fileName, "fonts");
2874 PathCat(fileName, fontData.fileName);
2878 #elif !defined(ECERE_NOFONTCONFIG)
2881 FcResult result = 0;
2882 FcPattern * pattern;
2883 FcPattern * matched;
2885 unichar testChar = 0;
2886 FcCharSet * charSet;
2888 fcConfig = FcInitLoadConfigAndFonts();
2890 charSet = FcCharSetCreate();
2892 if(!strcmpi(faceName, "Mangal"))
2898 FcCharSetAddChar(charSet, testChar);
2900 pattern = FcPatternBuild(null,
2901 //FC_SOURCE, FcTypeString, "freetype",
2902 FC_FAMILY, FcTypeString, faceName,
2903 //FC_SCALABLE, FcTypeBool, 1,
2904 FC_SIZE, FcTypeDouble, (double)size,
2905 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2906 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2907 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2909 FcDefaultSubstitute(pattern);
2910 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2912 matched = FcFontMatch (0, pattern, &result);
2913 // printf("Locating %s\n", faceName);
2916 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2917 //printf("Fontconfig returned %s\n", family);
2919 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2922 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2923 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2924 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2925 strcpy(fileName, fileName2);
2926 // size = (float)fontSize;
2928 //printf("Matched to %s, %f\n", fileName, size);
2932 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2934 if(pattern) FcPatternDestroy(pattern);
2935 if(matched) FcPatternDestroy(matched);
2936 if(charSet) FcCharSetDestroy(charSet);
2941 if(!FileExists(fileName))
2942 ChangeExtension(fileName, "otf", fileName);
2943 if(!FileExists(fileName))
2944 ChangeExtension(fileName, "ttc", fileName);
2946 //if(FileExists(fileName))
2949 char links[1024] = "";
2951 #if defined(__WIN32__)
2954 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2955 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2960 RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
2961 memset(links + size, 0, 1024 - size);
2969 while(linkCfg.GetLine(line, sizeof(line)))
2971 int len = strlen(faceName);
2972 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2974 while(linkCfg.GetLine(line, sizeof(line)))
2976 TrimLSpaces(line, line);
2977 if(!line[0] || line[0] == '[')
2980 memcpy(links + linksPos, line, len);
2982 links[linksPos] = 0;
2990 while(entry < MAX_FONT_LINK_ENTRIES)
2992 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2995 File file = FileOpen/*Buffered*/(fileName, read);
2998 FileSize fileSize = file.GetSize();
2999 FT_Open_Args args = { 0 };
3000 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3001 FT_Stream stream = new0 FT_StreamRec[1];
3004 FT_Init_FreeType( &ftLibrary );
3006 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3007 fontEntry.stream = stream;
3010 fontEntry.buffer = new byte[fileSize];
3011 file.Read(fontEntry.buffer, 1, fileSize);
3014 //args.num_params = 1;
3015 args.params = ¶m;
3017 stream->size = fileSize;
3018 stream->descriptor.pointer = file;
3019 stream->read = FT_stream_load;
3020 stream->close = FT_stream_close;
3022 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3023 args.stream = stream;
3024 //args.pathname = fileName;
3025 //args.memory_base = fontEntry.buffer;
3026 //args.memory_size = fileSize;
3028 // printf("Opening: %s\n", fileName);
3029 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3034 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3035 fontEntry.hbFont.klass = &hb_fontClass;
3036 fontEntry.hbFont.userData = fontEntry; //.face;
3039 loadedFonts.Add(fontEntry);
3044 // printf("Error opening font %s\n", fileName);
3053 FT_Vector pen = { 0, 0 };
3056 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3057 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3058 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3059 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3063 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3064 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3065 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3066 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3068 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3069 FaceSetCharSize(fontEntry.face, size);
3070 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3071 // printf("Font height is %d\n", font.height);
3072 font.fakeItalic = fakeItalic;
3076 font.fontEntries[entry++] = fontEntry;
3083 char fontName[1024];
3084 if(!links[linksPos]) break;
3085 for(c = 0; (ch = links[linksPos + c]); c++)
3088 if(ch == ',') break;
3091 if(fontName[0] || ch == ',')
3093 #if defined(__WIN32__)
3094 GetWindowsDirectory(fileName, MAX_LOCATION);
3095 PathCat(fileName, "fonts");
3096 PathCat(fileName, fontName);
3097 #elif !defined(ECERE_NOFONTCONFIG)
3098 if(getenv("ECERE_FONTS"))
3100 strcpy(fileName, ecereFonts);
3101 PathCat(fileName, fontName);
3107 FcResult result = 0;
3108 FcPattern * pattern;
3109 FcPattern * matched;
3111 pattern = FcPatternBuild(null,
3112 //FC_SOURCE, FcTypeString, "freetype",
3113 //FC_SCALABLE, FcTypeBool, 1,
3114 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3115 FC_SIZE, FcTypeDouble, (double)size,
3116 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3117 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3119 FcDefaultSubstitute(pattern);
3120 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3122 //printf("Locating %s\n", links + linksPos + c + 1);
3123 matched = FcFontMatch (0, pattern, &result);
3126 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3127 // printf("Fontconfig returned %s\n", family);
3129 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3130 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3133 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3134 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3135 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3136 strcpy(fileName, fileName2);
3137 //size = (float)fontSize;
3138 // printf("Matched to %s, %f\n", fileName, size);
3142 // 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);
3144 if(pattern) FcPatternDestroy(pattern);
3145 if(matched) FcPatternDestroy(matched);
3152 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3159 UnloadFont(displaySystem, font);
3162 font.asciiPack.Render(font, 0, displaySystem);
3164 #if !defined(__WIN32__)
3172 #if !defined(ECERE_NOTRUETYPE)
3173 void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
3174 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3175 Surface surface, Display display, int * x, int y)
3177 if(font && font.fontEntries && font.fontEntries[0])
3179 int previousGlyph = 0;
3180 FT_Face previousFace = 0;
3181 int c, nb, glyphIndex = 0;
3182 unichar lastPack = 0;
3183 GlyphPack pack = font.asciiPack;
3187 bool rightToLeft = false;
3188 int fontEntryNum = 0;
3189 int glyphScript = 0;
3190 FontEntry curFontEntry;
3192 pack.bitmap.alphaBlend = true;
3194 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3198 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3200 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3201 rightToLeft ? glyphIndex-- : glyphIndex++;
3205 HB_Script curScript = HB_Script_Common;
3206 const byte * scriptStart = text + c;
3207 //unichar nonASCIIch = 0;
3210 unichar testChar = 0;
3211 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3212 const char * testLang = null;
3217 HB_Script script = HB_Script_Common;
3218 ch = UTF8GetChar((const char *)text + c, &nb);
3219 //if(ch > 127) nonASCIIch = ch;
3221 if(ch == 32 && curScript)
3228 for(a = c + 1; a < c + len; a++)
3236 unichar ahead = UTF8GetChar((const char *)text + a, &nb);
3237 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3245 script = HB_Script_Common;
3246 else if(ch <= 0x11FF)
3250 case 0x300: script = HB_Script_Greek; break;
3251 case 0x400: script = HB_Script_Cyrillic; break;
3252 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3253 case 0x600: script = HB_Script_Arabic; break;
3254 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3255 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3256 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3257 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3258 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3259 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3260 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3261 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3262 case 0xF00: script = HB_Script_Tibetan; break;
3263 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3264 case 0x1100: script = HB_Script_Hangul; break;
3267 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3268 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3269 script = HB_Script_Hangul;
3270 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3271 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3272 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3273 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3274 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3275 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3276 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3277 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3278 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3281 if(!script || (script != curScript))
3289 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3290 if(!script) { c += nb; break; }
3297 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3299 rightToLeft = false;
3301 theCurrentScript = 0;
3305 int len = c - (int)(scriptStart - text);
3306 int max = len * 2 + 1;
3307 if(max > utf16BufferSize)
3309 utf16 = renew utf16 uint16[max];
3310 utf16BufferSize = max;
3312 wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
3313 theCurrentScript = glyphScript = curScript;
3317 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3318 //printf("Arabic ");
3320 case HB_Script_Devanagari: testChar = 0x905;
3321 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3324 //printf("Devanagari ");
3326 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3327 //printf("Hebrew ");
3330 testChar = (ch == '\t') ? ' ' : ch;
3332 case 60: testChar = 'あ'; break;
3333 case 61: testChar = 0x3400; break; //'愛'; break;
3339 // printf("Testing for char %x\n", testChar);
3340 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3342 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3344 /*if(font.fontEntries[fontEntryNum])
3345 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3349 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3351 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3353 double fontSize = font.size;
3354 FcResult result = 0;
3355 FcPattern * pattern;
3356 FcPattern * matched;
3357 FcCharSet * charSet;
3359 FontEntry fontEntry;
3360 char * fileName = null;
3361 bool fakeItalic = false;
3362 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3363 if(!font.fontEntries[fontEntryNum])
3365 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3369 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3371 charSet = FcCharSetCreate();
3372 FcCharSetAddChar(charSet, testChar);
3373 //printf("Loading with char %x\n", testChar);
3375 pattern = FcPatternBuild(null,
3376 //FC_SOURCE, FcTypeString, "freetype",
3377 //FC_SCALABLE, FcTypeBool, 1,
3378 FC_FAMILY, FcTypeString, font.faceName,
3379 FC_SIZE, FcTypeDouble, (double)font.size,
3380 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3381 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3382 FC_CHARSET,FcTypeCharSet, charSet,
3383 testLang ? FC_LANG : 0, FcTypeString,testLang,
3385 FcDefaultSubstitute(pattern);
3386 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3388 //printf("Locating %s for script %d\n", font.faceName, curScript);
3389 matched = FcFontMatch (0, pattern, &result);
3392 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3393 //printf("Fontconfig returned %s\n", family);
3395 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3397 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3398 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3399 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3400 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3404 //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);
3409 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3412 File file = FileOpen(fileName, read);
3415 FileSize fileSize = file.GetSize();
3416 FT_Open_Args args = { 0 };
3417 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3418 FT_Stream stream = new0 FT_StreamRec[1];
3421 FT_Init_FreeType( &ftLibrary );
3423 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3424 fontEntry.stream = stream;
3426 //args.num_params = 1;
3427 args.params = ¶m;
3429 stream->size = fileSize;
3430 stream->descriptor.pointer = file;
3431 stream->read = FT_stream_load;
3432 stream->close = FT_stream_close;
3434 args.flags = FT_OPEN_STREAM;
3435 args.stream = stream;
3436 //args.pathname = fileName;
3437 //args.memory_base = fontEntry.buffer;
3438 //args.memory_size = fileSize;
3440 // printf("Opening: %s\n", fileName);
3441 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3446 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3447 fontEntry.hbFont.klass = &hb_fontClass;
3448 fontEntry.hbFont.userData = fontEntry; //.face;
3451 loadedFonts.Add(fontEntry);
3456 // printf("Error opening font %s\n", fileName);
3462 FaceSetCharSize(fontEntry.face, font.size);
3464 font.fontEntries[fontEntryNum] = fontEntry;
3468 if(pattern) FcPatternDestroy(pattern);
3469 if(matched) FcPatternDestroy(matched);
3470 if(charSet) FcCharSetDestroy(charSet);
3473 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3474 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3476 font.fontEntries[fontEntryNum].font = font;
3477 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3481 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3482 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3483 rightToLeft ? glyphIndex-- : glyphIndex++;
3487 curFontEntry = font.fontEntries[fontEntryNum];
3489 packNo = glyphNo & 0xFFFFFF80;
3491 if(packNo != lastPack)
3494 pack = font.asciiPack;
3497 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3500 pack = GlyphPack { key = (uintptr)packNo };
3501 font.glyphPacks.Add(pack);
3502 pack.Render(font, fontEntryNum, displaySystem);
3505 pack.bitmap.alphaBlend = true;
3510 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3511 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3513 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3514 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3515 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3519 if(previousGlyph && curFontEntry.face == previousFace)
3521 FT_Vector delta = { 0, 0 };
3522 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3523 if(delta.x < 0) delta.x += (-delta.x) % 64;
3524 else if(delta.x) delta.x += 64 - (delta.x % 64);
3525 *x += delta.x * glyph->scale;
3528 FaceSetCharSize(curFontEntry.face, font.size);
3530 previousGlyph = glyph->glyphNo;
3531 previousFace = curFontEntry.face;
3534 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3537 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3543 LFBSurface lfbSurface = surface.driverData;
3544 lfbSurface.xOffset = 0;
3549 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3551 if(displaySystem && displaySystem.flags.text && len)
3556 *width = num * textCellW;
3558 if(height) *height = textCellH;
3560 else if(font && len)
3565 #if !defined(ECERE_NOTRUETYPE)
3566 ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
3568 //*width = (w + 64 - w % 64) >> 6;
3572 *height = font.height;
3576 if(width) *width = 0;
3577 if(height) *height = 0;
3581 #if !defined(ECERE_NOTRUETYPE)
3582 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3584 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3588 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3590 LFBSurface lfbSurface = surface.driverData;
3591 if(display && display.displaySystem.flags.text)
3593 LFBDisplay lfbDisplay = display.driverData;
3594 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3600 if(y > surface.box.bottom || y < surface.box.top)
3602 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3603 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3604 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3606 if(surface.textOpacity)
3607 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3609 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3614 lfbSurface.writingText = true;
3615 #if !defined(ECERE_NOTRUETYPE)
3617 ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
3619 lfbSurface.writingText = false;
3623 void TextFont(Display display, Surface surface, Font font)
3625 LFBSurface lfbSurface = surface.driverData;
3626 lfbSurface.font = font;
3629 void TextOpacity(Display display, Surface surface, bool opaque)
3634 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3636 LFBSurface lfbSurface = surface.driverData;
3637 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3640 void DrawingChar(Display display, Surface surface, byte character)
3642 LFBSurface lfbSurface = surface.driverData;
3643 lfbSurface.drawingChar = character;
3646 void LineStipple(Display display, Surface surface, uint32 stipple)
3648 LFBSurface lfbSurface = surface.driverData;
3649 lfbSurface.stipple = (uint16)stipple;
3652 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3653 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3655 if(mesh.vertices && !mesh.flags.vertices)
3656 delete mesh.vertices;
3657 if(mesh.normals && !mesh.flags.normals)
3658 delete mesh.normals;
3659 if(mesh.texCoords && !mesh.flags.texCoords1)
3660 delete mesh.texCoords;
3663 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3665 bool result = false;
3667 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3668 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3669 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3674 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3679 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3684 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3686 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3688 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)