1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
10 #if !defined(ECERE_NOTRUETYPE)
12 #include FT_FREETYPE_H
13 #include FT_TRUETYPE_TABLES_H
14 #include FT_UNPATENTED_HINTING_H
15 #define property _property
19 #if defined(__WIN32__)
20 #define WIN32_LEAN_AND_MEAN
21 #define String _String
24 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
26 #include <fontconfig/fontconfig.h>
27 static FcConfig * fcConfig;
36 #pragma warning(disable:4244)
37 #pragma warning(disable:4018)
43 public define LIGHTSHIFT = 5;
44 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
46 /*#ifndef ECERE_VANILLA
48 static bool rgbLookupSet = true;
50 /*static */byte defaultRGBLookup[32768];
51 /*static */bool rgbLookupSet = false;
57 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
58 import "OpenGLDisplayDriver"
59 import "Direct3D8DisplayDriver"
60 import "Direct3D9DisplayDriver"
63 #if !defined(ECERE_NOTRUETYPE)
65 #define MAX_FONT_LINK_ENTRIES 10
67 static HB_Script theCurrentScript;
69 static unichar UTF16GetChar(const uint16 *string, int * nw)
72 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
74 ch = HB_SurrogateToUcs4(string[0], string[1]);
85 static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
87 FT_Face face = ((FontEntry)font->userData).face;
91 if (length > *numGlyphs)
94 for (c = 0; c < length; c += nw)
96 unichar ch = UTF16GetChar(string + c, &nw);
97 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
99 *numGlyphs = glyph_pos;
103 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
105 FontEntry entry = font->userData;
106 Font glFont = entry.font;
109 GlyphPack pack = glFont.asciiPack;
111 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
113 if(glFont.fontEntries[fontEntryNum] == entry)
117 for(c = 0; c < numGlyphs; c++)
120 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
121 uint packNo = glyphNo & 0xFFFFFF80;
122 if(packNo != lastPack)
124 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
127 glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
128 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
129 pack.bitmap.alphaBlend = true;
133 glyph = &pack.glyphs[glyphNo & 0x7F];
134 advances[c] = glyph->ax;
138 static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
140 FT_Face face = ((FontEntry)font->userData).face;
143 for (c = 0; c < length; c += nw)
145 unichar ch = UTF16GetChar(string + c, &nw);
146 if(!FT_Get_Char_Index(face, ch))
152 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
154 FT_Face face = (FT_Face)font;
155 FT_ULong ftlen = *length;
158 if (!FT_IS_SFNT(face))
159 return HB_Err_Invalid_Argument;
161 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
162 *length = (uint)ftlen;
163 return (HB_Error)error;
166 static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
168 HB_Error error = HB_Err_Ok;
169 FT_Face face = (FT_Face)font->userData;
171 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
173 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
176 if (face->glyph->format != ft_glyph_format_outline)
177 return (HB_Error)HB_Err_Invalid_SubTable;
179 *nPoints = face->glyph->outline.n_points;
183 if (point > *nPoints)
184 return (HB_Error)HB_Err_Invalid_SubTable;
186 *xpos = (int)face->glyph->outline.points[point].x;
187 *ypos = (int)face->glyph->outline.points[point].y;
192 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
194 FontEntry entry = font->userData;
195 Font glFont = entry.font;
197 GlyphPack pack = glFont.asciiPack;
199 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
201 if(glFont.fontEntries[fontEntryNum] == entry)
206 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
207 uint packNo = glyphNo & 0xFFFFFF80;
208 if(packNo != lastPack)
210 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
213 pack = { key = (uintptr)packNo };
214 glFont.glyphPacks.Add(pack);
215 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
216 pack.bitmap.alphaBlend = true;
220 glyph = &pack.glyphs[glyphNo & 0x7F];
222 metrics->x = glyph->ax;
224 metrics->width = glyph->w;
225 metrics->height = glyph->h;
226 metrics->xOffset = glyph->bx;
227 metrics->yOffset = glyph->by;
231 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
233 FontEntry entry = font->userData;
234 FT_Face face = entry.face;
236 // Note that we aren't scanning the VDMX table which we probably would in
238 if(metric == HB_FontAscent)
239 return face->ascender;
243 static HB_FontClass hb_fontClass =
245 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
246 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
249 static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
251 File f = stream->descriptor.pointer;
252 f.Seek((int)offset, start);
253 return count ? f.Read(buffer, 1, (uint)count) : 0;
256 static void FT_stream_close(FT_Stream stream)
258 File f = stream->descriptor.pointer;
263 static FT_Library ftLibrary;
266 static BinaryTree loadedFonts
268 CompareKey = (void *)BinaryTree::CompareString
271 class FontEntry : BTNode
280 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
297 FT_Done_FreeType(ftLibrary);
304 static float FaceSetCharSize(FT_Face face, float size)
307 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
309 if(face->num_fixed_sizes)
312 int bestDiff = MAXINT, best = 0;
313 FT_Bitmap_Size * sizes = face->available_sizes;
314 int wishedHeight = (int)(size * 96 / 72);
315 for(c = 0; c < face->num_fixed_sizes; c++)
317 int diff = abs(sizes[c].height - wishedHeight);
324 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
327 face->ascender = sizes[best].height;
328 scale = (float)wishedHeight / sizes[best].height;
347 class GlyphPack : BTNode
349 GlyphInfo glyphs[256];
352 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
354 #if !defined(ECERE_NOTRUETYPE)
356 int maxWidth, maxHeight;
357 int cellWidth, cellHeight;
359 FontEntry fontEntry = null;
362 bool isGlyph = ((uint)key & 0x80000000) != 0;
363 //int curScript = ((uint)key & 0x7F000000) >> 24;
364 unichar testChar = 0;
370 case HB_Script_Arabic:
372 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
374 case HB_Script_Devanagari:
377 case 60: testChar = 'あ'; break;
378 case 61: testChar = 0x3400; break;
385 FT_Vector pen = { 0, 0 };
388 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
389 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
390 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
391 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
392 FT_Set_Transform( fontEntry.face, &matrix, &pen );
394 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
400 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
402 fontEntry = font.fontEntries[c];
406 FT_Vector pen = { 0, 0 };
410 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
411 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
412 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
413 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
414 FT_Set_Transform(fontEntry.face, &matrix, &pen);
416 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
417 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
419 font.scale = fontEntry.scale;
422 if(!fontEntry.face->units_per_EM)
423 font.ascent = (int)((double)fontEntry.face->ascender);
425 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
428 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
429 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
430 fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
431 fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
436 for(c = 0; c < 128; c++)
441 uint glyph = ((uint)key | c) & 0xFFFFFF;
442 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
444 fontEntry = font.fontEntries[entry];
445 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
447 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
449 //printf("%s: Accepted entry %d ", font.faceName, entry);
457 for(entry = startFontEntry; ; entry++)
460 fontEntry = font.fontEntries[entry];
461 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
463 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
468 scales[c] = fontEntry.scale;
469 faces[c] = fontEntry.face;
470 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
471 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
472 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
474 cellWidth = maxWidth;
475 cellHeight = maxHeight;
477 width = pow2i(maxWidth * 16);
478 height = pow2i(maxHeight * 8);
480 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
482 Bitmap bitmap = this.bitmap;
484 bitmap.transparent = true;
486 for(c = 0; c < 128; c++)
490 int sx = (c % 16) * cellWidth;
491 int sy = (c / 16) * cellHeight;
493 byte * picture = (byte *)bitmap.picture;
494 GlyphInfo * glyph = &glyphs[c];
495 FT_GlyphSlot slot = faces[c]->glyph;
496 double em_size = 1.0 * faces[c]->units_per_EM;
497 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
498 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
499 double ascender = faces[c]->ascender * y_scale;
500 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
502 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
504 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
508 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
510 glyph->left = slot->bitmap_left;
511 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
512 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
513 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
514 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
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;
517 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
519 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
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));
522 //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));
524 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
525 glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
527 // 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);
528 xMax = x + slot->bitmap.width;
529 yMax = y + slot->bitmap.rows;
535 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
537 for(j = y, q = 0; j<yMax; j++)
539 for(p = 0, i = x; i<xMax; i++)
541 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
548 q += slot->bitmap.pitch;
551 //max = numPixels ? (total / numPixels) : 1;
553 for(j = y, q = 0; j<yMax; j++)
556 for(p = 0, i = x; i<xMax; i++)
558 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
560 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
562 if(!bit) { bit = 0x80; p++; }
566 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
567 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
570 q += slot->bitmap.pitch;
575 glyph->w = slot->bitmap.width;
576 glyph->h = slot->bitmap.rows;
577 glyph->glyphNo = glyphNo;
578 glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
579 glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
580 glyph->scale = scales[c];
582 glyph->ax = (int)slot->advance.x;
583 glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
590 for(c = 0; c<256; c++)
591 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
592 bitmap.pixelFormat = pixelFormat8;
595 //strcpy(fileName, faceName);
597 strcat(fileName, "Bold");
599 sprintf(fileName, "font%d", fid++);
600 ChangeExtension(fileName, "pcx", fileName);
602 bitmap.Save(fileName, null, 0);
603 bitmap.pixelFormat = pixelFormatAlpha;
607 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
609 displaySystem.Lock();
610 #if defined(__WIN32__)
611 // Is this check still required?
612 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
613 displaySystem.driver == class(Direct3D8DisplayDriver) ||
614 displaySystem.driver == class(Direct3D9DisplayDriver))
616 bitmap.MakeDD(displaySystem);
617 displaySystem.Unlock();
624 #if !defined(ECERE_NOTRUETYPE)
625 static HB_ShaperItem shaper_item;
627 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
629 static uint maxGlyphs = 0;
630 HB_Glyph * glyphs = shaper_item.glyphs;
632 shaper_item.kerning_applied = 0;
633 shaper_item.string = string;
634 shaper_item.stringLength = len;
635 shaper_item.item.script = script;
636 shaper_item.item.pos = 0;
637 shaper_item.item.length = shaper_item.stringLength;
638 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
639 shaper_item.item.bidiLevel = 1;
641 shaper_item.item.bidiLevel = 0;
642 shaper_item.shaperFlags = 0;
643 shaper_item.font = &entry.hbFont;
644 shaper_item.face = entry.hbFace;
645 shaper_item.num_glyphs = shaper_item.item.length;
646 shaper_item.glyphIndicesPresent = 0;
647 shaper_item.initialGlyphCount = 0;
648 shaper_item.num_glyphs = 0;
649 shaper_item.glyphs = null;
651 while(!HB_ShapeItem(&shaper_item))
653 if(shaper_item.num_glyphs > maxGlyphs)
655 maxGlyphs = shaper_item.num_glyphs;
656 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
657 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
658 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
659 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
660 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
664 shaper_item.glyphs = glyphs;
665 shaper_item.num_glyphs = maxGlyphs;
669 *numGlyphs = shaper_item.num_glyphs;
670 *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
671 return shaper_item.glyphs;
675 delete shaper_item.glyphs;
676 delete shaper_item.attributes;
677 delete shaper_item.advances;
678 delete shaper_item.offsets;
679 delete shaper_item.log_clusters;
683 public class Font : struct
685 BinaryTree glyphPacks { };
686 GlyphPack asciiPack { };
687 #if !defined(ECERE_NOTRUETYPE)
688 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
695 DisplaySystem displaySystem;
701 #if !defined(ECERE_NOTRUETYPE)
703 while((pack = (GlyphPack)glyphPacks.root))
705 glyphPacks.Remove(pack);
710 public property int ascent
712 get { return (int)(this ? ascent * scale : 0); }
716 public class LFBDisplay : struct
720 byte rgbLookup[32768];
721 byte lightTable[256][LIGHTSTEPS];
725 void (* displayCallback)(Display display, Box updateBox);
728 public class LFBSystem : struct
732 ColorAlpha * palette;
733 byte rgbLookup[32768];
740 ColorAlpha * palette = GetDefaultPalette();
741 for(c = 16; c < 232; c++)
743 Color555 color = palette[c].color;
744 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
745 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
746 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
747 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
749 for(c = 232; c < 246; c++)
751 Color555 color = palette[c].color;
752 defaultRGBLookup[color] = (byte)c;
755 for(c = 246; c < 256; c++)
757 Color555 color = palette[c].color;
758 defaultRGBLookup[color] = (byte)c;
760 for(c = 0; c < 16; c++)
762 Color555 color = palette[c].color;
763 defaultRGBLookup[color] = (byte)c;
766 for(c = 0; c<32768; c++)
768 Color color = (Color)(Color555)c;
769 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
770 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
778 public class LFBSurface : struct
781 // For compatibility with 3D drivers as well
789 // Drawing attributes
790 uint foreground, background;
791 ColorAlpha foregroundRgb;
794 byte * paletteShades;
799 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
801 if(recordA->zMin > recordB->zMin)
803 else if(recordA->zMin < recordB->zMin)
805 else if(recordA > recordB)
807 else if(recordA < recordB)
814 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
817 char fileName[MAX_FILENAME];
822 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
824 //if(fontType == TRUETYPE_FONTTYPE)
826 FontData * fontData = (FontData *) lParam;
827 char * fileName = (char *)lParam;
829 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
830 int italic = (fontData->flags.italic) ? 1 : 0;
831 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
833 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
834 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
839 char entryName[1024];
840 char fontFileName[1024];
843 DWORD sizeFileName = 1024;
845 if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
847 if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
850 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
852 char ch = entryName[c];
853 if(ch == '&') { c = -1; break; }
854 else if(ch != ' ') break;
857 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
859 char ch = entryName[c];
860 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
861 else if(ch != ' ') break;
864 if(atoi(entryName + c))
868 strcpy(fileName, fontFileName);
882 #if !defined(ECERE_NOTRUETYPE)
883 static int utf16BufferSize = 0;
884 static uint16 * utf16 = null;
887 public class LFBDisplayDriver : DisplayDriver
889 class_property(name) = "LFB";
891 bool CreateDisplaySystem(DisplaySystem displaySystem)
893 displaySystem.flags.memBackBuffer = true;
894 // displaySystem.pixelFormat = pixelFormat888;
898 void DestroyDisplaySystem(DisplaySystem displaySystem)
902 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
904 delete bitmap.picture;
905 if(bitmap.allocatePalette)
906 delete bitmap.palette;
909 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
914 switch(GetColorDepthShifts(format))
916 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
917 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
918 case 2: stride = width; break;
921 bitmap.stride = stride;
922 bitmap.width = width;
923 bitmap.height = height;
924 bitmap.size = (uint32) stride * (uint32)height;
925 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
926 bitmap.pixelFormat = format;
927 bitmap.transparent = false;
929 surface.box.left = surface.box.top = 0;
930 surface.box.right = width - 1;
931 surface.box.bottom = height - 1;
933 bitmap.picture = new0 byte[bitmap.sizeBytes];
936 bitmap.allocatePalette = allocatePalette;
939 bitmap.palette = new ColorAlpha[256];
942 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
948 bitmap.palette = GetDefaultPalette();
953 FreeBitmap(displaySystem, bitmap);
957 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
960 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
964 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
966 if(src.transparent && src.pixelFormat == pixelFormat888)
970 DWORD * picture = (DWORD *)src.picture;
972 for(c = 0; c<src.size; c++, picture++)
974 if(*picture & 0xFFFFFF)
975 *picture = *picture | 0xFF000000;
977 *picture = *picture & 0xFFFFFF;
986 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
988 if(format == pixelFormat8)
991 bitmap.palette = palette;
992 else if(lfbSystem && lfbSystem.palette)
993 bitmap.palette = lfbSystem.palette;
995 bitmap.palette = src.palette;
998 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
1000 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
1001 bitmap.transparent = src.transparent;
1002 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
1004 if(src.palette != bitmap.palette)
1006 if(src.allocatePalette)
1008 src.allocatePalette = false;
1010 src.picture = bitmap.picture;
1011 src.palette = bitmap.palette;
1012 src.stride = bitmap.stride;
1013 src.size = bitmap.size;
1014 src.sizeBytes = bitmap.sizeBytes;
1015 src.pixelFormat = bitmap.pixelFormat;
1020 bitmap.palette = null;
1021 bitmap.picture = null;
1029 void DestroyDisplay(Display display)
1031 LFBDisplay lfbDisplay = display.driverData;
1032 delete lfbDisplay.bitmap.palette;
1035 bool CreateDisplay(Display display)
1037 bool result = false;
1038 LFBDisplay lfbDisplay = display.driverData;
1041 lfbDisplay = display.driverData = LFBDisplay { };
1042 lfbDisplay.selfManaged = true;
1043 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1046 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1048 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1054 bool DisplaySize(Display display, int width, int height)
1056 LFBDisplay lfbDisplay = display.driverData;
1057 //display.width = width;
1058 //display.height = height;
1059 lfbDisplay.bitmap.width = width;
1060 lfbDisplay.bitmap.height = height;
1062 lfbDisplay.updateBox.left = display.width;
1063 lfbDisplay.updateBox.top = display.height;
1064 lfbDisplay.updateBox.right = 0;
1065 lfbDisplay.updateBox.bottom = 0;
1068 if(lfbDisplay.selfManaged)
1070 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1071 lfbDisplay.bitmap.stride = width;
1073 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1077 void DisplayPosition(Display display, int x, int y)
1079 LFBDisplay lfbDisplay = display.driverData;
1084 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1086 LFBDisplay lfbDisplay = display.driverData;
1093 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1094 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1095 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1098 for(c = 0; c<32768; c++)
1099 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1101 for(c=0; c<256; c++)
1104 for(i=0; i<LIGHTSTEPS; i++)
1106 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1107 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1108 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1109 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1113 if(lfbDisplay.bitmap.palette)
1114 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1117 void Update(Display display, Box updateBox)
1119 LFBDisplay lfbDisplay = display.driverData;
1120 if(lfbDisplay.displayCallback)
1122 if(updateBox == null)
1124 Box box { 0,0, display.width,display.height };
1125 lfbDisplay.displayCallback(display, box);
1128 lfbDisplay.displayCallback(display, updateBox);
1132 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1134 if(bitmap.pixelFormat != pixelFormatAlpha)
1136 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1138 FreeBitmap(displaySystem, bitmap);
1145 void ReleaseSurface(Display display, Surface surface)
1147 LFBSurface lfbSurface = surface.driverData;
1149 surface.driverData = null;
1152 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1154 LFBDisplay lfbDisplay = display.driverData;
1155 LFBSurface lfbSurface = surface.driverData;
1158 lfbSurface = surface.driverData = LFBSurface { };
1161 lfbSurface.bitmap = lfbDisplay.bitmap;
1163 surface.offset.x = x;
1164 surface.offset.y = y;
1166 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1168 surface.offset.x /= textCellW;
1169 surface.offset.y /= textCellH;
1170 surface.box.left /= textCellW;
1171 surface.box.top /= textCellH;
1172 surface.box.right /= textCellW;
1173 surface.box.bottom /= textCellH;
1177 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1178 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1179 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1180 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1183 surface.unclippedBox = surface.box;
1184 lfbSurface.drawingChar = 219;
1188 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1190 bool result = false;
1191 LFBSurface lfbSurface = surface.driverData;
1192 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1194 lfbSurface.bitmap = bitmap;
1196 surface.offset.x = x;
1197 surface.offset.y = y;
1199 if(bitmap.pixelFormat == pixelFormatText)
1201 surface.offset.x /= textCellW;
1202 surface.offset.y /= textCellH;
1203 surface.box.left /= textCellW;
1204 surface.box.top /= textCellH;
1205 surface.box.right /= textCellW;
1206 surface.box.bottom /= textCellH;
1209 surface.unclippedBox = *&surface.box;
1210 lfbSurface.drawingChar = 219;
1217 void Clip(Display display, Surface surface, Box clip)
1219 LFBSurface lfbSurface = surface.driverData;
1224 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1226 box.left /= textCellW;
1227 box.top /= textCellH;
1228 box.right /= textCellW;
1229 box.bottom /= textCellH;
1231 box.Clip(surface.unclippedBox);
1235 surface.box = surface.unclippedBox;
1238 void SetForeground(Display display, Surface surface, ColorAlpha color)
1240 LFBDisplay lfbDisplay = display ? display.driverData : null;
1241 LFBSurface lfbSurface = surface.driverData;
1243 //if(display) color = color & 0xFFFFFF;
1244 lfbSurface.foregroundRgb = color;
1246 if(lfbSurface.font && lfbDisplay)
1248 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1249 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1252 switch(lfbSurface.bitmap.pixelFormat)
1256 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1258 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1260 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1261 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1262 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1263 case pixelFormat888: lfbSurface.foreground = color; break;
1264 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1265 case pixelFormatText:
1267 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1269 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1274 void SetBackground(Display display, Surface surface, ColorAlpha color)
1276 LFBDisplay lfbDisplay = display ? display.driverData : null;
1277 LFBSurface lfbSurface = surface.driverData;
1278 //color = color & 0xFFFFFF;
1279 switch(lfbSurface.bitmap.pixelFormat)
1283 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1285 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1287 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1288 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1289 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1290 case pixelFormat888: lfbSurface.background = color; break;
1291 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1292 case pixelFormatText:
1294 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1296 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1301 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1303 LFBSurface lfbSurface = surface.driverData;
1304 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1309 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1311 x += surface.offset.x;
1312 y += surface.offset.y;
1313 if(lfbSurface.bitmap.picture)
1315 switch(lfbSurface.bitmap.pixelFormat)
1317 case pixelFormatText:
1319 if(!lfbSurface.bitmap.palette) return 0;
1320 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1321 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1322 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1323 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1324 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1331 void PutPixel(Display display, Surface surface,int x,int y)
1333 LFBSurface lfbSurface = surface.driverData;
1334 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1339 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1341 x += surface.offset.x;
1342 y += surface.offset.y;
1343 if(lfbSurface.bitmap.picture)
1345 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1348 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1351 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1354 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1355 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1362 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1364 LFBSurface lfbSurface = surface.driverData;
1370 uint color = lfbSurface.foreground;
1371 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1372 bool invert = false;
1373 if(!lfbSurface.bitmap.picture) return;
1374 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1380 if(surface.textOpacity)
1381 color |= lfbSurface.background;
1382 color |= lfbSurface.drawingChar;
1386 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1388 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1389 if((x1>surface.box.right)||(x2<surface.box.left))return;
1390 if(x1<surface.box.left)x1=surface.box.left;
1391 if(x2>surface.box.right)x2=surface.box.right;
1395 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1396 if(stipple != 0xFFFF)
1399 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1402 for(x=x1; x<=x2; x++, offset++)
1404 if(stipple & 0x8000)
1405 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1407 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1409 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1413 for(x=x1; x<=x2; x++, offset++)
1415 if(stipple & 0x8000)
1416 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1418 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1420 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1424 for(x=x1; x<=x2; x++, offset++)
1426 if(stipple & 0x8000)
1427 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1429 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1431 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1438 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1440 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1442 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1443 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1444 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1450 for(x = x1; x <= x2; x++, offset++)
1452 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1453 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1462 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1464 if((x1>surface.box.right)||(x1<surface.box.left))return;
1465 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1466 if(y1<surface.box.top)y1=surface.box.top;
1467 if(y2>surface.box.bottom)y2=surface.box.bottom;
1469 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1470 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1473 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1475 if(stipple & 0x8000)
1476 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1478 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1480 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1484 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1486 if(stipple & 0x8000)
1488 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1489 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1492 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1493 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1497 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1499 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1503 if(stipple != 0xFFFF)
1505 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1507 if(stipple & 0x8000)
1508 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1510 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1512 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1517 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1518 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1527 if(x1 < surface.box.left)
1529 if(x2 < surface.box.left)
1531 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1532 x1 = surface.box.left;
1534 if(x2 > surface.box.right)
1536 if(x1 > surface.box.right)
1538 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1539 x2 = surface.box.right;
1543 if(y1 < surface.box.top)
1545 if(y2 < surface.box.top)
1547 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1548 y1 = surface.box.top;
1550 if(y2 > surface.box.bottom)
1552 if(y1 > surface.box.bottom)
1554 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1555 y2 = surface.box.bottom;
1560 if(y1 > surface.box.bottom)
1562 if(y2 > surface.box.bottom)
1564 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1565 y1 = surface.box.bottom;
1567 if(y2 < surface.box.top)
1569 if(y1 < surface.box.top)
1571 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1572 y2 = surface.box.top;
1578 if(x1 > surface.box.right)
1580 if(x2 > surface.box.right)
1582 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1583 x1 = surface.box.right;
1585 if(x2 < surface.box.left)
1587 if(x1 < surface.box.left)
1589 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1590 x2 = surface.box.left;
1594 if(y1 < surface.box.top)
1596 if(y2 < surface.box.top)
1598 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1599 y1 = surface.box.top;
1601 if(y2 > surface.box.bottom)
1603 if(y1 > surface.box.bottom)
1605 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1606 y2 = surface.box.bottom;
1611 if(y1 > surface.box.bottom)
1613 if(y2 > surface.box.bottom)
1615 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1616 y1 = surface.box.bottom;
1618 if(y2 < surface.box.top)
1620 if(y1 < surface.box.top)
1622 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1623 y2 = surface.box.top;
1641 yu=-(int)lfbSurface.bitmap.stride;
1644 yu=lfbSurface.bitmap.stride;
1646 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1652 for(i=0; i<=length; i++)
1654 if(stipple & 0x8000)
1655 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1657 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1658 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1659 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1668 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1674 for(i=0; i<=length; i++)
1676 if(stipple & 0x8000)
1677 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1679 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1680 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1681 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1695 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1697 DrawLine(display, surface,x1,y1,x2,y1);
1698 DrawLine(display, surface,x2,y1,x2,y2);
1699 DrawLine(display, surface,x2,y2,x1,y2);
1700 DrawLine(display, surface,x1,y2,x1,y1);
1703 #if !defined(__GNUC__)
1705 void memset_32_aligned(void *buf, int val, int dwords)
1710 *((uint32 *)(buf)) = val;
1711 buf = ((uint32 *)(buf))+1;
1737 if (dwords & 1) *((int*)(buf)) = val;
1743 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1747 if(((uint32)buf) & 0x7F)
1749 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1775 sub edx,ebx ; edx holds # of overflow bytes
1794 movdqa [edi+16],xmm0
1795 movdqa [edi+32],xmm0
1796 movdqa [edi+48],xmm0
1797 movdqa [edi+64],xmm0
1798 movdqa [edi+80],xmm0
1799 movdqa [edi+96],xmm0
1800 movdqa [edi+112],xmm0
1824 void memset_32(void *buf, uint32 val, uint32 dwords)
1827 if ((uint32)(buf) & 3)
1832 if (((uint32)(buf) & 1))
1834 *(byte *)(buf) = (byte)(val&0xFF);
1835 buf = ((byte *)(buf))+1;
1836 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1839 if (((uint32)(buf) & 2))
1841 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1842 buf = ((uint16 *)(buf))+1;
1843 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1847 memset_32_aligned(buf,val,dwords);
1852 *(byte *)(buf) = (byte)(val&0xFF);
1856 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1857 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1864 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1866 LFBSurface lfbSurface = surface.driverData;
1867 uint32 color = lfbSurface.background;
1869 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1871 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1877 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1879 if(x1<surface.box.left) x1=surface.box.left;
1880 if(x2>surface.box.right) x2=surface.box.right;
1881 if(y1<surface.box.top) y1=surface.box.top;
1882 if(y2>surface.box.bottom) y2=surface.box.bottom;
1884 if(x2>=x1 && y2>=y1)
1892 x1 += surface.offset.x;
1893 x2 += surface.offset.x;
1894 y1 += surface.offset.y;
1895 y2 += surface.offset.y;
1896 if(lfbSurface.bitmap.picture)
1898 if(!surface.writeColor)
1900 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1901 for(y = y1; y<= y2; y++)
1904 for(c = 0; c < w; c++, picture++)
1906 picture->a = (byte)((color & 0xFF000000) >> 24);
1907 picture += lfbSurface.bitmap.stride - w;
1912 if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
1914 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1917 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1918 for(y = y1; y<= y2; y++)
1920 FillBytes(theOffset,(byte)color,w);
1921 theOffset += lfbSurface.bitmap.stride;
1925 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1926 for(y = y1; y<= y2; y++)
1928 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1929 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1933 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1934 for(y = y1; y<= y2; y++)
1936 #if defined(__GNUC__)
1937 FillBytesBy4((uint32 *) theOffset,color,w);
1939 memset_32((uint32 *) theOffset,color,w);
1941 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1947 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1948 //memset_32((uint32 *) theOffset,color,w);
1984 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1987 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1988 for(y = y1; y<= y2; y++)
1990 // TODO: IMPLEMENT THIS
1991 FillBytes(theOffset,(byte)color,w);
1992 theOffset += lfbSurface.bitmap.stride;
1997 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1998 ColorAlpha c = surface.background;
2003 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
2005 for(y = y1; y <= y2; y++)
2008 for(c = 0; c < w; c++, dest++)
2010 Color destColor = 0;
2011 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2012 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2013 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2015 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2016 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2017 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2019 if(r > 255) r = 255;
2020 if(g > 255) g = 255;
2021 if(b > 255) b = 255;
2023 destColor = { (byte)r, (byte)g, (byte)b };
2025 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2026 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2027 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2030 dest += (lfbSurface.bitmap.stride - w);
2036 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2037 AlphaWriteMode alphaWrite = surface.alphaWrite;
2038 ColorAlpha c = surface.background;
2043 for(y = y1; y <= y2; y++)
2046 for(c = 0; c < w; c++, dest++)
2048 int dr = dest->color.r;
2049 int dg = dest->color.g;
2050 int db = dest->color.b;
2051 int r = a * cr / 255 + ((255 - a) * dr / 255);
2052 int g = a * cg / 255 + ((255 - a) * dg / 255);
2053 int b = a * cb / 255 + ((255 - a) * db / 255);
2055 if(r > 255) r = 255;
2056 if(g > 255) g = 255;
2057 if(b > 255) b = 255;
2058 dest->color = { (byte)r, (byte)g, (byte)b };
2060 if(alphaWrite == blend)
2062 int ca = (int)(a + ((255 - a) * dest->a / 255));
2063 if(ca > 255) ca = 255;
2069 dest += (lfbSurface.bitmap.stride - w);
2078 void Clear(Display display, Surface surface, ClearType type)
2080 LFBSurface lfbSurface = surface.driverData;
2082 lfbSurface.clearing = true;
2083 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2084 surface.box.left == 0 && surface.box.top == 0 &&
2085 surface.box.right == surface.width-1 &&
2086 surface.box.bottom == surface.height-1)
2088 uint32 color = /*0xFF000000 | */lfbSurface.background;
2089 if(type != depthBuffer)
2091 if(lfbSurface.bitmap.stride != surface.width)
2092 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2095 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2098 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2100 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2101 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2106 if((flags & CLEAR_Z) && zbuffer)
2107 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2112 if(type != depthBuffer)
2113 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2115 if((flags & CLEAR_Z))
2118 uint32 w = surface.box.right-surface.box.left+1;
2119 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2120 + surface.box.left+surface.offset.x;
2121 for(y = surface.box.top; y<= surface.box.bottom; y++)
2123 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2124 offset += DISPLAY.Width;
2129 lfbSurface.clearing = false;
2132 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2134 LFBSurface lfbSurface = surface.driverData;
2137 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2139 if(w < 0) { w = -w; flip = true; }
2141 //Clip against the edges of the source
2154 if(sx+w>src.width-1)
2155 w-=sx+w-(src.width-1)-1;
2156 if(sy+h>src.height-1)
2157 h-=sy+h-(src.height-1)-1;
2158 //Clip against the edges of the destination
2159 if(dx<surface.box.left)
2161 if(!flip) sx+=surface.box.left-dx;
2162 w-=surface.box.left-dx;
2163 dx=surface.box.left;
2165 if(dy<surface.box.top)
2167 sy+=surface.box.top-dy;
2168 h-=surface.box.top-dy;
2171 if((dx+w)>surface.box.right)
2173 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2174 w-=((uint32)(dx+w)-surface.box.right-1);
2176 if((dy+h)>surface.box.bottom)
2177 h-=((dy+h)-surface.box.bottom-1);
2181 dx += surface.offset.x;
2182 dy += surface.offset.y;
2184 if(lfbSurface.bitmap.picture)
2186 AlphaWriteMode alphaWrite = surface.alphaWrite;
2187 if(src.alphaBlend && surface.blend)
2190 if(src.pixelFormat == pixelFormatAlpha)
2192 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2194 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2195 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2196 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2197 for(y = 0; y < h; y++)
2199 for(x = 0; x < w; x++, picture++, source++)
2201 int a = *source * color.a;
2202 ColorAlpha dest = *picture;
2203 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2204 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2205 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2206 if(r > 255) r = 255;
2207 if(g > 255) g = 255;
2208 if(b > 255) b = 255;
2209 picture->color = { (byte)r, (byte)g, (byte)b };
2210 if(alphaWrite == blend)
2212 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2213 if(ca > 255) ca = 255;
2214 picture->a = (byte)ca;
2217 picture->a = (byte)(a / 255);
2219 picture += lfbSurface.bitmap.stride - w;
2220 source += src.stride - w;
2223 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2225 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2226 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2227 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2228 for(y = 0; y < h; y++)
2230 for(x = 0; x < w; x++, picture++, source++)
2232 int a = *source * color.a;
2233 Color dest = *picture;
2234 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2235 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2236 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2237 if(r > 255) r = 255;
2238 if(g > 255) g = 255;
2239 if(b > 255) b = 255;
2240 *picture = Color { (byte)r, (byte)g, (byte)b };
2242 picture += lfbSurface.bitmap.stride - w;
2243 source += src.stride - w;
2246 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2248 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2249 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2250 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2251 for(y = 0; y < h; y++)
2253 for(x = 0; x < w; x++, picture++, source++)
2255 int a = *source * color.a;
2256 Color dest = *picture;
2257 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2258 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2259 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2260 if(r > 255) r = 255;
2261 if(g > 255) g = 255;
2262 if(b > 255) b = 255;
2263 *picture = Color { (byte)r, (byte)g, (byte)b };
2265 picture += lfbSurface.bitmap.stride - w;
2266 source += src.stride - w;
2272 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2273 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2275 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2276 for(y = 0; y < h; y++)
2278 for(x = 0; x < w; x++, picture++, source++)
2280 ColorAlpha src = *source;
2281 ColorAlpha dest = *picture;
2282 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2283 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2284 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2285 if(r > 255) r = 255;
2286 if(g > 255) g = 255;
2287 if(b > 255) b = 255;
2288 picture->color = { (byte)r, (byte)g, (byte)b };
2289 if(alphaWrite == blend)
2291 int a = src.a + ((255 - src.a) * dest.a / 255);
2292 if(a > 255) a = 255;
2293 picture->a = (byte)a;
2298 picture += lfbSurface.bitmap.stride - w;
2299 source += src.stride - w;
2302 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2304 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2305 for(y = 0; y < h; y++)
2307 for(x = 0; x < w; x++, picture++, source++)
2309 ColorAlpha src = *source;
2310 Color565 dest = *picture;
2311 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2312 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2313 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2314 if(r > 255 * 31) r = 255 * 31;
2315 if(g > 255 * 63) g = 255 * 63;
2316 if(b > 255 * 31) b = 255 * 31;
2317 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2319 picture += lfbSurface.bitmap.stride - w;
2320 source += src.stride - w;
2323 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2325 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2326 for(y = 0; y < h; y++)
2328 for(x = 0; x < w; x++, picture++, source++)
2330 ColorAlpha psrc = *source;
2331 Color555 dest = *picture;
2332 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2333 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2334 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2335 if(r > 255 * 31) r = 255 * 31;
2336 if(g > 255 * 31) g = 255 * 31;
2337 if(b > 255 * 31) b = 255 * 31;
2338 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2340 picture += lfbSurface.bitmap.stride - w;
2341 source += src.stride - w;
2346 else if(src.paletteShades)
2347 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2348 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2349 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2350 else if(src.pixelFormat == pixelFormat8)
2351 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2355 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2357 bool result = false;
2358 LFBDisplay lfbDisplay = display.driverData;
2360 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2363 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2364 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2368 Surface surface = bitmap.GetSurface(0,0,null);
2371 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2372 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2373 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2381 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2383 LFBSurface lfbSurface = surface.driverData;
2386 float s2dw,s2dh,d2sw,d2sh;
2388 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2390 if(Sgn(w) != Sgn(sw))
2402 //Clip against the edges of the source
2405 dx+=(int)((0-sx) * s2dw);
2406 w-=(int)((0-sx) * s2dw);
2412 dy+=(int)((0-sy) * s2dh);
2413 h-=(int)((0-sy) * s2dh);
2418 if(sx+sw>src.width-1)
2420 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2421 sw-=sx+sw-(src.width-1)-1;
2423 if(sy+sh>(src.height-1))
2425 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2426 sh-=sy+sh-(src.height-1)-1;
2428 //Clip against the edges of the destination
2429 if(dx<surface.box.left)
2431 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2432 sw-=(int)((surface.box.left-dx)*d2sw);
2433 w-=surface.box.left-dx;
2434 dx=surface.box.left;
2436 if(dy<surface.box.top)
2438 sy+=(int)((surface.box.top-dy)*d2sh);
2439 sh-=(int)((surface.box.top-dy)*d2sh);
2440 h-=surface.box.top-dy;
2443 if((dx+w)>surface.box.right)
2445 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2446 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2447 w-=((dx+w)-surface.box.right-1);
2449 if((dy+h)>surface.box.bottom)
2451 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2452 h-=((dy+h)-surface.box.bottom-1);
2454 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2456 dx+=surface.offset.x;
2457 dy+=surface.offset.y;
2459 if(lfbSurface.bitmap.picture)
2461 AlphaWriteMode alphaWrite = surface.alphaWrite;
2462 if(src.alphaBlend && surface.blend)
2466 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2467 ColorAlpha * backsrc;
2468 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2469 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2470 if(flip) source += sw-1;
2488 ColorAlpha src = *source;
2489 ColorAlpha dst = *dest;
2490 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2491 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2492 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2493 if(r > 255) r = 255;
2494 if(g > 255) g = 255;
2495 if(b > 255) b = 255;
2496 dest->color = { (byte)r, (byte)g, (byte)b };
2497 if(alphaWrite == blend)
2499 int a = src.a + ((255 - src.a) * dst.a / 255);
2500 if(a > 255) a = 255;
2513 source += addsource;
2516 else if(src.paletteShades)
2517 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2518 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2519 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2520 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2521 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2525 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2527 LFBSurface lfbSurface = surface.driverData;
2530 float s2dw,s2dh,d2sw,d2sh;
2532 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2534 if(Sgn(w) != Sgn(sw))
2546 //Clip against the edges of the source
2549 dx+=(int)((0-sx) * s2dw);
2550 w-=(int)((0-sx) * s2dw);
2556 dy+=(int)((0-sy) * s2dh);
2557 h-=(int)((0-sy) * s2dh);
2562 if(sx+sw>src.width-1)
2564 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2565 sw-=sx+sw-(src.width-1)-1;
2567 if(sy+sh>(src.height-1))
2569 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2570 sh-=sy+sh-(src.height-1)-1;
2572 //Clip against the edges of the destination
2573 if(dx<surface.box.left)
2575 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2576 sw-=(int)((surface.box.left-dx)*d2sw);
2577 w-=surface.box.left-dx;
2578 dx=surface.box.left;
2580 if(dy<surface.box.top)
2582 sy+=(int)((surface.box.top-dy)*d2sh);
2583 sh-=(int)((surface.box.top-dy)*d2sh);
2584 h-=surface.box.top-dy;
2587 if((dx+w)>surface.box.right)
2589 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2590 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2591 w-=((dx+w)-surface.box.right-1);
2593 if((dy+h)>surface.box.bottom)
2595 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2596 h-=((dy+h)-surface.box.bottom-1);
2598 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2600 dx+=surface.offset.x;
2601 dy+=surface.offset.y;
2603 if(lfbSurface.bitmap.picture)
2605 AlphaWriteMode alphaWrite = surface.alphaWrite;
2606 if(src.alphaBlend && surface.blend)
2608 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2609 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2610 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2611 float scaleX = (float)sw / w;
2612 float scaleY = (float)sh / h;
2620 if (w > sw && h > sh)
2623 for (y = 0; y < h; y++)
2625 int y0 = y * sh / h;
2626 int y1 = Min(y0 + 1, sh - 1);
2627 float alpha = y * scaleY - y0;
2629 for(x = 0; x < w; x++, dest += 1)
2631 int x0 = x * sw / w;
2632 int x1 = Min(x0 + 1, sw - 1);
2633 float beta = x * scaleX - x0;
2634 ColorAlpha src00, src01, src10, src11;
2635 float a1,r1,g1,b1,a2,r2,g2,b2;
2637 src00 = source[y0 * src.stride + x0];
2638 src01 = source[y0 * src.stride + x1];
2639 src10 = source[y1 * src.stride + x0];
2640 src11 = source[y1 * src.stride + x1];
2641 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2642 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2643 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2644 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2645 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2646 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2647 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2648 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2649 a = a1 * (1.0f - alpha) + a2 * alpha;
2650 r = r1 * (1.0f - alpha) + r2 * alpha;
2651 g = g1 * (1.0f - alpha) + g2 * alpha;
2652 b = b1 * (1.0f - alpha) + b2 * alpha;
2654 ColorAlpha dst = *dest;
2655 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2656 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2657 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2658 if(cr > 255) cr = 255;
2659 if(cg > 255) cg = 255;
2660 if(cb > 255) cb = 255;
2661 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2663 if(alphaWrite == blend)
2665 int ca = (int)(a + ((255 - a) * dst.a / 255));
2666 if(ca > 255) ca = 255;
2679 for (y = 0; y < h; y++)
2681 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2682 int y1 = Min(y0 + 1, sh - 1);
2684 for (x = 0; x < w; x++, dest += 1)
2686 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2687 int x1 = Min(x0 + 1, sw - 1);
2688 float a = 0, r = 0, g = 0, b = 0;
2691 for (i = y0; i <= y1; i++)
2692 for (j = x0; j <= x1; j++)
2694 ColorAlpha pixel = source[i * src.stride + j];
2706 ColorAlpha dst = *dest;
2707 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2708 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2709 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2710 if(cr > 255) cr = 255;
2711 if(cg > 255) cg = 255;
2712 if(cb > 255) cb = 255;
2713 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2714 if(alphaWrite == blend)
2716 int ca = (int)(a + ((255 - a) * dst.a / 255));
2717 if(ca > 255) ca = 255;
2728 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2729 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2730 // Fail back on Stretch
2731 else if(src.paletteShades)
2732 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2733 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2734 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2735 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2736 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2740 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2742 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2745 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2747 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2750 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2752 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2755 void UnloadFont(DisplaySystem displaySystem, Font font)
2759 #if !defined(ECERE_NOTRUETYPE)
2761 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2763 FontEntry fontEntry = font.fontEntries[entry];
2769 loadedFonts.Remove(fontEntry);
2779 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
2781 void * result = null;
2783 #if !defined(ECERE_NOTRUETYPE)
2784 Font font = Font { };
2787 char fileName[MAX_LOCATION];
2788 bool fakeItalic = flags.italic;
2790 #if !defined(__WIN32__)
2793 const char * ecereFonts = getenv("ECERE_FONTS");
2794 if(!ecereFonts) ecereFonts = "<:ecere>";
2795 #if !defined(__WIN32__)
2797 char linkCfgPath[MAX_LOCATION];
2799 strcpy(linkCfgPath, ecereFonts);
2800 PathCat(linkCfgPath, "linking.cfg");
2801 linkCfg = FileOpen(linkCfgPath, read);
2804 strcpy(fileName, faceName);
2805 strcpy(font.faceName, faceName);
2807 font.displaySystem = displaySystem;
2809 if(!FileExists(fileName))
2811 strcpy(fileName, ecereFonts);
2812 PathCat(fileName, faceName);
2813 if(flags.bold && flags.italic) strcat(fileName, "bi");
2814 else if(flags.bold) strcat(fileName, "bd");
2815 else if(flags.italic) strcat(fileName, "i");
2816 strcat(fileName, ".ttf");
2820 if(flags.italic && !FileExists(fileName))
2822 strcpy(fileName, ecereFonts);
2823 PathCat(fileName, faceName);
2824 if(flags.bold) strcat(fileName, "bd");
2825 strcat(fileName, ".ttf");
2830 // Search in current working directory
2831 if(!FileExists(fileName))
2833 strcpy(fileName, faceName);
2834 if(flags.bold && flags.italic) strcat(fileName, "bi");
2835 else if(flags.bold) strcat(fileName, "bd");
2836 else if(flags.italic) strcat(fileName, "i");
2837 strcat(fileName, ".ttf");
2841 if(flags.italic && !FileExists(fileName))
2843 strcpy(fileName, faceName);
2844 if(flags.bold) strcat(fileName, "bd");
2845 strcat(fileName, ".ttf");
2851 #if defined(__WIN32__)
2852 if(!FileExists(fileName))
2854 FontData fontData = { { 0 } };
2855 LOGFONT logFont = { 0 };
2860 logFont.lfCharSet = DEFAULT_CHARSET;
2861 strcpy(logFont.lfFaceName, faceName);
2862 fontData.flags = flags;
2864 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2865 if(!fontData.fileName[0] && flags.bold)
2867 fontData.forgive = true;
2868 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2870 if(!fontData.fileName[0])
2873 fontData.flags.italic = false;
2874 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2878 if(fontData.fileName[0])
2880 GetWindowsDirectory(fileName, MAX_LOCATION);
2881 PathCat(fileName, "fonts");
2882 PathCat(fileName, fontData.fileName);
2886 #elif !defined(ECERE_NOFONTCONFIG)
2889 FcResult result = 0;
2890 FcPattern * pattern;
2891 FcPattern * matched;
2893 unichar testChar = 0;
2894 FcCharSet * charSet;
2896 fcConfig = FcInitLoadConfigAndFonts();
2898 charSet = FcCharSetCreate();
2900 if(!strcmpi(faceName, "Mangal"))
2906 FcCharSetAddChar(charSet, testChar);
2908 pattern = FcPatternBuild(null,
2909 //FC_SOURCE, FcTypeString, "freetype",
2910 FC_FAMILY, FcTypeString, faceName,
2911 //FC_SCALABLE, FcTypeBool, 1,
2912 FC_SIZE, FcTypeDouble, (double)size,
2913 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2914 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2915 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2917 FcDefaultSubstitute(pattern);
2918 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2920 matched = FcFontMatch (0, pattern, &result);
2921 // printf("Locating %s\n", faceName);
2924 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
2925 //printf("Fontconfig returned %s\n", family);
2927 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2930 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
2931 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2932 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2933 strcpy(fileName, fileName2);
2934 // size = (float)fontSize;
2936 //printf("Matched to %s, %f\n", fileName, size);
2940 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2942 if(pattern) FcPatternDestroy(pattern);
2943 if(matched) FcPatternDestroy(matched);
2944 if(charSet) FcCharSetDestroy(charSet);
2949 if(!FileExists(fileName))
2950 ChangeExtension(fileName, "otf", fileName);
2951 if(!FileExists(fileName))
2952 ChangeExtension(fileName, "ttc", fileName);
2954 //if(FileExists(fileName))
2957 char links[1024] = "";
2959 #if defined(__WIN32__)
2962 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2963 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2968 RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
2969 memset(links + size, 0, 1024 - size);
2977 while(linkCfg.GetLine(line, sizeof(line)))
2979 int len = strlen(faceName);
2980 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2982 while(linkCfg.GetLine(line, sizeof(line)))
2984 TrimLSpaces(line, line);
2985 if(!line[0] || line[0] == '[')
2988 memcpy(links + linksPos, line, len);
2990 links[linksPos] = 0;
2998 while(entry < MAX_FONT_LINK_ENTRIES)
3000 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3003 File file = FileOpen/*Buffered*/(fileName, read);
3006 FileSize fileSize = file.GetSize();
3007 FT_Open_Args args = { 0 };
3008 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3009 FT_Stream stream = new0 FT_StreamRec[1];
3012 FT_Init_FreeType( &ftLibrary );
3014 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3015 fontEntry.stream = stream;
3018 fontEntry.buffer = new byte[fileSize];
3019 file.Read(fontEntry.buffer, 1, fileSize);
3022 //args.num_params = 1;
3023 args.params = ¶m;
3025 stream->size = fileSize;
3026 stream->descriptor.pointer = file;
3027 stream->read = FT_stream_load;
3028 stream->close = FT_stream_close;
3030 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3031 args.stream = stream;
3032 //args.pathname = fileName;
3033 //args.memory_base = fontEntry.buffer;
3034 //args.memory_size = fileSize;
3036 // printf("Opening: %s\n", fileName);
3037 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3042 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3043 fontEntry.hbFont.klass = &hb_fontClass;
3044 fontEntry.hbFont.userData = fontEntry; //.face;
3047 loadedFonts.Add(fontEntry);
3052 // printf("Error opening font %s\n", fileName);
3061 FT_Vector pen = { 0, 0 };
3064 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3065 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3066 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3067 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3071 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3072 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3073 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3074 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3076 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3077 FaceSetCharSize(fontEntry.face, size);
3078 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3079 // printf("Font height is %d\n", font.height);
3080 font.fakeItalic = fakeItalic;
3084 font.fontEntries[entry++] = fontEntry;
3091 char fontName[1024];
3092 if(!links[linksPos]) break;
3093 for(c = 0; (ch = links[linksPos + c]); c++)
3096 if(ch == ',') break;
3099 if(fontName[0] || ch == ',')
3101 #if defined(__WIN32__)
3102 GetWindowsDirectory(fileName, MAX_LOCATION);
3103 PathCat(fileName, "fonts");
3104 PathCat(fileName, fontName);
3105 #elif !defined(ECERE_NOFONTCONFIG)
3106 if(getenv("ECERE_FONTS"))
3108 strcpy(fileName, ecereFonts);
3109 PathCat(fileName, fontName);
3115 FcResult result = 0;
3116 FcPattern * pattern;
3117 FcPattern * matched;
3119 pattern = FcPatternBuild(null,
3120 //FC_SOURCE, FcTypeString, "freetype",
3121 //FC_SCALABLE, FcTypeBool, 1,
3122 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3123 FC_SIZE, FcTypeDouble, (double)size,
3124 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3125 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3127 FcDefaultSubstitute(pattern);
3128 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3130 //printf("Locating %s\n", links + linksPos + c + 1);
3131 matched = FcFontMatch (0, pattern, &result);
3134 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3135 // printf("Fontconfig returned %s\n", family);
3137 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3138 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3141 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
3142 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3143 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3144 strcpy(fileName, fileName2);
3145 //size = (float)fontSize;
3146 // printf("Matched to %s, %f\n", fileName, size);
3150 // 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);
3152 if(pattern) FcPatternDestroy(pattern);
3153 if(matched) FcPatternDestroy(matched);
3160 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3167 UnloadFont(displaySystem, font);
3170 font.asciiPack.Render(font, 0, displaySystem);
3172 #if !defined(__WIN32__)
3180 #if !defined(ECERE_NOTRUETYPE)
3181 void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
3182 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3183 Surface surface, Display display, int * x, int y)
3185 if(font && font.fontEntries && font.fontEntries[0])
3187 int previousGlyph = 0;
3188 FT_Face previousFace = 0;
3189 int c, nb, glyphIndex = 0;
3190 unichar lastPack = 0;
3191 GlyphPack pack = font.asciiPack;
3193 uint * glyphs = null;
3195 bool rightToLeft = false;
3196 int fontEntryNum = 0;
3197 int glyphScript = 0;
3198 FontEntry curFontEntry;
3200 pack.bitmap.alphaBlend = true;
3202 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3206 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3208 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3209 rightToLeft ? glyphIndex-- : glyphIndex++;
3213 HB_Script curScript = HB_Script_Common;
3214 const byte * scriptStart = text + c;
3215 //unichar nonASCIIch = 0;
3218 unichar testChar = 0;
3219 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3220 const char * testLang = null;
3225 HB_Script script = HB_Script_Common;
3226 ch = UTF8GetChar((const char *)text + c, &nb);
3227 //if(ch > 127) nonASCIIch = ch;
3229 if(ch == 32 && curScript)
3236 for(a = c + 1; a < c + len; a++)
3244 unichar ahead = UTF8GetChar((const char *)text + a, &nb);
3245 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3253 script = HB_Script_Common;
3254 else if(ch <= 0x11FF)
3258 case 0x300: script = HB_Script_Greek; break;
3259 case 0x400: script = HB_Script_Cyrillic; break;
3260 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3261 case 0x600: script = HB_Script_Arabic; break;
3262 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3263 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3264 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3265 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3266 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3267 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3268 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3269 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3270 case 0xF00: script = HB_Script_Tibetan; break;
3271 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3272 case 0x1100: script = HB_Script_Hangul; break;
3275 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3276 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3277 script = HB_Script_Hangul;
3278 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3279 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3280 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3281 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3282 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3283 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3284 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3285 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3286 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3289 if(!script || (script != curScript))
3297 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3298 if(!script) { c += nb; break; }
3305 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3307 rightToLeft = false;
3309 theCurrentScript = 0;
3313 int len = c - (int)(scriptStart - text);
3314 int max = len * 2 + 1;
3315 if(max > utf16BufferSize)
3317 utf16 = renew utf16 uint16[max];
3318 utf16BufferSize = max;
3320 wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
3321 theCurrentScript = glyphScript = curScript;
3325 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3326 //printf("Arabic ");
3328 case HB_Script_Devanagari: testChar = 0x905;
3329 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3332 //printf("Devanagari ");
3334 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3335 //printf("Hebrew ");
3338 testChar = (ch == '\t') ? ' ' : ch;
3340 case 60: testChar = 'あ'; break;
3341 case 61: testChar = 0x3400; break; //'愛'; break;
3347 // printf("Testing for char %x\n", testChar);
3348 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3350 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3352 /*if(font.fontEntries[fontEntryNum])
3353 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3357 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3359 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3361 double fontSize = font.size;
3362 FcResult result = 0;
3363 FcPattern * pattern;
3364 FcPattern * matched;
3365 FcCharSet * charSet;
3367 FontEntry fontEntry;
3368 char * fileName = null;
3369 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3370 if(!font.fontEntries[fontEntryNum])
3372 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3376 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3378 charSet = FcCharSetCreate();
3379 FcCharSetAddChar(charSet, testChar);
3380 //printf("Loading with char %x\n", testChar);
3382 pattern = FcPatternBuild(null,
3383 //FC_SOURCE, FcTypeString, "freetype",
3384 //FC_SCALABLE, FcTypeBool, 1,
3385 FC_FAMILY, FcTypeString, font.faceName,
3386 FC_SIZE, FcTypeDouble, (double)font.size,
3387 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3388 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3389 FC_CHARSET,FcTypeCharSet, charSet,
3390 testLang ? FC_LANG : 0, FcTypeString,testLang,
3392 FcDefaultSubstitute(pattern);
3393 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3395 //printf("Locating %s for script %d\n", font.faceName, curScript);
3396 matched = FcFontMatch (0, pattern, &result);
3399 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3400 //printf("Fontconfig returned %s\n", family);
3402 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
3404 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName);
3405 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3406 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3407 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3411 //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);
3416 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3419 File file = FileOpen(fileName, read);
3422 FileSize fileSize = file.GetSize();
3423 FT_Open_Args args = { 0 };
3424 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3425 FT_Stream stream = new0 FT_StreamRec[1];
3428 FT_Init_FreeType( &ftLibrary );
3430 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3431 fontEntry.stream = stream;
3433 //args.num_params = 1;
3434 args.params = ¶m;
3436 stream->size = fileSize;
3437 stream->descriptor.pointer = file;
3438 stream->read = FT_stream_load;
3439 stream->close = FT_stream_close;
3441 args.flags = FT_OPEN_STREAM;
3442 args.stream = stream;
3443 //args.pathname = fileName;
3444 //args.memory_base = fontEntry.buffer;
3445 //args.memory_size = fileSize;
3447 // printf("Opening: %s\n", fileName);
3448 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3453 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3454 fontEntry.hbFont.klass = &hb_fontClass;
3455 fontEntry.hbFont.userData = fontEntry; //.face;
3458 loadedFonts.Add(fontEntry);
3463 // printf("Error opening font %s\n", fileName);
3469 FaceSetCharSize(fontEntry.face, font.size);
3471 font.fontEntries[fontEntryNum] = fontEntry;
3475 if(pattern) FcPatternDestroy(pattern);
3476 if(matched) FcPatternDestroy(matched);
3477 if(charSet) FcCharSetDestroy(charSet);
3480 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3481 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3483 font.fontEntries[fontEntryNum].font = font;
3484 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3488 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3489 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3490 rightToLeft ? glyphIndex-- : glyphIndex++;
3494 curFontEntry = font.fontEntries[fontEntryNum];
3496 packNo = glyphNo & 0xFFFFFF80;
3498 if(packNo != lastPack)
3501 pack = font.asciiPack;
3504 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3507 pack = GlyphPack { key = (uintptr)packNo };
3508 font.glyphPacks.Add(pack);
3509 pack.Render(font, fontEntryNum, displaySystem);
3512 pack.bitmap.alphaBlend = true;
3517 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3518 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3520 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3521 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3522 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3526 if(previousGlyph && curFontEntry.face == previousFace)
3528 FT_Vector delta = { 0, 0 };
3529 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3530 if(delta.x < 0) delta.x += (-delta.x) % 64;
3531 else if(delta.x) delta.x += 64 - (delta.x % 64);
3532 *x += delta.x * glyph->scale;
3535 FaceSetCharSize(curFontEntry.face, font.size);
3537 previousGlyph = glyph->glyphNo;
3538 previousFace = curFontEntry.face;
3541 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3544 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3550 LFBSurface lfbSurface = surface.driverData;
3551 lfbSurface.xOffset = 0;
3556 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3558 if(displaySystem && displaySystem.flags.text && len)
3563 *width = num * textCellW;
3565 if(height) *height = textCellH;
3567 else if(font && len)
3572 #if !defined(ECERE_NOTRUETYPE)
3573 ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
3575 //*width = (w + 64 - w % 64) >> 6;
3579 *height = font.height;
3583 if(width) *width = 0;
3584 if(height) *height = 0;
3588 #if !defined(ECERE_NOTRUETYPE)
3589 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3591 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3595 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3597 LFBSurface lfbSurface = surface.driverData;
3598 if(display && display.displaySystem.flags.text)
3600 LFBDisplay lfbDisplay = display.driverData;
3601 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3607 if(y > surface.box.bottom || y < surface.box.top)
3609 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3610 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3611 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3613 if(surface.textOpacity)
3614 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3616 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3621 lfbSurface.writingText = true;
3622 #if !defined(ECERE_NOTRUETYPE)
3624 ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
3626 lfbSurface.writingText = false;
3630 void TextFont(Display display, Surface surface, Font font)
3632 LFBSurface lfbSurface = surface.driverData;
3633 lfbSurface.font = font;
3636 void TextOpacity(Display display, Surface surface, bool opaque)
3641 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3643 LFBSurface lfbSurface = surface.driverData;
3644 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3647 void DrawingChar(Display display, Surface surface, byte character)
3649 LFBSurface lfbSurface = surface.driverData;
3650 lfbSurface.drawingChar = character;
3653 void LineStipple(Display display, Surface surface, uint32 stipple)
3655 LFBSurface lfbSurface = surface.driverData;
3656 lfbSurface.stipple = (uint16)stipple;
3659 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3660 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3662 if(mesh.vertices && !mesh.flags.vertices)
3663 delete mesh.vertices;
3664 if(mesh.normals && !mesh.flags.normals)
3665 delete mesh.normals;
3666 if(mesh.texCoords && !mesh.flags.texCoords1)
3667 delete mesh.texCoords;
3670 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3672 bool result = false;
3673 if(mesh.nVertices == nVertices)
3676 // Same number of vertices, adding features (Leaves the other features pointers alone)
3677 if(mesh.flags != flags)
3679 if(!mesh.flags.vertices && flags.vertices)
3681 if(flags.doubleVertices)
3683 mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3686 mesh.vertices = new Vector3Df[nVertices];
3688 if(!mesh.flags.normals && flags.normals)
3690 if(flags.doubleNormals)
3692 mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3695 mesh.normals = new Vector3Df[nVertices];
3697 if(!mesh.flags.texCoords1 && flags.texCoords1)
3698 mesh.texCoords = new Pointf[nVertices];
3699 if(!mesh.flags.colors && flags.colors)
3700 mesh.colors = new ColorRGBAf[nVertices];
3706 // New number of vertices, reallocate all current and new features
3707 flags |= mesh.flags;
3710 if(flags.doubleVertices)
3712 mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3715 mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
3719 if(flags.doubleNormals)
3721 mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
3724 mesh.normals = renew mesh.normals Vector3Df[nVertices];
3726 if(flags.texCoords1)
3727 mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
3729 mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
3734 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3739 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3744 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3746 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3748 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)