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 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2083 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2084 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2085 for(y = 0; y < h; y++)
2087 for(x = 0; x < w; x++, picture++, source++)
2089 int a = *source * color.a;
2090 ColorAlpha dest = *picture;
2091 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2092 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2093 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2094 if(r > 255) r = 255;
2095 if(g > 255) g = 255;
2096 if(b > 255) b = 255;
2097 picture->color = { (byte)r, (byte)g, (byte)b };
2098 if(alphaWrite == blend)
2100 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2101 if(ca > 255) ca = 255;
2102 picture->a = (byte)ca;
2105 picture->a = (byte)(a / 255);
2107 picture += lfbSurface.bitmap.stride - w;
2108 source += src.stride - w;
2113 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2114 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2116 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2117 for(y = 0; y < h; y++)
2119 for(x = 0; x < w; x++, picture++, source++)
2121 ColorAlpha src = *source;
2122 ColorAlpha dest = *picture;
2123 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2124 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2125 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2126 if(r > 255) r = 255;
2127 if(g > 255) g = 255;
2128 if(b > 255) b = 255;
2129 picture->color = { (byte)r, (byte)g, (byte)b };
2130 if(alphaWrite == blend)
2132 int a = src.a + ((255 - src.a) * dest.a / 255);
2133 if(a > 255) a = 255;
2134 picture->a = (byte)a;
2139 picture += lfbSurface.bitmap.stride - w;
2140 source += src.stride - w;
2143 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2145 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2146 for(y = 0; y < h; y++)
2148 for(x = 0; x < w; x++, picture++, source++)
2150 ColorAlpha src = *source;
2151 Color565 dest = *picture;
2152 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2153 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2154 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2155 if(r > 255 * 31) r = 255 * 31;
2156 if(g > 255 * 63) g = 255 * 63;
2157 if(b > 255 * 31) b = 255 * 31;
2158 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2160 picture += lfbSurface.bitmap.stride - w;
2161 source += src.stride - w;
2164 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2166 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2167 for(y = 0; y < h; y++)
2169 for(x = 0; x < w; x++, picture++, source++)
2171 ColorAlpha src = *source;
2172 Color555 dest = *picture;
2173 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2174 int g = src.a * src.color.g * 31 / 255 + ((255 - src.a) * dest.g);
2175 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2176 if(r > 255 * 31) r = 255 * 31;
2177 if(g > 255 * 31) g = 255 * 31;
2178 if(b > 255 * 31) b = 255 * 31;
2179 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2181 picture += lfbSurface.bitmap.stride - w;
2182 source += src.stride - w;
2187 else if(src.paletteShades)
2188 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2189 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2190 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2191 else if(src.pixelFormat == pixelFormat8)
2192 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2196 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2198 bool result = false;
2199 LFBDisplay lfbDisplay = display.driverData;
2201 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2204 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2205 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2209 Surface surface = bitmap.GetSurface(0,0,null);
2212 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2213 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2214 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2222 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2224 LFBSurface lfbSurface = surface.driverData;
2227 float s2dw,s2dh,d2sw,d2sh;
2229 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2231 if(Sgn(w) != Sgn(sw))
2243 //Clip against the edges of the source
2246 dx+=(int)((0-sx) * s2dw);
2247 w-=(int)((0-sx) * s2dw);
2253 dy+=(int)((0-sy) * s2dh);
2254 h-=(int)((0-sy) * s2dh);
2259 if(sx+sw>src.width-1)
2261 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2262 sw-=sx+sw-(src.width-1)-1;
2264 if(sy+sh>(src.height-1))
2266 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2267 sh-=sy+sh-(src.height-1)-1;
2269 //Clip against the edges of the destination
2270 if(dx<surface.box.left)
2272 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2273 sw-=(int)((surface.box.left-dx)*d2sw);
2274 w-=surface.box.left-dx;
2275 dx=surface.box.left;
2277 if(dy<surface.box.top)
2279 sy+=(int)((surface.box.top-dy)*d2sh);
2280 sh-=(int)((surface.box.top-dy)*d2sh);
2281 h-=surface.box.top-dy;
2284 if((dx+w)>surface.box.right)
2286 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2287 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2288 w-=((dx+w)-surface.box.right-1);
2290 if((dy+h)>surface.box.bottom)
2292 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2293 h-=((dy+h)-surface.box.bottom-1);
2295 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2297 dx+=surface.offset.x;
2298 dy+=surface.offset.y;
2300 if(lfbSurface.bitmap.picture)
2302 AlphaWriteMode alphaWrite = surface.alphaWrite;
2303 if(src.alphaBlend && surface.blend)
2307 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2308 ColorAlpha * backsrc;
2309 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2310 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2311 if(flip < 0) source += sw-1;
2329 ColorAlpha src = *source;
2330 ColorAlpha dst = *dest;
2331 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2332 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2333 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2334 if(r > 255) r = 255;
2335 if(g > 255) g = 255;
2336 if(b > 255) b = 255;
2337 dest->color = { (byte)r, (byte)g, (byte)b };
2338 if(alphaWrite == blend)
2340 int a = src.a + ((255 - src.a) * dst.a / 255);
2341 if(a > 255) a = 255;
2354 source += addsource;
2357 else if(src.paletteShades)
2358 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2359 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2360 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2361 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2362 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2366 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2368 LFBSurface lfbSurface = surface.driverData;
2371 float s2dw,s2dh,d2sw,d2sh;
2373 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2375 if(Sgn(w) != Sgn(sw))
2387 //Clip against the edges of the source
2390 dx+=(int)((0-sx) * s2dw);
2391 w-=(int)((0-sx) * s2dw);
2397 dy+=(int)((0-sy) * s2dh);
2398 h-=(int)((0-sy) * s2dh);
2403 if(sx+sw>src.width-1)
2405 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2406 sw-=sx+sw-(src.width-1)-1;
2408 if(sy+sh>(src.height-1))
2410 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2411 sh-=sy+sh-(src.height-1)-1;
2413 //Clip against the edges of the destination
2414 if(dx<surface.box.left)
2416 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2417 sw-=(int)((surface.box.left-dx)*d2sw);
2418 w-=surface.box.left-dx;
2419 dx=surface.box.left;
2421 if(dy<surface.box.top)
2423 sy+=(int)((surface.box.top-dy)*d2sh);
2424 sh-=(int)((surface.box.top-dy)*d2sh);
2425 h-=surface.box.top-dy;
2428 if((dx+w)>surface.box.right)
2430 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2431 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2432 w-=((dx+w)-surface.box.right-1);
2434 if((dy+h)>surface.box.bottom)
2436 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2437 h-=((dy+h)-surface.box.bottom-1);
2439 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2441 dx+=surface.offset.x;
2442 dy+=surface.offset.y;
2444 if(lfbSurface.bitmap.picture)
2446 AlphaWriteMode alphaWrite = surface.alphaWrite;
2447 if(src.alphaBlend && surface.blend)
2451 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2452 ColorAlpha * backsrc;
2453 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2454 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2455 float scaleX = (float)sw / w;
2456 float scaleY = (float)sh / h;
2464 if (w > sw && h > sh)
2467 for (y = 0; y < h; y++)
2469 int y0 = y * sh / h;
2470 int y1 = Min(y0 + 1, sh - 1);
2471 float alpha = y * scaleY - y0;
2473 for(x = 0; x < w; x++, dest += 1)
2475 int x0 = x * sw / w;
2476 int x1 = Min(x0 + 1, sw - 1);
2477 float beta = x * scaleX - x0;
2479 ColorAlpha src00, src01, src10, src11;
2480 float a1,r1,g1,b1,a2,r2,g2,b2;
2482 src00 = source[y0 * src.stride + x0];
2483 src01 = source[y0 * src.stride + x1];
2484 src10 = source[y1 * src.stride + x0];
2485 src11 = source[y1 * src.stride + x1];
2486 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2487 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2488 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2489 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2490 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2491 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2492 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2493 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2494 a = a1 * (1.0f - alpha) + a2 * alpha;
2495 r = r1 * (1.0f - alpha) + r2 * alpha;
2496 g = g1 * (1.0f - alpha) + g2 * alpha;
2497 b = b1 * (1.0f - alpha) + b2 * alpha;
2499 ColorAlpha dst = *dest;
2500 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2501 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2502 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2503 if(cr > 255) cr = 255;
2504 if(cg > 255) cg = 255;
2505 if(cb > 255) cb = 255;
2506 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2508 if(alphaWrite == blend)
2510 int ca = (int)(a + ((255 - a) * dst.a / 255));
2511 if(ca > 255) ca = 255;
2524 for (y = 0; y < h; y++)
2526 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2527 int y1 = Min(y0 + 1, sh - 1);
2529 for (x = 0; x < w; x++, dest += 1)
2531 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2532 int x1 = Min(x0 + 1, sw - 1);
2533 float a = 0, r = 0, g = 0, b = 0;
2537 for (i = y0; i <= y1; i++)
2538 for (j = x0; j <= x1; j++)
2540 ColorAlpha pixel = source[i * src.stride + j];
2552 ColorAlpha src = *source;
2553 ColorAlpha dst = *dest;
2554 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2555 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2556 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2557 if(cr > 255) cr = 255;
2558 if(cg > 255) cg = 255;
2559 if(cb > 255) cb = 255;
2560 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2561 if(alphaWrite == blend)
2563 int ca = (int)(a + ((255 - a) * dst.a / 255));
2564 if(ca > 255) ca = 255;
2575 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2576 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2577 // Fail back on Stretch
2578 else if(src.paletteShades)
2579 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2580 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2581 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2582 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2583 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2587 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2589 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2592 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2594 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2597 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2599 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2602 void UnloadFont(DisplaySystem displaySystem, Font font)
2606 #if !defined(ECERE_NOTRUETYPE)
2608 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2610 FontEntry fontEntry = font.fontEntries[entry];
2616 loadedFonts.Remove(fontEntry);
2626 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
2628 void * result = null;
2630 #if !defined(ECERE_NOTRUETYPE)
2631 Font font = Font { };
2634 char fileName[MAX_LOCATION];
2635 bool fakeItalic = flags.italic;
2636 char linkCfgPath[MAX_LOCATION];
2638 #if !defined(__WIN32__)
2641 char * ecereFonts = getenv("ECERE_FONTS");
2642 if(!ecereFonts) ecereFonts = "<:ecere>";
2643 #if !defined(__WIN32__)
2644 strcpy(linkCfgPath, ecereFonts);
2645 PathCat(linkCfgPath, "linking.cfg");
2646 linkCfg = FileOpen(linkCfgPath, read);
2648 strcpy(fileName, faceName);
2649 strcpy(font.faceName, faceName);
2652 if(!FileExists(fileName))
2654 strcpy(fileName, ecereFonts);
2655 PathCat(fileName, faceName);
2656 if(flags.bold && flags.italic) strcat(fileName, "bi");
2657 else if(flags.bold) strcat(fileName, "bd");
2658 else if(flags.italic) strcat(fileName, "i");
2659 strcat(fileName, ".ttf");
2663 if(flags.italic && !FileExists(fileName))
2665 strcpy(fileName, ecereFonts);
2666 PathCat(fileName, faceName);
2667 if(flags.bold) strcat(fileName, "bd");
2668 strcat(fileName, ".ttf");
2673 #if defined(__WIN32__)
2674 if(!FileExists(fileName))
2676 FontData fontData = { { 0 } };
2677 LOGFONT logFont = { 0 };
2682 logFont.lfCharSet = DEFAULT_CHARSET;
2683 strcpy(logFont.lfFaceName, faceName);
2684 fontData.flags = flags;
2686 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2687 if(!fontData.fileName[0])
2690 fontData.flags.italic = false;
2691 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
2695 if(fontData.fileName[0])
2697 GetWindowsDirectory(fileName, MAX_LOCATION);
2698 PathCat(fileName, "fonts");
2699 PathCat(fileName, fontData.fileName);
2706 FcResult result = 0;
2707 FcPattern * pattern;
2708 FcPattern * matched;
2710 unichar testChar = 0;
2711 FcCharSet * charSet;
2713 fcConfig = FcInitLoadConfigAndFonts();
2715 charSet = FcCharSetCreate();
2717 if(!strcmpi(faceName, "Mangal"))
2723 FcCharSetAddChar(charSet, testChar);
2725 pattern = FcPatternBuild(null,
2726 //FC_SOURCE, FcTypeString, "freetype",
2727 FC_FAMILY, FcTypeString, faceName,
2728 //FC_SCALABLE, FcTypeBool, 1,
2729 FC_SIZE, FcTypeDouble, (double)size,
2730 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2731 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2732 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2734 FcDefaultSubstitute(pattern);
2735 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2737 matched = FcFontMatch (0, pattern, &result);
2738 // printf("Locating %s\n", faceName);
2741 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2742 //printf("Fontconfig returned %s\n", family);
2744 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2747 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2748 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2749 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2750 strcpy(fileName, fileName2);
2751 // size = (float)fontSize;
2753 //printf("Matched to %s, %f\n", fileName, size);
2757 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2759 if(pattern) FcPatternDestroy(pattern);
2760 if(matched) FcPatternDestroy(matched);
2761 if(charSet) FcCharSetDestroy(charSet);
2766 if(!FileExists(fileName))
2767 ChangeExtension(fileName, "otf", fileName);
2768 if(!FileExists(fileName))
2769 ChangeExtension(fileName, "ttc", fileName);
2771 //if(FileExists(fileName))
2774 char links[1024] = "";
2776 #if defined(__WIN32__)
2779 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2780 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2785 RegQueryValueEx(key, faceName,null, &type, links, &size);
2793 while(linkCfg.GetLine(line, sizeof(line)))
2795 int len = strlen(faceName);
2796 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2798 while(linkCfg.GetLine(line, sizeof(line)))
2800 TrimLSpaces(line, line);
2801 if(!line[0] || line[0] == '[')
2804 memcpy(links + linksPos, line, len);
2806 links[linksPos] = 0;
2814 while(entry < MAX_FONT_LINK_ENTRIES)
2816 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2819 File file = FileOpen/*Buffered*/(fileName, read);
2822 FileSize fileSize = file.GetSize();
2823 FT_Open_Args args = { 0 };
2824 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
2825 FT_Stream stream = new0 FT_StreamRec[1];
2828 FT_Init_FreeType( &ftLibrary );
2830 fontEntry = FontEntry { key = (uint)CopyString(fileName) };
2831 fontEntry.stream = stream;
2834 fontEntry.buffer = new byte[fileSize];
2835 file.Read(fontEntry.buffer, 1, fileSize);
2838 //args.num_params = 1;
2839 args.params = ¶m;
2841 stream->size = fileSize;
2842 stream->descriptor.pointer = file;
2843 stream->read = FT_stream_load;
2844 stream->close = FT_stream_close;
2846 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
2847 args.stream = stream;
2848 //args.pathname = fileName;
2849 //args.memory_base = fontEntry.buffer;
2850 //args.memory_size = fileSize;
2852 // printf("Opening: %s\n", fileName);
2853 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
2858 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
2859 fontEntry.hbFont.klass = &hb_fontClass;
2860 fontEntry.hbFont.userData = fontEntry.face;
2863 loadedFonts.Add(fontEntry);
2868 // printf("Error opening font %s\n", fileName);
2877 FT_Vector pen = { 0, 0 };
2880 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
2881 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
2882 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
2883 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
2884 FT_Set_Transform(fontEntry.face, &matrix, &pen );
2886 FT_Set_Char_Size( fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
2887 font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
2888 // printf("Font height is %d\n", font.height);
2889 font.fakeItalic = fakeItalic;
2893 font.fontEntries[entry++] = fontEntry;
2900 char fontName[1024];
2901 if(!links[linksPos]) break;
2902 for(c = 0; (ch = links[linksPos + c]); c++)
2905 if(ch == ',') break;
2908 if(fontName[0] || ch == ',')
2910 #if defined(__WIN32__)
2911 GetWindowsDirectory(fileName, MAX_LOCATION);
2912 PathCat(fileName, "fonts");
2913 PathCat(fileName, fontName);
2914 #elif defined(ECERE_NOFONTCONFIG)
2915 if(getenv("ECERE_FONTS"))
2917 strcpy(fileName, ecereFonts);
2918 PathCat(fileName, fontName);
2924 FcResult result = 0;
2925 FcPattern * pattern;
2926 FcPattern * matched;
2928 pattern = FcPatternBuild(null,
2929 //FC_SOURCE, FcTypeString, "freetype",
2930 //FC_SCALABLE, FcTypeBool, 1,
2931 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
2932 FC_SIZE, FcTypeDouble, (double)size,
2933 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2934 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2936 FcDefaultSubstitute(pattern);
2937 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2939 //printf("Locating %s\n", links + linksPos + c + 1);
2940 matched = FcFontMatch (0, pattern, &result);
2943 FcPatternGetString(matched, FC_FAMILY, 0, &family);
2944 // printf("Fontconfig returned %s\n", family);
2946 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
2947 FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
2950 FcPatternGetString (matched, FC_FILE, 0, &fileName2);
2951 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2952 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2953 strcpy(fileName, fileName2);
2954 //size = (float)fontSize;
2955 // printf("Matched to %s, %f\n", fileName, size);
2959 // 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);
2961 if(pattern) FcPatternDestroy(pattern);
2962 if(matched) FcPatternDestroy(matched);
2969 while(links[linksPos]) linksPos++;
2976 UnloadFont(displaySystem, font);
2979 font.asciiPack.Render(font, 0, displaySystem);
2981 #if !defined(__WIN32__)
2989 #if !defined(ECERE_NOTRUETYPE)
2990 void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
2991 void (* callback)(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft),
2992 Surface surface, Display display, int * x, int y)
2994 if(font && font.fontEntries && font.fontEntries[0])
2996 int previousGlyph = 0;
2997 int c, nb, glyphIndex = 0;
2998 unichar lastPack = 0;
2999 GlyphPack pack = font.asciiPack;
3003 bool rightToLeft = false;
3004 int rightToLeftOffset = 0;
3005 int fontEntryNum = 0;
3006 bool foundArabic = false;
3007 int glyphScript = 0;
3009 pack.bitmap.alphaBlend = true;
3011 for(c = 0; c < len || glyphIndex < numGlyphs;)
3015 if(glyphIndex < numGlyphs)
3017 glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3021 HB_Script curScript = HB_Script_Common;
3022 byte * scriptStart = text + c;
3025 unichar testChar = 0;
3026 char * testLang = null;
3030 HB_Script script = HB_Script_Common;
3031 ch = UTF8GetChar(text + c, &nb);
3033 if(ch == 32 && curScript)
3040 for(a = c + 1; a < c + len; a++)
3048 unichar ahead = UTF8GetChar(text + a, &nb);
3049 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3057 script = HB_Script_Common;
3058 else if(ch <= 0x11FF)
3062 case 0x300: script = HB_Script_Greek; break;
3063 case 0x400: script = HB_Script_Cyrillic; break;
3064 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3065 case 0x600: script = HB_Script_Arabic; break;
3066 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3067 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3068 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3069 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3070 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3071 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3072 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3073 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3074 case 0xF00: script = HB_Script_Tibetan; break;
3075 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3076 case 0x1100: script = HB_Script_Hangul; break;
3079 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3080 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3081 script = HB_Script_Hangul;
3082 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3083 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3084 else if(ch >= 0x1780 && ch <= 0x17FF || ch >= 0x19E0 && ch <= 0x19FF) script = HB_Script_Khmer;
3085 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3086 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3087 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3088 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3089 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3090 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3093 if(!script || (script != curScript))
3101 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3102 if(!script) { c += nb; break; }
3109 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3111 rightToLeft = false;
3116 int len = c - (int)(scriptStart - text);
3117 int max = len * 2 + 1;
3118 if(max > utf16BufferSize)
3120 utf16 = renew utf16 uint16[max];
3121 utf16BufferSize = max;
3123 wc = UTF8toUTF16BufferLen(scriptStart, utf16, max, len);
3124 glyphScript = curScript;
3128 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3129 //printf("Arabic ");
3131 case HB_Script_Devanagari: testChar = 0x905; testLang = "sa";
3132 //printf("Devanagari ");
3137 case 60: testChar = 'あ'; break;
3138 case 61: testChar = 0x3400; break; //'愛'; break;
3144 // printf("Testing for char %x\n", testChar);
3145 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3147 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3149 /*if(font.fontEntries[fontEntryNum])
3150 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3154 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3156 #if !defined(__WIN32__)
3158 double fontSize = font.size;
3159 FcResult result = 0;
3160 FcPattern * pattern;
3161 FcPattern * matched;
3162 FcCharSet * charSet;
3164 FontEntry fontEntry;
3165 char * fileName = null;
3166 bool fakeItalic = false;
3167 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3168 if(!font.fontEntries[fontEntryNum])
3170 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3174 #if !defined(__WIN32__)
3176 charSet = FcCharSetCreate();
3177 FcCharSetAddChar(charSet, testChar);
3178 //printf("Loading with char %x\n", testChar);
3180 pattern = FcPatternBuild(null,
3181 //FC_SOURCE, FcTypeString, "freetype",
3182 //FC_SCALABLE, FcTypeBool, 1,
3183 FC_FAMILY, FcTypeString, font.faceName,
3184 FC_SIZE, FcTypeDouble, (double)font.size,
3185 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3186 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3187 FC_CHARSET,FcTypeCharSet, charSet,
3188 testLang ? FC_LANG : 0, FcTypeString,testLang,
3190 FcDefaultSubstitute(pattern);
3191 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3193 //printf("Locating %s for script %d\n", font.faceName, curScript);
3194 matched = FcFontMatch (0, pattern, &result);
3197 FcPatternGetString(matched, FC_FAMILY, 0, &family);
3198 //printf("Fontconfig returned %s\n", family);
3200 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
3202 FcPatternGetString (matched, FC_FILE, 0, &fileName);
3203 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3204 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3205 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3209 //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);
3214 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3217 File file = FileOpen(fileName, read);
3220 FileSize fileSize = file.GetSize();
3221 FT_Open_Args args = { 0 };
3222 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3223 FT_Stream stream = new0 FT_StreamRec[1];
3226 FT_Init_FreeType( &ftLibrary );
3228 fontEntry = FontEntry { key = (uint)CopyString(fileName) };
3229 fontEntry.stream = stream;
3231 //args.num_params = 1;
3232 args.params = ¶m;
3234 stream->size = fileSize;
3235 stream->descriptor.pointer = file;
3236 stream->read = FT_stream_load;
3237 stream->close = FT_stream_close;
3239 args.flags = FT_OPEN_STREAM;
3240 args.stream = stream;
3241 //args.pathname = fileName;
3242 //args.memory_base = fontEntry.buffer;
3243 //args.memory_size = fileSize;
3245 // printf("Opening: %s\n", fileName);
3246 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3251 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3252 fontEntry.hbFont.klass = &hb_fontClass;
3253 fontEntry.hbFont.userData = fontEntry.face;
3256 loadedFonts.Add(fontEntry);
3261 // printf("Error opening font %s\n", fileName);
3267 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
3269 font.fontEntries[fontEntryNum] = fontEntry;
3273 if(pattern) FcPatternDestroy(pattern);
3274 if(matched) FcPatternDestroy(matched);
3275 if(charSet) FcCharSetDestroy(charSet);
3278 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3279 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3282 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3285 if(rightToLeft /*&& surface*/)
3288 rightToLeftOffset = 0;
3289 for(c = 0; c<numGlyphs; c++)
3292 glyphNo = glyphs[c] | 0x80000000 | (glyphScript << 24);
3293 packNo = glyphNo & 0xFFFFFF80;
3294 if(packNo != lastPack)
3296 pack = (GlyphPack)font.glyphPacks.Find(packNo);
3299 pack = GlyphPack { key = packNo };
3300 font.glyphPacks.Add(pack);
3301 pack.Render(font, fontEntryNum, displaySystem);
3303 pack.bitmap.alphaBlend = true;
3306 glyph = &pack.glyphs[glyphNo & 0x7F];
3308 rightToLeftOffset += (int)glyph->ax - glyph->left;
3310 *x += rightToLeftOffset;
3314 glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
3317 packNo = glyphNo & 0xFFFFFF80;
3319 if(packNo != lastPack)
3322 pack = font.asciiPack;
3325 pack = (GlyphPack)font.glyphPacks.Find(packNo);
3328 pack = GlyphPack { key = packNo };
3329 font.glyphPacks.Add(pack);
3330 pack.Render(font, fontEntryNum, displaySystem);
3333 pack.bitmap.alphaBlend = true;
3338 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3343 FT_Get_Kerning(font.fontEntries[fontEntryNum].face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3346 previousGlyph = glyph->glyphNo;*/
3347 callback(surface, display, x, y, glyph, pack.bitmap, rightToLeft);
3349 if(numGlyphs && glyphIndex == numGlyphs)
3351 *x += rightToLeftOffset;
3358 LFBSurface lfbSurface = surface.driverData;
3359 lfbSurface.xOffset = 0;
3363 void ::AddWidth(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3367 *x -= (int)glyph->ax - glyph->left;
3375 void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
3377 if(displaySystem && displaySystem.flags.text && len)
3382 *width = num * textCellW;
3384 if(height) *height = textCellH;
3386 else if(font && len)
3391 #if !defined(ECERE_NOTRUETYPE)
3392 ProcessString(font, displaySystem, text, len, AddWidth, null, null, &w, 0);
3394 //*width = (w + 64 - w % 64) >> 6;
3398 *height = font.height;
3402 if(width) *width = 0;
3403 if(height) *height = 0;
3407 #if !defined(ECERE_NOTRUETYPE)
3408 void ::OutputGlyph(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
3410 LFBSurface lfbSurface = surface.driverData;
3411 //lfbSurface.xOffset = (*x & 0x3F);
3414 surface.driver.Blit(display, surface, bitmap, (*x >> 6) - glyph->w, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3415 *x -= (int)glyph->ax - glyph->left;
3419 surface.driver.Blit(display, surface, bitmap, (*x >> 6) + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3425 void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
3427 LFBSurface lfbSurface = surface.driverData;
3428 if(display && display.displaySystem.flags.text)
3430 LFBDisplay lfbDisplay = display.driverData;
3431 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3437 if(y > surface.box.bottom || y < surface.box.top)
3439 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3440 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3441 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3443 if(surface.textOpacity)
3444 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3446 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3451 lfbSurface.writingText = true;
3452 #if !defined(ECERE_NOTRUETYPE)
3454 ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
3456 lfbSurface.writingText = false;
3460 void TextFont(Display display, Surface surface, Font font)
3462 LFBSurface lfbSurface = surface.driverData;
3463 lfbSurface.font = font;
3466 void TextOpacity(Display display, Surface surface, bool opaque)
3468 LFBSurface lfbSurface = surface.driverData;
3472 void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
3474 LFBSurface lfbSurface = surface.driverData;
3475 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3478 void DrawingChar(Display display, Surface surface, byte character)
3480 LFBSurface lfbSurface = surface.driverData;
3481 lfbSurface.drawingChar = character;
3484 void LineStipple(Display display, Surface surface, uint32 stipple)
3486 LFBSurface lfbSurface = surface.driverData;
3487 lfbSurface.stipple = (uint16)stipple;
3490 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3491 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3493 if(mesh.vertices && !mesh.flags.vertices)
3494 delete mesh.vertices;
3495 if(mesh.normals && !mesh.flags.normals)
3496 delete mesh.normals;
3497 if(mesh.texCoords && !mesh.flags.texCoords1)
3498 delete mesh.texCoords;
3501 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3503 bool result = false;
3505 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3506 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3507 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3512 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3517 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3522 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3524 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3526 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)