1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
8 #if !defined(ECERE_NOTRUETYPE)
10 #include FT_FREETYPE_H
11 #include FT_TRUETYPE_TABLES_H
12 #include <freetype/ttunpat.h>
13 #define property _property
17 #if defined(__WIN32__)
18 #define WIN32_LEAN_AND_MEAN
20 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
22 #include <fontconfig/fontconfig.h>
23 static FcConfig * fcConfig;
31 #pragma warning(disable:4244)
32 #pragma warning(disable:4018)
38 public define LIGHTSHIFT = 5;
39 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
41 /*#ifndef ECERE_VANILLA
43 static bool rgbLookupSet = true;
45 /*static */byte defaultRGBLookup[32768];
46 /*static */bool rgbLookupSet = false;
52 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
53 import "OpenGLDisplayDriver"
54 import "Direct3D8DisplayDriver"
55 import "Direct3D9DisplayDriver"
58 #if !defined(ECERE_NOTRUETYPE)
60 static unichar UTF16GetChar(uint16 *string, int * nw)
63 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
65 ch = HB_SurrogateToUcs4(string[0], string[1]);
76 static HB_Bool hb_stringToGlyphs(HB_Font font, uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
78 FT_Face face = (FT_Face)font->userData;
82 if (length > *numGlyphs)
85 for (c = 0; c < length; c += nw)
87 unichar ch = UTF16GetChar(string + c, &nw);
88 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
90 *numGlyphs = glyph_pos;
94 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
97 for(c = 0; c < numGlyphs; c++)
98 advances[c] = 0; // ### not tested right now
101 static HB_Bool hb_canRender(HB_Font font, uint16 * string, uint length)
103 FT_Face face = (FT_Face)font->userData;
106 for (c = 0; c < length; c += nw)
108 unichar ch = UTF16GetChar(string + c, &nw);
109 if(!FT_Get_Char_Index(face, ch))
115 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
117 FT_Face face = (FT_Face)font;
118 FT_ULong ftlen = *length;
121 if (!FT_IS_SFNT(face))
122 return HB_Err_Invalid_Argument;
124 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
126 return (HB_Error)error;
129 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)
131 HB_Error error = HB_Err_Ok;
132 FT_Face face = (FT_Face)font->userData;
134 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
136 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
139 if (face->glyph->format != ft_glyph_format_outline)
140 return (HB_Error)HB_Err_Invalid_GPOS_SubTable;
142 *nPoints = face->glyph->outline.n_points;
146 if (point > *nPoints)
147 return (HB_Error)HB_Err_Invalid_GPOS_SubTable;
149 *xpos = face->glyph->outline.points[point].x;
150 *ypos = face->glyph->outline.points[point].y;
155 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)
158 metrics->x = metrics->y = metrics->width = metrics->height = metrics->xOffset = metrics->yOffset = 0;
161 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
166 static HB_FontClass hb_fontClass =
168 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
169 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
172 static uint FT_stream_load(FT_Stream stream, uint offset, byte * buffer, uint count)
174 File f = stream->descriptor.pointer;
175 f.Seek(offset, start);
176 return count ? f.Read(buffer, 1, count) : 0;
179 static void FT_stream_close(FT_Stream stream)
181 File f = stream->descriptor.pointer;
186 static FT_Library ftLibrary;
189 static BinaryTree loadedFonts
191 CompareKey = (void *)BinaryTree::CompareString
194 class FontEntry : BTNode
203 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
208 char * fileName = (char *)key;
219 FT_Done_FreeType(ftLibrary);
236 #define MAX_FONT_LINK_ENTRIES 10
238 class GlyphPack : BTNode
240 GlyphInfo glyphs[256];
243 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
245 #if !defined(ECERE_NOTRUETYPE)
247 int maxWidth, maxHeight;
248 int cellWidth, cellHeight;
250 FontEntry fontEntry = null;
252 bool isGlyph = key & 0x80000000;
253 int curScript = (key & 0x7F000000) >> 24;
254 unichar testChar = 0;
260 case HB_Script_Arabic:
262 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
264 case HB_Script_Devanagari:
267 case 60: testChar = 'あ'; break;
268 case 61: testChar = 0x3400; break;
275 FT_Vector pen = { 0, 0 };
278 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
279 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
280 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
281 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
282 FT_Set_Transform( fontEntry.face, &matrix, &pen );
284 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
290 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
292 fontEntry = font.fontEntries[c];
296 FT_Vector pen = { 0, 0 };
300 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
301 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
302 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
303 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
304 FT_Set_Transform(fontEntry.face, &matrix, &pen);
306 FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
308 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
309 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
310 fontEntry.hbFont.x_scale = fontEntry.face->size->metrics.x_scale;
311 fontEntry.hbFont.y_scale = fontEntry.face->size->metrics.y_scale;
316 for(c = 0; c < 128; c++)
321 uint glyph = (key | c) & 0xFFFFFF;
322 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
324 fontEntry = font.fontEntries[entry];
325 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
327 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
330 //printf("%s: Accepted entry %d ", font.faceName, entry);
338 for(entry = startFontEntry; ; entry++)
341 fontEntry = font.fontEntries[entry];
342 if((glyph = FT_Get_Char_Index(fontEntry.face, (key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
344 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
349 faces[c] = fontEntry.face;
350 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - faces[c]->glyph->metrics.width & 0x3F)) >> 6));
351 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6));
352 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
354 cellWidth = maxWidth;
355 cellHeight = maxHeight;
357 width = pow2i(maxWidth * 16);
358 height = pow2i(maxHeight * 8);
360 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
362 Bitmap bitmap = this.bitmap;
364 bitmap.transparent = true;
366 for(c = 0; c < 128; c++)
370 int sx = (c % 16) * cellWidth;
371 int sy = (c / 16) * cellHeight;
373 byte * picture = (byte *)bitmap.picture;
374 GlyphInfo * glyph = &glyphs[c];
375 FT_GlyphSlot slot = faces[c]->glyph;
376 double em_size = 1.0 * faces[c]->units_per_EM;
377 double x_scale = faces[c]->size->metrics.x_ppem / em_size;
378 double y_scale = faces[c]->size->metrics.y_ppem / em_size;
379 double ascender = faces[c]->ascender * y_scale;
380 int glyphNo = isGlyph ? ((key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], key | c);
382 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
384 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
388 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
390 glyph->left = slot->bitmap_left;
391 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
392 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
393 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
394 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
396 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
397 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
399 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
401 //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));
402 //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));
404 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
405 glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6)) / 2;
407 // 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);
408 xMax = x + slot->bitmap.width;
409 yMax = y + slot->bitmap.rows;
415 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
417 for(j = y, q = 0; j<yMax; j++)
419 for(p = 0, i = x; i<xMax; i++)
421 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
428 q += slot->bitmap.pitch;
431 max = numPixels ? (total / numPixels) : 1;
433 for(j = y, q = 0; j<yMax; j++)
436 for(p = 0, i = x; i<xMax; i++)
438 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
440 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
442 if(!bit) { bit = 0x80; p++; }
446 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
447 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
450 q += slot->bitmap.pitch;
455 glyph->w = slot->bitmap.width;
456 glyph->h = slot->bitmap.rows;
457 glyph->glyphNo = glyphNo;
459 glyph->ax = slot->advance.x;
460 glyph->ay = slot->advance.y + (64 - slot->advance.y % 64);
467 for(c = 0; c<256; c++)
468 bitmap.palette[c] = ColorAlpha { 255, { c,c,c } };
469 bitmap.pixelFormat = pixelFormat8;
472 //strcpy(fileName, faceName);
474 strcat(fileName, "Bold");
476 sprintf(fileName, "font%d", fid++);
477 ChangeExtension(fileName, "pcx", fileName);
479 bitmap.Save(fileName, null, 0);
480 bitmap.pixelFormat = pixelFormatAlpha;
484 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
486 displaySystem.Lock();
487 #if defined(__WIN32__)
488 // Is this check still required?
489 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
490 displaySystem.driver == class(Direct3D8DisplayDriver) ||
491 displaySystem.driver == class(Direct3D9DisplayDriver))
493 bitmap.MakeDD(displaySystem);
494 displaySystem.Unlock();
501 #if !defined(ECERE_NOTRUETYPE)
503 HB_LineBreakClass HB_GetLineBreakClass(unichar ch)
505 return 0; //(HB_LineBreakClass)QUnicodeTables::lineBreakClass(ch);
508 void HB_GetUnicodeCharProperties(unichar ch, HB_CharCategory *category, int *combiningClass)
510 *category = GetCharCategory(ch); //(HB_CharCategory)QChar::category(ch);
511 *combiningClass = 0; //QChar::combiningClass(ch);
514 HB_CharCategory HB_GetUnicodeCharCategory(unichar ch)
516 return GetCharCategory(ch);
519 int HB_GetUnicodeCharCombiningClass(unichar ch)
521 return 0; // QChar::combiningClass(ch);
524 uint16 HB_GetMirroredChar(uint16 ch)
526 return 0; //QChar::mirroredChar(ch);
530 static HB_ShaperItem shaper_item;
532 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
534 static uint maxGlyphs = 0;
535 HB_Glyph * glyphs = shaper_item.glyphs;
537 shaper_item.kerning_applied = 0;
538 shaper_item.string = string;
539 shaper_item.stringLength = len;
540 shaper_item.item.script = script;
541 shaper_item.item.pos = 0;
542 shaper_item.item.length = shaper_item.stringLength;
543 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
544 shaper_item.item.bidiLevel = 1;
546 shaper_item.item.bidiLevel = 0;
547 shaper_item.shaperFlags = 0;
548 shaper_item.font = &entry.hbFont;
549 shaper_item.face = entry.hbFace;
550 shaper_item.num_glyphs = shaper_item.item.length;
551 shaper_item.glyphIndicesPresent = 0;
552 shaper_item.initialGlyphCount = 0;
553 shaper_item.num_glyphs = 0;
554 shaper_item.glyphs = null;
556 while(!HB_ShapeItem(&shaper_item))
558 if(shaper_item.num_glyphs > maxGlyphs)
560 maxGlyphs = shaper_item.num_glyphs;
561 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
562 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
563 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
564 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
565 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
569 shaper_item.glyphs = glyphs;
570 shaper_item.num_glyphs = maxGlyphs;
574 *numGlyphs = shaper_item.num_glyphs;
575 *rightToLeft = shaper_item.item.bidiLevel % 2;
576 return shaper_item.glyphs;
580 delete shaper_item.glyphs;
581 delete shaper_item.attributes;
582 delete shaper_item.advances;
583 delete shaper_item.offsets;
584 delete shaper_item.log_clusters;
588 public class Font : struct
590 BinaryTree glyphPacks { };
591 GlyphPack asciiPack { };
592 #if !defined(ECERE_NOTRUETYPE)
593 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
603 #if !defined(ECERE_NOTRUETYPE)
605 while((pack = (GlyphPack)glyphPacks.root))
607 glyphPacks.Remove(pack);
614 public class LFBDisplay : struct
618 byte rgbLookup[32768];
619 byte lightTable[256][LIGHTSTEPS];
623 void (* displayCallback)(Display display, Box updateBox);
626 public class LFBSystem : struct
630 ColorAlpha * palette;
631 byte rgbLookup[32768];
638 ColorAlpha * palette = GetDefaultPalette();
639 for(c = 16; c < 232; c++)
641 Color555 color = palette[c].color;
642 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
643 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
644 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
645 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
647 for(c = 232; c < 246; c++)
649 Color555 color = palette[c].color;
650 defaultRGBLookup[color] = (byte)c;
653 for(c = 246; c < 256; c++)
655 Color555 color = palette[c].color;
656 defaultRGBLookup[color] = (byte)c;
658 for(c = 0; c < 16; c++)
660 Color555 color = palette[c].color;
661 defaultRGBLookup[color] = (byte)c;
664 for(c = 0; c<32768; c++)
666 Color color = (Color)(Color555)c;
667 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
668 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
676 public class LFBSurface : struct
679 // For compatibility with 3D drivers as well
687 // Drawing attributes
688 uint foreground, background;
689 ColorAlpha foregroundRgb;
692 byte * paletteShades;
697 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
699 if(recordA->zMin > recordB->zMin)
701 else if(recordA->zMin < recordB->zMin)
703 else if(recordA > recordB)
705 else if(recordA < recordB)
712 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
715 char fileName[MAX_FILENAME];
719 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
721 if(fontType == TRUETYPE_FONTTYPE)
723 FontData * fontData = (FontData *) lParam;
724 char * fileName = (char *)lParam;
726 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
727 int italic = (fontData->flags.italic) ? 1 : 0;
728 if(weight == font->elfLogFont.lfWeight && italic == (font->elfLogFont.lfItalic != 0))
730 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
731 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
736 char entryName[1024];
737 char fontFileName[1024];
740 int sizeFileName = 1024;
742 if(RegEnumValue(key, value++, entryName, &size, null, &type, fontFileName, &sizeFileName) != ERROR_SUCCESS)
744 if((occurence = SearchString(entryName, 0, font->elfFullName, false, false)))
747 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
749 char ch = entryName[c];
750 if(ch == '&') { c = -1; break; }
751 else if(ch != ' ') break;
754 for(c = (int)(occurence - entryName) + strlen(font->elfFullName); ; c++)
756 char ch = entryName[c];
757 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
758 else if(ch != ' ') break;
762 strcpy(fileName, fontFileName);
776 static int utf16BufferSize = 0;
777 static uint16 * utf16 = null;
779 public class LFBDisplayDriver : DisplayDriver
781 class_property(name) = "LFB";
783 bool CreateDisplaySystem(DisplaySystem displaySystem)
785 displaySystem.flags.memBackBuffer = true;
786 // displaySystem.pixelFormat = pixelFormat888;
790 void DestroyDisplaySystem(DisplaySystem displaySystem)
794 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
796 delete bitmap.picture;
797 if(bitmap.allocatePalette)
798 delete bitmap.palette;
801 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
806 switch(GetColorDepthShifts(format))
808 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
809 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
810 case 2: stride = width; break;
813 bitmap.stride = stride;
814 bitmap.width = width;
815 bitmap.height = height;
816 bitmap.size = (uint32) stride * (uint32)height;
817 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
818 bitmap.pixelFormat = format;
819 bitmap.transparent = false;
821 surface.box.left = surface.box.top = 0;
822 surface.box.right = width - 1;
823 surface.box.bottom = height - 1;
825 bitmap.picture = new0 byte[bitmap.sizeBytes];
828 bitmap.allocatePalette = allocatePalette;
831 bitmap.palette = new ColorAlpha[256];
834 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
840 bitmap.palette = GetDefaultPalette();
845 FreeBitmap(displaySystem, bitmap);
849 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
852 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
856 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
858 if(src.transparent && src.pixelFormat == pixelFormat888)
862 DWORD * picture = (DWORD *)src.picture;
864 for(c = 0; c<src.size; c++, picture++)
866 if(*picture & 0xFFFFFF)
867 *picture = *picture | 0xFF000000;
869 *picture = *picture & 0xFFFFFF;
878 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
880 if(format == pixelFormat8)
883 bitmap.palette = palette;
884 else if(lfbSystem && lfbSystem.palette)
885 bitmap.palette = lfbSystem.palette;
887 bitmap.palette = src.palette;
890 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
892 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
893 bitmap.transparent = src.transparent;
894 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
896 if(src.palette != bitmap.palette)
898 if(src.allocatePalette)
900 src.allocatePalette = false;
902 src.picture = bitmap.picture;
903 src.palette = bitmap.palette;
904 src.stride = bitmap.stride;
905 src.pixelFormat = bitmap.pixelFormat;
910 bitmap.palette = null;
911 bitmap.picture = null;
919 void DestroyDisplay(Display display)
921 LFBDisplay lfbDisplay = display.driverData;
922 delete lfbDisplay.bitmap.palette;
925 bool CreateDisplay(Display display)
928 LFBDisplay lfbDisplay = display.driverData;
931 lfbDisplay = display.driverData = LFBDisplay { };
932 lfbDisplay.selfManaged = true;
933 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
936 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
938 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
944 bool DisplaySize(Display display, int width, int height)
946 LFBDisplay lfbDisplay = display.driverData;
947 //display.width = width;
948 //display.height = height;
949 lfbDisplay.bitmap.width = width;
950 lfbDisplay.bitmap.height = height;
952 lfbDisplay.updateBox.left = display.width;
953 lfbDisplay.updateBox.top = display.height;
954 lfbDisplay.updateBox.right = 0;
955 lfbDisplay.updateBox.bottom = 0;
958 if(lfbDisplay.selfManaged)
960 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
961 lfbDisplay.bitmap.stride = width;
963 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
967 void DisplayPosition(Display display, int x, int y)
969 LFBDisplay lfbDisplay = display.driverData;
974 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
976 LFBDisplay lfbDisplay = display.driverData;
983 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
984 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
985 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
988 for(c = 0; c<32768; c++)
989 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
994 for(i=0; i<LIGHTSTEPS; i++)
996 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
997 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
998 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
999 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1003 if(lfbDisplay.bitmap.palette)
1004 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1007 void Update(Display display, Box updateBox)
1009 LFBDisplay lfbDisplay = display.driverData;
1010 if(lfbDisplay.displayCallback)
1012 if(updateBox == null)
1014 Box box { 0,0, display.width,display.height };
1015 lfbDisplay.displayCallback(display, box);
1018 lfbDisplay.displayCallback(display, updateBox);
1022 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1024 if(bitmap.pixelFormat != pixelFormatAlpha)
1026 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1028 FreeBitmap(displaySystem, bitmap);
1035 void ReleaseSurface(Display display, Surface surface)
1037 LFBSurface lfbSurface = surface.driverData;
1039 surface.driverData = null;
1042 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1044 LFBDisplay lfbDisplay = display.driverData;
1045 LFBSurface lfbSurface = surface.driverData;
1048 lfbSurface = surface.driverData = LFBSurface { };
1051 lfbSurface.bitmap = lfbDisplay.bitmap;
1053 surface.offset.x = x;
1054 surface.offset.y = y;
1056 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1058 surface.offset.x /= textCellW;
1059 surface.offset.y /= textCellH;
1060 surface.box.left /= textCellW;
1061 surface.box.top /= textCellH;
1062 surface.box.right /= textCellW;
1063 surface.box.bottom /= textCellH;
1067 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1068 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1069 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1070 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1073 surface.unclippedBox = surface.box;
1074 lfbSurface.drawingChar = 219;
1078 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1080 bool result = false;
1081 LFBSurface lfbSurface = surface.driverData;
1082 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1084 lfbSurface.bitmap = bitmap;
1086 surface.offset.x = x;
1087 surface.offset.y = y;
1089 if(bitmap.pixelFormat == pixelFormatText)
1091 surface.offset.x /= textCellW;
1092 surface.offset.y /= textCellH;
1093 surface.box.left /= textCellW;
1094 surface.box.top /= textCellH;
1095 surface.box.right /= textCellW;
1096 surface.box.bottom /= textCellH;
1099 surface.unclippedBox = *&surface.box;
1100 lfbSurface.drawingChar = 219;
1107 void Clip(Display display, Surface surface, Box clip)
1109 LFBSurface lfbSurface = surface.driverData;
1114 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1116 box.left /= textCellW;
1117 box.top /= textCellH;
1118 box.right /= textCellW;
1119 box.bottom /= textCellH;
1121 box.Clip(surface.unclippedBox);
1125 surface.box = surface.unclippedBox;
1128 void SetForeground(Display display, Surface surface, ColorAlpha color)
1130 LFBDisplay lfbDisplay = display ? display.driverData : null;
1131 LFBSurface lfbSurface = surface.driverData;
1133 if(display) color = color /*& 0xFFFFFF*/;
1134 lfbSurface.foregroundRgb = color;
1136 if(lfbSurface.font && lfbDisplay)
1138 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1139 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1142 switch(lfbSurface.bitmap.pixelFormat)
1146 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1148 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1150 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1151 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1152 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1153 case pixelFormat888: lfbSurface.foreground = color; break;
1154 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1155 case pixelFormatText:
1157 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1159 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1164 void SetBackground(Display display, Surface surface, ColorAlpha color)
1166 LFBDisplay lfbDisplay = display ? display.driverData : null;
1167 LFBSurface lfbSurface = surface.driverData;
1168 color = color /*& 0xFFFFFF*/;
1169 switch(lfbSurface.bitmap.pixelFormat)
1173 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1175 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1177 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1178 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1179 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1180 case pixelFormat888: lfbSurface.background = color; break;
1181 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1182 case pixelFormatText:
1184 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1186 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1191 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1193 LFBSurface lfbSurface = surface.driverData;
1194 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1199 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1201 x += surface.offset.x;
1202 y += surface.offset.y;
1203 if(lfbSurface.bitmap.picture)
1205 switch(lfbSurface.bitmap.pixelFormat)
1207 case pixelFormatText:
1209 if(!lfbSurface.bitmap.palette) return 0;
1210 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1211 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1212 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1213 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1214 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1221 void PutPixel(Display display, Surface surface,int x,int y)
1223 LFBSurface lfbSurface = surface.driverData;
1224 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1229 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1231 x += surface.offset.x;
1232 y += surface.offset.y;
1233 if(lfbSurface.bitmap.picture)
1235 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1238 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1241 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1244 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1245 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1252 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1254 LFBSurface lfbSurface = surface.driverData;
1260 uint color = lfbSurface.foreground;
1261 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1262 bool invert = false;
1263 if(!lfbSurface.bitmap.picture) return;
1264 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1270 if(surface.textOpacity)
1271 color |= lfbSurface.background;
1272 color |= lfbSurface.drawingChar;
1276 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1278 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1279 if((x1>surface.box.right)||(x2<surface.box.left))return;
1280 if(x1<surface.box.left)x1=surface.box.left;
1281 if(x2>surface.box.right)x2=surface.box.right;
1285 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1286 if(stipple != 0xFFFF)
1289 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1292 for(x=x1; x<=x2; x++, offset++)
1294 if(stipple & 0x8000)
1295 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1297 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1299 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1303 for(x=x1; x<=x2; x++, offset++)
1305 if(stipple & 0x8000)
1306 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1308 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1310 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1314 for(x=x1; x<=x2; x++, offset++)
1316 if(stipple & 0x8000)
1317 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1319 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1321 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1328 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1330 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1332 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1333 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1334 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1340 for(x = x1; x <= x2; x++, offset++)
1342 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1343 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1352 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1354 if((x1>surface.box.right)||(x1<surface.box.left))return;
1355 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1356 if(y1<surface.box.top)y1=surface.box.top;
1357 if(y2>surface.box.bottom)y2=surface.box.bottom;
1359 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1360 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1363 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1365 if(stipple & 0x8000)
1366 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1368 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1370 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1374 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1376 if(stipple & 0x8000)
1378 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1379 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1382 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1383 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1387 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1389 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1393 if(stipple != 0xFFFF)
1395 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1397 if(stipple & 0x8000)
1398 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1400 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1402 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1407 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1408 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1417 if(x1 < surface.box.left)
1419 if(x2 < surface.box.left)
1421 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1422 x1 = surface.box.left;
1424 if(x2 > surface.box.right)
1426 if(x1 > surface.box.right)
1428 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1429 x2 = surface.box.right;
1433 if(y1 < surface.box.top)
1435 if(y2 < surface.box.top)
1437 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1438 y1 = surface.box.top;
1440 if(y2 > surface.box.bottom)
1442 if(y1 > surface.box.bottom)
1444 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1445 y2 = surface.box.bottom;
1450 if(y1 > surface.box.bottom)
1452 if(y2 > surface.box.bottom)
1454 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1455 y1 = surface.box.bottom;
1457 if(y2 < surface.box.top)
1459 if(y1 < surface.box.top)
1461 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1462 y2 = surface.box.top;
1468 if(x1 > surface.box.right)
1470 if(x2 > surface.box.right)
1472 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1473 x1 = surface.box.right;
1475 if(x2 < surface.box.left)
1477 if(x1 < surface.box.left)
1479 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1480 x2 = surface.box.left;
1484 if(y1 < surface.box.top)
1486 if(y2 < surface.box.top)
1488 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1489 y1 = surface.box.top;
1491 if(y2 > surface.box.bottom)
1493 if(y1 > surface.box.bottom)
1495 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1496 y2 = surface.box.bottom;
1501 if(y1 > surface.box.bottom)
1503 if(y2 > surface.box.bottom)
1505 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1506 y1 = surface.box.bottom;
1508 if(y2 < surface.box.top)
1510 if(y1 < surface.box.top)
1512 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1513 y2 = surface.box.top;
1531 yu=-(int)lfbSurface.bitmap.stride;
1534 yu=lfbSurface.bitmap.stride;
1536 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1542 for(i=0; i<=length; i++)
1544 if(stipple & 0x8000)
1545 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1547 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1548 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1549 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1558 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1564 for(i=0; i<=length; i++)
1566 if(stipple & 0x8000)
1567 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1569 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1570 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1571 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1585 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1587 DrawLine(display, surface,x1,y1,x2,y1);
1588 DrawLine(display, surface,x2,y1,x2,y2);
1589 DrawLine(display, surface,x2,y2,x1,y2);
1590 DrawLine(display, surface,x1,y2,x1,y1);
1593 #if !defined(__GNUC__)
1595 void memset_32_aligned(void *buf, int val, int dwords)
1600 *((uint32 *)(buf)) = val;
1601 buf = ((uint32 *)(buf))+1;
1627 if (dwords & 1) *((int*)(buf)) = val;
1633 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1637 if(((uint32)buf) & 0x7F)
1639 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1665 sub edx,ebx ; edx holds # of overflow bytes
1684 movdqa [edi+16],xmm0
1685 movdqa [edi+32],xmm0
1686 movdqa [edi+48],xmm0
1687 movdqa [edi+64],xmm0
1688 movdqa [edi+80],xmm0
1689 movdqa [edi+96],xmm0
1690 movdqa [edi+112],xmm0
1714 void memset_32(void *buf, uint32 val, uint32 dwords)
1717 if ((uint32)(buf) & 3)
1722 if (((uint32)(buf) & 1))
1724 *(byte *)(buf) = (byte)(val&0xFF);
1725 buf = ((byte *)(buf))+1;
1726 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1729 if (((uint32)(buf) & 2))
1731 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1732 buf = ((uint16 *)(buf))+1;
1733 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1737 memset_32_aligned(buf,val,dwords);
1742 *(byte *)(buf) = (byte)(val&0xFF);
1746 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1747 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1754 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1756 LFBSurface lfbSurface = surface.driverData;
1757 uint32 color = lfbSurface.background;
1759 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1761 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1767 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1769 if(x1<surface.box.left) x1=surface.box.left;
1770 if(x2>surface.box.right) x2=surface.box.right;
1771 if(y1<surface.box.top) y1=surface.box.top;
1772 if(y2>surface.box.bottom) y2=surface.box.bottom;
1774 if(x2>=x1 && y2>=y1)
1782 x1 += surface.offset.x;
1783 x2 += surface.offset.x;
1784 y1 += surface.offset.y;
1785 y2 += surface.offset.y;
1786 if(lfbSurface.bitmap.picture)
1788 if(!surface.writeColor)
1790 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1791 for(y = y1; y<= y2; y++)
1794 for(c = 0; c < w; c++, picture++)
1796 picture->a = (byte)((color & 0xFF000000) >> 24);
1797 picture += lfbSurface.bitmap.stride - w;
1802 if(surface.background.a == 255 || lfbSurface.clearing)
1804 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1807 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1808 for(y = y1; y<= y2; y++)
1810 FillBytes(theOffset,(byte)color,w);
1811 theOffset += lfbSurface.bitmap.stride;
1815 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1816 for(y = y1; y<= y2; y++)
1818 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1819 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1823 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1824 for(y = y1; y<= y2; y++)
1826 #if defined(__GNUC__)
1827 FillBytesBy4((uint32 *) theOffset,color,w);
1829 memset_32((uint32 *) theOffset,color,w);
1831 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1837 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1838 //memset_32((uint32 *) theOffset,color,w);
1874 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1877 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1878 for(y = y1; y<= y2; y++)
1880 // TODO: IMPLEMENT THIS
1881 FillBytes(theOffset,(byte)color,w);
1882 theOffset += lfbSurface.bitmap.stride;
1887 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1888 ColorAlpha c = surface.background;
1893 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1895 for(y = y1; y <= y2; y++)
1898 for(c = 0; c < w; c++, dest++)
1901 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
1902 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
1903 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
1905 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
1906 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
1907 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
1909 if(r > 255) r = 255;
1910 if(g > 255) g = 255;
1911 if(b > 255) b = 255;
1913 destColor = { (byte)r, (byte)g, (byte)b };
1915 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
1916 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
1917 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
1920 dest += (lfbSurface.bitmap.stride - w);
1926 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1927 AlphaWriteMode alphaWrite = surface.alphaWrite;
1928 ColorAlpha c = surface.background;
1933 for(y = y1; y <= y2; y++)
1936 for(c = 0; c < w; c++, dest++)
1938 int dr = dest->color.r;
1939 int dg = dest->color.g;
1940 int db = dest->color.b;
1941 int r = a * cr / 255 + ((255 - a) * dr / 255);
1942 int g = a * cg / 255 + ((255 - a) * dg / 255);
1943 int b = a * cb / 255 + ((255 - a) * db / 255);
1945 if(r > 255) r = 255;
1946 if(g > 255) g = 255;
1947 if(b > 255) b = 255;
1948 dest->color = { (byte)r, (byte)g, (byte)b };
1950 if(alphaWrite == blend)
1952 int ca = (int)(a + ((255 - a) * dest->a / 255));
1953 if(ca > 255) ca = 255;
1959 dest += (lfbSurface.bitmap.stride - w);
1968 void Clear(Display display, Surface surface, ClearType type)
1970 LFBSurface lfbSurface = surface.driverData;
1972 lfbSurface.clearing = true;
1973 if(surface.offset.x == 0 && surface.offset.y == 0 &&
1974 surface.box.left == 0 && surface.box.top == 0 &&
1975 surface.box.right == surface.width-1 &&
1976 surface.box.bottom == surface.height-1)
1978 uint32 color = /*0xFF000000 | */lfbSurface.background;
1979 if(type != depthBuffer)
1981 if(lfbSurface.bitmap.stride != surface.width)
1982 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
1985 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1988 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
1990 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
1991 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
1996 if((flags & CLEAR_Z) && zbuffer)
1997 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2002 if(type != depthBuffer)
2003 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2005 if((flags & CLEAR_Z))
2008 uint32 w = surface.box.right-surface.box.left+1;
2009 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2010 + surface.box.left+surface.offset.x;
2011 for(y = surface.box.top; y<= surface.box.bottom; y++)
2013 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2014 offset += DISPLAY.Width;
2019 lfbSurface.clearing = false;
2022 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2024 LFBSurface lfbSurface = surface.driverData;
2027 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2029 if(w < 0) { w = -w; flip = true; }
2031 //Clip against the edges of the source
2044 if(sx+w>src.width-1)
2045 w-=sx+w-(src.width-1)-1;
2046 if(sy+h>src.height-1)
2047 h-=sy+h-(src.height-1)-1;
2048 //Clip against the edges of the destination
2049 if(dx<surface.box.left)
2051 if(!flip) sx+=surface.box.left-dx;
2052 w-=surface.box.left-dx;
2053 dx=surface.box.left;
2055 if(dy<surface.box.top)
2057 sy+=surface.box.top-dy;
2058 h-=surface.box.top-dy;
2061 if((dx+w)>surface.box.right)
2063 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2064 w-=((uint32)(dx+w)-surface.box.right-1);
2066 if((dy+h)>surface.box.bottom)
2067 h-=((dy+h)-surface.box.bottom-1);
2071 dx += surface.offset.x;
2072 dy += surface.offset.y;
2074 if(lfbSurface.bitmap.picture)
2076 AlphaWriteMode alphaWrite = surface.alphaWrite;
2077 if(src.alphaBlend && surface.blend)
2080 if(src.pixelFormat == pixelFormatAlpha)
2082 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2084 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2085 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2086 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2087 for(y = 0; y < h; y++)
2089 for(x = 0; x < w; x++, picture++, source++)
2091 int a = *source * color.a;
2092 ColorAlpha dest = *picture;
2093 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2094 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2095 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2096 if(r > 255) r = 255;
2097 if(g > 255) g = 255;
2098 if(b > 255) b = 255;
2099 picture->color = { (byte)r, (byte)g, (byte)b };
2100 if(alphaWrite == blend)
2102 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2103 if(ca > 255) ca = 255;
2104 picture->a = (byte)ca;
2107 picture->a = (byte)(a / 255);
2109 picture += lfbSurface.bitmap.stride - w;
2110 source += src.stride - w;
2113 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2115 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2116 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2117 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2118 for(y = 0; y < h; y++)
2120 for(x = 0; x < w; x++, picture++, source++)
2122 int a = *source * color.a;
2123 Color dest = *picture;
2124 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2125 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2126 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2127 if(r > 255) r = 255;
2128 if(g > 255) g = 255;
2129 if(b > 255) b = 255;
2130 *picture = Color { (byte)r, (byte)g, (byte)b };
2132 picture += lfbSurface.bitmap.stride - w;
2133 source += src.stride - w;
2136 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2138 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2139 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2140 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2141 for(y = 0; y < h; y++)
2143 for(x = 0; x < w; x++, picture++, source++)
2145 int a = *source * color.a;
2146 Color dest = *picture;
2147 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2148 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2149 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2150 if(r > 255) r = 255;
2151 if(g > 255) g = 255;
2152 if(b > 255) b = 255;
2153 *picture = Color { (byte)r, (byte)g, (byte)b };
2155 picture += lfbSurface.bitmap.stride - w;
2156 source += src.stride - w;
2162 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2163 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2165 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2166 for(y = 0; y < h; y++)
2168 for(x = 0; x < w; x++, picture++, source++)
2170 ColorAlpha src = *source;
2171 ColorAlpha dest = *picture;
2172 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2173 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2174 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2175 if(r > 255) r = 255;
2176 if(g > 255) g = 255;
2177 if(b > 255) b = 255;
2178 picture->color = { (byte)r, (byte)g, (byte)b };
2179 if(alphaWrite == blend)
2181 int a = src.a + ((255 - src.a) * dest.a / 255);
2182 if(a > 255) a = 255;
2183 picture->a = (byte)a;
2188 picture += lfbSurface.bitmap.stride - w;
2189 source += src.stride - w;
2192 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2194 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2195 for(y = 0; y < h; y++)
2197 for(x = 0; x < w; x++, picture++, source++)
2199 ColorAlpha src = *source;
2200 Color565 dest = *picture;
2201 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2202 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2203 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2204 if(r > 255 * 31) r = 255 * 31;
2205 if(g > 255 * 63) g = 255 * 63;
2206 if(b > 255 * 31) b = 255 * 31;
2207 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2209 picture += lfbSurface.bitmap.stride - w;
2210 source += src.stride - w;
2213 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2215 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2216 for(y = 0; y < h; y++)
2218 for(x = 0; x < w; x++, picture++, source++)
2220 ColorAlpha psrc = *source;
2221 Color555 dest = *picture;
2222 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2223 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2224 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2225 if(r > 255 * 31) r = 255 * 31;
2226 if(g > 255 * 31) g = 255 * 31;
2227 if(b > 255 * 31) b = 255 * 31;
2228 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2230 picture += lfbSurface.bitmap.stride - w;
2231 source += src.stride - w;
2236 else if(src.paletteShades)
2237 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2238 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2239 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2240 else if(src.pixelFormat == pixelFormat8)
2241 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2245 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2247 bool result = false;
2248 LFBDisplay lfbDisplay = display.driverData;
2250 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2253 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2254 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2258 Surface surface = bitmap.GetSurface(0,0,null);
2261 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2262 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2263 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2271 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2273 LFBSurface lfbSurface = surface.driverData;
2276 float s2dw,s2dh,d2sw,d2sh;
2278 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2280 if(Sgn(w) != Sgn(sw))
2292 //Clip against the edges of the source
2295 dx+=(int)((0-sx) * s2dw);
2296 w-=(int)((0-sx) * s2dw);
2302 dy+=(int)((0-sy) * s2dh);
2303 h-=(int)((0-sy) * s2dh);
2308 if(sx+sw>src.width-1)
2310 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2311 sw-=sx+sw-(src.width-1)-1;
2313 if(sy+sh>(src.height-1))
2315 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2316 sh-=sy+sh-(src.height-1)-1;
2318 //Clip against the edges of the destination
2319 if(dx<surface.box.left)
2321 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2322 sw-=(int)((surface.box.left-dx)*d2sw);
2323 w-=surface.box.left-dx;
2324 dx=surface.box.left;
2326 if(dy<surface.box.top)
2328 sy+=(int)((surface.box.top-dy)*d2sh);
2329 sh-=(int)((surface.box.top-dy)*d2sh);
2330 h-=surface.box.top-dy;
2333 if((dx+w)>surface.box.right)
2335 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2336 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2337 w-=((dx+w)-surface.box.right-1);
2339 if((dy+h)>surface.box.bottom)
2341 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2342 h-=((dy+h)-surface.box.bottom-1);
2344 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2346 dx+=surface.offset.x;
2347 dy+=surface.offset.y;
2349 if(lfbSurface.bitmap.picture)
2351 AlphaWriteMode alphaWrite = surface.alphaWrite;
2352 if(src.alphaBlend && surface.blend)
2356 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2357 ColorAlpha * backsrc;
2358 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2359 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2360 if(flip < 0) source += sw-1;
2378 ColorAlpha src = *source;
2379 ColorAlpha dst = *dest;
2380 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2381 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2382 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2383 if(r > 255) r = 255;
2384 if(g > 255) g = 255;
2385 if(b > 255) b = 255;
2386 dest->color = { (byte)r, (byte)g, (byte)b };
2387 if(alphaWrite == blend)
2389 int a = src.a + ((255 - src.a) * dst.a / 255);
2390 if(a > 255) a = 255;
2403 source += addsource;
2406 else if(src.paletteShades)
2407 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2408 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2409 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2410 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2411 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2415 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2417 LFBSurface lfbSurface = surface.driverData;
2420 float s2dw,s2dh,d2sw,d2sh;
2422 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2424 if(Sgn(w) != Sgn(sw))
2436 //Clip against the edges of the source
2439 dx+=(int)((0-sx) * s2dw);
2440 w-=(int)((0-sx) * s2dw);
2446 dy+=(int)((0-sy) * s2dh);
2447 h-=(int)((0-sy) * s2dh);
2452 if(sx+sw>src.width-1)
2454 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2455 sw-=sx+sw-(src.width-1)-1;
2457 if(sy+sh>(src.height-1))
2459 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2460 sh-=sy+sh-(src.height-1)-1;
2462 //Clip against the edges of the destination
2463 if(dx<surface.box.left)
2465 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2466 sw-=(int)((surface.box.left-dx)*d2sw);
2467 w-=surface.box.left-dx;
2468 dx=surface.box.left;
2470 if(dy<surface.box.top)
2472 sy+=(int)((surface.box.top-dy)*d2sh);
2473 sh-=(int)((surface.box.top-dy)*d2sh);
2474 h-=surface.box.top-dy;
2477 if((dx+w)>surface.box.right)
2479 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2480 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2481 w-=((dx+w)-surface.box.right-1);
2483 if((dy+h)>surface.box.bottom)
2485 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2486 h-=((dy+h)-surface.box.bottom-1);
2488 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2490 dx+=surface.offset.x;
2491 dy+=surface.offset.y;
2493 if(lfbSurface.bitmap.picture)
2495 AlphaWriteMode alphaWrite = surface.alphaWrite;
2496 if(src.alphaBlend && surface.blend)
2500 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2501 ColorAlpha * backsrc;
2502 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2503 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2504 float scaleX = (float)sw / w;
2505 float scaleY = (float)sh / h;
2513 if (w > sw && h > sh)
2516 for (y = 0; y < h; y++)
2518 int y0 = y * sh / h;
2519 int y1 = Min(y0 + 1, sh - 1);
2520 float alpha = y * scaleY - y0;
2522 for(x = 0; x < w; x++, dest += 1)
2524 int x0 = x * sw / w;
2525 int x1 = Min(x0 + 1, sw - 1);
2526 float beta = x * scaleX - x0;
2528 ColorAlpha src00, src01, src10, src11;
2529 float a1,r1,g1,b1,a2,r2,g2,b2;
2531 src00 = source[y0 * src.stride + x0];
2532 src01 = source[y0 * src.stride + x1];
2533 src10 = source[y1 * src.stride + x0];
2534 src11 = source[y1 * src.stride + x1];
2535 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2536 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2537 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2538 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2539 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2540 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2541 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2542 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2543 a = a1 * (1.0f - alpha) + a2 * alpha;
2544 r = r1 * (1.0f - alpha) + r2 * alpha;
2545 g = g1 * (1.0f - alpha) + g2 * alpha;
2546 b = b1 * (1.0f - alpha) + b2 * alpha;
2548 ColorAlpha dst = *dest;
2549 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2550 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2551 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2552 if(cr > 255) cr = 255;
2553 if(cg > 255) cg = 255;
2554 if(cb > 255) cb = 255;
2555 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2557 if(alphaWrite == blend)
2559 int ca = (int)(a + ((255 - a) * dst.a / 255));
2560 if(ca > 255) ca = 255;
2573 for (y = 0; y < h; y++)
2575 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2576 int y1 = Min(y0 + 1, sh - 1);
2578 for (x = 0; x < w; x++, dest += 1)
2580 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2581 int x1 = Min(x0 + 1, sw - 1);
2582 float a = 0, r = 0, g = 0, b = 0;
2586 for (i = y0; i <= y1; i++)
2587 for (j = x0; j <= x1; j++)
2589 ColorAlpha pixel = source[i * src.stride + j];
2601 ColorAlpha src = *source;
2602 ColorAlpha dst = *dest;
2603 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2604 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2605 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2606 if(cr > 255) cr = 255;
2607 if(cg > 255) cg = 255;
2608 if(cb > 255) cb = 255;
2609 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2610 if(alphaWrite == blend)
2612 int ca = (int)(a + ((255 - a) * dst.a / 255));
2613 if(ca > 255) ca = 255;
2624 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2625 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2626 // Fail back on Stretch
2627 else if(src.paletteShades)
2628 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2629 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2630 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2631 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2632 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2636 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2638 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2641 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2643 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2646 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2648 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2651 void UnloadFont(DisplaySystem displaySystem, Font font)
2655 #if !defined(ECERE_NOTRUETYPE)
2657 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2659 FontEntry fontEntry = font.fontEntries[entry];
2665 loadedFonts.Remove(fontEntry);
2675 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2677 void * result = null;
2679 #if !defined(ECERE_NOTRUETYPE)
2680 Font font = Font { };
2683 char fileName[MAX_LOCATION];
2684 bool fakeItalic = flags.italic;
2685 char linkCfgPath[MAX_LOCATION];
2687 #if !defined(__WIN32__)
2690 char * ecereFonts = getenv("ECERE_FONTS");
2691 if(!ecereFonts) ecereFonts = "<:ecere>";
2692 #if !defined(__WIN32__)
2693 strcpy(linkCfgPath, ecereFonts);
2694 PathCat(linkCfgPath, "linking.cfg");
2695 linkCfg = FileOpen(linkCfgPath, read);
2697 strcpy(fileName, faceName);
2698 strcpy(font.faceName, faceName);
2701 if(!FileExists(fileName))
2703 strcpy(fileName, ecereFonts);
2704 PathCat(fileName, faceName);
2705 if(flags.bold && flags.italic) strcat(fileName, "bi");
2706 else if(flags.bold) strcat(fileName, "bd");
2707 else if(flags.italic) strcat(fileName, "i");
2708 strcat(fileName, ".ttf");
2712 if(flags.italic && !FileExists(fileName))
2714 strcpy(fileName, ecereFonts);
2715 PathCat(fileName, faceName);
2716 if(flags.bold) strcat(fileName, "bd");
2717 strcat(fileName, ".ttf");
2722 #if defined(__WIN32__)
2723 if(!FileExists(fileName))
2725 FontData fontData = { { 0 } };
2726 LOGFONT logFont = { 0 };
2731 logFont.lfCharSet = DEFAULT_CHARSET;
2732 strcpy(logFont.lfFaceName, faceName);
2733 fontData.flags = flags;
2735 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2736 if(!fontData.fileName[0])
2739 fontData.flags.italic = false;
2740 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2744 if(fontData.fileName[0])
2746 GetWindowsDirectory(fileName, MAX_LOCATION);
2747 PathCat(fileName, "fonts");
2748 PathCat(fileName, fontData.fileName);
2755 FcResult result = 0;
2756 FcPattern * pattern;
2757 FcPattern * matched;
2759 unichar testChar = 0;
2760 FcCharSet * charSet;
2762 fcConfig = FcInitLoadConfigAndFonts();
2764 charSet = FcCharSetCreate();
2766 if(!strcmpi(faceName, "Mangal"))
2772 FcCharSetAddChar(charSet, testChar);
2774 pattern = FcPatternBuild(null,
2775 //FC_SOURCE, FcTypeString, "freetype",
2776 FC_FAMILY, FcTypeString, faceName,
2777 //FC_SCALABLE, FcTypeBool, 1,
2778 FC_SIZE, FcTypeDouble, (double)size,
2779 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2780 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2781 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2783 FcDefaultSubstitute(pattern);
2784 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2786 matched = FcFontMatch (0, pattern, &result);
2787 // printf("Locating %s\n", faceName);
2790 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2791 //printf("Fontconfig returned %s\n", family);
2793 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2796 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2797 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2798 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2799 strcpy(fileName, fileName2);
2800 // size = (float)fontSize;
2802 //printf("Matched to %s, %f\n", fileName, size);
2806 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2808 if(pattern) FcPatternDestroy(pattern);
2809 if(matched) FcPatternDestroy(matched);
2810 if(charSet) FcCharSetDestroy(charSet);
2815 if(!FileExists(fileName))
2816 ChangeExtension(fileName, "otf", fileName);
2817 if(!FileExists(fileName))
2818 ChangeExtension(fileName, "ttc", fileName);
2820 //if(FileExists(fileName))
2823 char links[1024] = "";
2825 #if defined(__WIN32__)
2828 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2829 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2834 RegQueryValueEx(key, faceName,null, &type, links, &size);
2842 while(linkCfg.GetLine(line, sizeof(line)))
2844 int len = strlen(faceName);
2845 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2847 while(linkCfg.GetLine(line, sizeof(line)))
2849 TrimLSpaces(line, line);
2850 if(!line[0] || line[0] == '[')
2853 memcpy(links + linksPos, line, len);
2855 links[linksPos] = 0;
2863 while(entry < MAX_FONT_LINK_ENTRIES)
2865 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2868 File file = FileOpen/*Buffered*/(fileName, read);
2871 FileSize fileSize = file.GetSize();
2872 FT_Open_Args args = { 0 };
2873 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
2874 FT_Stream stream = new0 FT_StreamRec[1];
2877 FT_Init_FreeType( &ftLibrary );
2879 fontEntry = FontEntry { key = (uint)CopyString(fileName) };
2880 fontEntry.stream = stream;
2883 fontEntry.buffer = new byte[fileSize];
2884 file.Read(fontEntry.buffer, 1, fileSize);
2887 //args.num_params = 1;
2888 args.params = ¶m;
2890 stream->size = fileSize;
2891 stream->descriptor.pointer = file;
2892 stream->read = FT_stream_load;
2893 stream->close = FT_stream_close;
2895 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
2896 args.stream = stream;
2897 //args.pathname = fileName;
2898 //args.memory_base = fontEntry.buffer;
2899 //args.memory_size = fileSize;
2901 // printf("Opening: %s\n", fileName);
2902 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
2907 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
2908 fontEntry.hbFont.klass = &hb_fontClass;
2909 fontEntry.hbFont.userData = fontEntry.face;
2912 loadedFonts.Add(fontEntry);
2917 // printf("Error opening font %s\n", fileName);
2926 FT_Vector pen = { 0, 0 };
2929 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
2930 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
2931 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
2932 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
2933 FT_Set_Transform(fontEntry.face, &matrix, &pen );
2935 FT_Set_Char_Size( fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
2936 font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
2937 // printf("Font height is %d\n", font.height);
2938 font.fakeItalic = fakeItalic;
2942 font.fontEntries[entry++] = fontEntry;
2949 char fontName[1024];
2950 if(!links[linksPos]) break;
2951 for(c = 0; (ch = links[linksPos + c]); c++)
2954 if(ch == ',') break;
2957 if(fontName[0] || ch == ',')
2959 #if defined(__WIN32__)
2960 GetWindowsDirectory(fileName, MAX_LOCATION);
2961 PathCat(fileName, "fonts");
2962 PathCat(fileName, fontName);
2963 #elif defined(ECERE_NOFONTCONFIG)
2964 if(getenv("ECERE_FONTS"))
2966 strcpy(fileName, ecereFonts);
2967 PathCat(fileName, fontName);
2973 FcResult result = 0;
2974 FcPattern * pattern;
2975 FcPattern * matched;
2977 pattern = FcPatternBuild(null,
2978 //FC_SOURCE, FcTypeString, "freetype",
2979 //FC_SCALABLE, FcTypeBool, 1,
2980 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
2981 FC_SIZE, FcTypeDouble, (double)size,
2982 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2983 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2985 FcDefaultSubstitute(pattern);
2986 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2988 //printf("Locating %s\n", links + linksPos + c + 1);
2989 matched = FcFontMatch (0, pattern, &result);
2992 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2993 // printf("Fontconfig returned %s\n", family);
2995 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
2996 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
2999 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
3000 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3001 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3002 strcpy(fileName, fileName2);
3003 //size = (float)fontSize;
3004 // printf("Matched to %s, %f\n", fileName, size);
3008 // 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);
3010 if(pattern) FcPatternDestroy(pattern);
3011 if(matched) FcPatternDestroy(matched);
3018 while(links[linksPos]) linksPos++;
3025 UnloadFont(displaySystem, font);
3028 font.asciiPack.Render(font, 0, displaySystem);
3030 #if !defined(__WIN32__)
3038 #if !defined(ECERE_NOTRUETYPE)
3039 void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
3040 void (* callback)(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft),
3041 Surface surface, Display display, int * x, int y)
3043 if(font && font.fontEntries && font.fontEntries[0])
3045 int previousGlyph = 0;
3046 int c, nb, glyphIndex = 0;
3047 unichar lastPack = 0;
3048 GlyphPack pack = font.asciiPack;
3052 bool rightToLeft = false;
3053 int rightToLeftOffset = 0;
3054 int fontEntryNum = 0;
3055 bool foundArabic = false;
3056 int glyphScript = 0;
3058 pack.bitmap.alphaBlend = true;
3060 for(c = 0; c < len || glyphIndex < numGlyphs;)
3064 if(glyphIndex < numGlyphs)
3066 glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3070 HB_Script curScript = HB_Script_Common;
3071 byte * scriptStart = text + c;
3074 unichar testChar = 0;
3075 char * testLang = null;
3079 HB_Script script = HB_Script_Common;
3080 ch = UTF8GetChar(text + c, &nb);
3082 if(ch == 32 && curScript)
3089 for(a = c + 1; a < c + len; a++)
3097 unichar ahead = UTF8GetChar(text + a, &nb);
3098 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3106 script = HB_Script_Common;
3107 else if(ch <= 0x11FF)
3111 case 0x300: script = HB_Script_Greek; break;
3112 case 0x400: script = HB_Script_Cyrillic; break;
3113 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3114 case 0x600: script = HB_Script_Arabic; break;
3115 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3116 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3117 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3118 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3119 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3120 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3121 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3122 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3123 case 0xF00: script = HB_Script_Tibetan; break;
3124 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3125 case 0x1100: script = HB_Script_Hangul; break;
3128 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3129 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3130 script = HB_Script_Hangul;
3131 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3132 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3133 else if(ch >= 0x1780 && ch <= 0x17FF || ch >= 0x19E0 && ch <= 0x19FF) script = HB_Script_Khmer;
3134 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3135 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3136 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3137 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3138 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3139 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3142 if(!script || (script != curScript))
3150 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3151 if(!script) { c += nb; break; }
3158 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3160 rightToLeft = false;
3165 int len = c - (int)(scriptStart - text);
3166 int max = len * 2 + 1;
3167 if(max > utf16BufferSize)
3169 utf16 = renew utf16 uint16[max];
3170 utf16BufferSize = max;
3172 wc = UTF8toUTF16BufferLen(scriptStart, utf16, max, len);
3173 glyphScript = curScript;
3177 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3178 //printf("Arabic ");
3180 case HB_Script_Devanagari: testChar = 0x905; testLang = "sa";
3181 //printf("Devanagari ");
3186 case 60: testChar = 'あ'; break;
3187 case 61: testChar = 0x3400; break; //'愛'; break;
3193 // printf("Testing for char %x\n", testChar);
3194 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3196 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3198 /*if(font.fontEntries[fontEntryNum])
3199 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3203 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3205 #if !defined(__WIN32__)
3207 double fontSize = font.size;
3208 FcResult result = 0;
3209 FcPattern * pattern;
3210 FcPattern * matched;
3211 FcCharSet * charSet;
3213 FontEntry fontEntry;
3214 char * fileName = null;
3215 bool fakeItalic = false;
3216 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3217 if(!font.fontEntries[fontEntryNum])
3219 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3223 #if !defined(__WIN32__)
3225 charSet = FcCharSetCreate();
3226 FcCharSetAddChar(charSet, testChar);
3227 //printf("Loading with char %x\n", testChar);
3229 pattern = FcPatternBuild(null,
3230 //FC_SOURCE, FcTypeString, "freetype",
3231 //FC_SCALABLE, FcTypeBool, 1,
3232 FC_FAMILY, FcTypeString, font.faceName,
3233 FC_SIZE, FcTypeDouble, (double)font.size,
3234 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3235 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3236 FC_CHARSET,FcTypeCharSet, charSet,
3237 testLang ? FC_LANG : 0, FcTypeString,testLang,
3239 FcDefaultSubstitute(pattern);
3240 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3242 //printf("Locating %s for script %d\n", font.faceName, curScript);
3243 matched = FcFontMatch (0, pattern, &result);
3246 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3247 //printf("Fontconfig returned %s\n", family);
3249 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3251 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3252 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3253 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3254 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3258 //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);
3263 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3266 File file = FileOpen(fileName, read);
3269 FileSize fileSize = file.GetSize();
3270 FT_Open_Args args = { 0 };
3271 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3272 FT_Stream stream = new0 FT_StreamRec[1];
3275 FT_Init_FreeType( &ftLibrary );
3277 fontEntry = FontEntry { key = (uint)CopyString(fileName) };
3278 fontEntry.stream = stream;
3280 //args.num_params = 1;
3281 args.params = ¶m;
3283 stream->size = fileSize;
3284 stream->descriptor.pointer = file;
3285 stream->read = FT_stream_load;
3286 stream->close = FT_stream_close;
3288 args.flags = FT_OPEN_STREAM;
3289 args.stream = stream;
3290 //args.pathname = fileName;
3291 //args.memory_base = fontEntry.buffer;
3292 //args.memory_size = fileSize;
3294 // printf("Opening: %s\n", fileName);
3295 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3300 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3301 fontEntry.hbFont.klass = &hb_fontClass;
3302 fontEntry.hbFont.userData = fontEntry.face;
3305 loadedFonts.Add(fontEntry);
3310 // printf("Error opening font %s\n", fileName);
3316 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
3318 font.fontEntries[fontEntryNum] = fontEntry;
3322 if(pattern) FcPatternDestroy(pattern);
3323 if(matched) FcPatternDestroy(matched);
3324 if(charSet) FcCharSetDestroy(charSet);
3327 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3328 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3331 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3334 if(rightToLeft /*&& surface*/)
3337 rightToLeftOffset = 0;
3338 for(c = 0; c<numGlyphs; c++)
3341 glyphNo = glyphs[c] | 0x80000000 | (glyphScript << 24);
3342 packNo = glyphNo & 0xFFFFFF80;
3343 if(packNo != lastPack)
3345 pack = (GlyphPack)font.glyphPacks.Find(packNo);
3348 pack = GlyphPack { key = packNo };
3349 font.glyphPacks.Add(pack);
3350 pack.Render(font, fontEntryNum, displaySystem);
3352 pack.bitmap.alphaBlend = true;
3355 glyph = &pack.glyphs[glyphNo & 0x7F];
3357 rightToLeftOffset += (int)glyph->ax - glyph->left;
3359 *x += rightToLeftOffset;
3363 glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3366 packNo = glyphNo & 0xFFFFFF80;
3368 if(packNo != lastPack)
3371 pack = font.asciiPack;
3374 pack = (GlyphPack)font.glyphPacks.Find(packNo);
3377 pack = GlyphPack { key = packNo };
3378 font.glyphPacks.Add(pack);
3379 pack.Render(font, fontEntryNum, displaySystem);
3382 pack.bitmap.alphaBlend = true;
3387 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3392 FT_Get_Kerning(font.fontEntries[fontEntryNum].face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3395 previousGlyph = glyph->glyphNo;*/
3396 callback(surface, display, x, y, glyph, pack.bitmap, rightToLeft);
3398 if(numGlyphs && glyphIndex == numGlyphs)
3400 *x += rightToLeftOffset;
3407 LFBSurface lfbSurface = surface.driverData;
3408 lfbSurface.xOffset = 0;
3412 void ::AddWidth(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3416 *x -= (int)glyph->ax - glyph->left;
3424 void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3426 if(displaySystem && displaySystem.flags.text && len)
3431 *width = num * textCellW;
3433 if(height) *height = textCellH;
3435 else if(font && len)
3440 #if !defined(ECERE_NOTRUETYPE)
3441 ProcessString(font, displaySystem, text, len, AddWidth, null, null, &w, 0);
3443 //*width = (w + 64 - w % 64) >> 6;
3447 *height = font.height;
3451 if(width) *width = 0;
3452 if(height) *height = 0;
3456 #if !defined(ECERE_NOTRUETYPE)
3457 void ::OutputGlyph(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3459 LFBSurface lfbSurface = surface.driverData;
3460 //lfbSurface.xOffset = (*x & 0x3F);
3463 surface.driver.Blit(display, surface, bitmap, (*x >> 6) - glyph->w, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3464 *x -= (int)glyph->ax - glyph->left;
3468 surface.driver.Blit(display, surface, bitmap, (*x >> 6) + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3474 void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3476 LFBSurface lfbSurface = surface.driverData;
3477 if(display && display.displaySystem.flags.text)
3479 LFBDisplay lfbDisplay = display.driverData;
3480 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3486 if(y > surface.box.bottom || y < surface.box.top)
3488 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3489 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3490 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3492 if(surface.textOpacity)
3493 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3495 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3500 lfbSurface.writingText = true;
3501 #if !defined(ECERE_NOTRUETYPE)
3503 ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3505 lfbSurface.writingText = false;
3509 void TextFont(Display display, Surface surface, Font font)
3511 LFBSurface lfbSurface = surface.driverData;
3512 lfbSurface.font = font;
3515 void TextOpacity(Display display, Surface surface, bool opaque)
3517 LFBSurface lfbSurface = surface.driverData;
3521 void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3523 LFBSurface lfbSurface = surface.driverData;
3524 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3527 void DrawingChar(Display display, Surface surface, byte character)
3529 LFBSurface lfbSurface = surface.driverData;
3530 lfbSurface.drawingChar = character;
3533 void LineStipple(Display display, Surface surface, uint32 stipple)
3535 LFBSurface lfbSurface = surface.driverData;
3536 lfbSurface.stipple = (uint16)stipple;
3539 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3540 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3542 if(mesh.vertices && !mesh.flags.vertices)
3543 delete mesh.vertices;
3544 if(mesh.normals && !mesh.flags.normals)
3545 delete mesh.normals;
3546 if(mesh.texCoords && !mesh.flags.texCoords1)
3547 delete mesh.texCoords;
3550 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3552 bool result = false;
3554 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3555 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3556 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3561 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3566 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3571 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3573 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3575 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)