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 <freetype/ttunpat.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(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, 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, 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
287 char * fileName = (char *)key;
298 FT_Done_FreeType(ftLibrary);
305 static float FaceSetCharSize(FT_Face face, float size)
308 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
310 if(face->num_fixed_sizes)
313 int bestDiff = MAXINT, best = 0;
314 FT_Bitmap_Size * sizes = face->available_sizes;
315 int wishedHeight = (int)(size * 96 / 72);
316 for(c = 0; c < face->num_fixed_sizes; c++)
318 int diff = abs(sizes[c].height - wishedHeight);
325 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
328 face->ascender = sizes[best].height;
329 scale = (float)wishedHeight / sizes[best].height;
348 class GlyphPack : BTNode
350 GlyphInfo glyphs[256];
353 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
355 #if !defined(ECERE_NOTRUETYPE)
357 int maxWidth, maxHeight;
358 int cellWidth, cellHeight;
360 FontEntry fontEntry = null;
363 bool isGlyph = (uint)key & 0x80000000;
364 int curScript = ((uint)key & 0x7F000000) >> 24;
365 unichar testChar = 0;
371 case HB_Script_Arabic:
373 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
375 case HB_Script_Devanagari:
378 case 60: testChar = 'あ'; break;
379 case 61: testChar = 0x3400; break;
386 FT_Vector pen = { 0, 0 };
389 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
390 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
391 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
392 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
393 FT_Set_Transform( fontEntry.face, &matrix, &pen );
395 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
401 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
403 fontEntry = font.fontEntries[c];
407 FT_Vector pen = { 0, 0 };
411 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
412 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
413 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
414 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
415 FT_Set_Transform(fontEntry.face, &matrix, &pen);
417 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
418 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
421 if(!fontEntry.face->units_per_EM)
422 font.ascent = (int)((double)fontEntry.face->ascender);
424 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
427 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
428 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
429 fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
430 fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
435 for(c = 0; c < 128; c++)
440 uint glyph = ((uint)key | c) & 0xFFFFFF;
441 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
443 fontEntry = font.fontEntries[entry];
444 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
446 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
448 //printf("%s: Accepted entry %d ", font.faceName, entry);
456 for(entry = startFontEntry; ; entry++)
459 fontEntry = font.fontEntries[entry];
460 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
462 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
467 scales[c] = fontEntry.scale;
468 faces[c] = fontEntry.face;
469 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
470 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
471 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
473 cellWidth = maxWidth;
474 cellHeight = maxHeight;
476 width = pow2i(maxWidth * 16);
477 height = pow2i(maxHeight * 8);
479 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
481 Bitmap bitmap = this.bitmap;
483 bitmap.transparent = true;
485 for(c = 0; c < 128; c++)
489 int sx = (c % 16) * cellWidth;
490 int sy = (c / 16) * cellHeight;
492 byte * picture = (byte *)bitmap.picture;
493 GlyphInfo * glyph = &glyphs[c];
494 FT_GlyphSlot slot = faces[c]->glyph;
495 double em_size = 1.0 * faces[c]->units_per_EM;
496 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
497 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
498 double ascender = faces[c]->ascender * y_scale;
499 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
501 FT_Load_Glyph(faces[c], glyphNo, /*FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT*/ FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/); // FT_LOAD_RENDER // FT_LOAD_NO_HINTING
503 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
507 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
509 glyph->left = slot->bitmap_left;
510 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
511 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
512 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
513 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
515 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
516 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
518 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
520 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
521 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
523 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
524 glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
526 // 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);
527 xMax = x + slot->bitmap.width;
528 yMax = y + slot->bitmap.rows;
534 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
536 for(j = y, q = 0; j<yMax; j++)
538 for(p = 0, i = x; i<xMax; i++)
540 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
547 q += slot->bitmap.pitch;
550 max = numPixels ? (total / numPixels) : 1;
552 for(j = y, q = 0; j<yMax; j++)
555 for(p = 0, i = x; i<xMax; i++)
557 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
559 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
561 if(!bit) { bit = 0x80; p++; }
565 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
566 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
569 q += slot->bitmap.pitch;
574 glyph->w = slot->bitmap.width;
575 glyph->h = slot->bitmap.rows;
576 glyph->glyphNo = glyphNo;
577 glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
578 glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
579 glyph->scale = scales[c];
581 glyph->ax = (int)slot->advance.x;
582 glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
589 for(c = 0; c<256; c++)
590 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
591 bitmap.pixelFormat = pixelFormat8;
594 //strcpy(fileName, faceName);
596 strcat(fileName, "Bold");
598 sprintf(fileName, "font%d", fid++);
599 ChangeExtension(fileName, "pcx", fileName);
601 bitmap.Save(fileName, null, 0);
602 bitmap.pixelFormat = pixelFormatAlpha;
606 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
608 displaySystem.Lock();
609 #if defined(__WIN32__)
610 // Is this check still required?
611 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
612 displaySystem.driver == class(Direct3D8DisplayDriver) ||
613 displaySystem.driver == class(Direct3D9DisplayDriver))
615 bitmap.MakeDD(displaySystem);
616 displaySystem.Unlock();
623 #if !defined(ECERE_NOTRUETYPE)
624 static HB_ShaperItem shaper_item;
626 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
628 static uint maxGlyphs = 0;
629 HB_Glyph * glyphs = shaper_item.glyphs;
631 shaper_item.kerning_applied = 0;
632 shaper_item.string = string;
633 shaper_item.stringLength = len;
634 shaper_item.item.script = script;
635 shaper_item.item.pos = 0;
636 shaper_item.item.length = shaper_item.stringLength;
637 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
638 shaper_item.item.bidiLevel = 1;
640 shaper_item.item.bidiLevel = 0;
641 shaper_item.shaperFlags = 0;
642 shaper_item.font = &entry.hbFont;
643 shaper_item.face = entry.hbFace;
644 shaper_item.num_glyphs = shaper_item.item.length;
645 shaper_item.glyphIndicesPresent = 0;
646 shaper_item.initialGlyphCount = 0;
647 shaper_item.num_glyphs = 0;
648 shaper_item.glyphs = null;
650 while(!HB_ShapeItem(&shaper_item))
652 if(shaper_item.num_glyphs > maxGlyphs)
654 maxGlyphs = shaper_item.num_glyphs;
655 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
656 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
657 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
658 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
659 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
663 shaper_item.glyphs = glyphs;
664 shaper_item.num_glyphs = maxGlyphs;
668 *numGlyphs = shaper_item.num_glyphs;
669 *rightToLeft = shaper_item.item.bidiLevel % 2;
670 return shaper_item.glyphs;
674 delete shaper_item.glyphs;
675 delete shaper_item.attributes;
676 delete shaper_item.advances;
677 delete shaper_item.offsets;
678 delete shaper_item.log_clusters;
682 public class Font : struct
684 BinaryTree glyphPacks { };
685 GlyphPack asciiPack { };
686 #if !defined(ECERE_NOTRUETYPE)
687 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
694 DisplaySystem displaySystem;
700 #if !defined(ECERE_NOTRUETYPE)
702 while((pack = (GlyphPack)glyphPacks.root))
704 glyphPacks.Remove(pack);
711 public class LFBDisplay : struct
715 byte rgbLookup[32768];
716 byte lightTable[256][LIGHTSTEPS];
720 void (* displayCallback)(Display display, Box updateBox);
723 public class LFBSystem : struct
727 ColorAlpha * palette;
728 byte rgbLookup[32768];
735 ColorAlpha * palette = GetDefaultPalette();
736 for(c = 16; c < 232; c++)
738 Color555 color = palette[c].color;
739 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
740 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
741 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
742 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
744 for(c = 232; c < 246; c++)
746 Color555 color = palette[c].color;
747 defaultRGBLookup[color] = (byte)c;
750 for(c = 246; c < 256; c++)
752 Color555 color = palette[c].color;
753 defaultRGBLookup[color] = (byte)c;
755 for(c = 0; c < 16; c++)
757 Color555 color = palette[c].color;
758 defaultRGBLookup[color] = (byte)c;
761 for(c = 0; c<32768; c++)
763 Color color = (Color)(Color555)c;
764 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
765 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
773 public class LFBSurface : struct
776 // For compatibility with 3D drivers as well
784 // Drawing attributes
785 uint foreground, background;
786 ColorAlpha foregroundRgb;
789 byte * paletteShades;
794 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
796 if(recordA->zMin > recordB->zMin)
798 else if(recordA->zMin < recordB->zMin)
800 else if(recordA > recordB)
802 else if(recordA < recordB)
809 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
812 char fileName[MAX_FILENAME];
817 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
819 //if(fontType == TRUETYPE_FONTTYPE)
821 FontData * fontData = (FontData *) lParam;
822 char * fileName = (char *)lParam;
824 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
825 int italic = (fontData->flags.italic) ? 1 : 0;
826 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
828 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
829 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
834 char entryName[1024];
835 char fontFileName[1024];
838 int sizeFileName = 1024;
840 if(RegEnumValue(key, value++, entryName, (PDWORD)&size, null, (PDWORD)&type, (LPBYTE)fontFileName, (PDWORD)&sizeFileName) != ERROR_SUCCESS)
842 if((occurence = SearchString((char *)entryName, 0, (char *)font->elfFullName, false, false)))
845 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
847 char ch = entryName[c];
848 if(ch == '&') { c = -1; break; }
849 else if(ch != ' ') break;
852 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
854 char ch = entryName[c];
855 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
856 else if(ch != ' ') break;
859 if(atoi(entryName + c))
863 strcpy(fileName, fontFileName);
877 static int utf16BufferSize = 0;
878 static uint16 * utf16 = null;
880 public class LFBDisplayDriver : DisplayDriver
882 class_property(name) = "LFB";
884 bool CreateDisplaySystem(DisplaySystem displaySystem)
886 displaySystem.flags.memBackBuffer = true;
887 // displaySystem.pixelFormat = pixelFormat888;
891 void DestroyDisplaySystem(DisplaySystem displaySystem)
895 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
897 delete bitmap.picture;
898 if(bitmap.allocatePalette)
899 delete bitmap.palette;
902 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
907 switch(GetColorDepthShifts(format))
909 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
910 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
911 case 2: stride = width; break;
914 bitmap.stride = stride;
915 bitmap.width = width;
916 bitmap.height = height;
917 bitmap.size = (uint32) stride * (uint32)height;
918 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
919 bitmap.pixelFormat = format;
920 bitmap.transparent = false;
922 surface.box.left = surface.box.top = 0;
923 surface.box.right = width - 1;
924 surface.box.bottom = height - 1;
926 bitmap.picture = new0 byte[bitmap.sizeBytes];
929 bitmap.allocatePalette = allocatePalette;
932 bitmap.palette = new ColorAlpha[256];
935 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
941 bitmap.palette = GetDefaultPalette();
946 FreeBitmap(displaySystem, bitmap);
950 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
953 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
957 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
959 if(src.transparent && src.pixelFormat == pixelFormat888)
963 DWORD * picture = (DWORD *)src.picture;
965 for(c = 0; c<src.size; c++, picture++)
967 if(*picture & 0xFFFFFF)
968 *picture = *picture | 0xFF000000;
970 *picture = *picture & 0xFFFFFF;
979 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
981 if(format == pixelFormat8)
984 bitmap.palette = palette;
985 else if(lfbSystem && lfbSystem.palette)
986 bitmap.palette = lfbSystem.palette;
988 bitmap.palette = src.palette;
991 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
993 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
994 bitmap.transparent = src.transparent;
995 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
997 if(src.palette != bitmap.palette)
999 if(src.allocatePalette)
1001 src.allocatePalette = false;
1003 src.picture = bitmap.picture;
1004 src.palette = bitmap.palette;
1005 src.stride = bitmap.stride;
1006 src.size = bitmap.size;
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.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)
2602 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2603 ColorAlpha * backsrc;
2604 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2605 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2606 float scaleX = (float)sw / w;
2607 float scaleY = (float)sh / h;
2615 if (w > sw && h > sh)
2618 for (y = 0; y < h; y++)
2620 int y0 = y * sh / h;
2621 int y1 = Min(y0 + 1, sh - 1);
2622 float alpha = y * scaleY - y0;
2624 for(x = 0; x < w; x++, dest += 1)
2626 int x0 = x * sw / w;
2627 int x1 = Min(x0 + 1, sw - 1);
2628 float beta = x * scaleX - x0;
2630 ColorAlpha src00, src01, src10, src11;
2631 float a1,r1,g1,b1,a2,r2,g2,b2;
2633 src00 = source[y0 * src.stride + x0];
2634 src01 = source[y0 * src.stride + x1];
2635 src10 = source[y1 * src.stride + x0];
2636 src11 = source[y1 * src.stride + x1];
2637 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2638 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2639 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2640 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2641 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2642 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2643 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2644 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2645 a = a1 * (1.0f - alpha) + a2 * alpha;
2646 r = r1 * (1.0f - alpha) + r2 * alpha;
2647 g = g1 * (1.0f - alpha) + g2 * alpha;
2648 b = b1 * (1.0f - alpha) + b2 * alpha;
2650 ColorAlpha dst = *dest;
2651 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2652 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2653 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2654 if(cr > 255) cr = 255;
2655 if(cg > 255) cg = 255;
2656 if(cb > 255) cb = 255;
2657 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2659 if(alphaWrite == blend)
2661 int ca = (int)(a + ((255 - a) * dst.a / 255));
2662 if(ca > 255) ca = 255;
2675 for (y = 0; y < h; y++)
2677 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2678 int y1 = Min(y0 + 1, sh - 1);
2680 for (x = 0; x < w; x++, dest += 1)
2682 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2683 int x1 = Min(x0 + 1, sw - 1);
2684 float a = 0, r = 0, g = 0, b = 0;
2688 for (i = y0; i <= y1; i++)
2689 for (j = x0; j <= x1; j++)
2691 ColorAlpha pixel = source[i * src.stride + j];
2703 ColorAlpha src = *source;
2704 ColorAlpha dst = *dest;
2705 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2706 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2707 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2708 if(cr > 255) cr = 255;
2709 if(cg > 255) cg = 255;
2710 if(cb > 255) cb = 255;
2711 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2712 if(alphaWrite == blend)
2714 int ca = (int)(a + ((255 - a) * dst.a / 255));
2715 if(ca > 255) ca = 255;
2726 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2727 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2728 // Fail back on Stretch
2729 else if(src.paletteShades)
2730 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2731 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2732 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2733 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2734 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2738 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2740 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2743 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2745 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2748 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2750 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2753 void UnloadFont(DisplaySystem displaySystem, Font font)
2757 #if !defined(ECERE_NOTRUETYPE)
2759 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2761 FontEntry fontEntry = font.fontEntries[entry];
2767 loadedFonts.Remove(fontEntry);
2777 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2779 void * result = null;
2781 #if !defined(ECERE_NOTRUETYPE)
2782 Font font = Font { };
2785 char fileName[MAX_LOCATION];
2786 bool fakeItalic = flags.italic;
2787 char linkCfgPath[MAX_LOCATION];
2789 #if !defined(__WIN32__)
2792 char * ecereFonts = getenv("ECERE_FONTS");
2793 if(!ecereFonts) ecereFonts = "<:ecere>";
2794 #if !defined(__WIN32__)
2795 strcpy(linkCfgPath, ecereFonts);
2796 PathCat(linkCfgPath, "linking.cfg");
2797 linkCfg = FileOpen(linkCfgPath, read);
2799 strcpy(fileName, faceName);
2800 strcpy(font.faceName, faceName);
2802 font.displaySystem = displaySystem;
2804 if(!FileExists(fileName))
2806 strcpy(fileName, ecereFonts);
2807 PathCat(fileName, faceName);
2808 if(flags.bold && flags.italic) strcat(fileName, "bi");
2809 else if(flags.bold) strcat(fileName, "bd");
2810 else if(flags.italic) strcat(fileName, "i");
2811 strcat(fileName, ".ttf");
2815 if(flags.italic && !FileExists(fileName))
2817 strcpy(fileName, ecereFonts);
2818 PathCat(fileName, faceName);
2819 if(flags.bold) strcat(fileName, "bd");
2820 strcat(fileName, ".ttf");
2825 // Search in current working directory
2826 if(!FileExists(fileName))
2828 strcpy(fileName, faceName);
2829 if(flags.bold && flags.italic) strcat(fileName, "bi");
2830 else if(flags.bold) strcat(fileName, "bd");
2831 else if(flags.italic) strcat(fileName, "i");
2832 strcat(fileName, ".ttf");
2836 if(flags.italic && !FileExists(fileName))
2838 strcpy(fileName, faceName);
2839 if(flags.bold) strcat(fileName, "bd");
2840 strcat(fileName, ".ttf");
2846 #if defined(__WIN32__)
2847 if(!FileExists(fileName))
2849 FontData fontData = { { 0 } };
2850 LOGFONT logFont = { 0 };
2855 logFont.lfCharSet = DEFAULT_CHARSET;
2856 strcpy(logFont.lfFaceName, faceName);
2857 fontData.flags = flags;
2859 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2860 if(!fontData.fileName[0] && flags.bold)
2862 fontData.forgive = true;
2863 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2865 if(!fontData.fileName[0])
2868 fontData.flags.italic = false;
2869 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2873 if(fontData.fileName[0])
2875 GetWindowsDirectory(fileName, MAX_LOCATION);
2876 PathCat(fileName, "fonts");
2877 PathCat(fileName, fontData.fileName);
2881 #elif !defined(ECERE_NOFONTCONFIG)
2884 FcResult result = 0;
2885 FcPattern * pattern;
2886 FcPattern * matched;
2888 unichar testChar = 0;
2889 FcCharSet * charSet;
2891 fcConfig = FcInitLoadConfigAndFonts();
2893 charSet = FcCharSetCreate();
2895 if(!strcmpi(faceName, "Mangal"))
2901 FcCharSetAddChar(charSet, testChar);
2903 pattern = FcPatternBuild(null,
2904 //FC_SOURCE, FcTypeString, "freetype",
2905 FC_FAMILY, FcTypeString, faceName,
2906 //FC_SCALABLE, FcTypeBool, 1,
2907 FC_SIZE, FcTypeDouble, (double)size,
2908 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2909 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2910 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2912 FcDefaultSubstitute(pattern);
2913 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2915 matched = FcFontMatch (0, pattern, &result);
2916 // printf("Locating %s\n", faceName);
2919 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2920 //printf("Fontconfig returned %s\n", family);
2922 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2925 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2926 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2927 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2928 strcpy(fileName, fileName2);
2929 // size = (float)fontSize;
2931 //printf("Matched to %s, %f\n", fileName, size);
2935 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2937 if(pattern) FcPatternDestroy(pattern);
2938 if(matched) FcPatternDestroy(matched);
2939 if(charSet) FcCharSetDestroy(charSet);
2944 if(!FileExists(fileName))
2945 ChangeExtension(fileName, "otf", fileName);
2946 if(!FileExists(fileName))
2947 ChangeExtension(fileName, "ttc", fileName);
2949 //if(FileExists(fileName))
2952 char links[1024] = "";
2954 #if defined(__WIN32__)
2957 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2958 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2963 RegQueryValueEx(key, faceName, null, (LPDWORD)&type, (LPBYTE)links, (LPDWORD)&size);
2964 memset(links + size, 0, 1024 - size);
2972 while(linkCfg.GetLine(line, sizeof(line)))
2974 int len = strlen(faceName);
2975 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2977 while(linkCfg.GetLine(line, sizeof(line)))
2979 TrimLSpaces(line, line);
2980 if(!line[0] || line[0] == '[')
2983 memcpy(links + linksPos, line, len);
2985 links[linksPos] = 0;
2993 while(entry < MAX_FONT_LINK_ENTRIES)
2995 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2998 File file = FileOpen/*Buffered*/(fileName, read);
3001 FileSize fileSize = file.GetSize();
3002 FT_Open_Args args = { 0 };
3003 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3004 FT_Stream stream = new0 FT_StreamRec[1];
3007 FT_Init_FreeType( &ftLibrary );
3009 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3010 fontEntry.stream = stream;
3013 fontEntry.buffer = new byte[fileSize];
3014 file.Read(fontEntry.buffer, 1, fileSize);
3017 //args.num_params = 1;
3018 args.params = ¶m;
3020 stream->size = fileSize;
3021 stream->descriptor.pointer = file;
3022 stream->read = FT_stream_load;
3023 stream->close = FT_stream_close;
3025 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3026 args.stream = stream;
3027 //args.pathname = fileName;
3028 //args.memory_base = fontEntry.buffer;
3029 //args.memory_size = fileSize;
3031 // printf("Opening: %s\n", fileName);
3032 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3037 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3038 fontEntry.hbFont.klass = &hb_fontClass;
3039 fontEntry.hbFont.userData = fontEntry; //.face;
3042 loadedFonts.Add(fontEntry);
3047 // printf("Error opening font %s\n", fileName);
3056 FT_Vector pen = { 0, 0 };
3059 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3060 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3061 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3062 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3066 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3067 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3068 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3069 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3071 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3072 FaceSetCharSize(fontEntry.face, size);
3073 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3074 // printf("Font height is %d\n", font.height);
3075 font.fakeItalic = fakeItalic;
3079 font.fontEntries[entry++] = fontEntry;
3086 char fontName[1024];
3087 if(!links[linksPos]) break;
3088 for(c = 0; (ch = links[linksPos + c]); c++)
3091 if(ch == ',') break;
3094 if(fontName[0] || ch == ',')
3096 #if defined(__WIN32__)
3097 GetWindowsDirectory(fileName, MAX_LOCATION);
3098 PathCat(fileName, "fonts");
3099 PathCat(fileName, fontName);
3100 #elif !defined(ECERE_NOFONTCONFIG)
3101 if(getenv("ECERE_FONTS"))
3103 strcpy(fileName, ecereFonts);
3104 PathCat(fileName, fontName);
3110 FcResult result = 0;
3111 FcPattern * pattern;
3112 FcPattern * matched;
3114 pattern = FcPatternBuild(null,
3115 //FC_SOURCE, FcTypeString, "freetype",
3116 //FC_SCALABLE, FcTypeBool, 1,
3117 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3118 FC_SIZE, FcTypeDouble, (double)size,
3119 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3120 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3122 FcDefaultSubstitute(pattern);
3123 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3125 //printf("Locating %s\n", links + linksPos + c + 1);
3126 matched = FcFontMatch (0, pattern, &result);
3129 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3130 // printf("Fontconfig returned %s\n", family);
3132 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3133 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3136 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3137 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3138 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3139 strcpy(fileName, fileName2);
3140 //size = (float)fontSize;
3141 // printf("Matched to %s, %f\n", fileName, size);
3145 // 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);
3147 if(pattern) FcPatternDestroy(pattern);
3148 if(matched) FcPatternDestroy(matched);
3155 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3162 UnloadFont(displaySystem, font);
3165 font.asciiPack.Render(font, 0, displaySystem);
3167 #if !defined(__WIN32__)
3175 #if !defined(ECERE_NOTRUETYPE)
3176 void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
3177 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3178 Surface surface, Display display, int * x, int y)
3180 if(font && font.fontEntries && font.fontEntries[0])
3182 int previousGlyph = 0;
3183 FT_Face previousFace = 0;
3184 int c, nb, glyphIndex = 0;
3185 unichar lastPack = 0;
3186 GlyphPack pack = font.asciiPack;
3190 bool rightToLeft = false;
3191 int fontEntryNum = 0;
3192 int glyphScript = 0;
3193 FontEntry curFontEntry;
3195 pack.bitmap.alphaBlend = true;
3197 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3201 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3203 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3204 rightToLeft ? glyphIndex-- : glyphIndex++;
3208 HB_Script curScript = HB_Script_Common;
3209 byte * scriptStart = text + c;
3210 unichar nonASCIIch = 0;
3213 unichar testChar = 0;
3214 char * testLang = null;
3218 HB_Script script = HB_Script_Common;
3219 ch = UTF8GetChar((char *)text + c, &nb);
3220 if(ch > 127) nonASCIIch = ch;
3222 if(ch == 32 && curScript)
3229 for(a = c + 1; a < c + len; a++)
3237 unichar ahead = UTF8GetChar((char *)text + a, &nb);
3238 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3246 script = HB_Script_Common;
3247 else if(ch <= 0x11FF)
3251 case 0x300: script = HB_Script_Greek; break;
3252 case 0x400: script = HB_Script_Cyrillic; break;
3253 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3254 case 0x600: script = HB_Script_Arabic; break;
3255 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3256 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3257 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3258 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3259 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3260 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3261 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3262 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3263 case 0xF00: script = HB_Script_Tibetan; break;
3264 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3265 case 0x1100: script = HB_Script_Hangul; break;
3268 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3269 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3270 script = HB_Script_Hangul;
3271 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3272 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3273 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3274 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3275 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3276 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3277 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3278 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3279 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3282 if(!script || (script != curScript))
3290 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3291 if(!script) { c += nb; break; }
3298 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3300 rightToLeft = false;
3302 theCurrentScript = 0;
3306 int len = c - (int)(scriptStart - text);
3307 int max = len * 2 + 1;
3308 if(max > utf16BufferSize)
3310 utf16 = renew utf16 uint16[max];
3311 utf16BufferSize = max;
3313 wc = UTF8toUTF16BufferLen((char *)scriptStart, utf16, max, len);
3314 theCurrentScript = glyphScript = curScript;
3318 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3319 //printf("Arabic ");
3321 case HB_Script_Devanagari: testChar = 0x905; testLang = "sa";
3322 //printf("Devanagari ");
3324 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3325 //printf("Hebrew ");
3328 testChar = (ch == '\t') ? ' ' : ch;
3330 case 60: testChar = 'あ'; break;
3331 case 61: testChar = 0x3400; break; //'愛'; break;
3337 // printf("Testing for char %x\n", testChar);
3338 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3340 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3342 /*if(font.fontEntries[fontEntryNum])
3343 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3347 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3349 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3351 double fontSize = font.size;
3352 FcResult result = 0;
3353 FcPattern * pattern;
3354 FcPattern * matched;
3355 FcCharSet * charSet;
3357 FontEntry fontEntry;
3358 char * fileName = null;
3359 bool fakeItalic = false;
3360 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3361 if(!font.fontEntries[fontEntryNum])
3363 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3367 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3369 charSet = FcCharSetCreate();
3370 FcCharSetAddChar(charSet, testChar);
3371 //printf("Loading with char %x\n", testChar);
3373 pattern = FcPatternBuild(null,
3374 //FC_SOURCE, FcTypeString, "freetype",
3375 //FC_SCALABLE, FcTypeBool, 1,
3376 FC_FAMILY, FcTypeString, font.faceName,
3377 FC_SIZE, FcTypeDouble, (double)font.size,
3378 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3379 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3380 FC_CHARSET,FcTypeCharSet, charSet,
3381 testLang ? FC_LANG : 0, FcTypeString,testLang,
3383 FcDefaultSubstitute(pattern);
3384 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3386 //printf("Locating %s for script %d\n", font.faceName, curScript);
3387 matched = FcFontMatch (0, pattern, &result);
3390 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3391 //printf("Fontconfig returned %s\n", family);
3393 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3395 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3396 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3397 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3398 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3402 //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);
3407 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3410 File file = FileOpen(fileName, read);
3413 FileSize fileSize = file.GetSize();
3414 FT_Open_Args args = { 0 };
3415 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3416 FT_Stream stream = new0 FT_StreamRec[1];
3419 FT_Init_FreeType( &ftLibrary );
3421 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3422 fontEntry.stream = stream;
3424 //args.num_params = 1;
3425 args.params = ¶m;
3427 stream->size = fileSize;
3428 stream->descriptor.pointer = file;
3429 stream->read = FT_stream_load;
3430 stream->close = FT_stream_close;
3432 args.flags = FT_OPEN_STREAM;
3433 args.stream = stream;
3434 //args.pathname = fileName;
3435 //args.memory_base = fontEntry.buffer;
3436 //args.memory_size = fileSize;
3438 // printf("Opening: %s\n", fileName);
3439 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3444 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3445 fontEntry.hbFont.klass = &hb_fontClass;
3446 fontEntry.hbFont.userData = fontEntry; //.face;
3449 loadedFonts.Add(fontEntry);
3454 // printf("Error opening font %s\n", fileName);
3460 FaceSetCharSize(fontEntry.face, font.size);
3462 font.fontEntries[fontEntryNum] = fontEntry;
3466 if(pattern) FcPatternDestroy(pattern);
3467 if(matched) FcPatternDestroy(matched);
3468 if(charSet) FcCharSetDestroy(charSet);
3471 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3472 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3474 font.fontEntries[fontEntryNum].font = font;
3475 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3479 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3480 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3481 rightToLeft ? glyphIndex-- : glyphIndex++;
3485 curFontEntry = font.fontEntries[fontEntryNum];
3487 packNo = glyphNo & 0xFFFFFF80;
3489 if(packNo != lastPack)
3492 pack = font.asciiPack;
3495 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3498 pack = GlyphPack { key = (uintptr)packNo };
3499 font.glyphPacks.Add(pack);
3500 pack.Render(font, fontEntryNum, displaySystem);
3503 pack.bitmap.alphaBlend = true;
3508 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3509 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3511 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3512 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3513 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3517 if(previousGlyph && curFontEntry.face == previousFace)
3519 FT_Vector delta = { 0, 0 };
3520 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3521 if(delta.x < 0) delta.x += (-delta.x) % 64;
3522 else if(delta.x) delta.x += 64 - (delta.x % 64);
3523 *x += delta.x * glyph->scale;
3526 FaceSetCharSize(curFontEntry.face, font.size);
3528 previousGlyph = glyph->glyphNo;
3529 previousFace = curFontEntry.face;
3532 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3535 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3541 LFBSurface lfbSurface = surface.driverData;
3542 lfbSurface.xOffset = 0;
3547 void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3549 if(displaySystem && displaySystem.flags.text && len)
3554 *width = num * textCellW;
3556 if(height) *height = textCellH;
3558 else if(font && len)
3563 #if !defined(ECERE_NOTRUETYPE)
3564 ProcessString(font, displaySystem, text, len, null, null, null, &w, 0);
3566 //*width = (w + 64 - w % 64) >> 6;
3570 *height = font.height;
3574 if(width) *width = 0;
3575 if(height) *height = 0;
3579 #if !defined(ECERE_NOTRUETYPE)
3580 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3582 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3586 void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3588 LFBSurface lfbSurface = surface.driverData;
3589 if(display && display.displaySystem.flags.text)
3591 LFBDisplay lfbDisplay = display.driverData;
3592 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3598 if(y > surface.box.bottom || y < surface.box.top)
3600 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3601 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3602 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3604 if(surface.textOpacity)
3605 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3607 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3612 lfbSurface.writingText = true;
3613 #if !defined(ECERE_NOTRUETYPE)
3615 ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3617 lfbSurface.writingText = false;
3621 void TextFont(Display display, Surface surface, Font font)
3623 LFBSurface lfbSurface = surface.driverData;
3624 lfbSurface.font = font;
3627 void TextOpacity(Display display, Surface surface, bool opaque)
3629 LFBSurface lfbSurface = surface.driverData;
3633 void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3635 LFBSurface lfbSurface = surface.driverData;
3636 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3639 void DrawingChar(Display display, Surface surface, byte character)
3641 LFBSurface lfbSurface = surface.driverData;
3642 lfbSurface.drawingChar = character;
3645 void LineStipple(Display display, Surface surface, uint32 stipple)
3647 LFBSurface lfbSurface = surface.driverData;
3648 lfbSurface.stipple = (uint16)stipple;
3651 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3652 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3654 if(mesh.vertices && !mesh.flags.vertices)
3655 delete mesh.vertices;
3656 if(mesh.normals && !mesh.flags.normals)
3657 delete mesh.normals;
3658 if(mesh.texCoords && !mesh.flags.texCoords1)
3659 delete mesh.texCoords;
3662 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3664 bool result = false;
3666 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3667 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3668 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3673 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3678 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3683 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3685 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3687 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)