1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
10 #if !defined(ECERE_NOTRUETYPE)
12 #include FT_FREETYPE_H
13 #include FT_TRUETYPE_TABLES_H
14 #include FT_UNPATENTED_HINTING_H
15 #define property _property
19 #if defined(__WIN32__)
20 #define WIN32_LEAN_AND_MEAN
21 #define String _String
24 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
26 #include <fontconfig/fontconfig.h>
27 static FcConfig * fcConfig;
36 #pragma warning(disable:4244)
37 #pragma warning(disable:4018)
43 public define LIGHTSHIFT = 5;
44 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
46 /*#ifndef ECERE_VANILLA
48 static bool rgbLookupSet = true;
50 /*static */byte defaultRGBLookup[32768];
51 /*static */bool rgbLookupSet = false;
57 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
58 import "OpenGLDisplayDriver"
59 import "Direct3D8DisplayDriver"
60 import "Direct3D9DisplayDriver"
63 #if !defined(ECERE_NOTRUETYPE)
65 #define MAX_FONT_LINK_ENTRIES 10
67 static HB_Script theCurrentScript;
69 static unichar UTF16GetChar(const uint16 *string, int * nw)
72 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
74 ch = HB_SurrogateToUcs4(string[0], string[1]);
85 static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
87 FT_Face face = ((FontEntry)font->userData).face;
91 if (length > *numGlyphs)
94 for (c = 0; c < length; c += nw)
96 unichar ch = UTF16GetChar(string + c, &nw);
97 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
99 *numGlyphs = glyph_pos;
103 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
105 FontEntry entry = font->userData;
106 Font glFont = entry.font;
109 GlyphPack pack = glFont.asciiPack;
111 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
113 if(glFont.fontEntries[fontEntryNum] == entry)
117 for(c = 0; c < numGlyphs; c++)
120 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
121 uint packNo = glyphNo & 0xFFFFFF80;
122 if(packNo != lastPack)
124 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
127 glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
128 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
129 pack.bitmap.alphaBlend = true;
133 glyph = &pack.glyphs[glyphNo & 0x7F];
134 advances[c] = glyph->ax;
138 static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
140 FT_Face face = ((FontEntry)font->userData).face;
143 for (c = 0; c < length; c += nw)
145 unichar ch = UTF16GetChar(string + c, &nw);
146 if(!FT_Get_Char_Index(face, ch))
152 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
154 FT_Face face = (FT_Face)font;
155 FT_ULong ftlen = *length;
158 if (!FT_IS_SFNT(face))
159 return HB_Err_Invalid_Argument;
161 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
162 *length = (uint)ftlen;
163 return (HB_Error)error;
166 static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
168 HB_Error error = HB_Err_Ok;
169 FT_Face face = (FT_Face)font->userData;
171 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
173 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
176 if (face->glyph->format != ft_glyph_format_outline)
177 return (HB_Error)HB_Err_Invalid_SubTable;
179 *nPoints = face->glyph->outline.n_points;
183 if (point > *nPoints)
184 return (HB_Error)HB_Err_Invalid_SubTable;
186 *xpos = (int)face->glyph->outline.points[point].x;
187 *ypos = (int)face->glyph->outline.points[point].y;
192 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
194 FontEntry entry = font->userData;
195 Font glFont = entry.font;
197 GlyphPack pack = glFont.asciiPack;
199 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
201 if(glFont.fontEntries[fontEntryNum] == entry)
206 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
207 uint packNo = glyphNo & 0xFFFFFF80;
208 if(packNo != lastPack)
210 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
213 pack = { key = (uintptr)packNo };
214 glFont.glyphPacks.Add(pack);
215 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
216 pack.bitmap.alphaBlend = true;
220 glyph = &pack.glyphs[glyphNo & 0x7F];
222 metrics->x = glyph->ax;
224 metrics->width = glyph->w;
225 metrics->height = glyph->h;
226 metrics->xOffset = glyph->bx;
227 metrics->yOffset = glyph->by;
231 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
233 FontEntry entry = font->userData;
234 FT_Face face = entry.face;
236 // Note that we aren't scanning the VDMX table which we probably would in
238 if(metric == HB_FontAscent)
239 return face->ascender;
243 static HB_FontClass hb_fontClass =
245 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
246 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
249 static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
251 File f = stream->descriptor.pointer;
252 f.Seek((int)offset, start);
253 return count ? f.Read(buffer, 1, (uint)count) : 0;
256 static void FT_stream_close(FT_Stream stream)
258 File f = stream->descriptor.pointer;
263 static FT_Library ftLibrary;
266 static BinaryTree loadedFonts
268 CompareKey = (void *)BinaryTree::CompareString
271 class FontEntry : BTNode
280 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
297 FT_Done_FreeType(ftLibrary);
304 static float FaceSetCharSize(FT_Face face, float size)
307 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
309 if(face->num_fixed_sizes)
312 int bestDiff = MAXINT, best = 0;
313 FT_Bitmap_Size * sizes = face->available_sizes;
314 int wishedHeight = (int)(size * 96 / 72);
315 for(c = 0; c < face->num_fixed_sizes; c++)
317 int diff = abs(sizes[c].height - wishedHeight);
324 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
327 face->ascender = sizes[best].height;
328 scale = (float)wishedHeight / sizes[best].height;
347 class GlyphPack : BTNode
349 GlyphInfo glyphs[256];
352 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
354 #if !defined(ECERE_NOTRUETYPE)
356 int maxWidth, maxHeight;
357 int cellWidth, cellHeight;
359 FontEntry fontEntry = null;
362 bool isGlyph = ((uint)key & 0x80000000) != 0;
363 //int curScript = ((uint)key & 0x7F000000) >> 24;
364 unichar testChar = 0;
370 case HB_Script_Arabic:
372 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
374 case HB_Script_Devanagari:
377 case 60: testChar = 'あ'; break;
378 case 61: testChar = 0x3400; break;
385 FT_Vector pen = { 0, 0 };
388 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
389 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
390 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
391 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
392 FT_Set_Transform( fontEntry.face, &matrix, &pen );
394 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
400 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
402 fontEntry = font.fontEntries[c];
406 FT_Vector pen = { 0, 0 };
410 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
411 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
412 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
413 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
414 FT_Set_Transform(fontEntry.face, &matrix, &pen);
416 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
417 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
420 if(!fontEntry.face->units_per_EM)
421 font.ascent = (int)((double)fontEntry.face->ascender);
423 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
426 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
427 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
428 fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
429 fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
434 for(c = 0; c < 128; c++)
439 uint glyph = ((uint)key | c) & 0xFFFFFF;
440 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
442 fontEntry = font.fontEntries[entry];
443 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
445 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
447 //printf("%s: Accepted entry %d ", font.faceName, entry);
455 for(entry = startFontEntry; ; entry++)
458 fontEntry = font.fontEntries[entry];
459 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
461 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
466 scales[c] = fontEntry.scale;
467 faces[c] = fontEntry.face;
468 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
469 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
470 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
472 cellWidth = maxWidth;
473 cellHeight = maxHeight;
475 width = pow2i(maxWidth * 16);
476 height = pow2i(maxHeight * 8);
478 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
480 Bitmap bitmap = this.bitmap;
482 bitmap.transparent = true;
484 for(c = 0; c < 128; c++)
488 int sx = (c % 16) * cellWidth;
489 int sy = (c / 16) * cellHeight;
491 byte * picture = (byte *)bitmap.picture;
492 GlyphInfo * glyph = &glyphs[c];
493 FT_GlyphSlot slot = faces[c]->glyph;
494 double em_size = 1.0 * faces[c]->units_per_EM;
495 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
496 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
497 double ascender = faces[c]->ascender * y_scale;
498 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
500 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
502 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
506 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
508 glyph->left = slot->bitmap_left;
509 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
510 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
511 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
512 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
514 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
515 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
517 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
519 //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));
520 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
522 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
523 glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
525 // 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);
526 xMax = x + slot->bitmap.width;
527 yMax = y + slot->bitmap.rows;
533 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
535 for(j = y, q = 0; j<yMax; j++)
537 for(p = 0, i = x; i<xMax; i++)
539 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
546 q += slot->bitmap.pitch;
549 //max = numPixels ? (total / numPixels) : 1;
551 for(j = y, q = 0; j<yMax; j++)
554 for(p = 0, i = x; i<xMax; i++)
556 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
558 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
560 if(!bit) { bit = 0x80; p++; }
564 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
565 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
568 q += slot->bitmap.pitch;
573 glyph->w = slot->bitmap.width;
574 glyph->h = slot->bitmap.rows;
575 glyph->glyphNo = glyphNo;
576 glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
577 glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
578 glyph->scale = scales[c];
580 glyph->ax = (int)slot->advance.x;
581 glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
588 for(c = 0; c<256; c++)
589 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
590 bitmap.pixelFormat = pixelFormat8;
593 //strcpy(fileName, faceName);
595 strcat(fileName, "Bold");
597 sprintf(fileName, "font%d", fid++);
598 ChangeExtension(fileName, "pcx", fileName);
600 bitmap.Save(fileName, null, 0);
601 bitmap.pixelFormat = pixelFormatAlpha;
605 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
607 displaySystem.Lock();
608 #if defined(__WIN32__)
609 // Is this check still required?
610 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
611 displaySystem.driver == class(Direct3D8DisplayDriver) ||
612 displaySystem.driver == class(Direct3D9DisplayDriver))
614 bitmap.MakeDD(displaySystem);
615 displaySystem.Unlock();
622 #if !defined(ECERE_NOTRUETYPE)
623 static HB_ShaperItem shaper_item;
625 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
627 static uint maxGlyphs = 0;
628 HB_Glyph * glyphs = shaper_item.glyphs;
630 shaper_item.kerning_applied = 0;
631 shaper_item.string = string;
632 shaper_item.stringLength = len;
633 shaper_item.item.script = script;
634 shaper_item.item.pos = 0;
635 shaper_item.item.length = shaper_item.stringLength;
636 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
637 shaper_item.item.bidiLevel = 1;
639 shaper_item.item.bidiLevel = 0;
640 shaper_item.shaperFlags = 0;
641 shaper_item.font = &entry.hbFont;
642 shaper_item.face = entry.hbFace;
643 shaper_item.num_glyphs = shaper_item.item.length;
644 shaper_item.glyphIndicesPresent = 0;
645 shaper_item.initialGlyphCount = 0;
646 shaper_item.num_glyphs = 0;
647 shaper_item.glyphs = null;
649 while(!HB_ShapeItem(&shaper_item))
651 if(shaper_item.num_glyphs > maxGlyphs)
653 maxGlyphs = shaper_item.num_glyphs;
654 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
655 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
656 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
657 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
658 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
662 shaper_item.glyphs = glyphs;
663 shaper_item.num_glyphs = maxGlyphs;
667 *numGlyphs = shaper_item.num_glyphs;
668 *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
669 return shaper_item.glyphs;
673 delete shaper_item.glyphs;
674 delete shaper_item.attributes;
675 delete shaper_item.advances;
676 delete shaper_item.offsets;
677 delete shaper_item.log_clusters;
681 public class Font : struct
683 BinaryTree glyphPacks { };
684 GlyphPack asciiPack { };
685 #if !defined(ECERE_NOTRUETYPE)
686 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
693 DisplaySystem displaySystem;
699 #if !defined(ECERE_NOTRUETYPE)
701 while((pack = (GlyphPack)glyphPacks.root))
703 glyphPacks.Remove(pack);
710 public class LFBDisplay : struct
714 byte rgbLookup[32768];
715 byte lightTable[256][LIGHTSTEPS];
719 void (* displayCallback)(Display display, Box updateBox);
722 public class LFBSystem : struct
726 ColorAlpha * palette;
727 byte rgbLookup[32768];
734 ColorAlpha * palette = GetDefaultPalette();
735 for(c = 16; c < 232; c++)
737 Color555 color = palette[c].color;
738 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
739 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
740 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
741 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
743 for(c = 232; c < 246; c++)
745 Color555 color = palette[c].color;
746 defaultRGBLookup[color] = (byte)c;
749 for(c = 246; c < 256; c++)
751 Color555 color = palette[c].color;
752 defaultRGBLookup[color] = (byte)c;
754 for(c = 0; c < 16; c++)
756 Color555 color = palette[c].color;
757 defaultRGBLookup[color] = (byte)c;
760 for(c = 0; c<32768; c++)
762 Color color = (Color)(Color555)c;
763 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
764 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
772 public class LFBSurface : struct
775 // For compatibility with 3D drivers as well
783 // Drawing attributes
784 uint foreground, background;
785 ColorAlpha foregroundRgb;
788 byte * paletteShades;
793 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
795 if(recordA->zMin > recordB->zMin)
797 else if(recordA->zMin < recordB->zMin)
799 else if(recordA > recordB)
801 else if(recordA < recordB)
808 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
811 char fileName[MAX_FILENAME];
816 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
818 //if(fontType == TRUETYPE_FONTTYPE)
820 FontData * fontData = (FontData *) lParam;
821 char * fileName = (char *)lParam;
823 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
824 int italic = (fontData->flags.italic) ? 1 : 0;
825 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
827 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
828 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
833 char entryName[1024];
834 char fontFileName[1024];
837 DWORD sizeFileName = 1024;
839 if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
841 if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
844 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
846 char ch = entryName[c];
847 if(ch == '&') { c = -1; break; }
848 else if(ch != ' ') break;
851 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
853 char ch = entryName[c];
854 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
855 else if(ch != ' ') break;
858 if(atoi(entryName + c))
862 strcpy(fileName, fontFileName);
876 #if !defined(ECERE_NOTRUETYPE)
877 static int utf16BufferSize = 0;
878 static uint16 * utf16 = null;
881 public class LFBDisplayDriver : DisplayDriver
883 class_property(name) = "LFB";
885 bool CreateDisplaySystem(DisplaySystem displaySystem)
887 displaySystem.flags.memBackBuffer = true;
888 // displaySystem.pixelFormat = pixelFormat888;
892 void DestroyDisplaySystem(DisplaySystem displaySystem)
896 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
898 delete bitmap.picture;
899 if(bitmap.allocatePalette)
900 delete bitmap.palette;
903 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
908 switch(GetColorDepthShifts(format))
910 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
911 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
912 case 2: stride = width; break;
915 bitmap.stride = stride;
916 bitmap.width = width;
917 bitmap.height = height;
918 bitmap.size = (uint32) stride * (uint32)height;
919 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
920 bitmap.pixelFormat = format;
921 bitmap.transparent = false;
923 surface.box.left = surface.box.top = 0;
924 surface.box.right = width - 1;
925 surface.box.bottom = height - 1;
927 bitmap.picture = new0 byte[bitmap.sizeBytes];
930 bitmap.allocatePalette = allocatePalette;
933 bitmap.palette = new ColorAlpha[256];
936 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
942 bitmap.palette = GetDefaultPalette();
947 FreeBitmap(displaySystem, bitmap);
951 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
954 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
958 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
960 if(src.transparent && src.pixelFormat == pixelFormat888)
964 DWORD * picture = (DWORD *)src.picture;
966 for(c = 0; c<src.size; c++, picture++)
968 if(*picture & 0xFFFFFF)
969 *picture = *picture | 0xFF000000;
971 *picture = *picture & 0xFFFFFF;
980 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
982 if(format == pixelFormat8)
985 bitmap.palette = palette;
986 else if(lfbSystem && lfbSystem.palette)
987 bitmap.palette = lfbSystem.palette;
989 bitmap.palette = src.palette;
992 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
994 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
995 bitmap.transparent = src.transparent;
996 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
998 if(src.palette != bitmap.palette)
1000 if(src.allocatePalette)
1002 src.allocatePalette = false;
1004 src.picture = bitmap.picture;
1005 src.palette = bitmap.palette;
1006 src.stride = bitmap.stride;
1007 src.size = bitmap.size;
1008 src.sizeBytes = bitmap.sizeBytes;
1009 src.pixelFormat = bitmap.pixelFormat;
1014 bitmap.palette = null;
1015 bitmap.picture = null;
1023 void DestroyDisplay(Display display)
1025 LFBDisplay lfbDisplay = display.driverData;
1026 delete lfbDisplay.bitmap.palette;
1029 bool CreateDisplay(Display display)
1031 bool result = false;
1032 LFBDisplay lfbDisplay = display.driverData;
1035 lfbDisplay = display.driverData = LFBDisplay { };
1036 lfbDisplay.selfManaged = true;
1037 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1040 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1042 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1048 bool DisplaySize(Display display, int width, int height)
1050 LFBDisplay lfbDisplay = display.driverData;
1051 //display.width = width;
1052 //display.height = height;
1053 lfbDisplay.bitmap.width = width;
1054 lfbDisplay.bitmap.height = height;
1056 lfbDisplay.updateBox.left = display.width;
1057 lfbDisplay.updateBox.top = display.height;
1058 lfbDisplay.updateBox.right = 0;
1059 lfbDisplay.updateBox.bottom = 0;
1062 if(lfbDisplay.selfManaged)
1064 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1065 lfbDisplay.bitmap.stride = width;
1067 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1071 void DisplayPosition(Display display, int x, int y)
1073 LFBDisplay lfbDisplay = display.driverData;
1078 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1080 LFBDisplay lfbDisplay = display.driverData;
1087 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1088 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1089 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1092 for(c = 0; c<32768; c++)
1093 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1095 for(c=0; c<256; c++)
1098 for(i=0; i<LIGHTSTEPS; i++)
1100 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1101 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1102 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1103 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1107 if(lfbDisplay.bitmap.palette)
1108 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1111 void Update(Display display, Box updateBox)
1113 LFBDisplay lfbDisplay = display.driverData;
1114 if(lfbDisplay.displayCallback)
1116 if(updateBox == null)
1118 Box box { 0,0, display.width,display.height };
1119 lfbDisplay.displayCallback(display, box);
1122 lfbDisplay.displayCallback(display, updateBox);
1126 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1128 if(bitmap.pixelFormat != pixelFormatAlpha)
1130 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1132 FreeBitmap(displaySystem, bitmap);
1139 void ReleaseSurface(Display display, Surface surface)
1141 LFBSurface lfbSurface = surface.driverData;
1143 surface.driverData = null;
1146 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1148 LFBDisplay lfbDisplay = display.driverData;
1149 LFBSurface lfbSurface = surface.driverData;
1152 lfbSurface = surface.driverData = LFBSurface { };
1155 lfbSurface.bitmap = lfbDisplay.bitmap;
1157 surface.offset.x = x;
1158 surface.offset.y = y;
1160 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1162 surface.offset.x /= textCellW;
1163 surface.offset.y /= textCellH;
1164 surface.box.left /= textCellW;
1165 surface.box.top /= textCellH;
1166 surface.box.right /= textCellW;
1167 surface.box.bottom /= textCellH;
1171 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1172 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1173 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1174 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1177 surface.unclippedBox = surface.box;
1178 lfbSurface.drawingChar = 219;
1182 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1184 bool result = false;
1185 LFBSurface lfbSurface = surface.driverData;
1186 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1188 lfbSurface.bitmap = bitmap;
1190 surface.offset.x = x;
1191 surface.offset.y = y;
1193 if(bitmap.pixelFormat == pixelFormatText)
1195 surface.offset.x /= textCellW;
1196 surface.offset.y /= textCellH;
1197 surface.box.left /= textCellW;
1198 surface.box.top /= textCellH;
1199 surface.box.right /= textCellW;
1200 surface.box.bottom /= textCellH;
1203 surface.unclippedBox = *&surface.box;
1204 lfbSurface.drawingChar = 219;
1211 void Clip(Display display, Surface surface, Box clip)
1213 LFBSurface lfbSurface = surface.driverData;
1218 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1220 box.left /= textCellW;
1221 box.top /= textCellH;
1222 box.right /= textCellW;
1223 box.bottom /= textCellH;
1225 box.Clip(surface.unclippedBox);
1229 surface.box = surface.unclippedBox;
1232 void SetForeground(Display display, Surface surface, ColorAlpha color)
1234 LFBDisplay lfbDisplay = display ? display.driverData : null;
1235 LFBSurface lfbSurface = surface.driverData;
1237 //if(display) color = color & 0xFFFFFF;
1238 lfbSurface.foregroundRgb = color;
1240 if(lfbSurface.font && lfbDisplay)
1242 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1243 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1246 switch(lfbSurface.bitmap.pixelFormat)
1250 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1252 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1254 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1255 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1256 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1257 case pixelFormat888: lfbSurface.foreground = color; break;
1258 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1259 case pixelFormatText:
1261 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1263 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1268 void SetBackground(Display display, Surface surface, ColorAlpha color)
1270 LFBDisplay lfbDisplay = display ? display.driverData : null;
1271 LFBSurface lfbSurface = surface.driverData;
1272 //color = color & 0xFFFFFF;
1273 switch(lfbSurface.bitmap.pixelFormat)
1277 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1279 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1281 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1282 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1283 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1284 case pixelFormat888: lfbSurface.background = color; break;
1285 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1286 case pixelFormatText:
1288 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1290 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1295 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1297 LFBSurface lfbSurface = surface.driverData;
1298 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1303 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1305 x += surface.offset.x;
1306 y += surface.offset.y;
1307 if(lfbSurface.bitmap.picture)
1309 switch(lfbSurface.bitmap.pixelFormat)
1311 case pixelFormatText:
1313 if(!lfbSurface.bitmap.palette) return 0;
1314 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1315 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1316 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1317 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1318 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1325 void PutPixel(Display display, Surface surface,int x,int y)
1327 LFBSurface lfbSurface = surface.driverData;
1328 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1333 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1335 x += surface.offset.x;
1336 y += surface.offset.y;
1337 if(lfbSurface.bitmap.picture)
1339 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1342 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1345 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1348 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1349 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1356 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1358 LFBSurface lfbSurface = surface.driverData;
1364 uint color = lfbSurface.foreground;
1365 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1366 bool invert = false;
1367 if(!lfbSurface.bitmap.picture) return;
1368 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1374 if(surface.textOpacity)
1375 color |= lfbSurface.background;
1376 color |= lfbSurface.drawingChar;
1380 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1382 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1383 if((x1>surface.box.right)||(x2<surface.box.left))return;
1384 if(x1<surface.box.left)x1=surface.box.left;
1385 if(x2>surface.box.right)x2=surface.box.right;
1389 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1390 if(stipple != 0xFFFF)
1393 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1396 for(x=x1; x<=x2; x++, offset++)
1398 if(stipple & 0x8000)
1399 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1401 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1403 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1407 for(x=x1; x<=x2; x++, offset++)
1409 if(stipple & 0x8000)
1410 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1412 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1414 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1418 for(x=x1; x<=x2; x++, offset++)
1420 if(stipple & 0x8000)
1421 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1423 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1425 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1432 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1434 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1436 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1437 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1438 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1444 for(x = x1; x <= x2; x++, offset++)
1446 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1447 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1456 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1458 if((x1>surface.box.right)||(x1<surface.box.left))return;
1459 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1460 if(y1<surface.box.top)y1=surface.box.top;
1461 if(y2>surface.box.bottom)y2=surface.box.bottom;
1463 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1464 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1467 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1469 if(stipple & 0x8000)
1470 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1472 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1474 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1478 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1480 if(stipple & 0x8000)
1482 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1483 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1486 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1487 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1491 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1493 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1497 if(stipple != 0xFFFF)
1499 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1501 if(stipple & 0x8000)
1502 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1504 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1506 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1511 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1512 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1521 if(x1 < surface.box.left)
1523 if(x2 < surface.box.left)
1525 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1526 x1 = surface.box.left;
1528 if(x2 > surface.box.right)
1530 if(x1 > surface.box.right)
1532 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1533 x2 = surface.box.right;
1537 if(y1 < surface.box.top)
1539 if(y2 < surface.box.top)
1541 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1542 y1 = surface.box.top;
1544 if(y2 > surface.box.bottom)
1546 if(y1 > surface.box.bottom)
1548 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1549 y2 = surface.box.bottom;
1554 if(y1 > surface.box.bottom)
1556 if(y2 > surface.box.bottom)
1558 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1559 y1 = surface.box.bottom;
1561 if(y2 < surface.box.top)
1563 if(y1 < surface.box.top)
1565 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1566 y2 = surface.box.top;
1572 if(x1 > surface.box.right)
1574 if(x2 > surface.box.right)
1576 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1577 x1 = surface.box.right;
1579 if(x2 < surface.box.left)
1581 if(x1 < surface.box.left)
1583 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1584 x2 = surface.box.left;
1588 if(y1 < surface.box.top)
1590 if(y2 < surface.box.top)
1592 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1593 y1 = surface.box.top;
1595 if(y2 > surface.box.bottom)
1597 if(y1 > surface.box.bottom)
1599 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1600 y2 = surface.box.bottom;
1605 if(y1 > surface.box.bottom)
1607 if(y2 > surface.box.bottom)
1609 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1610 y1 = surface.box.bottom;
1612 if(y2 < surface.box.top)
1614 if(y1 < surface.box.top)
1616 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1617 y2 = surface.box.top;
1635 yu=-(int)lfbSurface.bitmap.stride;
1638 yu=lfbSurface.bitmap.stride;
1640 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1646 for(i=0; i<=length; i++)
1648 if(stipple & 0x8000)
1649 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1651 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1652 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1653 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1662 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1668 for(i=0; i<=length; i++)
1670 if(stipple & 0x8000)
1671 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1673 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1674 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1675 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1689 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1691 DrawLine(display, surface,x1,y1,x2,y1);
1692 DrawLine(display, surface,x2,y1,x2,y2);
1693 DrawLine(display, surface,x2,y2,x1,y2);
1694 DrawLine(display, surface,x1,y2,x1,y1);
1697 #if !defined(__GNUC__)
1699 void memset_32_aligned(void *buf, int val, int dwords)
1704 *((uint32 *)(buf)) = val;
1705 buf = ((uint32 *)(buf))+1;
1731 if (dwords & 1) *((int*)(buf)) = val;
1737 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
1741 if(((uint32)buf) & 0x7F)
1743 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
1769 sub edx,ebx ; edx holds # of overflow bytes
1788 movdqa [edi+16],xmm0
1789 movdqa [edi+32],xmm0
1790 movdqa [edi+48],xmm0
1791 movdqa [edi+64],xmm0
1792 movdqa [edi+80],xmm0
1793 movdqa [edi+96],xmm0
1794 movdqa [edi+112],xmm0
1818 void memset_32(void *buf, uint32 val, uint32 dwords)
1821 if ((uint32)(buf) & 3)
1826 if (((uint32)(buf) & 1))
1828 *(byte *)(buf) = (byte)(val&0xFF);
1829 buf = ((byte *)(buf))+1;
1830 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
1833 if (((uint32)(buf) & 2))
1835 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1836 buf = ((uint16 *)(buf))+1;
1837 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
1841 memset_32_aligned(buf,val,dwords);
1846 *(byte *)(buf) = (byte)(val&0xFF);
1850 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
1851 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
1858 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
1860 LFBSurface lfbSurface = surface.driverData;
1861 uint32 color = lfbSurface.background;
1863 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1865 color |= lfbSurface.foreground | lfbSurface.drawingChar;
1871 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
1873 if(x1<surface.box.left) x1=surface.box.left;
1874 if(x2>surface.box.right) x2=surface.box.right;
1875 if(y1<surface.box.top) y1=surface.box.top;
1876 if(y2>surface.box.bottom) y2=surface.box.bottom;
1878 if(x2>=x1 && y2>=y1)
1886 x1 += surface.offset.x;
1887 x2 += surface.offset.x;
1888 y1 += surface.offset.y;
1889 y2 += surface.offset.y;
1890 if(lfbSurface.bitmap.picture)
1892 if(!surface.writeColor)
1894 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1895 for(y = y1; y<= y2; y++)
1898 for(c = 0; c < w; c++, picture++)
1900 picture->a = (byte)((color & 0xFF000000) >> 24);
1901 picture += lfbSurface.bitmap.stride - w;
1906 if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
1908 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1911 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1912 for(y = y1; y<= y2; y++)
1914 FillBytes(theOffset,(byte)color,w);
1915 theOffset += lfbSurface.bitmap.stride;
1919 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1920 for(y = y1; y<= y2; y++)
1922 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
1923 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
1927 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1928 for(y = y1; y<= y2; y++)
1930 #if defined(__GNUC__)
1931 FillBytesBy4((uint32 *) theOffset,color,w);
1933 memset_32((uint32 *) theOffset,color,w);
1935 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
1941 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
1942 //memset_32((uint32 *) theOffset,color,w);
1978 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1981 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
1982 for(y = y1; y<= y2; y++)
1984 // TODO: IMPLEMENT THIS
1985 FillBytes(theOffset,(byte)color,w);
1986 theOffset += lfbSurface.bitmap.stride;
1991 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
1992 ColorAlpha c = surface.background;
1997 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
1999 for(y = y1; y <= y2; y++)
2002 for(c = 0; c < w; c++, dest++)
2004 Color destColor = 0;
2005 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2006 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2007 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2009 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2010 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2011 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2013 if(r > 255) r = 255;
2014 if(g > 255) g = 255;
2015 if(b > 255) b = 255;
2017 destColor = { (byte)r, (byte)g, (byte)b };
2019 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2020 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2021 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2024 dest += (lfbSurface.bitmap.stride - w);
2030 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2031 AlphaWriteMode alphaWrite = surface.alphaWrite;
2032 ColorAlpha c = surface.background;
2037 for(y = y1; y <= y2; y++)
2040 for(c = 0; c < w; c++, dest++)
2042 int dr = dest->color.r;
2043 int dg = dest->color.g;
2044 int db = dest->color.b;
2045 int r = a * cr / 255 + ((255 - a) * dr / 255);
2046 int g = a * cg / 255 + ((255 - a) * dg / 255);
2047 int b = a * cb / 255 + ((255 - a) * db / 255);
2049 if(r > 255) r = 255;
2050 if(g > 255) g = 255;
2051 if(b > 255) b = 255;
2052 dest->color = { (byte)r, (byte)g, (byte)b };
2054 if(alphaWrite == blend)
2056 int ca = (int)(a + ((255 - a) * dest->a / 255));
2057 if(ca > 255) ca = 255;
2063 dest += (lfbSurface.bitmap.stride - w);
2072 void Clear(Display display, Surface surface, ClearType type)
2074 LFBSurface lfbSurface = surface.driverData;
2076 lfbSurface.clearing = true;
2077 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2078 surface.box.left == 0 && surface.box.top == 0 &&
2079 surface.box.right == surface.width-1 &&
2080 surface.box.bottom == surface.height-1)
2082 uint32 color = /*0xFF000000 | */lfbSurface.background;
2083 if(type != depthBuffer)
2085 if(lfbSurface.bitmap.stride != surface.width)
2086 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2089 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2092 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2094 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2095 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2100 if((flags & CLEAR_Z) && zbuffer)
2101 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2106 if(type != depthBuffer)
2107 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2109 if((flags & CLEAR_Z))
2112 uint32 w = surface.box.right-surface.box.left+1;
2113 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2114 + surface.box.left+surface.offset.x;
2115 for(y = surface.box.top; y<= surface.box.bottom; y++)
2117 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2118 offset += DISPLAY.Width;
2123 lfbSurface.clearing = false;
2126 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2128 LFBSurface lfbSurface = surface.driverData;
2131 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2133 if(w < 0) { w = -w; flip = true; }
2135 //Clip against the edges of the source
2148 if(sx+w>src.width-1)
2149 w-=sx+w-(src.width-1)-1;
2150 if(sy+h>src.height-1)
2151 h-=sy+h-(src.height-1)-1;
2152 //Clip against the edges of the destination
2153 if(dx<surface.box.left)
2155 if(!flip) sx+=surface.box.left-dx;
2156 w-=surface.box.left-dx;
2157 dx=surface.box.left;
2159 if(dy<surface.box.top)
2161 sy+=surface.box.top-dy;
2162 h-=surface.box.top-dy;
2165 if((dx+w)>surface.box.right)
2167 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2168 w-=((uint32)(dx+w)-surface.box.right-1);
2170 if((dy+h)>surface.box.bottom)
2171 h-=((dy+h)-surface.box.bottom-1);
2175 dx += surface.offset.x;
2176 dy += surface.offset.y;
2178 if(lfbSurface.bitmap.picture)
2180 AlphaWriteMode alphaWrite = surface.alphaWrite;
2181 if(src.alphaBlend && surface.blend)
2184 if(src.pixelFormat == pixelFormatAlpha)
2186 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2188 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2189 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2190 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2191 for(y = 0; y < h; y++)
2193 for(x = 0; x < w; x++, picture++, source++)
2195 int a = *source * color.a;
2196 ColorAlpha dest = *picture;
2197 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2198 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2199 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2200 if(r > 255) r = 255;
2201 if(g > 255) g = 255;
2202 if(b > 255) b = 255;
2203 picture->color = { (byte)r, (byte)g, (byte)b };
2204 if(alphaWrite == blend)
2206 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2207 if(ca > 255) ca = 255;
2208 picture->a = (byte)ca;
2211 picture->a = (byte)(a / 255);
2213 picture += lfbSurface.bitmap.stride - w;
2214 source += src.stride - w;
2217 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2219 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2220 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2221 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2222 for(y = 0; y < h; y++)
2224 for(x = 0; x < w; x++, picture++, source++)
2226 int a = *source * color.a;
2227 Color dest = *picture;
2228 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2229 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2230 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2231 if(r > 255) r = 255;
2232 if(g > 255) g = 255;
2233 if(b > 255) b = 255;
2234 *picture = Color { (byte)r, (byte)g, (byte)b };
2236 picture += lfbSurface.bitmap.stride - w;
2237 source += src.stride - w;
2240 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2242 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2243 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2244 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2245 for(y = 0; y < h; y++)
2247 for(x = 0; x < w; x++, picture++, source++)
2249 int a = *source * color.a;
2250 Color dest = *picture;
2251 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2252 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2253 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2254 if(r > 255) r = 255;
2255 if(g > 255) g = 255;
2256 if(b > 255) b = 255;
2257 *picture = Color { (byte)r, (byte)g, (byte)b };
2259 picture += lfbSurface.bitmap.stride - w;
2260 source += src.stride - w;
2266 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2267 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2269 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2270 for(y = 0; y < h; y++)
2272 for(x = 0; x < w; x++, picture++, source++)
2274 ColorAlpha src = *source;
2275 ColorAlpha dest = *picture;
2276 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2277 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2278 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2279 if(r > 255) r = 255;
2280 if(g > 255) g = 255;
2281 if(b > 255) b = 255;
2282 picture->color = { (byte)r, (byte)g, (byte)b };
2283 if(alphaWrite == blend)
2285 int a = src.a + ((255 - src.a) * dest.a / 255);
2286 if(a > 255) a = 255;
2287 picture->a = (byte)a;
2292 picture += lfbSurface.bitmap.stride - w;
2293 source += src.stride - w;
2296 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2298 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2299 for(y = 0; y < h; y++)
2301 for(x = 0; x < w; x++, picture++, source++)
2303 ColorAlpha src = *source;
2304 Color565 dest = *picture;
2305 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2306 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2307 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2308 if(r > 255 * 31) r = 255 * 31;
2309 if(g > 255 * 63) g = 255 * 63;
2310 if(b > 255 * 31) b = 255 * 31;
2311 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2313 picture += lfbSurface.bitmap.stride - w;
2314 source += src.stride - w;
2317 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2319 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2320 for(y = 0; y < h; y++)
2322 for(x = 0; x < w; x++, picture++, source++)
2324 ColorAlpha psrc = *source;
2325 Color555 dest = *picture;
2326 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2327 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2328 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2329 if(r > 255 * 31) r = 255 * 31;
2330 if(g > 255 * 31) g = 255 * 31;
2331 if(b > 255 * 31) b = 255 * 31;
2332 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2334 picture += lfbSurface.bitmap.stride - w;
2335 source += src.stride - w;
2340 else if(src.paletteShades)
2341 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2342 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2343 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2344 else if(src.pixelFormat == pixelFormat8)
2345 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2349 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2351 bool result = false;
2352 LFBDisplay lfbDisplay = display.driverData;
2354 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2357 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2358 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2362 Surface surface = bitmap.GetSurface(0,0,null);
2365 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2366 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2367 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2375 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2377 LFBSurface lfbSurface = surface.driverData;
2380 float s2dw,s2dh,d2sw,d2sh;
2382 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2384 if(Sgn(w) != Sgn(sw))
2396 //Clip against the edges of the source
2399 dx+=(int)((0-sx) * s2dw);
2400 w-=(int)((0-sx) * s2dw);
2406 dy+=(int)((0-sy) * s2dh);
2407 h-=(int)((0-sy) * s2dh);
2412 if(sx+sw>src.width-1)
2414 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2415 sw-=sx+sw-(src.width-1)-1;
2417 if(sy+sh>(src.height-1))
2419 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2420 sh-=sy+sh-(src.height-1)-1;
2422 //Clip against the edges of the destination
2423 if(dx<surface.box.left)
2425 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2426 sw-=(int)((surface.box.left-dx)*d2sw);
2427 w-=surface.box.left-dx;
2428 dx=surface.box.left;
2430 if(dy<surface.box.top)
2432 sy+=(int)((surface.box.top-dy)*d2sh);
2433 sh-=(int)((surface.box.top-dy)*d2sh);
2434 h-=surface.box.top-dy;
2437 if((dx+w)>surface.box.right)
2439 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2440 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2441 w-=((dx+w)-surface.box.right-1);
2443 if((dy+h)>surface.box.bottom)
2445 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2446 h-=((dy+h)-surface.box.bottom-1);
2448 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2450 dx+=surface.offset.x;
2451 dy+=surface.offset.y;
2453 if(lfbSurface.bitmap.picture)
2455 AlphaWriteMode alphaWrite = surface.alphaWrite;
2456 if(src.alphaBlend && surface.blend)
2460 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2461 ColorAlpha * backsrc;
2462 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2463 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2464 if(flip) source += sw-1;
2482 ColorAlpha src = *source;
2483 ColorAlpha dst = *dest;
2484 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2485 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2486 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2487 if(r > 255) r = 255;
2488 if(g > 255) g = 255;
2489 if(b > 255) b = 255;
2490 dest->color = { (byte)r, (byte)g, (byte)b };
2491 if(alphaWrite == blend)
2493 int a = src.a + ((255 - src.a) * dst.a / 255);
2494 if(a > 255) a = 255;
2507 source += addsource;
2510 else if(src.paletteShades)
2511 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2512 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2513 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2514 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2515 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2519 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2521 LFBSurface lfbSurface = surface.driverData;
2524 float s2dw,s2dh,d2sw,d2sh;
2526 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2528 if(Sgn(w) != Sgn(sw))
2540 //Clip against the edges of the source
2543 dx+=(int)((0-sx) * s2dw);
2544 w-=(int)((0-sx) * s2dw);
2550 dy+=(int)((0-sy) * s2dh);
2551 h-=(int)((0-sy) * s2dh);
2556 if(sx+sw>src.width-1)
2558 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2559 sw-=sx+sw-(src.width-1)-1;
2561 if(sy+sh>(src.height-1))
2563 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2564 sh-=sy+sh-(src.height-1)-1;
2566 //Clip against the edges of the destination
2567 if(dx<surface.box.left)
2569 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2570 sw-=(int)((surface.box.left-dx)*d2sw);
2571 w-=surface.box.left-dx;
2572 dx=surface.box.left;
2574 if(dy<surface.box.top)
2576 sy+=(int)((surface.box.top-dy)*d2sh);
2577 sh-=(int)((surface.box.top-dy)*d2sh);
2578 h-=surface.box.top-dy;
2581 if((dx+w)>surface.box.right)
2583 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2584 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2585 w-=((dx+w)-surface.box.right-1);
2587 if((dy+h)>surface.box.bottom)
2589 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2590 h-=((dy+h)-surface.box.bottom-1);
2592 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2594 dx+=surface.offset.x;
2595 dy+=surface.offset.y;
2597 if(lfbSurface.bitmap.picture)
2599 AlphaWriteMode alphaWrite = surface.alphaWrite;
2600 if(src.alphaBlend && surface.blend)
2602 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2603 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2604 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2605 float scaleX = (float)sw / w;
2606 float scaleY = (float)sh / h;
2614 if (w > sw && h > sh)
2617 for (y = 0; y < h; y++)
2619 int y0 = y * sh / h;
2620 int y1 = Min(y0 + 1, sh - 1);
2621 float alpha = y * scaleY - y0;
2623 for(x = 0; x < w; x++, dest += 1)
2625 int x0 = x * sw / w;
2626 int x1 = Min(x0 + 1, sw - 1);
2627 float beta = x * scaleX - x0;
2628 ColorAlpha src00, src01, src10, src11;
2629 float a1,r1,g1,b1,a2,r2,g2,b2;
2631 src00 = source[y0 * src.stride + x0];
2632 src01 = source[y0 * src.stride + x1];
2633 src10 = source[y1 * src.stride + x0];
2634 src11 = source[y1 * src.stride + x1];
2635 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2636 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2637 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2638 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2639 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2640 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2641 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2642 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2643 a = a1 * (1.0f - alpha) + a2 * alpha;
2644 r = r1 * (1.0f - alpha) + r2 * alpha;
2645 g = g1 * (1.0f - alpha) + g2 * alpha;
2646 b = b1 * (1.0f - alpha) + b2 * alpha;
2648 ColorAlpha dst = *dest;
2649 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2650 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2651 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2652 if(cr > 255) cr = 255;
2653 if(cg > 255) cg = 255;
2654 if(cb > 255) cb = 255;
2655 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2657 if(alphaWrite == blend)
2659 int ca = (int)(a + ((255 - a) * dst.a / 255));
2660 if(ca > 255) ca = 255;
2673 for (y = 0; y < h; y++)
2675 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2676 int y1 = Min(y0 + 1, sh - 1);
2678 for (x = 0; x < w; x++, dest += 1)
2680 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2681 int x1 = Min(x0 + 1, sw - 1);
2682 float a = 0, r = 0, g = 0, b = 0;
2685 for (i = y0; i <= y1; i++)
2686 for (j = x0; j <= x1; j++)
2688 ColorAlpha pixel = source[i * src.stride + j];
2700 ColorAlpha dst = *dest;
2701 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2702 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2703 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2704 if(cr > 255) cr = 255;
2705 if(cg > 255) cg = 255;
2706 if(cb > 255) cb = 255;
2707 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2708 if(alphaWrite == blend)
2710 int ca = (int)(a + ((255 - a) * dst.a / 255));
2711 if(ca > 255) ca = 255;
2722 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2723 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2724 // Fail back on Stretch
2725 else if(src.paletteShades)
2726 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2727 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2728 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2729 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2730 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2734 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2736 Blit(display, surface, src, dx, dy, sx, sy, w, h);
2739 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2741 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2744 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2746 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
2749 void UnloadFont(DisplaySystem displaySystem, Font font)
2753 #if !defined(ECERE_NOTRUETYPE)
2755 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
2757 FontEntry fontEntry = font.fontEntries[entry];
2763 loadedFonts.Remove(fontEntry);
2773 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
2775 void * result = null;
2777 #if !defined(ECERE_NOTRUETYPE)
2778 Font font = Font { };
2781 char fileName[MAX_LOCATION];
2782 bool fakeItalic = flags.italic;
2784 #if !defined(__WIN32__)
2787 const char * ecereFonts = getenv("ECERE_FONTS");
2788 if(!ecereFonts) ecereFonts = "<:ecere>";
2789 #if !defined(__WIN32__)
2791 char linkCfgPath[MAX_LOCATION];
2793 strcpy(linkCfgPath, ecereFonts);
2794 PathCat(linkCfgPath, "linking.cfg");
2795 linkCfg = FileOpen(linkCfgPath, read);
2798 strcpy(fileName, faceName);
2799 strcpy(font.faceName, faceName);
2801 font.displaySystem = displaySystem;
2803 if(!FileExists(fileName))
2805 strcpy(fileName, ecereFonts);
2806 PathCat(fileName, faceName);
2807 if(flags.bold && flags.italic) strcat(fileName, "bi");
2808 else if(flags.bold) strcat(fileName, "bd");
2809 else if(flags.italic) strcat(fileName, "i");
2810 strcat(fileName, ".ttf");
2814 if(flags.italic && !FileExists(fileName))
2816 strcpy(fileName, ecereFonts);
2817 PathCat(fileName, faceName);
2818 if(flags.bold) strcat(fileName, "bd");
2819 strcat(fileName, ".ttf");
2824 // Search in current working directory
2825 if(!FileExists(fileName))
2827 strcpy(fileName, faceName);
2828 if(flags.bold && flags.italic) strcat(fileName, "bi");
2829 else if(flags.bold) strcat(fileName, "bd");
2830 else if(flags.italic) strcat(fileName, "i");
2831 strcat(fileName, ".ttf");
2835 if(flags.italic && !FileExists(fileName))
2837 strcpy(fileName, faceName);
2838 if(flags.bold) strcat(fileName, "bd");
2839 strcat(fileName, ".ttf");
2845 #if defined(__WIN32__)
2846 if(!FileExists(fileName))
2848 FontData fontData = { { 0 } };
2849 LOGFONT logFont = { 0 };
2854 logFont.lfCharSet = DEFAULT_CHARSET;
2855 strcpy(logFont.lfFaceName, faceName);
2856 fontData.flags = flags;
2858 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2859 if(!fontData.fileName[0] && flags.bold)
2861 fontData.forgive = true;
2862 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2864 if(!fontData.fileName[0])
2867 fontData.flags.italic = false;
2868 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
2872 if(fontData.fileName[0])
2874 GetWindowsDirectory(fileName, MAX_LOCATION);
2875 PathCat(fileName, "fonts");
2876 PathCat(fileName, fontData.fileName);
2880 #elif !defined(ECERE_NOFONTCONFIG)
2883 FcResult result = 0;
2884 FcPattern * pattern;
2885 FcPattern * matched;
2887 unichar testChar = 0;
2888 FcCharSet * charSet;
2890 fcConfig = FcInitLoadConfigAndFonts();
2892 charSet = FcCharSetCreate();
2894 if(!strcmpi(faceName, "Mangal"))
2900 FcCharSetAddChar(charSet, testChar);
2902 pattern = FcPatternBuild(null,
2903 //FC_SOURCE, FcTypeString, "freetype",
2904 FC_FAMILY, FcTypeString, faceName,
2905 //FC_SCALABLE, FcTypeBool, 1,
2906 FC_SIZE, FcTypeDouble, (double)size,
2907 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
2908 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
2909 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
2911 FcDefaultSubstitute(pattern);
2912 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
2914 matched = FcFontMatch (0, pattern, &result);
2915 // printf("Locating %s\n", faceName);
2918 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
2919 //printf("Fontconfig returned %s\n", family);
2921 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
2924 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
2925 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
2926 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
2927 strcpy(fileName, fileName2);
2928 // size = (float)fontSize;
2930 //printf("Matched to %s, %f\n", fileName, size);
2934 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
2936 if(pattern) FcPatternDestroy(pattern);
2937 if(matched) FcPatternDestroy(matched);
2938 if(charSet) FcCharSetDestroy(charSet);
2943 if(!FileExists(fileName))
2944 ChangeExtension(fileName, "otf", fileName);
2945 if(!FileExists(fileName))
2946 ChangeExtension(fileName, "ttc", fileName);
2948 //if(FileExists(fileName))
2951 char links[1024] = "";
2953 #if defined(__WIN32__)
2956 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
2957 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
2962 RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
2963 memset(links + size, 0, 1024 - size);
2971 while(linkCfg.GetLine(line, sizeof(line)))
2973 int len = strlen(faceName);
2974 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
2976 while(linkCfg.GetLine(line, sizeof(line)))
2978 TrimLSpaces(line, line);
2979 if(!line[0] || line[0] == '[')
2982 memcpy(links + linksPos, line, len);
2984 links[linksPos] = 0;
2992 while(entry < MAX_FONT_LINK_ENTRIES)
2994 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
2997 File file = FileOpen/*Buffered*/(fileName, read);
3000 FileSize fileSize = file.GetSize();
3001 FT_Open_Args args = { 0 };
3002 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3003 FT_Stream stream = new0 FT_StreamRec[1];
3006 FT_Init_FreeType( &ftLibrary );
3008 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3009 fontEntry.stream = stream;
3012 fontEntry.buffer = new byte[fileSize];
3013 file.Read(fontEntry.buffer, 1, fileSize);
3016 //args.num_params = 1;
3017 args.params = ¶m;
3019 stream->size = fileSize;
3020 stream->descriptor.pointer = file;
3021 stream->read = FT_stream_load;
3022 stream->close = FT_stream_close;
3024 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3025 args.stream = stream;
3026 //args.pathname = fileName;
3027 //args.memory_base = fontEntry.buffer;
3028 //args.memory_size = fileSize;
3030 // printf("Opening: %s\n", fileName);
3031 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3036 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3037 fontEntry.hbFont.klass = &hb_fontClass;
3038 fontEntry.hbFont.userData = fontEntry; //.face;
3041 loadedFonts.Add(fontEntry);
3046 // printf("Error opening font %s\n", fileName);
3055 FT_Vector pen = { 0, 0 };
3058 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3059 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3060 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3061 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3065 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3066 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3067 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3068 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3070 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3071 FaceSetCharSize(fontEntry.face, size);
3072 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3073 // printf("Font height is %d\n", font.height);
3074 font.fakeItalic = fakeItalic;
3078 font.fontEntries[entry++] = fontEntry;
3085 char fontName[1024];
3086 if(!links[linksPos]) break;
3087 for(c = 0; (ch = links[linksPos + c]); c++)
3090 if(ch == ',') break;
3093 if(fontName[0] || ch == ',')
3095 #if defined(__WIN32__)
3096 GetWindowsDirectory(fileName, MAX_LOCATION);
3097 PathCat(fileName, "fonts");
3098 PathCat(fileName, fontName);
3099 #elif !defined(ECERE_NOFONTCONFIG)
3100 if(getenv("ECERE_FONTS"))
3102 strcpy(fileName, ecereFonts);
3103 PathCat(fileName, fontName);
3109 FcResult result = 0;
3110 FcPattern * pattern;
3111 FcPattern * matched;
3113 pattern = FcPatternBuild(null,
3114 //FC_SOURCE, FcTypeString, "freetype",
3115 //FC_SCALABLE, FcTypeBool, 1,
3116 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3117 FC_SIZE, FcTypeDouble, (double)size,
3118 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3119 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3121 FcDefaultSubstitute(pattern);
3122 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3124 //printf("Locating %s\n", links + linksPos + c + 1);
3125 matched = FcFontMatch (0, pattern, &result);
3128 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3129 // printf("Fontconfig returned %s\n", family);
3131 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3132 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3135 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
3136 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3137 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3138 strcpy(fileName, fileName2);
3139 //size = (float)fontSize;
3140 // printf("Matched to %s, %f\n", fileName, size);
3144 // 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);
3146 if(pattern) FcPatternDestroy(pattern);
3147 if(matched) FcPatternDestroy(matched);
3154 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3161 UnloadFont(displaySystem, font);
3164 font.asciiPack.Render(font, 0, displaySystem);
3166 #if !defined(__WIN32__)
3174 #if !defined(ECERE_NOTRUETYPE)
3175 void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
3176 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3177 Surface surface, Display display, int * x, int y)
3179 if(font && font.fontEntries && font.fontEntries[0])
3181 int previousGlyph = 0;
3182 FT_Face previousFace = 0;
3183 int c, nb, glyphIndex = 0;
3184 unichar lastPack = 0;
3185 GlyphPack pack = font.asciiPack;
3187 uint * glyphs = null;
3189 bool rightToLeft = false;
3190 int fontEntryNum = 0;
3191 int glyphScript = 0;
3192 FontEntry curFontEntry;
3194 pack.bitmap.alphaBlend = true;
3196 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3200 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3202 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3203 rightToLeft ? glyphIndex-- : glyphIndex++;
3207 HB_Script curScript = HB_Script_Common;
3208 const byte * scriptStart = text + c;
3209 //unichar nonASCIIch = 0;
3212 unichar testChar = 0;
3213 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3214 const char * testLang = null;
3219 HB_Script script = HB_Script_Common;
3220 ch = UTF8GetChar((const char *)text + c, &nb);
3221 //if(ch > 127) nonASCIIch = ch;
3223 if(ch == 32 && curScript)
3230 for(a = c + 1; a < c + len; a++)
3238 unichar ahead = UTF8GetChar((const char *)text + a, &nb);
3239 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3247 script = HB_Script_Common;
3248 else if(ch <= 0x11FF)
3252 case 0x300: script = HB_Script_Greek; break;
3253 case 0x400: script = HB_Script_Cyrillic; break;
3254 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3255 case 0x600: script = HB_Script_Arabic; break;
3256 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3257 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3258 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3259 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3260 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3261 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3262 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3263 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3264 case 0xF00: script = HB_Script_Tibetan; break;
3265 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3266 case 0x1100: script = HB_Script_Hangul; break;
3269 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3270 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3271 script = HB_Script_Hangul;
3272 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3273 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3274 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3275 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3276 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3277 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3278 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3279 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3280 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3283 if(!script || (script != curScript))
3291 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3292 if(!script) { c += nb; break; }
3299 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3301 rightToLeft = false;
3303 theCurrentScript = 0;
3307 int len = c - (int)(scriptStart - text);
3308 int max = len * 2 + 1;
3309 if(max > utf16BufferSize)
3311 utf16 = renew utf16 uint16[max];
3312 utf16BufferSize = max;
3314 wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
3315 theCurrentScript = glyphScript = curScript;
3319 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3320 //printf("Arabic ");
3322 case HB_Script_Devanagari: testChar = 0x905;
3323 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3326 //printf("Devanagari ");
3328 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3329 //printf("Hebrew ");
3332 testChar = (ch == '\t') ? ' ' : ch;
3334 case 60: testChar = 'あ'; break;
3335 case 61: testChar = 0x3400; break; //'愛'; break;
3341 // printf("Testing for char %x\n", testChar);
3342 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3344 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3346 /*if(font.fontEntries[fontEntryNum])
3347 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3351 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3353 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3355 double fontSize = font.size;
3356 FcResult result = 0;
3357 FcPattern * pattern;
3358 FcPattern * matched;
3359 FcCharSet * charSet;
3361 FontEntry fontEntry;
3362 char * fileName = null;
3363 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3364 if(!font.fontEntries[fontEntryNum])
3366 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3370 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3372 charSet = FcCharSetCreate();
3373 FcCharSetAddChar(charSet, testChar);
3374 //printf("Loading with char %x\n", testChar);
3376 pattern = FcPatternBuild(null,
3377 //FC_SOURCE, FcTypeString, "freetype",
3378 //FC_SCALABLE, FcTypeBool, 1,
3379 FC_FAMILY, FcTypeString, font.faceName,
3380 FC_SIZE, FcTypeDouble, (double)font.size,
3381 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3382 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3383 FC_CHARSET,FcTypeCharSet, charSet,
3384 testLang ? FC_LANG : 0, FcTypeString,testLang,
3386 FcDefaultSubstitute(pattern);
3387 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3389 //printf("Locating %s for script %d\n", font.faceName, curScript);
3390 matched = FcFontMatch (0, pattern, &result);
3393 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3394 //printf("Fontconfig returned %s\n", family);
3396 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
3398 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName);
3399 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3400 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3401 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3405 //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);
3410 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3413 File file = FileOpen(fileName, read);
3416 FileSize fileSize = file.GetSize();
3417 FT_Open_Args args = { 0 };
3418 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3419 FT_Stream stream = new0 FT_StreamRec[1];
3422 FT_Init_FreeType( &ftLibrary );
3424 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3425 fontEntry.stream = stream;
3427 //args.num_params = 1;
3428 args.params = ¶m;
3430 stream->size = fileSize;
3431 stream->descriptor.pointer = file;
3432 stream->read = FT_stream_load;
3433 stream->close = FT_stream_close;
3435 args.flags = FT_OPEN_STREAM;
3436 args.stream = stream;
3437 //args.pathname = fileName;
3438 //args.memory_base = fontEntry.buffer;
3439 //args.memory_size = fileSize;
3441 // printf("Opening: %s\n", fileName);
3442 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3447 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3448 fontEntry.hbFont.klass = &hb_fontClass;
3449 fontEntry.hbFont.userData = fontEntry; //.face;
3452 loadedFonts.Add(fontEntry);
3457 // printf("Error opening font %s\n", fileName);
3463 FaceSetCharSize(fontEntry.face, font.size);
3465 font.fontEntries[fontEntryNum] = fontEntry;
3469 if(pattern) FcPatternDestroy(pattern);
3470 if(matched) FcPatternDestroy(matched);
3471 if(charSet) FcCharSetDestroy(charSet);
3474 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3475 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3477 font.fontEntries[fontEntryNum].font = font;
3478 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3482 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3483 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3484 rightToLeft ? glyphIndex-- : glyphIndex++;
3488 curFontEntry = font.fontEntries[fontEntryNum];
3490 packNo = glyphNo & 0xFFFFFF80;
3492 if(packNo != lastPack)
3495 pack = font.asciiPack;
3498 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3501 pack = GlyphPack { key = (uintptr)packNo };
3502 font.glyphPacks.Add(pack);
3503 pack.Render(font, fontEntryNum, displaySystem);
3506 pack.bitmap.alphaBlend = true;
3511 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3512 GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
3514 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3515 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3516 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3520 if(previousGlyph && curFontEntry.face == previousFace)
3522 FT_Vector delta = { 0, 0 };
3523 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3524 if(delta.x < 0) delta.x += (-delta.x) % 64;
3525 else if(delta.x) delta.x += 64 - (delta.x % 64);
3526 *x += delta.x * glyph->scale;
3529 FaceSetCharSize(curFontEntry.face, font.size);
3531 previousGlyph = glyph->glyphNo;
3532 previousFace = curFontEntry.face;
3535 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
3538 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3544 LFBSurface lfbSurface = surface.driverData;
3545 lfbSurface.xOffset = 0;
3550 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3552 if(displaySystem && displaySystem.flags.text && len)
3557 *width = num * textCellW;
3559 if(height) *height = textCellH;
3561 else if(font && len)
3566 #if !defined(ECERE_NOTRUETYPE)
3567 ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
3569 //*width = (w + 64 - w % 64) >> 6;
3573 *height = font.height;
3577 if(width) *width = 0;
3578 if(height) *height = 0;
3582 #if !defined(ECERE_NOTRUETYPE)
3583 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3585 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3589 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3591 LFBSurface lfbSurface = surface.driverData;
3592 if(display && display.displaySystem.flags.text)
3594 LFBDisplay lfbDisplay = display.driverData;
3595 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3601 if(y > surface.box.bottom || y < surface.box.top)
3603 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3604 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3605 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3607 if(surface.textOpacity)
3608 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3610 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3615 lfbSurface.writingText = true;
3616 #if !defined(ECERE_NOTRUETYPE)
3618 ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
3620 lfbSurface.writingText = false;
3624 void TextFont(Display display, Surface surface, Font font)
3626 LFBSurface lfbSurface = surface.driverData;
3627 lfbSurface.font = font;
3630 void TextOpacity(Display display, Surface surface, bool opaque)
3635 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3637 LFBSurface lfbSurface = surface.driverData;
3638 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3641 void DrawingChar(Display display, Surface surface, byte character)
3643 LFBSurface lfbSurface = surface.driverData;
3644 lfbSurface.drawingChar = character;
3647 void LineStipple(Display display, Surface surface, uint32 stipple)
3649 LFBSurface lfbSurface = surface.driverData;
3650 lfbSurface.stipple = (uint16)stipple;
3653 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3654 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3656 if(mesh.vertices && !mesh.flags.vertices)
3657 delete mesh.vertices;
3658 if(mesh.normals && !mesh.flags.normals)
3659 delete mesh.normals;
3660 if(mesh.texCoords && !mesh.flags.texCoords1)
3661 delete mesh.texCoords;
3664 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
3666 bool result = false;
3668 if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
3669 (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
3670 (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
3675 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
3680 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
3685 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3687 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3689 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)