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(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.sizeBytes = bitmap.sizeBytes;
1008 src.pixelFormat = bitmap.pixelFormat;
1013 bitmap.palette = null;
1014 bitmap.picture = null;
1022 void DestroyDisplay(Display display)
1024 LFBDisplay lfbDisplay = display.driverData;
1025 delete lfbDisplay.bitmap.palette;
1028 bool CreateDisplay(Display display)
1030 bool result = false;
1031 LFBDisplay lfbDisplay = display.driverData;
1034 lfbDisplay = display.driverData = LFBDisplay { };
1035 lfbDisplay.selfManaged = true;
1036 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1039 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1041 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1047 bool DisplaySize(Display display, int width, int height)
1049 LFBDisplay lfbDisplay = display.driverData;
1050 //display.width = width;
1051 //display.height = height;
1052 lfbDisplay.bitmap.width = width;
1053 lfbDisplay.bitmap.height = height;
1055 lfbDisplay.updateBox.left = display.width;
1056 lfbDisplay.updateBox.top = display.height;
1057 lfbDisplay.updateBox.right = 0;
1058 lfbDisplay.updateBox.bottom = 0;
1061 if(lfbDisplay.selfManaged)
1063 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1064 lfbDisplay.bitmap.stride = width;
1066 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1070 void DisplayPosition(Display display, int x, int y)
1072 LFBDisplay lfbDisplay = display.driverData;
1077 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1079 LFBDisplay lfbDisplay = display.driverData;
1086 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1087 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1088 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1091 for(c = 0; c<32768; c++)
1092 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1094 for(c=0; c<256; c++)
1097 for(i=0; i<LIGHTSTEPS; i++)
1099 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1100 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1101 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1102 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1106 if(lfbDisplay.bitmap.palette)
1107 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1110 void Update(Display display, Box updateBox)
1112 LFBDisplay lfbDisplay = display.driverData;
1113 if(lfbDisplay.displayCallback)
1115 if(updateBox == null)
1117 Box box { 0,0, display.width,display.height };
1118 lfbDisplay.displayCallback(display, box);
1121 lfbDisplay.displayCallback(display, updateBox);
1125 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1127 if(bitmap.pixelFormat != pixelFormatAlpha)
1129 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1131 FreeBitmap(displaySystem, bitmap);
1138 void ReleaseSurface(Display display, Surface surface)
1140 LFBSurface lfbSurface = surface.driverData;
1142 surface.driverData = null;
1145 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1147 LFBDisplay lfbDisplay = display.driverData;
1148 LFBSurface lfbSurface = surface.driverData;
1151 lfbSurface = surface.driverData = LFBSurface { };
1154 lfbSurface.bitmap = lfbDisplay.bitmap;
1156 surface.offset.x = x;
1157 surface.offset.y = y;
1159 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1161 surface.offset.x /= textCellW;
1162 surface.offset.y /= textCellH;
1163 surface.box.left /= textCellW;
1164 surface.box.top /= textCellH;
1165 surface.box.right /= textCellW;
1166 surface.box.bottom /= textCellH;
1170 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1171 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1172 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1173 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1176 surface.unclippedBox = surface.box;
1177 lfbSurface.drawingChar = 219;
1181 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1183 bool result = false;
1184 LFBSurface lfbSurface = surface.driverData;
1185 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1187 lfbSurface.bitmap = bitmap;
1189 surface.offset.x = x;
1190 surface.offset.y = y;
1192 if(bitmap.pixelFormat == pixelFormatText)
1194 surface.offset.x /= textCellW;
1195 surface.offset.y /= textCellH;
1196 surface.box.left /= textCellW;
1197 surface.box.top /= textCellH;
1198 surface.box.right /= textCellW;
1199 surface.box.bottom /= textCellH;
1202 surface.unclippedBox = *&surface.box;
1203 lfbSurface.drawingChar = 219;
1210 void Clip(Display display, Surface surface, Box clip)
1212 LFBSurface lfbSurface = surface.driverData;
1217 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1219 box.left /= textCellW;
1220 box.top /= textCellH;
1221 box.right /= textCellW;
1222 box.bottom /= textCellH;
1224 box.Clip(surface.unclippedBox);
1228 surface.box = surface.unclippedBox;
1231 void SetForeground(Display display, Surface surface, ColorAlpha color)
1233 LFBDisplay lfbDisplay = display ? display.driverData : null;
1234 LFBSurface lfbSurface = surface.driverData;
1236 if(display) color = color /*& 0xFFFFFF*/;
1237 lfbSurface.foregroundRgb = color;
1239 if(lfbSurface.font && lfbDisplay)
1241 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1242 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1245 switch(lfbSurface.bitmap.pixelFormat)
1249 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1251 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1253 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1254 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1255 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1256 case pixelFormat888: lfbSurface.foreground = color; break;
1257 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1258 case pixelFormatText:
1260 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1262 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1267 void SetBackground(Display display, Surface surface, ColorAlpha color)
1269 LFBDisplay lfbDisplay = display ? display.driverData : null;
1270 LFBSurface lfbSurface = surface.driverData;
1271 color = color /*& 0xFFFFFF*/;
1272 switch(lfbSurface.bitmap.pixelFormat)
1276 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1278 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1280 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1281 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1282 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1283 case pixelFormat888: lfbSurface.background = color; break;
1284 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1285 case pixelFormatText:
1287 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1289 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1294 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1296 LFBSurface lfbSurface = surface.driverData;
1297 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1302 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1304 x += surface.offset.x;
1305 y += surface.offset.y;
1306 if(lfbSurface.bitmap.picture)
1308 switch(lfbSurface.bitmap.pixelFormat)
1310 case pixelFormatText:
1312 if(!lfbSurface.bitmap.palette) return 0;
1313 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1314 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1315 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1316 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1317 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1324 void PutPixel(Display display, Surface surface,int x,int y)
1326 LFBSurface lfbSurface = surface.driverData;
1327 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1332 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1334 x += surface.offset.x;
1335 y += surface.offset.y;
1336 if(lfbSurface.bitmap.picture)
1338 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1341 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1344 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1347 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1348 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1355 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1357 LFBSurface lfbSurface = surface.driverData;
1363 uint color = lfbSurface.foreground;
1364 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1365 bool invert = false;
1366 if(!lfbSurface.bitmap.picture) return;
1367 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1373 if(surface.textOpacity)
1374 color |= lfbSurface.background;
1375 color |= lfbSurface.drawingChar;
1379 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1381 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1382 if((x1>surface.box.right)||(x2<surface.box.left))return;
1383 if(x1<surface.box.left)x1=surface.box.left;
1384 if(x2>surface.box.right)x2=surface.box.right;
1388 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1389 if(stipple != 0xFFFF)
1392 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1395 for(x=x1; x<=x2; x++, offset++)
1397 if(stipple & 0x8000)
1398 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1400 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1402 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1406 for(x=x1; x<=x2; x++, offset++)
1408 if(stipple & 0x8000)
1409 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1411 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1413 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1417 for(x=x1; x<=x2; x++, offset++)
1419 if(stipple & 0x8000)
1420 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1422 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1424 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1431 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1433 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1435 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1436 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1437 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1443 for(x = x1; x <= x2; x++, offset++)
1445 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1446 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1455 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1457 if((x1>surface.box.right)||(x1<surface.box.left))return;
1458 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1459 if(y1<surface.box.top)y1=surface.box.top;
1460 if(y2>surface.box.bottom)y2=surface.box.bottom;
1462 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1463 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1466 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1468 if(stipple & 0x8000)
1469 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1471 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1473 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1477 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1479 if(stipple & 0x8000)
1481 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1482 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1485 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1486 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1490 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1492 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1496 if(stipple != 0xFFFF)
1498 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1500 if(stipple & 0x8000)
1501 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1503 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1505 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1510 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1511 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1520 if(x1 < surface.box.left)
1522 if(x2 < surface.box.left)
1524 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1525 x1 = surface.box.left;
1527 if(x2 > surface.box.right)
1529 if(x1 > surface.box.right)
1531 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1532 x2 = surface.box.right;
1536 if(y1 < surface.box.top)
1538 if(y2 < surface.box.top)
1540 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1541 y1 = surface.box.top;
1543 if(y2 > surface.box.bottom)
1545 if(y1 > surface.box.bottom)
1547 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1548 y2 = surface.box.bottom;
1553 if(y1 > surface.box.bottom)
1555 if(y2 > surface.box.bottom)
1557 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1558 y1 = surface.box.bottom;
1560 if(y2 < surface.box.top)
1562 if(y1 < surface.box.top)
1564 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1565 y2 = surface.box.top;
1571 if(x1 > surface.box.right)
1573 if(x2 > surface.box.right)
1575 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1576 x1 = surface.box.right;
1578 if(x2 < surface.box.left)
1580 if(x1 < surface.box.left)
1582 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1583 x2 = surface.box.left;
1587 if(y1 < surface.box.top)
1589 if(y2 < surface.box.top)
1591 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1592 y1 = surface.box.top;
1594 if(y2 > surface.box.bottom)
1596 if(y1 > surface.box.bottom)
1598 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1599 y2 = surface.box.bottom;
1604 if(y1 > surface.box.bottom)
1606 if(y2 > surface.box.bottom)
1608 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1609 y1 = surface.box.bottom;
1611 if(y2 < surface.box.top)
1613 if(y1 < surface.box.top)
1615 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1616 y2 = surface.box.top;
1634 yu=-(int)lfbSurface.bitmap.stride;
1637 yu=lfbSurface.bitmap.stride;
1639 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1645 for(i=0; i<=length; i++)
1647 if(stipple & 0x8000)
1648 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1650 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1651 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1652 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1661 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1667 for(i=0; i<=length; i++)
1669 if(stipple & 0x8000)
1670 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1672 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1673 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1674 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1688 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1690 DrawLine(display, surface,x1,y1,x2,y1);
1691 DrawLine(display, surface,x2,y1,x2,y2);
1692 DrawLine(display, surface,x2,y2,x1,y2);
1693 DrawLine(display, surface,x1,y2,x1,y1);
1696 #if !defined(__GNUC__)
1698 void memset_32_aligned(void *buf, int val, int dwords)
1703 *((uint32 *)(buf)) = val;
1704 buf = ((uint32 *)(buf))+1;
1730 if (dwords & 1) *((int*)(buf)) = val;
1736 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1740 if(((uint32)buf) & 0x7F)
1742 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1768 sub edx,ebx ; edx holds # of overflow bytes
1787 movdqa [edi+16],xmm0
1788 movdqa [edi+32],xmm0
1789 movdqa [edi+48],xmm0
1790 movdqa [edi+64],xmm0
1791 movdqa [edi+80],xmm0
1792 movdqa [edi+96],xmm0
1793 movdqa [edi+112],xmm0
1817 void memset_32(void *buf, uint32 val, uint32 dwords)
1820 if ((uint32)(buf) & 3)
1825 if (((uint32)(buf) & 1))
1827 *(byte *)(buf) = (byte)(val&0xFF);
1828 buf = ((byte *)(buf))+1;
1829 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1832 if (((uint32)(buf) & 2))
1834 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1835 buf = ((uint16 *)(buf))+1;
1836 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1840 memset_32_aligned(buf,val,dwords);
1845 *(byte *)(buf) = (byte)(val&0xFF);
1849 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1850 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1857 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1859 LFBSurface lfbSurface = surface.driverData;
1860 uint32 color = lfbSurface.background;
1862 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1864 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1870 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1872 if(x1<surface.box.left) x1=surface.box.left;
1873 if(x2>surface.box.right) x2=surface.box.right;
1874 if(y1<surface.box.top) y1=surface.box.top;
1875 if(y2>surface.box.bottom) y2=surface.box.bottom;
1877 if(x2>=x1 && y2>=y1)
1885 x1 += surface.offset.x;
1886 x2 += surface.offset.x;
1887 y1 += surface.offset.y;
1888 y2 += surface.offset.y;
1889 if(lfbSurface.bitmap.picture)
1891 if(!surface.writeColor)
1893 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1894 for(y = y1; y<= y2; y++)
1897 for(c = 0; c < w; c++, picture++)
1899 picture->a = (byte)((color & 0xFF000000) >> 24);
1900 picture += lfbSurface.bitmap.stride - w;
1905 if(surface.background.a == 255 || lfbSurface.clearing)
1907 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1910 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1911 for(y = y1; y<= y2; y++)
1913 FillBytes(theOffset,(byte)color,w);
1914 theOffset += lfbSurface.bitmap.stride;
1918 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1919 for(y = y1; y<= y2; y++)
1921 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1922 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1926 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1927 for(y = y1; y<= y2; y++)
1929 #if defined(__GNUC__)
1930 FillBytesBy4((uint32 *) theOffset,color,w);
1932 memset_32((uint32 *) theOffset,color,w);
1934 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1940 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1941 //memset_32((uint32 *) theOffset,color,w);
1977 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1980 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1981 for(y = y1; y<= y2; y++)
1983 // TODO: IMPLEMENT THIS
1984 FillBytes(theOffset,(byte)color,w);
1985 theOffset += lfbSurface.bitmap.stride;
1990 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1991 ColorAlpha c = surface.background;
1996 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1998 for(y = y1; y <= y2; y++)
2001 for(c = 0; c < w; c++, dest++)
2004 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2005 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2006 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2008 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2009 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2010 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2012 if(r > 255) r = 255;
2013 if(g > 255) g = 255;
2014 if(b > 255) b = 255;
2016 destColor = { (byte)r, (byte)g, (byte)b };
2018 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2019 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2020 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2023 dest += (lfbSurface.bitmap.stride - w);
2029 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2030 AlphaWriteMode alphaWrite = surface.alphaWrite;
2031 ColorAlpha c = surface.background;
2036 for(y = y1; y <= y2; y++)
2039 for(c = 0; c < w; c++, dest++)
2041 int dr = dest->color.r;
2042 int dg = dest->color.g;
2043 int db = dest->color.b;
2044 int r = a * cr / 255 + ((255 - a) * dr / 255);
2045 int g = a * cg / 255 + ((255 - a) * dg / 255);
2046 int b = a * cb / 255 + ((255 - a) * db / 255);
2048 if(r > 255) r = 255;
2049 if(g > 255) g = 255;
2050 if(b > 255) b = 255;
2051 dest->color = { (byte)r, (byte)g, (byte)b };
2053 if(alphaWrite == blend)
2055 int ca = (int)(a + ((255 - a) * dest->a / 255));
2056 if(ca > 255) ca = 255;
2062 dest += (lfbSurface.bitmap.stride - w);
2071 void Clear(Display display, Surface surface, ClearType type)
2073 LFBSurface lfbSurface = surface.driverData;
2075 lfbSurface.clearing = true;
2076 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2077 surface.box.left == 0 && surface.box.top == 0 &&
2078 surface.box.right == surface.width-1 &&
2079 surface.box.bottom == surface.height-1)
2081 uint32 color = /*0xFF000000 | */lfbSurface.background;
2082 if(type != depthBuffer)
2084 if(lfbSurface.bitmap.stride != surface.width)
2085 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2088 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2091 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2093 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2094 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2099 if((flags & CLEAR_Z) && zbuffer)
2100 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2105 if(type != depthBuffer)
2106 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2108 if((flags & CLEAR_Z))
2111 uint32 w = surface.box.right-surface.box.left+1;
2112 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2113 + surface.box.left+surface.offset.x;
2114 for(y = surface.box.top; y<= surface.box.bottom; y++)
2116 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2117 offset += DISPLAY.Width;
2122 lfbSurface.clearing = false;
2125 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2127 LFBSurface lfbSurface = surface.driverData;
2130 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2132 if(w < 0) { w = -w; flip = true; }
2134 //Clip against the edges of the source
2147 if(sx+w>src.width-1)
2148 w-=sx+w-(src.width-1)-1;
2149 if(sy+h>src.height-1)
2150 h-=sy+h-(src.height-1)-1;
2151 //Clip against the edges of the destination
2152 if(dx<surface.box.left)
2154 if(!flip) sx+=surface.box.left-dx;
2155 w-=surface.box.left-dx;
2156 dx=surface.box.left;
2158 if(dy<surface.box.top)
2160 sy+=surface.box.top-dy;
2161 h-=surface.box.top-dy;
2164 if((dx+w)>surface.box.right)
2166 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2167 w-=((uint32)(dx+w)-surface.box.right-1);
2169 if((dy+h)>surface.box.bottom)
2170 h-=((dy+h)-surface.box.bottom-1);
2174 dx += surface.offset.x;
2175 dy += surface.offset.y;
2177 if(lfbSurface.bitmap.picture)
2179 AlphaWriteMode alphaWrite = surface.alphaWrite;
2180 if(src.alphaBlend && surface.blend)
2183 if(src.pixelFormat == pixelFormatAlpha)
2185 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2187 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2188 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2189 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2190 for(y = 0; y < h; y++)
2192 for(x = 0; x < w; x++, picture++, source++)
2194 int a = *source * color.a;
2195 ColorAlpha dest = *picture;
2196 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2197 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2198 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2199 if(r > 255) r = 255;
2200 if(g > 255) g = 255;
2201 if(b > 255) b = 255;
2202 picture->color = { (byte)r, (byte)g, (byte)b };
2203 if(alphaWrite == blend)
2205 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2206 if(ca > 255) ca = 255;
2207 picture->a = (byte)ca;
2210 picture->a = (byte)(a / 255);
2212 picture += lfbSurface.bitmap.stride - w;
2213 source += src.stride - w;
2216 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2218 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2219 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2220 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2221 for(y = 0; y < h; y++)
2223 for(x = 0; x < w; x++, picture++, source++)
2225 int a = *source * color.a;
2226 Color dest = *picture;
2227 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2228 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2229 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2230 if(r > 255) r = 255;
2231 if(g > 255) g = 255;
2232 if(b > 255) b = 255;
2233 *picture = Color { (byte)r, (byte)g, (byte)b };
2235 picture += lfbSurface.bitmap.stride - w;
2236 source += src.stride - w;
2239 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2241 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2242 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2243 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2244 for(y = 0; y < h; y++)
2246 for(x = 0; x < w; x++, picture++, source++)
2248 int a = *source * color.a;
2249 Color dest = *picture;
2250 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2251 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2252 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2253 if(r > 255) r = 255;
2254 if(g > 255) g = 255;
2255 if(b > 255) b = 255;
2256 *picture = Color { (byte)r, (byte)g, (byte)b };
2258 picture += lfbSurface.bitmap.stride - w;
2259 source += src.stride - w;
2265 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2266 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2268 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2269 for(y = 0; y < h; y++)
2271 for(x = 0; x < w; x++, picture++, source++)
2273 ColorAlpha src = *source;
2274 ColorAlpha dest = *picture;
2275 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2276 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2277 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2278 if(r > 255) r = 255;
2279 if(g > 255) g = 255;
2280 if(b > 255) b = 255;
2281 picture->color = { (byte)r, (byte)g, (byte)b };
2282 if(alphaWrite == blend)
2284 int a = src.a + ((255 - src.a) * dest.a / 255);
2285 if(a > 255) a = 255;
2286 picture->a = (byte)a;
2291 picture += lfbSurface.bitmap.stride - w;
2292 source += src.stride - w;
2295 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2297 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2298 for(y = 0; y < h; y++)
2300 for(x = 0; x < w; x++, picture++, source++)
2302 ColorAlpha src = *source;
2303 Color565 dest = *picture;
2304 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2305 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2306 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2307 if(r > 255 * 31) r = 255 * 31;
2308 if(g > 255 * 63) g = 255 * 63;
2309 if(b > 255 * 31) b = 255 * 31;
2310 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2312 picture += lfbSurface.bitmap.stride - w;
2313 source += src.stride - w;
2316 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2318 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2319 for(y = 0; y < h; y++)
2321 for(x = 0; x < w; x++, picture++, source++)
2323 ColorAlpha psrc = *source;
2324 Color555 dest = *picture;
2325 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2326 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2327 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2328 if(r > 255 * 31) r = 255 * 31;
2329 if(g > 255 * 31) g = 255 * 31;
2330 if(b > 255 * 31) b = 255 * 31;
2331 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2333 picture += lfbSurface.bitmap.stride - w;
2334 source += src.stride - w;
2339 else if(src.paletteShades)
2340 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2341 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2342 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2343 else if(src.pixelFormat == pixelFormat8)
2344 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2348 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2350 bool result = false;
2351 LFBDisplay lfbDisplay = display.driverData;
2353 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2356 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2357 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2361 Surface surface = bitmap.GetSurface(0,0,null);
2364 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2365 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2366 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2374 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2376 LFBSurface lfbSurface = surface.driverData;
2379 float s2dw,s2dh,d2sw,d2sh;
2381 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2383 if(Sgn(w) != Sgn(sw))
2395 //Clip against the edges of the source
2398 dx+=(int)((0-sx) * s2dw);
2399 w-=(int)((0-sx) * s2dw);
2405 dy+=(int)((0-sy) * s2dh);
2406 h-=(int)((0-sy) * s2dh);
2411 if(sx+sw>src.width-1)
2413 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2414 sw-=sx+sw-(src.width-1)-1;
2416 if(sy+sh>(src.height-1))
2418 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2419 sh-=sy+sh-(src.height-1)-1;
2421 //Clip against the edges of the destination
2422 if(dx<surface.box.left)
2424 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2425 sw-=(int)((surface.box.left-dx)*d2sw);
2426 w-=surface.box.left-dx;
2427 dx=surface.box.left;
2429 if(dy<surface.box.top)
2431 sy+=(int)((surface.box.top-dy)*d2sh);
2432 sh-=(int)((surface.box.top-dy)*d2sh);
2433 h-=surface.box.top-dy;
2436 if((dx+w)>surface.box.right)
2438 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2439 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2440 w-=((dx+w)-surface.box.right-1);
2442 if((dy+h)>surface.box.bottom)
2444 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2445 h-=((dy+h)-surface.box.bottom-1);
2447 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2449 dx+=surface.offset.x;
2450 dy+=surface.offset.y;
2452 if(lfbSurface.bitmap.picture)
2454 AlphaWriteMode alphaWrite = surface.alphaWrite;
2455 if(src.alphaBlend && surface.blend)
2459 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2460 ColorAlpha * backsrc;
2461 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2462 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2463 if(flip < 0) source += sw-1;
2481 ColorAlpha src = *source;
2482 ColorAlpha dst = *dest;
2483 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2484 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2485 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2486 if(r > 255) r = 255;
2487 if(g > 255) g = 255;
2488 if(b > 255) b = 255;
2489 dest->color = { (byte)r, (byte)g, (byte)b };
2490 if(alphaWrite == blend)
2492 int a = src.a + ((255 - src.a) * dst.a / 255);
2493 if(a > 255) a = 255;
2506 source += addsource;
2509 else if(src.paletteShades)
2510 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2511 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2512 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2513 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2514 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2518 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2520 LFBSurface lfbSurface = surface.driverData;
2523 float s2dw,s2dh,d2sw,d2sh;
2525 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2527 if(Sgn(w) != Sgn(sw))
2539 //Clip against the edges of the source
2542 dx+=(int)((0-sx) * s2dw);
2543 w-=(int)((0-sx) * s2dw);
2549 dy+=(int)((0-sy) * s2dh);
2550 h-=(int)((0-sy) * s2dh);
2555 if(sx+sw>src.width-1)
2557 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2558 sw-=sx+sw-(src.width-1)-1;
2560 if(sy+sh>(src.height-1))
2562 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2563 sh-=sy+sh-(src.height-1)-1;
2565 //Clip against the edges of the destination
2566 if(dx<surface.box.left)
2568 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2569 sw-=(int)((surface.box.left-dx)*d2sw);
2570 w-=surface.box.left-dx;
2571 dx=surface.box.left;
2573 if(dy<surface.box.top)
2575 sy+=(int)((surface.box.top-dy)*d2sh);
2576 sh-=(int)((surface.box.top-dy)*d2sh);
2577 h-=surface.box.top-dy;
2580 if((dx+w)>surface.box.right)
2582 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2583 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2584 w-=((dx+w)-surface.box.right-1);
2586 if((dy+h)>surface.box.bottom)
2588 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2589 h-=((dy+h)-surface.box.bottom-1);
2591 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2593 dx+=surface.offset.x;
2594 dy+=surface.offset.y;
2596 if(lfbSurface.bitmap.picture)
2598 AlphaWriteMode alphaWrite = surface.alphaWrite;
2599 if(src.alphaBlend && surface.blend)
2603 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2604 ColorAlpha * backsrc;
2605 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2606 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2607 float scaleX = (float)sw / w;
2608 float scaleY = (float)sh / h;
2616 if (w > sw && h > sh)
2619 for (y = 0; y < h; y++)
2621 int y0 = y * sh / h;
2622 int y1 = Min(y0 + 1, sh - 1);
2623 float alpha = y * scaleY - y0;
2625 for(x = 0; x < w; x++, dest += 1)
2627 int x0 = x * sw / w;
2628 int x1 = Min(x0 + 1, sw - 1);
2629 float beta = x * scaleX - x0;
2631 ColorAlpha src00, src01, src10, src11;
2632 float a1,r1,g1,b1,a2,r2,g2,b2;
2634 src00 = source[y0 * src.stride + x0];
2635 src01 = source[y0 * src.stride + x1];
2636 src10 = source[y1 * src.stride + x0];
2637 src11 = source[y1 * src.stride + x1];
2638 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2639 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2640 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2641 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2642 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2643 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2644 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2645 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2646 a = a1 * (1.0f - alpha) + a2 * alpha;
2647 r = r1 * (1.0f - alpha) + r2 * alpha;
2648 g = g1 * (1.0f - alpha) + g2 * alpha;
2649 b = b1 * (1.0f - alpha) + b2 * alpha;
2651 ColorAlpha dst = *dest;
2652 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2653 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2654 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2655 if(cr > 255) cr = 255;
2656 if(cg > 255) cg = 255;
2657 if(cb > 255) cb = 255;
2658 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2660 if(alphaWrite == blend)
2662 int ca = (int)(a + ((255 - a) * dst.a / 255));
2663 if(ca > 255) ca = 255;
2676 for (y = 0; y < h; y++)
2678 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2679 int y1 = Min(y0 + 1, sh - 1);
2681 for (x = 0; x < w; x++, dest += 1)
2683 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2684 int x1 = Min(x0 + 1, sw - 1);
2685 float a = 0, r = 0, g = 0, b = 0;
2689 for (i = y0; i <= y1; i++)
2690 for (j = x0; j <= x1; j++)
2692 ColorAlpha pixel = source[i * src.stride + j];
2704 ColorAlpha src = *source;
2705 ColorAlpha dst = *dest;
2706 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2707 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2708 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2709 if(cr > 255) cr = 255;
2710 if(cg > 255) cg = 255;
2711 if(cb > 255) cb = 255;
2712 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2713 if(alphaWrite == blend)
2715 int ca = (int)(a + ((255 - a) * dst.a / 255));
2716 if(ca > 255) ca = 255;
2727 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2728 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2729 // Fail back on Stretch
2730 else if(src.paletteShades)
2731 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2732 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2733 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2734 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2735 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2739 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2741 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2744 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2746 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2749 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2751 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2754 void UnloadFont(DisplaySystem displaySystem, Font font)
2758 #if !defined(ECERE_NOTRUETYPE)
2760 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2762 FontEntry fontEntry = font.fontEntries[entry];
2768 loadedFonts.Remove(fontEntry);
2778 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2780 void * result = null;
2782 #if !defined(ECERE_NOTRUETYPE)
2783 Font font = Font { };
2786 char fileName[MAX_LOCATION];
2787 bool fakeItalic = flags.italic;
2788 char linkCfgPath[MAX_LOCATION];
2790 #if !defined(__WIN32__)
2793 char * ecereFonts = getenv("ECERE_FONTS");
2794 if(!ecereFonts) ecereFonts = "<:ecere>";
2795 #if !defined(__WIN32__)
2796 strcpy(linkCfgPath, ecereFonts);
2797 PathCat(linkCfgPath, "linking.cfg");
2798 linkCfg = FileOpen(linkCfgPath, read);
2800 strcpy(fileName, faceName);
2801 strcpy(font.faceName, faceName);
2803 font.displaySystem = displaySystem;
2805 if(!FileExists(fileName))
2807 strcpy(fileName, ecereFonts);
2808 PathCat(fileName, faceName);
2809 if(flags.bold && flags.italic) strcat(fileName, "bi");
2810 else if(flags.bold) strcat(fileName, "bd");
2811 else if(flags.italic) strcat(fileName, "i");
2812 strcat(fileName, ".ttf");
2816 if(flags.italic && !FileExists(fileName))
2818 strcpy(fileName, ecereFonts);
2819 PathCat(fileName, faceName);
2820 if(flags.bold) strcat(fileName, "bd");
2821 strcat(fileName, ".ttf");
2826 // Search in current working directory
2827 if(!FileExists(fileName))
2829 strcpy(fileName, faceName);
2830 if(flags.bold && flags.italic) strcat(fileName, "bi");
2831 else if(flags.bold) strcat(fileName, "bd");
2832 else if(flags.italic) strcat(fileName, "i");
2833 strcat(fileName, ".ttf");
2837 if(flags.italic && !FileExists(fileName))
2839 strcpy(fileName, faceName);
2840 if(flags.bold) strcat(fileName, "bd");
2841 strcat(fileName, ".ttf");
2847 #if defined(__WIN32__)
2848 if(!FileExists(fileName))
2850 FontData fontData = { { 0 } };
2851 LOGFONT logFont = { 0 };
2856 logFont.lfCharSet = DEFAULT_CHARSET;
2857 strcpy(logFont.lfFaceName, faceName);
2858 fontData.flags = flags;
2860 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2861 if(!fontData.fileName[0] && flags.bold)
2863 fontData.forgive = true;
2864 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2866 if(!fontData.fileName[0])
2869 fontData.flags.italic = false;
2870 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2874 if(fontData.fileName[0])
2876 GetWindowsDirectory(fileName, MAX_LOCATION);
2877 PathCat(fileName, "fonts");
2878 PathCat(fileName, fontData.fileName);
2882 #elif !defined(ECERE_NOFONTCONFIG)
2885 FcResult result = 0;
2886 FcPattern * pattern;
2887 FcPattern * matched;
2889 unichar testChar = 0;
2890 FcCharSet * charSet;
2892 fcConfig = FcInitLoadConfigAndFonts();
2894 charSet = FcCharSetCreate();
2896 if(!strcmpi(faceName, "Mangal"))
2902 FcCharSetAddChar(charSet, testChar);
2904 pattern = FcPatternBuild(null,
2905 //FC_SOURCE, FcTypeString, "freetype",
2906 FC_FAMILY, FcTypeString, faceName,
2907 //FC_SCALABLE, FcTypeBool, 1,
2908 FC_SIZE, FcTypeDouble, (double)size,
2909 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2910 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2911 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2913 FcDefaultSubstitute(pattern);
2914 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2916 matched = FcFontMatch (0, pattern, &result);
2917 // printf("Locating %s\n", faceName);
2920 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2921 //printf("Fontconfig returned %s\n", family);
2923 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2926 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2927 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2928 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2929 strcpy(fileName, fileName2);
2930 // size = (float)fontSize;
2932 //printf("Matched to %s, %f\n", fileName, size);
2936 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2938 if(pattern) FcPatternDestroy(pattern);
2939 if(matched) FcPatternDestroy(matched);
2940 if(charSet) FcCharSetDestroy(charSet);
2945 if(!FileExists(fileName))
2946 ChangeExtension(fileName, "otf", fileName);
2947 if(!FileExists(fileName))
2948 ChangeExtension(fileName, "ttc", fileName);
2950 //if(FileExists(fileName))
2953 char links[1024] = "";
2955 #if defined(__WIN32__)
2958 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2959 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2964 RegQueryValueEx(key, faceName, null, (LPDWORD)&type, (LPBYTE)links, (LPDWORD)&size);
2965 memset(links + size, 0, 1024 - size);
2973 while(linkCfg.GetLine(line, sizeof(line)))
2975 int len = strlen(faceName);
2976 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2978 while(linkCfg.GetLine(line, sizeof(line)))
2980 TrimLSpaces(line, line);
2981 if(!line[0] || line[0] == '[')
2984 memcpy(links + linksPos, line, len);
2986 links[linksPos] = 0;
2994 while(entry < MAX_FONT_LINK_ENTRIES)
2996 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2999 File file = FileOpen/*Buffered*/(fileName, read);
3002 FileSize fileSize = file.GetSize();
3003 FT_Open_Args args = { 0 };
3004 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3005 FT_Stream stream = new0 FT_StreamRec[1];
3008 FT_Init_FreeType( &ftLibrary );
3010 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3011 fontEntry.stream = stream;
3014 fontEntry.buffer = new byte[fileSize];
3015 file.Read(fontEntry.buffer, 1, fileSize);
3018 //args.num_params = 1;
3019 args.params = ¶m;
3021 stream->size = fileSize;
3022 stream->descriptor.pointer = file;
3023 stream->read = FT_stream_load;
3024 stream->close = FT_stream_close;
3026 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3027 args.stream = stream;
3028 //args.pathname = fileName;
3029 //args.memory_base = fontEntry.buffer;
3030 //args.memory_size = fileSize;
3032 // printf("Opening: %s\n", fileName);
3033 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3038 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3039 fontEntry.hbFont.klass = &hb_fontClass;
3040 fontEntry.hbFont.userData = fontEntry; //.face;
3043 loadedFonts.Add(fontEntry);
3048 // printf("Error opening font %s\n", fileName);
3057 FT_Vector pen = { 0, 0 };
3060 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3061 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3062 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3063 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3067 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3068 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3069 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3070 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3072 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3073 FaceSetCharSize(fontEntry.face, size);
3074 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3075 // printf("Font height is %d\n", font.height);
3076 font.fakeItalic = fakeItalic;
3080 font.fontEntries[entry++] = fontEntry;
3087 char fontName[1024];
3088 if(!links[linksPos]) break;
3089 for(c = 0; (ch = links[linksPos + c]); c++)
3092 if(ch == ',') break;
3095 if(fontName[0] || ch == ',')
3097 #if defined(__WIN32__)
3098 GetWindowsDirectory(fileName, MAX_LOCATION);
3099 PathCat(fileName, "fonts");
3100 PathCat(fileName, fontName);
3101 #elif !defined(ECERE_NOFONTCONFIG)
3102 if(getenv("ECERE_FONTS"))
3104 strcpy(fileName, ecereFonts);
3105 PathCat(fileName, fontName);
3111 FcResult result = 0;
3112 FcPattern * pattern;
3113 FcPattern * matched;
3115 pattern = FcPatternBuild(null,
3116 //FC_SOURCE, FcTypeString, "freetype",
3117 //FC_SCALABLE, FcTypeBool, 1,
3118 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3119 FC_SIZE, FcTypeDouble, (double)size,
3120 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3121 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3123 FcDefaultSubstitute(pattern);
3124 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3126 //printf("Locating %s\n", links + linksPos + c + 1);
3127 matched = FcFontMatch (0, pattern, &result);
3130 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3131 // printf("Fontconfig returned %s\n", family);
3133 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3134 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3137 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3138 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3139 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3140 strcpy(fileName, fileName2);
3141 //size = (float)fontSize;
3142 // printf("Matched to %s, %f\n", fileName, size);
3146 // 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);
3148 if(pattern) FcPatternDestroy(pattern);
3149 if(matched) FcPatternDestroy(matched);
3156 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3163 UnloadFont(displaySystem, font);
3166 font.asciiPack.Render(font, 0, displaySystem);
3168 #if !defined(__WIN32__)
3176 #if !defined(ECERE_NOTRUETYPE)
3177 void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
3178 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3179 Surface surface, Display display, int * x, int y)
3181 if(font && font.fontEntries && font.fontEntries[0])
3183 int previousGlyph = 0;
3184 FT_Face previousFace = 0;
3185 int c, nb, glyphIndex = 0;
3186 unichar lastPack = 0;
3187 GlyphPack pack = font.asciiPack;
3191 bool rightToLeft = false;
3192 int fontEntryNum = 0;
3193 int glyphScript = 0;
3194 FontEntry curFontEntry;
3196 pack.bitmap.alphaBlend = true;
3198 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3202 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3204 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3205 rightToLeft ? glyphIndex-- : glyphIndex++;
3209 HB_Script curScript = HB_Script_Common;
3210 byte * scriptStart = text + c;
3211 unichar nonASCIIch = 0;
3214 unichar testChar = 0;
3215 char * testLang = null;
3219 HB_Script script = HB_Script_Common;
3220 ch = UTF8GetChar((char *)text + c, &nb);
3221 if(ch > 127) nonASCIIch = ch;
3223 if(ch == 32 && curScript)
3230 for(a = c + 1; a < c + len; a++)
3238 unichar ahead = UTF8GetChar((char *)text + a, &nb);
3239 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3247 script = HB_Script_Common;
3248 else if(ch <= 0x11FF)
3252 case 0x300: script = HB_Script_Greek; break;
3253 case 0x400: script = HB_Script_Cyrillic; break;
3254 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3255 case 0x600: script = HB_Script_Arabic; break;
3256 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3257 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3258 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3259 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3260 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3261 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3262 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3263 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3264 case 0xF00: script = HB_Script_Tibetan; break;
3265 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3266 case 0x1100: script = HB_Script_Hangul; break;
3269 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3270 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3271 script = HB_Script_Hangul;
3272 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3273 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3274 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3275 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3276 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3277 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3278 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3279 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3280 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3283 if(!script || (script != curScript))
3291 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3292 if(!script) { c += nb; break; }
3299 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3301 rightToLeft = false;
3303 theCurrentScript = 0;
3307 int len = c - (int)(scriptStart - text);
3308 int max = len * 2 + 1;
3309 if(max > utf16BufferSize)
3311 utf16 = renew utf16 uint16[max];
3312 utf16BufferSize = max;
3314 wc = UTF8toUTF16BufferLen((char *)scriptStart, utf16, max, len);
3315 theCurrentScript = glyphScript = curScript;
3319 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3320 //printf("Arabic ");
3322 case HB_Script_Devanagari: testChar = 0x905; testLang = "sa";
3323 //printf("Devanagari ");
3325 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3326 //printf("Hebrew ");
3329 testChar = (ch == '\t') ? ' ' : ch;
3331 case 60: testChar = 'あ'; break;
3332 case 61: testChar = 0x3400; break; //'愛'; break;
3338 // printf("Testing for char %x\n", testChar);
3339 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3341 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3343 /*if(font.fontEntries[fontEntryNum])
3344 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3348 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3350 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3352 double fontSize = font.size;
3353 FcResult result = 0;
3354 FcPattern * pattern;
3355 FcPattern * matched;
3356 FcCharSet * charSet;
3358 FontEntry fontEntry;
3359 char * fileName = null;
3360 bool fakeItalic = false;
3361 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3362 if(!font.fontEntries[fontEntryNum])
3364 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3368 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3370 charSet = FcCharSetCreate();
3371 FcCharSetAddChar(charSet, testChar);
3372 //printf("Loading with char %x\n", testChar);
3374 pattern = FcPatternBuild(null,
3375 //FC_SOURCE, FcTypeString, "freetype",
3376 //FC_SCALABLE, FcTypeBool, 1,
3377 FC_FAMILY, FcTypeString, font.faceName,
3378 FC_SIZE, FcTypeDouble, (double)font.size,
3379 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3380 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3381 FC_CHARSET,FcTypeCharSet, charSet,
3382 testLang ? FC_LANG : 0, FcTypeString,testLang,
3384 FcDefaultSubstitute(pattern);
3385 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3387 //printf("Locating %s for script %d\n", font.faceName, curScript);
3388 matched = FcFontMatch (0, pattern, &result);
3391 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3392 //printf("Fontconfig returned %s\n", family);
3394 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3396 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3397 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3398 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3399 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3403 //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);
3408 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3411 File file = FileOpen(fileName, read);
3414 FileSize fileSize = file.GetSize();
3415 FT_Open_Args args = { 0 };
3416 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3417 FT_Stream stream = new0 FT_StreamRec[1];
3420 FT_Init_FreeType( &ftLibrary );
3422 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3423 fontEntry.stream = stream;
3425 //args.num_params = 1;
3426 args.params = ¶m;
3428 stream->size = fileSize;
3429 stream->descriptor.pointer = file;
3430 stream->read = FT_stream_load;
3431 stream->close = FT_stream_close;
3433 args.flags = FT_OPEN_STREAM;
3434 args.stream = stream;
3435 //args.pathname = fileName;
3436 //args.memory_base = fontEntry.buffer;
3437 //args.memory_size = fileSize;
3439 // printf("Opening: %s\n", fileName);
3440 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3445 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3446 fontEntry.hbFont.klass = &hb_fontClass;
3447 fontEntry.hbFont.userData = fontEntry; //.face;
3450 loadedFonts.Add(fontEntry);
3455 // printf("Error opening font %s\n", fileName);
3461 FaceSetCharSize(fontEntry.face, font.size);
3463 font.fontEntries[fontEntryNum] = fontEntry;
3467 if(pattern) FcPatternDestroy(pattern);
3468 if(matched) FcPatternDestroy(matched);
3469 if(charSet) FcCharSetDestroy(charSet);
3472 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3473 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3475 font.fontEntries[fontEntryNum].font = font;
3476 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3480 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3481 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3482 rightToLeft ? glyphIndex-- : glyphIndex++;
3486 curFontEntry = font.fontEntries[fontEntryNum];
3488 packNo = glyphNo & 0xFFFFFF80;
3490 if(packNo != lastPack)
3493 pack = font.asciiPack;
3496 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3499 pack = GlyphPack { key = (uintptr)packNo };
3500 font.glyphPacks.Add(pack);
3501 pack.Render(font, fontEntryNum, displaySystem);
3504 pack.bitmap.alphaBlend = true;
3509 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3510 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3512 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3513 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3514 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3518 if(previousGlyph && curFontEntry.face == previousFace)
3520 FT_Vector delta = { 0, 0 };
3521 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3522 if(delta.x < 0) delta.x += (-delta.x) % 64;
3523 else if(delta.x) delta.x += 64 - (delta.x % 64);
3524 *x += delta.x * glyph->scale;
3527 FaceSetCharSize(curFontEntry.face, font.size);
3529 previousGlyph = glyph->glyphNo;
3530 previousFace = curFontEntry.face;
3533 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3536 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3542 LFBSurface lfbSurface = surface.driverData;
3543 lfbSurface.xOffset = 0;
3548 void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3550 if(displaySystem && displaySystem.flags.text && len)
3555 *width = num * textCellW;
3557 if(height) *height = textCellH;
3559 else if(font && len)
3564 #if !defined(ECERE_NOTRUETYPE)
3565 ProcessString(font, displaySystem, text, len, null, null, null, &w, 0);
3567 //*width = (w + 64 - w % 64) >> 6;
3571 *height = font.height;
3575 if(width) *width = 0;
3576 if(height) *height = 0;
3580 #if !defined(ECERE_NOTRUETYPE)
3581 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3583 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3587 void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3589 LFBSurface lfbSurface = surface.driverData;
3590 if(display && display.displaySystem.flags.text)
3592 LFBDisplay lfbDisplay = display.driverData;
3593 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3599 if(y > surface.box.bottom || y < surface.box.top)
3601 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3602 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3603 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3605 if(surface.textOpacity)
3606 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3608 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3613 lfbSurface.writingText = true;
3614 #if !defined(ECERE_NOTRUETYPE)
3616 ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3618 lfbSurface.writingText = false;
3622 void TextFont(Display display, Surface surface, Font font)
3624 LFBSurface lfbSurface = surface.driverData;
3625 lfbSurface.font = font;
3628 void TextOpacity(Display display, Surface surface, bool opaque)
3630 LFBSurface lfbSurface = surface.driverData;
3634 void TextExtent(Display display, Surface surface, byte * 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)