namespace gfx::drivers;
-#if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
-#define ECERE_NOTRUETYPE
-#endif
-
-#undef __BLOCKS__
-#define uint _uint
-#define strlen _strlen
-#if !defined(ECERE_NOTRUETYPE)
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_TRUETYPE_TABLES_H
-#include FT_UNPATENTED_HINTING_H
-#define property _property
-#include "harfbuzz.h"
-#undef property
-
-#if defined(__WIN32__)
-#define WIN32_LEAN_AND_MEAN
-#define String _String
-#include <windows.h>
-#undef String
-#elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
-#define set _set
-#include <fontconfig/fontconfig.h>
-static FcConfig * fcConfig;
-#undef set
-#endif
-
-#endif
-#undef uint
-#undef strlen
-
#ifdef __MSC__
#pragma warning(disable:4244)
#pragma warning(disable:4018)
/*static */bool rgbLookupSet = false;
//#endif
+#if defined(ECERE_VANILLA)
+ #define ECERE_NOTRUETYPE
+#endif
+
+#if !defined(ECERE_NOTRUETYPE)
+import "fontManagement"
+import "fontRendering"
+#else
+public class Font : struct { }
+#endif
+
import "lfbBlit"
import "lfbConvert"
#endif
-#if !defined(ECERE_NOTRUETYPE)
-
-#if !defined(ECERE_VANILLA)
-import "edtaa3func"
-
-static void ComputeOutline(byte *out, byte *src, uint w, uint h, float size, float fade)
+public class LFBDisplay : struct
{
- uint i, numPixels = w * h;
- short * distx = new short[2 * numPixels], * disty = distx + numPixels;
- float * data = new0 float[4 * numPixels], * gx = data + numPixels, * gy = gx + numPixels, * dist = gy + numPixels;
- float rb = Max(1.5f, size), ra = rb - (rb-1)*fade*4 - 1;
- float inv_rw = 1/(rb-ra);
-
- for(i = 0; i < numPixels; i++)
- data[i] = src[i] / 255.0f;
-
- computegradient(data, w, h, gx, gy);
- edtaa3(data, gx, gy, w, h, distx, disty, dist);
-
- for(i = 0; i < numPixels; i++)
- {
- float value = 1 - Max(0.0f, Min(1.0f, (dist[i]-ra)*inv_rw));
- out[i] = (byte)(255 * value * value);
- }
- delete distx;
- delete data;
-}
+public:
+ Bitmap bitmap { };
+ byte rgbLookup[32768];
+ byte lightTable[256][LIGHTSTEPS];
+ OldList updateBoxes;
+ int x,y;
+ bool selfManaged;
+ void (* displayCallback)(Display display, Box updateBox);
+};
-static void BlitOutline(byte * dst, int dx, int dy, int w, int h, byte * src, int sx, int sy, int sw, int sh, int srcStride)
+public class LFBSystem : struct
{
- sh = Min(h - dy, sh);
- sw = Min(w - dx, sw);
- if(sw > 0 && sh > 0)
- {
- int y;
- for(y = 0; y < sh; y++)
- memcpy(dst + w * (dy+y) + dx, src + srcStride * (sy+y) + sx, sw);
- }
-}
+public:
+ int format;
+ ColorAlpha * palette;
+ byte rgbLookup[32768];
-static void MeasureOutline(byte * image, int w, int h, int * _x1, int * _y1, int * _x2, int * _y2)
-{
- int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
- int x, y;
- for(x = 0; x < w && x1 == MAXINT; x++)
+ LFBSystem()
{
- for(y = 0; y < h; y++)
- if(image[(y*w)+x])
+ if(!rgbLookupSet)
+ {
+ int c, r, g, b;
+ ColorAlpha * palette = GetDefaultPalette();
+ for(c = 16; c < 232; c++)
{
- x1 = x;
- break;
+ Color555 color = palette[c].color;
+ for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
+ for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
+ for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
+ defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
}
- }
- for(x = w-1; x >= 0 && x2 == MININT; x--)
- {
- for(y = 0; y < h; y++)
- if(image[(y*w)+x])
+ for(c = 232; c < 246; c++)
{
- x2 = x;
- break;
+ Color555 color = palette[c].color;
+ defaultRGBLookup[color] = (byte)c;
}
- }
- for(y = 0; y < h && y1 == MAXINT; y++)
- {
- for(x = 0; x < w; x++)
- if(image[(y*w)+x])
+ /*
+ for(c = 246; c < 256; c++)
{
- y1 = y;
- break;
+ Color555 color = palette[c].color;
+ defaultRGBLookup[color] = (byte)c;
}
- }
- for(y = h-1; y >= 0 && y2 == MININT; y--)
- {
- for(x = 0; x < w; x++)
- if(image[(y*w)+x])
+ for(c = 0; c < 16; c++)
{
- y2 = y;
- break;
+ Color555 color = palette[c].color;
+ defaultRGBLookup[color] = (byte)c;
+ }*/
+ /*
+ for(c = 0; c<32768; c++)
+ {
+ Color color = (Color)(Color555)c;
+ defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
+ // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
}
+ */
+ rgbLookupSet = true;
+ }
}
- *_x1 = x1;
- *_y1 = y1;
- *_x2 = x2;
- *_y2 = y2;
-}
+};
-#endif
+public class LFBSurface : struct
+{
+public:
+ // For compatibility with 3D drivers as well
+ Font font;
+ bool opaqueText;
+ int xOffset;
+ bool writingText;
+ bool writingOutline;
-#define MAX_FONT_LINK_ENTRIES 10
+ Bitmap bitmap;
-static HB_Script theCurrentScript;
+ // Drawing attributes
+ uint foreground, background;
+ ColorAlpha foregroundRgb;
+ uint16 stipple;
+ byte drawingChar;
+ byte * paletteShades;
+ bool clearing;
+};
-static unichar UTF16GetChar(const uint16 *string, int * nw)
+/*
+static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
{
- unichar ch;
- if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
- {
- ch = HB_SurrogateToUcs4(string[0], string[1]);
- *nw = 2;
- }
+ if(recordA->zMin > recordB->zMin)
+ return 1;
+ else if(recordA->zMin < recordB->zMin)
+ return -1;
+ else if(recordA > recordB)
+ return 1;
+ else if(recordA < recordB)
+ return -1;
else
- {
- ch = *string;
- *nw = 1;
- }
- return ch;
+ return 0;
}
+*/
-static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
+public class LFBDisplayDriver : DisplayDriver
{
- FT_Face face = ((FontEntry)font->userData).face;
- int glyph_pos = 0;
- int c, nw;
+ class_property(name) = "LFB";
- if (length > *numGlyphs)
- return 0;
+ bool CreateDisplaySystem(DisplaySystem displaySystem)
+ {
+ displaySystem.flags.memBackBuffer = true;
+ // displaySystem.pixelFormat = pixelFormat888;
+ return true;
+ }
- for (c = 0; c < length; c += nw)
+ void DestroyDisplaySystem(DisplaySystem displaySystem)
{
- unichar ch = UTF16GetChar(string + c, &nw);
- glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
}
- *numGlyphs = glyph_pos;
- return 1;
-}
-static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
-{
- FontEntry entry = font->userData;
- Font glFont = entry.font;
- int c;
- uint lastPack = 0;
- GlyphPack pack = glFont.asciiPack;
- int fontEntryNum;
- for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
+ void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
{
- if(glFont.fontEntries[fontEntryNum] == entry)
- break;
+ delete bitmap.picture;
+ if(bitmap.allocatePalette)
+ delete bitmap.palette;
}
- for(c = 0; c < numGlyphs; c++)
+ bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
{
- GlyphInfo * glyph;
- uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
- uint packNo = glyphNo & 0xFFFFFF80;
- if(packNo != lastPack)
+ bool result = false;
+ if(!stride)
{
- pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
- if(!pack)
+ switch(GetColorDepthShifts(format))
{
- glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
- pack.Render(glFont, fontEntryNum, glFont.displaySystem);
- pack.bitmap.alphaBlend = true;
+ case 0: stride = (width + 3) & 0xFFFFFFFC; break;
+ case 1: stride = (width + 1) & 0xFFFFFFFE; break;
+ case 2: stride = width; break;
}
- lastPack = packNo;
}
- glyph = &pack.glyphs[glyphNo & 0x7F];
- advances[c] = glyph->ax;
- }
-}
-
-static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
-{
- FT_Face face = ((FontEntry)font->userData).face;
- int c, nw;
-
- for (c = 0; c < length; c += nw)
- {
- unichar ch = UTF16GetChar(string + c, &nw);
- if(!FT_Get_Char_Index(face, ch))
- return 0;
- }
- return 1;
-}
-
-static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
-{
- FT_Face face = (FT_Face)font;
- FT_ULong ftlen = *length;
- FT_Error error = 0;
-
- if (!FT_IS_SFNT(face))
- return HB_Err_Invalid_Argument;
-
- error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
- *length = (uint)ftlen;
- return (HB_Error)error;
-}
-
-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)
-{
- HB_Error error = HB_Err_Ok;
- FT_Face face = (FT_Face)font->userData;
-
- int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
-
- if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
- return error;
-
- if (face->glyph->format != ft_glyph_format_outline)
- return (HB_Error)HB_Err_Invalid_SubTable;
-
- *nPoints = face->glyph->outline.n_points;
- if (!(*nPoints))
- return HB_Err_Ok;
-
- if (point > *nPoints)
- return (HB_Error)HB_Err_Invalid_SubTable;
-
- *xpos = (int)face->glyph->outline.points[point].x;
- *ypos = (int)face->glyph->outline.points[point].y;
-
- return HB_Err_Ok;
-}
-
-static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
-{
- FontEntry entry = font->userData;
- Font glFont = entry.font;
- uint lastPack = 0;
- GlyphPack pack = glFont.asciiPack;
- int fontEntryNum;
- for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
- {
- if(glFont.fontEntries[fontEntryNum] == entry)
- break;
- }
- {
- GlyphInfo * glyph;
- uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
- uint packNo = glyphNo & 0xFFFFFF80;
- if(packNo != lastPack)
+ bitmap.stride = stride;
+ bitmap.width = width;
+ bitmap.height = height;
+ bitmap.size = (uint32) stride * (uint32)height;
+ bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
+ bitmap.pixelFormat = format;
+ bitmap.transparent = false;
+ /*
+ surface.box.left = surface.box.top = 0;
+ surface.box.right = width - 1;
+ surface.box.bottom = height - 1;
+ */
+ bitmap.picture = new0 byte[bitmap.sizeBytes];
+ if(bitmap.picture)
{
- pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
- if(!pack)
+ bitmap.allocatePalette = allocatePalette;
+ if(allocatePalette)
{
- pack = { key = (uintptr)packNo };
- glFont.glyphPacks.Add(pack);
- pack.Render(glFont, fontEntryNum, glFont.displaySystem);
- pack.bitmap.alphaBlend = true;
+ bitmap.palette = new ColorAlpha[256];
+ if(bitmap.palette)
+ {
+ CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
+ result = true;
+ }
}
- lastPack = packNo;
- }
- glyph = &pack.glyphs[glyphNo & 0x7F];
-
- metrics->x = glyph->ax;
- metrics->y = 0;
- metrics->width = glyph->w;
- metrics->height = glyph->h;
- metrics->xOffset = glyph->bx;
- metrics->yOffset = glyph->by;
- }
-}
-
-static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
-{
- FontEntry entry = font->userData;
- FT_Face face = entry.face;
-
- // Note that we aren't scanning the VDMX table which we probably would in
- // an ideal world.
- if(metric == HB_FontAscent)
- return face->ascender;
- return 0;
-}
-
-static HB_FontClass hb_fontClass =
-{
- hb_stringToGlyphs, hb_getAdvances, hb_canRender,
- hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
-};
-
-static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
-{
- File f = stream->descriptor.pointer;
- f.Seek((int)offset, start);
- return count ? f.Read(buffer, 1, (uint)count) : 0;
-}
-
-static void FT_stream_close(FT_Stream stream)
-{
- File f = stream->descriptor.pointer;
- delete f;
- delete stream;
-}
-
-static FT_Library ftLibrary;
-static int numFonts;
-#undef CompareString
-static BinaryTree loadedFonts
-{
- CompareKey = (void *)BinaryTree::CompareString
-};
-
-class FontEntry : BTNode
-{
- FT_Face face;
- HB_FontRec hbFont;
- HB_Face hbFace;
-
- int used;
- byte * buffer;
-
- //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
- FT_Stream stream;
- Font font;
- float scale;
-
- ~FontEntry()
- {
- delete (char *)key;
- delete buffer;
- if(hbFace)
- HB_FreeFace(hbFace);
- if(face)
- {
- FT_Done_Face(face);
- numFonts--;
- if(!numFonts)
+ else
{
- FT_Done_FreeType(ftLibrary);
- ftLibrary = null;
+ bitmap.palette = GetDefaultPalette();
+ result = true;
}
}
+ if(!result)
+ FreeBitmap(displaySystem, bitmap);
+ return result;
}
-}
-static float FaceSetCharSize(FT_Face face, float size)
-{
- float scale = 1;
- if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
+ bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
{
- if(face->num_fixed_sizes)
+ bool result = false;
+ LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
+
+ if(src)
{
- int c;
- int bestDiff = MAXINT, best = 0;
- FT_Bitmap_Size * sizes = face->available_sizes;
- int wishedHeight = (int)(size * 96 / 72);
- for(c = 0; c < face->num_fixed_sizes; c++)
+ if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
{
- int diff = abs(sizes[c].height - wishedHeight);
- if(diff < bestDiff)
+ if(src.transparent && src.pixelFormat == pixelFormat888)
{
- best = c;
- bestDiff = diff;
+ /*
+ DWORD c;
+ DWORD * picture = (DWORD *)src.picture;
+
+ for(c = 0; c<src.size; c++, picture++)
+ {
+ if(*picture & 0xFFFFFF)
+ *picture = *picture | 0xFF000000;
+ else
+ *picture = *picture & 0xFFFFFF;
+ }
+ */
}
+ result = true;
}
- FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
-
- if(!face->ascender)
- face->ascender = sizes[best].height;
- scale = (float)wishedHeight / sizes[best].height;
- }
- }
- return scale;
-}
-
-#endif
-
-struct GlyphInfo
-{
- int ax, ay;
- int x, y;
- int w, h;
- int left, top;
- int bx, by;
- int glyphNo;
- float scale;
-};
-
-class GlyphPack : BTNode
-{
- GlyphInfo glyphs[256];
- Bitmap bitmap { };
- BinaryTree outlines { };
- int cellWidth, cellHeight;
-
- void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
- {
-#if !defined(ECERE_NOTRUETYPE)
- unichar c;
- int maxWidth, maxHeight;
- int cellWidth, cellHeight;
- int width, height;
- FontEntry fontEntry = null;
- FT_Face faces[128];
- float scales[128];
- bool isGlyph = ((uint)key & 0x80000000) != 0;
- //int curScript = ((uint)key & 0x7F000000) >> 24;
- unichar testChar = 0;
- /*
- if(isGlyph)
- {
- switch(curScript)
- {
- case HB_Script_Arabic:
- testChar = 0x621;
- // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
- break;
- case HB_Script_Devanagari:
- testChar = 0x905;
- break;
- case 60: testChar = 'あ'; break;
- case 61: testChar = 0x3400; break;
- }
- }
- */
- /*
- FT_GlyphSlot slot;
- FT_Matrix matrix;
- FT_Vector pen = { 0, 0 };
- if(font.fakeItalic)
- {
- matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
- matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
- matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
- matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
- FT_Set_Transform( fontEntry.face, &matrix, &pen );
- }
- FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
- */
-
- maxWidth = 0;
- maxHeight = 0;
-
- for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
- {
- fontEntry = font.fontEntries[c];
- if(fontEntry)
+ else
{
- FT_Matrix matrix;
- FT_Vector pen = { 0, 0 };
-
- if(font.fakeItalic)
- {
- matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
- matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
- matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
- matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
- FT_Set_Transform(fontEntry.face, &matrix, &pen);
- }
- //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
- fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
- if(!font.scale)
- font.scale = fontEntry.scale;
- if(!c)
+ Bitmap bitmap { };
+ if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
{
- if(!fontEntry.face->units_per_EM)
- font.ascent = (int)((double)fontEntry.face->ascender);
- else
- font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
- }
-
- fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
- fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
- fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
- fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
- }
- }
+ if(format == pixelFormat8)
+ {
+ if(palette)
+ bitmap.palette = palette;
+ else if(lfbSystem && lfbSystem.palette)
+ bitmap.palette = lfbSystem.palette;
+ else
+ bitmap.palette = src.palette;
+ }
- fontEntry = null;
- for(c = 0; c < 128; c++)
- {
- int entry = 0;
- if(isGlyph)
- {
- uint glyph = ((uint)key | c) & 0xFFFFFF;
- for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
- {
- fontEntry = font.fontEntries[entry];
- if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
+ if(converters_table[src.pixelFormat][bitmap.pixelFormat])
{
- if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
+ converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
+ bitmap.transparent = src.transparent;
+ bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
+ delete src.picture;
+ if(src.palette != bitmap.palette)
{
- //printf("%s: Accepted entry %d ", font.faceName, entry);
- break;
+ if(src.allocatePalette)
+ delete src.palette;
+ src.allocatePalette = false;
}
+ src.picture = bitmap.picture;
+ src.palette = bitmap.palette;
+ src.stride = bitmap.stride;
+ src.size = bitmap.size;
+ src.sizeBytes = bitmap.sizeBytes;
+ src.pixelFormat = bitmap.pixelFormat;
+
+ result = true;
}
+
+ bitmap.palette = null;
+ bitmap.picture = null;
}
+ delete bitmap;
}
- else
- {
- for(entry = startFontEntry; ; entry++)
- {
- uint glyph;
- fontEntry = font.fontEntries[entry];
- if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
- {
- if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
- break;
- }
- }
- }
- scales[c] = fontEntry.scale;
- faces[c] = fontEntry.face;
- maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
- maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
- //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
}
- this.cellWidth = cellWidth = maxWidth;
- this.cellHeight = cellHeight = maxHeight;
+ return result;
+ }
- width = maxWidth * 16;
- height = maxHeight * 8;
+ void DestroyDisplay(Display display)
+ {
+ LFBDisplay lfbDisplay = display.driverData;
+ delete lfbDisplay.bitmap.palette;
+ }
- if(true)
+ bool CreateDisplay(Display display)
+ {
+ bool result = false;
+ LFBDisplay lfbDisplay = display.driverData;
+ if(!lfbDisplay)
{
- width = pow2i(width);
- height = pow2i(height);
+ lfbDisplay = display.driverData = LFBDisplay { };
+ lfbDisplay.selfManaged = true;
+ lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
}
- if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
+ if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
{
- Bitmap bitmap = this.bitmap;
-
- bitmap.transparent = true;
-
- for(c = 0; c < 128; c++)
- {
- FT_Int i, j, p, q;
- FT_Int xMax, yMax;
- int sx = (c % 16) * cellWidth;
- int sy = (c / 16) * cellHeight;
- int x, y;
- byte * picture = (byte *)bitmap.picture;
- GlyphInfo * glyph = &glyphs[c];
- FT_GlyphSlot slot = faces[c]->glyph;
- double em_size = 1.0 * faces[c]->units_per_EM;
- //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
- double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
- double ascender = faces[c]->ascender * y_scale;
- int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
-
- 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
-
- FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
-
- x = sx;
- y = sy;
- //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
-
- glyph->left = slot->bitmap_left;
- // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
- // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
- //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
- //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
-
- //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
- //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
-
- //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
+ CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
+ result = true;
+ }
+ return result;
+ }
- //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));
- //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));
+ bool DisplaySize(Display display, int width, int height)
+ {
+ LFBDisplay lfbDisplay = display.driverData;
+ //display.width = width;
+ //display.height = height;
+ lfbDisplay.bitmap.width = width;
+ lfbDisplay.bitmap.height = height;
+ /*
+ lfbDisplay.updateBox.left = display.width;
+ lfbDisplay.updateBox.top = display.height;
+ lfbDisplay.updateBox.right = 0;
+ lfbDisplay.updateBox.bottom = 0;
+ */
- //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
- glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
+ if(lfbDisplay.selfManaged)
+ {
+ lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
+ lfbDisplay.bitmap.stride = width;
+ }
+ lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
+ return true;
+ }
- // 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);
- xMax = x + slot->bitmap.width;
- yMax = y + slot->bitmap.rows;
+ void DisplayPosition(Display display, int x, int y)
+ {
+ LFBDisplay lfbDisplay = display.driverData;
+ lfbDisplay.x = x;
+ lfbDisplay.y = y;
+ }
- {
- int total = 0;
- int numPixels = 0;
- //int max;
- if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
- {
- for(j = y, q = 0; j<yMax; j++)
- {
- for(p = 0, i = x; i<xMax; i++)
- {
- byte value = ((byte *)slot->bitmap.buffer)[q + p++];
- if(value > 32)
- {
- total += value;
- numPixels++;
- }
- }
- q += slot->bitmap.pitch;
- }
- }
- //max = numPixels ? (total / numPixels) : 1;
+ void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
+ {
+ LFBDisplay lfbDisplay = display.driverData;
+ if(colorMatch)
+ {
+ int c;
- for(j = y, q = 0; j<yMax; j++)
- {
- int bit = 0x80;
- for(p = 0, i = x; i<xMax; i++)
- {
- if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
- {
- picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
- bit >>= 1;
- if(!bit) { bit = 0x80; p++; }
- }
- else
- {
- byte value = ((byte *)slot->bitmap.buffer)[q + p++];
- picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
- }
- }
- q += slot->bitmap.pitch;
- }
- }
- glyph->x = sx;
- glyph->y = sy;
- glyph->w = slot->bitmap.width;
- glyph->h = slot->bitmap.rows;
- glyph->glyphNo = glyphNo;
- glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
- glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
- glyph->scale = scales[c];
-
- glyph->ax = (int)slot->advance.x;
- glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
- }
- #if 0
+ if(!palette)
{
- int c;
- char fileName[256];
- static int fid = 0;
- for(c = 0; c<256; c++)
- bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
- bitmap.pixelFormat = pixelFormat8;
-
- /*
- //strcpy(fileName, faceName);
- if(flags)
- strcat(fileName, "Bold");
- */
- sprintf(fileName, "font%d", fid++);
- ChangeExtension(fileName, "pcx", fileName);
-
- bitmap.Save(fileName, null, 0);
- bitmap.pixelFormat = pixelFormatAlpha;
+ LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
+ palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
+ CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
}
- #endif
+ else
+ for(c = 0; c<32768; c++)
+ lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
- if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
+ for(c=0; c<256; c++)
{
- bitmap.keepData = true; // For outlines
- displaySystem.Lock();
-#if defined(__WIN32__)
- // Is this check still required?
- if(displaySystem.driver == class(OpenGLDisplayDriver)
-
-#if !defined(_GLES) && !defined(ECERE_STATIC)
- || displaySystem.driver == class(Direct3D8DisplayDriver)
- || displaySystem.driver == class(Direct3D9DisplayDriver)
-#endif
-
- )
-#endif
- bitmap.MakeDD(displaySystem);
- displaySystem.Unlock();
+ int i;
+ for(i=0; i<LIGHTSTEPS; i++)
+ {
+ lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
+ (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
+ (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
+ (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
+ }
}
}
-#endif
+ if(lfbDisplay.bitmap.palette)
+ CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
}
- void RenderOutline(GlyphPack outline, Font font, DisplaySystem displaySystem)
+ void Update(Display display, Box updateBox)
{
-#if !defined(ECERE_NOTRUETYPE) && !defined(ECERE_VANILLA)
- unichar c;
- int pCellWidth = this.cellWidth, pCellHeight = this.cellHeight;
- int cellWidth, cellHeight;
- int width, height;
- uintptr key = outline.key;
- float outlineSize = (float)(key >> 16);
- float fade = ((uint32)key & 0xFFFF) / 255.f;
- GlyphInfo * widest = null, * highest = null;
- uint widestIndex = 0, highestIndex = 0;
- GlyphInfo * glyph;
- int minX1 = MAXINT, minY1 = MAXINT;
- int maxX2 = MININT, maxY2 = MININT;
- int timesBigger = 2;
- byte * bigger = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
- byte * field = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
- int ox, oy;
-
- // Test biggest glyphs to determine cell width & height:
- for(c = 0; c < 128; c++)
- {
- glyph = &glyphs[c];
- if(glyph->w > (widest ? widest->w : 0))
- widest = glyph, widestIndex = c;
- if(glyph->h > (highest ? highest->h : 0))
- highest = glyph, highestIndex = c;
- }
-
- cellWidth = 0;
- cellHeight = 0;
- for(glyph = widest; glyph; glyph = (glyph == widest && glyph != highest) ? highest : null)
- {
- int index = (glyph == widest) ? widestIndex : highestIndex;
- int x = (index & 0xF) * pCellWidth, y = (index >> 4) * pCellHeight;
- int w = pCellWidth * timesBigger, h = pCellHeight * timesBigger;
- int x1,y1,x2,y2;
-
- memset(bigger, 0, w * h);
- BlitOutline(bigger, (w - pCellWidth)/2, (h - pCellHeight)/2, w, h, bitmap.picture, x, y, pCellWidth, pCellHeight, bitmap.width);
- ComputeOutline(field, bigger, w, h, outlineSize, fade);
- MeasureOutline(field, w, h, &x1, &y1, &x2, &y2);
- minX1 = Min(minX1, x1);
- minY1 = Min(minY1, y1);
- maxX2 = Max(maxX2, x2);
- maxY2 = Max(maxY2, y2);
- }
- {
- int x1 = (timesBigger*pCellWidth - pCellWidth) / 2, x2 = x1 + pCellWidth-1;
- int y1 = (timesBigger*pCellHeight - pCellHeight) / 2, y2 = y1 + pCellHeight-1;
- ox = -Max(0, x1 - minX1);
- oy = -Max(0, y1 - minY1);
- cellWidth = pCellWidth - ox + Max(0, (maxX2 > x2) ? (maxX2 - x2) : 0);
- cellHeight = pCellHeight - oy + Max(0, (maxY2 > y2) ? (maxY2 - y2) : 0);
- }
-
- width = cellWidth * 16;
- height = cellHeight * 8;
- if(true) //TEXTURES_MUST_BE_POWER_OF_2)
- {
- width = pow2i(width);
- height = pow2i(height);
- }
-
- if(outline.bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false))
- {
- Bitmap bitmap = outline.bitmap;
- byte * picture = (byte *)bitmap.picture;
- memset(picture, 0, width * height);
-
- for(c = 0; c < 128; c++)
- {
- GlyphInfo * glyph = &outline.glyphs[c];
- int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
- int w = 0, h = 0;
- memset(bigger, 0, cellWidth * cellHeight);
- BlitOutline(bigger, -ox, -oy, cellWidth, cellHeight,
- this.bitmap.picture,
- (c & 0xF) * pCellWidth, (c >> 4) * pCellHeight,
- pCellWidth, pCellHeight,
- this.bitmap.width);
-
- // Don't waste time on empty glyphs
- if(glyphs[c].w)
- {
- ComputeOutline(field, bigger, cellWidth, cellHeight, outlineSize, fade);
- MeasureOutline(field, cellWidth, cellHeight, &x1, &y1, &x2, &y2);
- if(x2 > x1) w = x2-x1+1;
- if(y2 > y1) h = y2-y1+1;
- }
- else
- memset(field, 0, cellWidth * cellHeight);
-
- glyph->x = (c & 0xF) * cellWidth;
- glyph->y = (c >> 4) * cellHeight;
- BlitOutline(picture, glyph->x, glyph->y, width, height, field, 0, 0, cellWidth, cellHeight, cellWidth);
-
- glyph->glyphNo = glyphs[c].glyphNo;
- glyph->scale = glyphs[c].scale;
- glyph->left = glyphs[c].left + ox;
- glyph->top = glyphs[c].top + oy;
- if(w) { glyph->x += x1; glyph->left += x1; }
- if(h) { glyph->y += y1; glyph->top += y1; }
- glyph->w = w;
- glyph->h = h;
- glyph->bx = glyphs[c].bx;
- glyph->by = glyphs[c].by;
- glyph->ax = glyphs[c].ax;
- glyph->ay = glyphs[c].ay;
- }
-
- #if 0
+ LFBDisplay lfbDisplay = display.driverData;
+ if(lfbDisplay.displayCallback)
+ {
+ if(updateBox == null)
{
- int c;
- char fileName[256];
- static int fid = 0;
- for(c = 0; c<256; c++)
- outline.bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
- outline.bitmap.pixelFormat = pixelFormat8;
-
- /*
- //strcpy(fileName, faceName);
- if(flags)
- strcat(fileName, "Bold");
- */
- sprintf(fileName, "outline%d", fid++);
- ChangeExtension(fileName, "pcx", fileName);
-
- outline.bitmap.Save(fileName, null, 0);
- outline.bitmap.pixelFormat = pixelFormatAlpha;
+ Box box { 0,0, display.width,display.height };
+ lfbDisplay.displayCallback(display, box);
}
+ else
+ lfbDisplay.displayCallback(display, updateBox);
+ }
+ }
- /*{
- static int num = 0;
- char fileName[MAX_LOCATION];
-
- sprintf(fileName, "template%03d.png", num);
- bitmap.Save(fileName, null, 0);
- sprintf(fileName, "outline%03d.png", num++);
- outline.bitmap.Save(fileName, null, 0);
- }*/
- #endif
- if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
+ bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
+ {
+ if(bitmap.pixelFormat != pixelFormatAlpha)
+ {
+ if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
{
- displaySystem.Lock();
-#if defined(__WIN32__)
- // Is this check still required?
- if(displaySystem.driver == class(OpenGLDisplayDriver)
-
-#if !defined(_GLES) && !defined(ECERE_STATIC)
- || displaySystem.driver == class(Direct3D8DisplayDriver)
- || displaySystem.driver == class(Direct3D9DisplayDriver)
-#endif
- )
-#endif
- bitmap.MakeDD(displaySystem);
- displaySystem.Unlock();
+ FreeBitmap(displaySystem, bitmap);
+ return false;
}
}
- delete bigger;
- delete field;
-#endif
+ return true;
}
-}
-#if !defined(ECERE_NOTRUETYPE)
-static HB_ShaperItem shaper_item;
+ void ReleaseSurface(Display display, Surface surface)
+ {
+ LFBSurface lfbSurface = surface.driverData;
+ delete lfbSurface;
+ surface.driverData = null;
+ }
-static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
-{
- static uint maxGlyphs = 0;
- HB_Glyph * glyphs = shaper_item.glyphs;
-
- shaper_item.kerning_applied = 0;
- shaper_item.string = string;
- shaper_item.stringLength = len;
- shaper_item.item.script = script;
- shaper_item.item.pos = 0;
- shaper_item.item.length = shaper_item.stringLength;
- if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
- shaper_item.item.bidiLevel = 1;
- else
- shaper_item.item.bidiLevel = 0;
- shaper_item.shaperFlags = 0;
- shaper_item.font = &entry.hbFont;
- shaper_item.face = entry.hbFace;
- shaper_item.num_glyphs = shaper_item.item.length;
- shaper_item.glyphIndicesPresent = 0;
- shaper_item.initialGlyphCount = 0;
- shaper_item.num_glyphs = 0;
- shaper_item.glyphs = null;
-
- while(!HB_ShapeItem(&shaper_item))
+ bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
{
- if(shaper_item.num_glyphs > maxGlyphs)
- {
- maxGlyphs = shaper_item.num_glyphs;
- glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
- shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
- shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
- shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
- shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
- }
- else
+ LFBDisplay lfbDisplay = display.driverData;
+ LFBSurface lfbSurface = surface.driverData;
+ if(!lfbSurface)
{
- shaper_item.glyphs = glyphs;
- shaper_item.num_glyphs = maxGlyphs;
+ lfbSurface = surface.driverData = LFBSurface { };
}
- }
-
- *numGlyphs = shaper_item.num_glyphs;
- *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
- return shaper_item.glyphs;
-}
-/*
- delete shaper_item.glyphs;
- delete shaper_item.attributes;
- delete shaper_item.advances;
- delete shaper_item.offsets;
- delete shaper_item.log_clusters;
-*/
-#endif
+ lfbSurface.bitmap = lfbDisplay.bitmap;
-public class Font : struct
-{
- BinaryTree glyphPacks { };
- GlyphPack asciiPack { };
-#if !defined(ECERE_NOTRUETYPE)
- FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
-#endif
- float size;
- bool fakeItalic;
- int height;
- FontFlags flags;
- char faceName[512];
- DisplaySystem displaySystem;
- int ascent;
- float scale;
-
- ~Font()
- {
-#if !defined(ECERE_NOTRUETYPE)
- GlyphPack pack;
- while((pack = (GlyphPack)glyphPacks.root))
+ surface.offset.x = x;
+ surface.offset.y = y;
+ surface.box = clip;
+ if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
{
- glyphPacks.Remove(pack);
- delete pack;
+ surface.offset.x /= textCellW;
+ surface.offset.y /= textCellH;
+ surface.box.left /= textCellW;
+ surface.box.top /= textCellH;
+ surface.box.right /= textCellW;
+ surface.box.bottom /= textCellH;
}
-#endif
- }
- public property int ascent
- {
- get { return (int)(this ? ascent * scale : 0); }
- }
-};
-public class LFBDisplay : struct
-{
-public:
- Bitmap bitmap { };
- byte rgbLookup[32768];
- byte lightTable[256][LIGHTSTEPS];
- OldList updateBoxes;
- int x,y;
- bool selfManaged;
- void (* displayCallback)(Display display, Box updateBox);
-};
+ /*
+ lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
+ lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
+ lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
+ lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
+ */
-public class LFBSystem : struct
-{
-public:
- int format;
- ColorAlpha * palette;
- byte rgbLookup[32768];
+ surface.unclippedBox = surface.box;
+ lfbSurface.drawingChar = 219;
+ return true;
+ }
- LFBSystem()
+ bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
{
- if(!rgbLookupSet)
+ bool result = false;
+ LFBSurface lfbSurface = surface.driverData;
+ if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
{
- int c, r, g, b;
- ColorAlpha * palette = GetDefaultPalette();
- for(c = 16; c < 232; c++)
- {
- Color555 color = palette[c].color;
- for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
- for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
- for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
- defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
- }
- for(c = 232; c < 246; c++)
- {
- Color555 color = palette[c].color;
- defaultRGBLookup[color] = (byte)c;
- }
- /*
- for(c = 246; c < 256; c++)
- {
- Color555 color = palette[c].color;
- defaultRGBLookup[color] = (byte)c;
- }
- for(c = 0; c < 16; c++)
- {
- Color555 color = palette[c].color;
- defaultRGBLookup[color] = (byte)c;
- }*/
- /*
- for(c = 0; c<32768; c++)
+ lfbSurface.bitmap = bitmap;
+
+ surface.offset.x = x;
+ surface.offset.y = y;
+ surface.box = clip;
+ if(bitmap.pixelFormat == pixelFormatText)
{
- Color color = (Color)(Color555)c;
- defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
- // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
+ surface.offset.x /= textCellW;
+ surface.offset.y /= textCellH;
+ surface.box.left /= textCellW;
+ surface.box.top /= textCellH;
+ surface.box.right /= textCellW;
+ surface.box.bottom /= textCellH;
}
- */
- rgbLookupSet = true;
- }
- }
-};
-
-public class LFBSurface : struct
-{
-public:
- // For compatibility with 3D drivers as well
- Font font;
- bool opaqueText;
- int xOffset;
- bool writingText;
- bool writingOutline;
-
- Bitmap bitmap;
- // Drawing attributes
- uint foreground, background;
- ColorAlpha foregroundRgb;
- uint16 stipple;
- byte drawingChar;
- byte * paletteShades;
- bool clearing;
-};
-
-/*
-static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
-{
- if(recordA->zMin > recordB->zMin)
- return 1;
- else if(recordA->zMin < recordB->zMin)
- return -1;
- else if(recordA > recordB)
- return 1;
- else if(recordA < recordB)
- return -1;
- else
- return 0;
-}
-*/
+ surface.unclippedBox = *&surface.box;
+ lfbSurface.drawingChar = 219;
-#if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
-struct FontData
-{
- char fileName[MAX_FILENAME];
- FontFlags flags;
- bool forgive;
-};
+ result = true;
+ }
+ return result;
+ }
-static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
-{
- //if(fontType == TRUETYPE_FONTTYPE)
+ void Clip(Display display, Surface surface, Box clip)
{
- FontData * fontData = (FontData *) lParam;
- char * fileName = (char *)lParam;
- HKEY key;
- int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
- int italic = (fontData->flags.italic) ? 1 : 0;
- if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
- {
- if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
- !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
- {
- int value = 0;
- while(true)
- {
- char entryName[1024];
- char fontFileName[1024];
- DWORD type;
- DWORD size = 1024;
- DWORD sizeFileName = 1024;
- char * occurrence;
- if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
- break;
- if((occurrence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
- {
- int c;
- for(c = (int)(occurrence - entryName) - 1; c >= 0; c--)
- {
- char ch = entryName[c];
- if(ch == '&') { c = -1; break; }
- else if(ch != ' ') break;
- }
- if(c >= 0) continue;
- for(c = (int)(occurrence - entryName) + strlen((char *)font->elfFullName); ; c++)
- {
- char ch = entryName[c];
- if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
- else if(ch != ' ') break;
- }
-
- if(atoi(entryName + c))
- c = -1;
- if(c >= 0) continue;
+ LFBSurface lfbSurface = surface.driverData;
+ if(clip != null)
+ {
+ Box box = clip;
- strcpy(fileName, fontFileName);
- RegCloseKey(key);
- return 0;
- }
- }
- RegCloseKey(key);
- return 1;
+ if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
+ {
+ box.left /= textCellW;
+ box.top /= textCellH;
+ box.right /= textCellW;
+ box.bottom /= textCellH;
}
+ box.Clip(surface.unclippedBox);
+ surface.box = box;
}
+ else
+ surface.box = surface.unclippedBox;
}
- return 1;
-}
-#endif
-
-#if !defined(ECERE_NOTRUETYPE)
-static int utf16BufferSize = 0;
-static uint16 * utf16 = null;
-#endif
-
-public class LFBDisplayDriver : DisplayDriver
-{
- class_property(name) = "LFB";
- bool CreateDisplaySystem(DisplaySystem displaySystem)
+ void SetForeground(Display display, Surface surface, ColorAlpha color)
{
- displaySystem.flags.memBackBuffer = true;
- // displaySystem.pixelFormat = pixelFormat888;
- return true;
- }
+ LFBDisplay lfbDisplay = display ? display.driverData : null;
+ LFBSurface lfbSurface = surface.driverData;
+ uint index;
+ //if(display) color = color & 0xFFFFFF;
+ lfbSurface.foregroundRgb = color;
- void DestroyDisplaySystem(DisplaySystem displaySystem)
- {
+ if(lfbSurface.font && lfbDisplay)
+ {
+ index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
+ lfbSurface.paletteShades = lfbDisplay.lightTable[index];
+ }
+
+ switch(lfbSurface.bitmap.pixelFormat)
+ {
+ case pixelFormat8:
+ if(display)
+ lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
+ else
+ lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
+ break;
+ case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
+ case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
+ case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
+ case pixelFormat888: lfbSurface.foreground = color; break;
+ case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
+ case pixelFormatText:
+ if(display)
+ lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
+ else
+ lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
+ break;
+ }
}
- void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
+ void SetBackground(Display display, Surface surface, ColorAlpha color)
{
- delete bitmap.picture;
- if(bitmap.allocatePalette)
- delete bitmap.palette;
+ LFBDisplay lfbDisplay = display ? display.driverData : null;
+ LFBSurface lfbSurface = surface.driverData;
+ //color = color & 0xFFFFFF;
+ switch(lfbSurface.bitmap.pixelFormat)
+ {
+ case pixelFormat8:
+ if(display)
+ lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
+ else
+ lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
+ break;
+ case pixelFormat444: lfbSurface.background = (Color444)color; break;
+ case pixelFormat555: lfbSurface.background = (Color555)color; break;
+ case pixelFormat565: lfbSurface.background = (Color565)color; break;
+ case pixelFormat888: lfbSurface.background = color; break;
+ case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
+ case pixelFormatText:
+ if(display)
+ lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
+ else
+ lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
+ break;
+ }
}
- bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
+ ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
{
- bool result = false;
- if(!stride)
+ LFBSurface lfbSurface = surface.driverData;
+ if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
{
- switch(GetColorDepthShifts(format))
- {
- case 0: stride = (width + 3) & 0xFFFFFFFC; break;
- case 1: stride = (width + 1) & 0xFFFFFFFE; break;
- case 2: stride = width; break;
- }
+ x /= textCellW;
+ y /= textCellH;
}
- bitmap.stride = stride;
- bitmap.width = width;
- bitmap.height = height;
- bitmap.size = (uint32) stride * (uint32)height;
- bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
- bitmap.pixelFormat = format;
- bitmap.transparent = false;
- /*
- surface.box.left = surface.box.top = 0;
- surface.box.right = width - 1;
- surface.box.bottom = height - 1;
- */
- bitmap.picture = new0 byte[bitmap.sizeBytes];
- if(bitmap.picture)
+ if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
{
- bitmap.allocatePalette = allocatePalette;
- if(allocatePalette)
+ x += surface.offset.x;
+ y += surface.offset.y;
+ if(lfbSurface.bitmap.picture)
{
- bitmap.palette = new ColorAlpha[256];
- if(bitmap.palette)
+ switch(lfbSurface.bitmap.pixelFormat)
{
- CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
- result = true;
+ case pixelFormatText:
+ case pixelFormat8:
+ if(!lfbSurface.bitmap.palette) return 0;
+ return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
+ case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
+ case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
+ case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
+ case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
}
}
- else
- {
- bitmap.palette = GetDefaultPalette();
- result = true;
- }
}
- if(!result)
- FreeBitmap(displaySystem, bitmap);
- return result;
+ return 0;
}
- bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
+ void PutPixel(Display display, Surface surface,int x,int y)
{
- bool result = false;
- LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
-
- if(src)
+ LFBSurface lfbSurface = surface.driverData;
+ if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
{
- if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
- {
- if(src.transparent && src.pixelFormat == pixelFormat888)
- {
- /*
- DWORD c;
- DWORD * picture = (DWORD *)src.picture;
-
- for(c = 0; c<src.size; c++, picture++)
- {
- if(*picture & 0xFFFFFF)
- *picture = *picture | 0xFF000000;
- else
- *picture = *picture & 0xFFFFFF;
- }
- */
- }
- result = true;
- }
- else
+ x /= textCellW;
+ y /= textCellH;
+ }
+ if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
+ {
+ x += surface.offset.x;
+ y += surface.offset.y;
+ if(lfbSurface.bitmap.picture)
{
- Bitmap bitmap { };
- if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
{
- if(format == pixelFormat8)
- {
- if(palette)
- bitmap.palette = palette;
- else if(lfbSystem && lfbSystem.palette)
- bitmap.palette = lfbSystem.palette;
- else
- bitmap.palette = src.palette;
- }
-
- if(converters_table[src.pixelFormat][bitmap.pixelFormat])
- {
- converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
- bitmap.transparent = src.transparent;
- bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
- delete src.picture;
- if(src.palette != bitmap.palette)
- {
- if(src.allocatePalette)
- delete src.palette;
- src.allocatePalette = false;
- }
- src.picture = bitmap.picture;
- src.palette = bitmap.palette;
- src.stride = bitmap.stride;
- src.size = bitmap.size;
- src.sizeBytes = bitmap.sizeBytes;
- src.pixelFormat = bitmap.pixelFormat;
-
- result = true;
- }
-
- bitmap.palette = null;
- bitmap.picture = null;
+ case 0:
+ ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
+ break;
+ case 1:
+ ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
+ break;
+ case 2:
+ if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
+ ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
+ break;
}
- delete bitmap;
}
}
- return result;
- }
-
- void DestroyDisplay(Display display)
- {
- LFBDisplay lfbDisplay = display.driverData;
- delete lfbDisplay.bitmap.palette;
}
- bool CreateDisplay(Display display)
+ void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
{
- bool result = false;
- LFBDisplay lfbDisplay = display.driverData;
- if(!lfbDisplay)
- {
- lfbDisplay = display.driverData = LFBDisplay { };
- lfbDisplay.selfManaged = true;
- lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
- }
+ LFBSurface lfbSurface = surface.driverData;
- if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
+ int xd, yd;
+ int xu,yu;
+ int errorterm;
+ uint offset;
+ uint color = lfbSurface.foreground;
+ uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
+ bool invert = false;
+ if(!lfbSurface.bitmap.picture) return;
+ if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
{
- CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
- result = true;
+ x1 /= textCellW;
+ x2 /= textCellW;
+ y1 /= textCellH;
+ y2 /= textCellH;
+ if(surface.textOpacity)
+ color |= lfbSurface.background;
+ color |= lfbSurface.drawingChar;
}
- return result;
- }
-
- bool DisplaySize(Display display, int width, int height)
- {
- LFBDisplay lfbDisplay = display.driverData;
- //display.width = width;
- //display.height = height;
- lfbDisplay.bitmap.width = width;
- lfbDisplay.bitmap.height = height;
- /*
- lfbDisplay.updateBox.left = display.width;
- lfbDisplay.updateBox.top = display.height;
- lfbDisplay.updateBox.right = 0;
- lfbDisplay.updateBox.bottom = 0;
- */
-
- if(lfbDisplay.selfManaged)
+ if(y1 == y2)
{
- lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
- lfbDisplay.bitmap.stride = width;
- }
- lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
- return true;
- }
+ if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
- void DisplayPosition(Display display, int x, int y)
- {
- LFBDisplay lfbDisplay = display.driverData;
- lfbDisplay.x = x;
- lfbDisplay.y = y;
- }
+ if((y1>surface.box.bottom)||(y1<surface.box.top))return;
+ if((x1>surface.box.right)||(x2<surface.box.left))return;
+ if(x1<surface.box.left)x1=surface.box.left;
+ if(x2>surface.box.right)x2=surface.box.right;
- void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
- {
- LFBDisplay lfbDisplay = display.driverData;
- if(colorMatch)
- {
- int c;
+ if(x2 < x1) return;
- if(!palette)
+ offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
+ if(stipple != 0xFFFF)
{
- LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
- palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
- CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
+ int x;
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
+ {
+ case 0:
+ for(x=x1; x<=x2; x++, offset++)
+ {
+ if(stipple & 0x8000)
+ ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
+ if(invert)
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ else
+ stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
+ }
+ break;
+ case 1:
+ for(x=x1; x<=x2; x++, offset++)
+ {
+ if(stipple & 0x8000)
+ ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
+ if(invert)
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ else
+ stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
+ }
+ break;
+ case 2:
+ for(x=x1; x<=x2; x++, offset++)
+ {
+ if(stipple & 0x8000)
+ ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
+ if(invert)
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ else
+ stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
+ }
+ break;
+ }
}
else
- for(c = 0; c<32768; c++)
- lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
-
- for(c=0; c<256; c++)
{
- int i;
- for(i=0; i<LIGHTSTEPS; i++)
+ if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
{
- lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
- (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
- (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
- (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
+ {
+ case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
+ case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
+ case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
+ }
}
- }
- }
- if(lfbDisplay.bitmap.palette)
- CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
- }
-
- void Update(Display display, Box updateBox)
- {
- LFBDisplay lfbDisplay = display.driverData;
- if(lfbDisplay.displayCallback)
- {
- if(updateBox == null)
- {
- Box box { 0,0, display.width,display.height };
- lfbDisplay.displayCallback(display, box);
- }
- else
- lfbDisplay.displayCallback(display, updateBox);
- }
- }
-
- bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
- {
- if(bitmap.pixelFormat != pixelFormatAlpha)
- {
- if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
- {
- FreeBitmap(displaySystem, bitmap);
- return false;
- }
- }
- return true;
- }
-
- void ReleaseSurface(Display display, Surface surface)
- {
- LFBSurface lfbSurface = surface.driverData;
- delete lfbSurface;
- surface.driverData = null;
- }
-
- bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
- {
- LFBDisplay lfbDisplay = display.driverData;
- LFBSurface lfbSurface = surface.driverData;
- if(!lfbSurface)
- {
- lfbSurface = surface.driverData = LFBSurface { };
- }
-
- lfbSurface.bitmap = lfbDisplay.bitmap;
-
- surface.offset.x = x;
- surface.offset.y = y;
- surface.box = clip;
- if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
- {
- surface.offset.x /= textCellW;
- surface.offset.y /= textCellH;
- surface.box.left /= textCellW;
- surface.box.top /= textCellH;
- surface.box.right /= textCellW;
- surface.box.bottom /= textCellH;
- }
-
- /*
- lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
- lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
- lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
- lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
- */
-
- surface.unclippedBox = surface.box;
- lfbSurface.drawingChar = 219;
- return true;
- }
-
- bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
- {
- bool result = false;
- LFBSurface lfbSurface = surface.driverData;
- if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
- {
- lfbSurface.bitmap = bitmap;
-
- surface.offset.x = x;
- surface.offset.y = y;
- surface.box = clip;
- if(bitmap.pixelFormat == pixelFormatText)
- {
- surface.offset.x /= textCellW;
- surface.offset.y /= textCellH;
- surface.box.left /= textCellW;
- surface.box.top /= textCellH;
- surface.box.right /= textCellW;
- surface.box.bottom /= textCellH;
- }
-
- surface.unclippedBox = *&surface.box;
- lfbSurface.drawingChar = 219;
-
- result = true;
- }
- return result;
- }
-
- void Clip(Display display, Surface surface, Box clip)
- {
- LFBSurface lfbSurface = surface.driverData;
- if(clip != null)
- {
- Box box = clip;
-
- if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
- {
- box.left /= textCellW;
- box.top /= textCellH;
- box.right /= textCellW;
- box.bottom /= textCellH;
- }
- box.Clip(surface.unclippedBox);
- surface.box = box;
- }
- else
- surface.box = surface.unclippedBox;
- }
-
- void SetForeground(Display display, Surface surface, ColorAlpha color)
- {
- LFBDisplay lfbDisplay = display ? display.driverData : null;
- LFBSurface lfbSurface = surface.driverData;
- uint index;
- //if(display) color = color & 0xFFFFFF;
- lfbSurface.foregroundRgb = color;
-
- if(lfbSurface.font && lfbDisplay)
- {
- index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
- lfbSurface.paletteShades = lfbDisplay.lightTable[index];
- }
-
- switch(lfbSurface.bitmap.pixelFormat)
- {
- case pixelFormat8:
- if(display)
- lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
- else
- lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
- break;
- case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
- case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
- case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
- case pixelFormat888: lfbSurface.foreground = color; break;
- case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
- case pixelFormatText:
- if(display)
- lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
- else
- lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
- break;
- }
- }
-
- void SetBackground(Display display, Surface surface, ColorAlpha color)
- {
- LFBDisplay lfbDisplay = display ? display.driverData : null;
- LFBSurface lfbSurface = surface.driverData;
- //color = color & 0xFFFFFF;
- switch(lfbSurface.bitmap.pixelFormat)
- {
- case pixelFormat8:
- if(display)
- lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
- else
- lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
- break;
- case pixelFormat444: lfbSurface.background = (Color444)color; break;
- case pixelFormat555: lfbSurface.background = (Color555)color; break;
- case pixelFormat565: lfbSurface.background = (Color565)color; break;
- case pixelFormat888: lfbSurface.background = color; break;
- case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
- case pixelFormatText:
- if(display)
- lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
- else
- lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
- break;
- }
- }
-
- ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
- {
- LFBSurface lfbSurface = surface.driverData;
- if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
- {
- x /= textCellW;
- y /= textCellH;
- }
- if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
- {
- x += surface.offset.x;
- y += surface.offset.y;
- if(lfbSurface.bitmap.picture)
- {
- switch(lfbSurface.bitmap.pixelFormat)
- {
- case pixelFormatText:
- case pixelFormat8:
- if(!lfbSurface.bitmap.palette) return 0;
- return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
- case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
- case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
- case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
- case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
- }
- }
- }
- return 0;
- }
-
- void PutPixel(Display display, Surface surface,int x,int y)
- {
- LFBSurface lfbSurface = surface.driverData;
- if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
- {
- x /= textCellW;
- y /= textCellH;
- }
- if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
- {
- x += surface.offset.x;
- y += surface.offset.y;
- if(lfbSurface.bitmap.picture)
- {
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0:
- ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
- break;
- case 1:
- ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
- break;
- case 2:
- if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
- ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
- break;
- }
- }
- }
- }
-
- void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
- {
- LFBSurface lfbSurface = surface.driverData;
-
- int xd, yd;
- int xu,yu;
- int errorterm;
- uint offset;
- uint color = lfbSurface.foreground;
- uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
- bool invert = false;
- if(!lfbSurface.bitmap.picture) return;
- if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
- {
- x1 /= textCellW;
- x2 /= textCellW;
- y1 /= textCellH;
- y2 /= textCellH;
- if(surface.textOpacity)
- color |= lfbSurface.background;
- color |= lfbSurface.drawingChar;
- }
- if(y1 == y2)
- {
- if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
-
- if((y1>surface.box.bottom)||(y1<surface.box.top))return;
- if((x1>surface.box.right)||(x2<surface.box.left))return;
- if(x1<surface.box.left)x1=surface.box.left;
- if(x2>surface.box.right)x2=surface.box.right;
-
- if(x2 < x1) return;
-
- offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
- if(stipple != 0xFFFF)
- {
- int x;
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0:
- for(x=x1; x<=x2; x++, offset++)
- {
- if(stipple & 0x8000)
- ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
- if(invert)
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- else
- stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
- }
- break;
- case 1:
- for(x=x1; x<=x2; x++, offset++)
- {
- if(stipple & 0x8000)
- ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
- if(invert)
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- else
- stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
- }
- break;
- case 2:
- for(x=x1; x<=x2; x++, offset++)
- {
- if(stipple & 0x8000)
- ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
- if(invert)
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- else
- stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
- }
- break;
- }
- }
- else
- {
- if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
- {
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
- case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
- case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
- }
- }
- else
- {
- int x;
- for(x = x1; x <= x2; x++, offset++)
- {
- ((uint16 *)lfbSurface.bitmap.picture)[offset] =
- (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
- }
- }
- }
- }
- else if(x1 == x2)
- {
- int y;
-
- if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
-
- if((x1>surface.box.right)||(x1<surface.box.left))return;
- if((y1>surface.box.bottom)||(y2<surface.box.top))return;
- if(y1<surface.box.top)y1=surface.box.top;
- if(y2>surface.box.bottom)y2=surface.box.bottom;
-
- offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0:
- for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
- {
- if(stipple & 0x8000)
- ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
- if(invert)
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- else
- stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
- }
- break;
- case 1:
- for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
- {
- if(stipple & 0x8000)
- {
- if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
- ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
- else
- {
- ((uint16 *)lfbSurface.bitmap.picture)[offset] =
- (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
- }
- }
- if(invert)
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- else
- stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
- }
- break;
- case 2:
- if(stipple != 0xFFFF)
- {
- for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
- {
- if(stipple & 0x8000)
- ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
- if(invert)
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- else
- stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
- }
- }
- else
- {
- for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
- ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
- }
- break;
- }
- }
- else
- {
- if(x2 >= x1)
- {
- if(x1 < surface.box.left)
- {
- if(x2 < surface.box.left)
- return;
- y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
- x1 = surface.box.left;
- }
- if(x2 > surface.box.right)
- {
- if(x1 > surface.box.right)
- return;
- y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
- x2 = surface.box.right;
- }
- if(y2 >= y1)
- {
- if(y1 < surface.box.top)
- {
- if(y2 < surface.box.top)
- return;
- x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
- y1 = surface.box.top;
- }
- if(y2 > surface.box.bottom)
- {
- if(y1 > surface.box.bottom)
- return;
- x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
- y2 = surface.box.bottom;
- }
- }
- else
- {
- if(y1 > surface.box.bottom)
- {
- if(y2 > surface.box.bottom)
- return;
- x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
- y1 = surface.box.bottom;
- }
- if(y2 < surface.box.top)
- {
- if(y1 < surface.box.top)
- return;
- x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
- y2 = surface.box.top;
- }
- }
- }
- else
- {
- if(x1 > surface.box.right)
- {
- if(x2 > surface.box.right)
- return;
- y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
- x1 = surface.box.right;
- }
- if(x2 < surface.box.left)
- {
- if(x1 < surface.box.left)
- return;
- y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
- x2 = surface.box.left;
- }
- if(y2 >= y1)
- {
- if(y1 < surface.box.top)
- {
- if(y2 < surface.box.top)
- return;
- x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
- y1 = surface.box.top;
- }
- if(y2 > surface.box.bottom)
- {
- if(y1 > surface.box.bottom)
- return;
- x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
- y2 = surface.box.bottom;
- }
- }
- else
- {
- if(y1 > surface.box.bottom)
- {
- if(y2 > surface.box.bottom)
- return;
- x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
- y1 = surface.box.bottom;
- }
- if(y2 < surface.box.top)
- {
- if(y1 < surface.box.top)
- return;
- x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
- y2 = surface.box.top;
- }
- }
- }
-
- xd=x2-x1;
- yd=y2-y1;
-
- if(xd<0)
- {
- xd=-xd;
- xu=-1;
- }
- else
- xu=1;
- if(yd<0)
- {
- yd=-yd;
- yu=-(int)lfbSurface.bitmap.stride;
- }
- else
- yu=lfbSurface.bitmap.stride;
-
- offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
- errorterm=0;
-
- if(xd>yd)
- {
- int i, length=xd;
- for(i=0; i<=length; i++)
- {
- if(stipple & 0x8000)
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
- case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
- case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
- }
- offset+=xu;
- errorterm+=yd;
- if(errorterm>=xd)
- {
- errorterm-=xd;
- offset+=yu;
- }
- stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
- }
- }
- else
- {
- int i, length=yd;
- for(i=0; i<=length; i++)
- {
- if(stipple & 0x8000)
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
- case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
- case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
- }
- offset+=yu;
- errorterm+=xd;
- if(errorterm>=yd)
- {
- errorterm-=yd;
- offset+=xu;
- }
- }
- }
- }
- }
-
- void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
- {
- DrawLine(display, surface,x1,y1,x2,y1);
- DrawLine(display, surface,x2,y1,x2,y2);
- DrawLine(display, surface,x2,y2,x1,y2);
- DrawLine(display, surface,x1,y2,x1,y1);
- }
-
- #if !defined(__GNUC__)
- /*
- void memset_32_aligned(void *buf, int val, int dwords)
- {
- // Qword align
- if ((int)(buf) & 4)
- {
- *((uint32 *)(buf)) = val;
- buf = ((uint32 *)(buf))+1;
- dwords--;
- }
-
- if (dwords > 1)
- {
- __asm {
- cld
- mov edi, buf
- mov ecx, dwords
- shr ecx, 1
- mov eax, val
- movd mm0, eax
- movd mm1, eax
- psllq mm1, 32
- por mm0, mm1
- align 16
- repeat:
- movq [edi], mm0
- add edi, 8
- loop repeat
- emms
- };
- }
-
- // Final dword
- if (dwords & 1) *((int*)(buf)) = val;
- }*/
-
- //#define USE_SSE
-
-/*
- void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
- {
- dwords <<= 2;
- #ifdef USE_SSE
- if(((uint32)buf) & 0x7F)
- {
- for( ; ((uint32)buf) & 0x7F && dwords; buf++)
- {
- *buf = val;
- dwords--;
- }
- }
- if(dwords)
- #endif
- __asm
- {
- mov edi, buf
- mov eax, val
- mov ecx, dwords
-
- mov edx,ecx
- #ifdef USE_SSE
- shr ecx,7
- #else
- shr ecx,6
- #endif
- mov ebx,ecx
- #ifdef USE_SSE
- shl ebx,7
- #else
- shl ebx,6
- #endif
- sub edx,ebx ; edx holds # of overflow bytes
-
- #ifdef USE_SSE
- mov [edi],eax
- mov [edi+4],eax
- mov [edi+8],eax
- mov [edi+12],eax
- movdqa xmm0, [edi]
- #else
- mov [edi],eax
- mov [edi+4],eax
- movq mm0, [edi]
- #endif
- cmp ecx,0
- je doneloop
- setloop:
-
- #ifdef USE_SSE
- movdqa [edi],xmm0
- movdqa [edi+16],xmm0
- movdqa [edi+32],xmm0
- movdqa [edi+48],xmm0
- movdqa [edi+64],xmm0
- movdqa [edi+80],xmm0
- movdqa [edi+96],xmm0
- movdqa [edi+112],xmm0
- add edi,8*16
- #else
- movq [edi],mm0
- movq [edi+8],mm0
- movq [edi+16],mm0
- movq [edi+24],mm0
- movq [edi+32],mm0
- movq [edi+40],mm0
- movq [edi+48],mm0
- movq [edi+56],mm0
- add edi,8*8
- #endif
- dec ecx
- jnz setloop
-
- doneloop:
- mov ecx,edx
- shr ecx,2
- rep stosd
-
- emms
- };
- }
- void memset_32(void *buf, uint32 val, uint32 dwords)
- {
- int align = 0;
- if ((uint32)(buf) & 3)
- {
- align = 4;
- dwords--;
-
- if (((uint32)(buf) & 1))
- {
- *(byte *)(buf) = (byte)(val&0xFF);
- buf = ((byte *)(buf))+1;
- val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
- align --;
- }
- if (((uint32)(buf) & 2))
- {
- *(uint16 *)(buf) = (uint16)(val&0xFFFF);
- buf = ((uint16 *)(buf))+1;
- val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
- align-=2;
- }
- }
- memset_32_aligned(buf,val,dwords);
- if (align)
- {
- if (align == 1)
- {
- *(byte *)(buf) = (byte)(val&0xFF);
- }
- else
- {
- *(uint16 *)(buf) = (uint16)(val&0xFFFF);
- if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
- }
- }
- }
- */
- #endif
-
- void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
- {
- LFBSurface lfbSurface = surface.driverData;
- uint32 color = lfbSurface.background;
-
- if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
- {
- color |= lfbSurface.foreground | lfbSurface.drawingChar;
- x1 /= textCellW;
- x2 /= textCellW;
- y1 /= textCellH;
- y2 /= textCellH;
- }
- if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
-
- if(x1<surface.box.left) x1=surface.box.left;
- if(x2>surface.box.right) x2=surface.box.right;
- if(y1<surface.box.top) y1=surface.box.top;
- if(y2>surface.box.bottom) y2=surface.box.bottom;
-
- if(x2>=x1 && y2>=y1)
- {
- int w,y;
- byte * theOffset;
-
- w = x2-x1+1;
- if(w<1) return;
-
- x1 += surface.offset.x;
- x2 += surface.offset.x;
- y1 += surface.offset.y;
- y2 += surface.offset.y;
- if(lfbSurface.bitmap.picture)
- {
- if(!surface.writeColor)
- {
- ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
- for(y = y1; y<= y2; y++)
- {
- int c;
- for(c = 0; c < w; c++, picture++)
- if(!picture->a)
- picture->a = (byte)((color & 0xFF000000) >> 24);
- picture += lfbSurface.bitmap.stride - w;
- }
- }
- else
- {
- if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
- {
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0:
- theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
- for(y = y1; y<= y2; y++)
- {
- FillBytes(theOffset,(byte)color,w);
- theOffset += lfbSurface.bitmap.stride;
- }
- break;
- case 1:
- theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
- for(y = y1; y<= y2; y++)
- {
- FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
- theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
- }
- break;
- case 2:
- theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
- for(y = y1; y<= y2; y++)
- {
- #if defined(__GNUC__)
- FillBytesBy4((uint32 *) theOffset,color,w);
- #else
- memset_32((uint32 *) theOffset,color,w);
- #endif
- theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
-
- }
- /*
- y = y2-y1+1;
- {
- int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
- //memset_32((uint32 *) theOffset,color,w);
- /-*_asm
- {
- push edi
- push ecx
- push eax
- push ebx
- push edx
-
- mov ebx,bla
-
- mov edi,theOffset
- mov eax,color
- mov edx,y
- mov ecx,w
-
- start:
- push ecx
-
- rep stosd
- add edi,ebx
- pop ecx
- dec edx
- jnz start
- pop edx
- pop ebx
- pop eax
- pop ecx
- pop edi
- };
- break;
- }*/
- }
- }
- else
- {
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
- {
- case 0:
- theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
- for(y = y1; y<= y2; y++)
- {
- // TODO: IMPLEMENT THIS
- FillBytes(theOffset,(byte)color,w);
- theOffset += lfbSurface.bitmap.stride;
- }
- break;
- case 1:
- {
- uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
- ColorAlpha c = surface.background;
- int a = c.a;
- int cr = c.color.r;
- int cg = c.color.g;
- int cb = c.color.b;
- PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
-
- for(y = y1; y <= y2; y++)
- {
- int c;
- for(c = 0; c < w; c++, dest++)
- {
- Color destColor = 0;
- if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
- else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
- else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
- {
- int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
- int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
- int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
-
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
-
- destColor = { (byte)r, (byte)g, (byte)b };
-
- if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
- else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
- else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
- }
- }
- dest += (lfbSurface.bitmap.stride - w);
- }
- break;
- }
- case 2:
- {
- ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
- AlphaWriteMode alphaWrite = surface.alphaWrite;
- ColorAlpha c = surface.background;
- int a = c.a;
- int cr = c.color.r;
- int cg = c.color.g;
- int cb = c.color.b;
- for(y = y1; y <= y2; y++)
- {
- int c;
- for(c = 0; c < w; c++, dest++)
- {
- int dr = dest->color.r;
- int dg = dest->color.g;
- int db = dest->color.b;
- int r = a * cr / 255 + ((255 - a) * dr / 255);
- int g = a * cg / 255 + ((255 - a) * dg / 255);
- int b = a * cb / 255 + ((255 - a) * db / 255);
-
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
- dest->color = { (byte)r, (byte)g, (byte)b };
-
- if(alphaWrite == blend)
- {
- int ca = (int)(a + ((255 - a) * dest->a / 255));
- if(ca > 255) ca = 255;
- dest->a = (byte)ca;
- }
- else if(alphaWrite)
- dest->a = (byte)a;
- }
- dest += (lfbSurface.bitmap.stride - w);
- }
- }
- }
- }
- }
- }
- }
- }
- void Clear(Display display, Surface surface, ClearType type)
- {
- LFBSurface lfbSurface = surface.driverData;
-
- lfbSurface.clearing = true;
- if(surface.offset.x == 0 && surface.offset.y == 0 &&
- surface.box.left == 0 && surface.box.top == 0 &&
- surface.box.right == surface.width-1 &&
- surface.box.bottom == surface.height-1)
- {
- uint32 color = /*0xFF000000 | */lfbSurface.background;
- if(type != depthBuffer)
- {
- if(lfbSurface.bitmap.stride != surface.width)
- Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
else
{
- switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
+ int x;
+ for(x = x1; x <= x2; x++, offset++)
{
- case 0:
- FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
- break;
- case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
- case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
+ ((uint16 *)lfbSurface.bitmap.picture)[offset] =
+ (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
}
}
}
- /*
- if((flags & CLEAR_Z) && zbuffer)
- FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
- */
}
- else
+ else if(x1 == x2)
{
- if(type != depthBuffer)
- Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
- /*
- if((flags & CLEAR_Z))
- {
- int y;
- uint32 w = surface.box.right-surface.box.left+1;
- float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
- + surface.box.left+surface.offset.x;
- for(y = surface.box.top; y<= surface.box.bottom; y++)
- {
- FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
- offset += DISPLAY.Width;
- }
- }
- */
- }
- lfbSurface.clearing = false;
- }
-
- void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
- {
- LFBSurface lfbSurface = surface.driverData;
- bool flip = false;
-
- if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
-
- if(w < 0) { w = -w; flip = true; }
+ int y;
- //Clip against the edges of the source
- if(sx<0)
- {
- dx+=-sx;
- w-=-sx;
- sx=0;
- }
- if(sy<0)
- {
- dy+=0-sy;
- h-=0-sy;
- sy=0;
- }
- if(sx+w>src.width-1)
- w-=sx+w-(src.width-1)-1;
- if(sy+h>src.height-1)
- h-=sy+h-(src.height-1)-1;
- //Clip against the edges of the destination
- if(dx<surface.box.left)
- {
- if(!flip) sx+=surface.box.left-dx;
- w-=surface.box.left-dx;
- dx=surface.box.left;
- }
- if(dy<surface.box.top)
- {
- sy+=surface.box.top-dy;
- h-=surface.box.top-dy;
- dy=surface.box.top;
- }
- if((dx+w)>surface.box.right)
- {
- if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
- w-=((uint32)(dx+w)-surface.box.right-1);
- }
- if((dy+h)>surface.box.bottom)
- h-=((dy+h)-surface.box.bottom-1);
- if((w<=0)||(h<=0))
- return;
+ if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
- dx += surface.offset.x;
- dy += surface.offset.y;
+ if((x1>surface.box.right)||(x1<surface.box.left))return;
+ if((y1>surface.box.bottom)||(y2<surface.box.top))return;
+ if(y1<surface.box.top)y1=surface.box.top;
+ if(y2>surface.box.bottom)y2=surface.box.bottom;
- if(lfbSurface.bitmap.picture)
- {
- AlphaWriteMode alphaWrite = surface.alphaWrite;
- if(src.alphaBlend && surface.blend)
- {
- int x, y;
- if(src.pixelFormat == pixelFormatAlpha)
- {
- if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
+ offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
+ {
+ case 0:
+ for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
{
- ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
- byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
- ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
- for(y = 0; y < h; y++)
- {
- for(x = 0; x < w; x++, picture++, source++)
- {
- int a = *source * color.a;
- ColorAlpha dest = *picture;
- int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
- int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
- int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
- picture->color = { (byte)r, (byte)g, (byte)b };
- if(alphaWrite == blend)
- {
- int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
- if(ca > 255) ca = 255;
- picture->a = (byte)ca;
- }
- else if(alphaWrite)
- picture->a = (byte)(a / 255);
- }
- picture += lfbSurface.bitmap.stride - w;
- source += src.stride - w;
- }
+ if(stipple & 0x8000)
+ ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
+ if(invert)
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ else
+ stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
}
- else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
+ break;
+ case 1:
+ for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
{
- Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
- byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
- ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
- for(y = 0; y < h; y++)
+ if(stipple & 0x8000)
{
- for(x = 0; x < w; x++, picture++, source++)
+ if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
+ ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
+ else
{
- int a = *source * color.a;
- Color dest = *picture;
- int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
- int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
- int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
- *picture = Color { (byte)r, (byte)g, (byte)b };
+ ((uint16 *)lfbSurface.bitmap.picture)[offset] =
+ (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
}
- picture += lfbSurface.bitmap.stride - w;
- source += src.stride - w;
}
+ if(invert)
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ else
+ stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
}
- else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
+ break;
+ case 2:
+ if(stipple != 0xFFFF)
{
- Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
- byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
- ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
- for(y = 0; y < h; y++)
+ for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
{
- for(x = 0; x < w; x++, picture++, source++)
- {
- int a = *source * color.a;
- Color dest = *picture;
- int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
- int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
- int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
- *picture = Color { (byte)r, (byte)g, (byte)b };
- }
- picture += lfbSurface.bitmap.stride - w;
- source += src.stride - w;
+ if(stipple & 0x8000)
+ ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
+ if(invert)
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ else
+ stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
}
}
+ else
+ {
+ for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
+ ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if(x2 >= x1)
+ {
+ if(x1 < surface.box.left)
+ {
+ if(x2 < surface.box.left)
+ return;
+ y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
+ x1 = surface.box.left;
+ }
+ if(x2 > surface.box.right)
+ {
+ if(x1 > surface.box.right)
+ return;
+ y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
+ x2 = surface.box.right;
+ }
+ if(y2 >= y1)
+ {
+ if(y1 < surface.box.top)
+ {
+ if(y2 < surface.box.top)
+ return;
+ x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
+ y1 = surface.box.top;
+ }
+ if(y2 > surface.box.bottom)
+ {
+ if(y1 > surface.box.bottom)
+ return;
+ x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
+ y2 = surface.box.bottom;
+ }
}
else
{
- ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
- if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
+ if(y1 > surface.box.bottom)
{
- ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
- for(y = 0; y < h; y++)
- {
- for(x = 0; x < w; x++, picture++, source++)
- {
- ColorAlpha src = *source;
- ColorAlpha dest = *picture;
- int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
- int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
- int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
- picture->color = { (byte)r, (byte)g, (byte)b };
- if(alphaWrite == blend)
- {
- int a = src.a + ((255 - src.a) * dest.a / 255);
- if(a > 255) a = 255;
- picture->a = (byte)a;
- }
- else if(alphaWrite)
- picture->a = src.a;
- }
- picture += lfbSurface.bitmap.stride - w;
- source += src.stride - w;
- }
+ if(y2 > surface.box.bottom)
+ return;
+ x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
+ y1 = surface.box.bottom;
}
- else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
+ if(y2 < surface.box.top)
{
- Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
- for(y = 0; y < h; y++)
- {
- for(x = 0; x < w; x++, picture++, source++)
- {
- ColorAlpha src = *source;
- Color565 dest = *picture;
- int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
- int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
- int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
- if(r > 255 * 31) r = 255 * 31;
- if(g > 255 * 63) g = 255 * 63;
- if(b > 255 * 31) b = 255 * 31;
- *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
- }
- picture += lfbSurface.bitmap.stride - w;
- source += src.stride - w;
- }
+ if(y1 < surface.box.top)
+ return;
+ x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
+ y2 = surface.box.top;
}
- else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
+ }
+ }
+ else
+ {
+ if(x1 > surface.box.right)
+ {
+ if(x2 > surface.box.right)
+ return;
+ y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
+ x1 = surface.box.right;
+ }
+ if(x2 < surface.box.left)
+ {
+ if(x1 < surface.box.left)
+ return;
+ y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
+ x2 = surface.box.left;
+ }
+ if(y2 >= y1)
+ {
+ if(y1 < surface.box.top)
{
- Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
- for(y = 0; y < h; y++)
- {
- for(x = 0; x < w; x++, picture++, source++)
- {
- ColorAlpha psrc = *source;
- Color555 dest = *picture;
- int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
- int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
- int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
- if(r > 255 * 31) r = 255 * 31;
- if(g > 255 * 31) g = 255 * 31;
- if(b > 255 * 31) b = 255 * 31;
- *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
- }
- picture += lfbSurface.bitmap.stride - w;
- source += src.stride - w;
- }
+ if(y2 < surface.box.top)
+ return;
+ x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
+ y1 = surface.box.top;
+ }
+ if(y2 > surface.box.bottom)
+ {
+ if(y1 > surface.box.bottom)
+ return;
+ x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
+ y2 = surface.box.bottom;
+ }
+ }
+ else
+ {
+ if(y1 > surface.box.bottom)
+ {
+ if(y2 > surface.box.bottom)
+ return;
+ x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
+ y1 = surface.box.bottom;
+ }
+ if(y2 < surface.box.top)
+ {
+ if(y1 < surface.box.top)
+ return;
+ x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
+ y2 = surface.box.top;
}
}
}
- else if(src.paletteShades)
- shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
- else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
- blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
- else if(src.pixelFormat == pixelFormat8)
- blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
- }
- }
- bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
- {
- bool result = false;
- LFBDisplay lfbDisplay = display.driverData;
+ xd=x2-x1;
+ yd=y2-y1;
- if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
- {
- bitmap.Free();
- bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
- (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
- }
- if(bitmap)
- {
- Surface surface = bitmap.GetSurface(0,0,null);
- if(surface)
+ if(xd<0)
{
- Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
- if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
- CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
- delete surface;
+ xd=-xd;
+ xu=-1;
}
- result = true;
- }
- return result;
- }
-
- void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
- {
- LFBSurface lfbSurface = surface.driverData;
- bool flip = false;
-
- float s2dw,s2dh,d2sw,d2sh;
-
- if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
-
- if(Sgn(w) != Sgn(sw))
- {
- w = Abs(w);
- sw = Abs(sw);
- flip = true;
- }
-
- s2dw=(float)w / sw;
- s2dh=(float)h / sh;
- d2sw=(float)sw / w;
- d2sh=(float)sh / h;
-
- //Clip against the edges of the source
- if(sx<0)
- {
- dx+=(int)((0-sx) * s2dw);
- w-=(int)((0-sx) * s2dw);
- sw-=0-sx;
- sx=0;
- }
- if(sy<0)
- {
- dy+=(int)((0-sy) * s2dh);
- h-=(int)((0-sy) * s2dh);
-
- sh-=0-sy;
- sy=0;
- }
- if(sx+sw>src.width-1)
- {
- w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
- sw-=sx+sw-(src.width-1)-1;
- }
- if(sy+sh>(src.height-1))
- {
- h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
- sh-=sy+sh-(src.height-1)-1;
- }
- //Clip against the edges of the destination
- if(dx<surface.box.left)
- {
- if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
- sw-=(int)((surface.box.left-dx)*d2sw);
- w-=surface.box.left-dx;
- dx=surface.box.left;
- }
- if(dy<surface.box.top)
- {
- sy+=(int)((surface.box.top-dy)*d2sh);
- sh-=(int)((surface.box.top-dy)*d2sh);
- h-=surface.box.top-dy;
- dy=surface.box.top;
- }
- if((dx+w)>surface.box.right)
- {
- if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
- sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
- w-=((dx+w)-surface.box.right-1);
- }
- if((dy+h)>surface.box.bottom)
- {
- sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
- h-=((dy+h)-surface.box.bottom-1);
- }
- if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
+ else
+ xu=1;
+ if(yd<0)
+ {
+ yd=-yd;
+ yu=-(int)lfbSurface.bitmap.stride;
+ }
+ else
+ yu=lfbSurface.bitmap.stride;
- dx+=surface.offset.x;
- dy+=surface.offset.y;
+ offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
+ errorterm=0;
- if(lfbSurface.bitmap.picture)
- {
- AlphaWriteMode alphaWrite = surface.alphaWrite;
- if(src.alphaBlend && surface.blend)
+ if(xd>yd)
{
- int x, y;
- uint xerr,yerr;
- uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
- ColorAlpha * backsrc;
- ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
- ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
- if(flip) source += sw-1;
- adddest -= w;
- yerr = 0;
- for(y=0; y<sh; y++)
+ int i, length=xd;
+ for(i=0; i<=length; i++)
{
- yerr+=h;
- backsrc = source;
- while(yerr >= sh)
+ if(stipple & 0x8000)
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
+ {
+ case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
+ case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
+ case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
+ }
+ offset+=xu;
+ errorterm+=yd;
+ if(errorterm>=xd)
{
- yerr-=sh;
- xerr = 0;
- for(x=0; x<sw; x++)
+ errorterm-=xd;
+ offset+=yu;
+ }
+ stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
+ }
+ }
+ else
+ {
+ int i, length=yd;
+ for(i=0; i<=length; i++)
+ {
+ if(stipple & 0x8000)
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
{
- xerr+=w;
- while(xerr>=sw)
- {
- xerr-=sw;
- {
- ColorAlpha src = *source;
- ColorAlpha dst = *dest;
- int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
- int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
- int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
- if(r > 255) r = 255;
- if(g > 255) g = 255;
- if(b > 255) b = 255;
- dest->color = { (byte)r, (byte)g, (byte)b };
- if(alphaWrite == blend)
- {
- int a = src.a + ((255 - src.a) * dst.a / 255);
- if(a > 255) a = 255;
- dest->a = (byte)a;
- }
- else if(alphaWrite)
- dest->a = src.a;
- }
- dest++;
- }
- source ++;
+ case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
+ case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
+ case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
}
- dest+=adddest;
- source = backsrc;
+ offset+=yu;
+ errorterm+=xd;
+ if(errorterm>=yd)
+ {
+ errorterm-=yd;
+ offset+=xu;
}
- source += addsource;
}
}
- else if(src.paletteShades)
- shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
- else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
- stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
- else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
- stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
}
}
- void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+ void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
{
- LFBSurface lfbSurface = surface.driverData;
- bool flip = false;
+ DrawLine(display, surface,x1,y1,x2,y1);
+ DrawLine(display, surface,x2,y1,x2,y2);
+ DrawLine(display, surface,x2,y2,x1,y2);
+ DrawLine(display, surface,x1,y2,x1,y1);
+ }
+
+ #if !defined(__GNUC__)
+ /*
+ void memset_32_aligned(void *buf, int val, int dwords)
+ {
+ // Qword align
+ if ((int)(buf) & 4)
+ {
+ *((uint32 *)(buf)) = val;
+ buf = ((uint32 *)(buf))+1;
+ dwords--;
+ }
+
+ if (dwords > 1)
+ {
+ __asm {
+ cld
+ mov edi, buf
+ mov ecx, dwords
+ shr ecx, 1
+ mov eax, val
+ movd mm0, eax
+ movd mm1, eax
+ psllq mm1, 32
+ por mm0, mm1
+ align 16
+ repeat:
+ movq [edi], mm0
+ add edi, 8
+ loop repeat
+ emms
+ };
+ }
- float s2dw,s2dh,d2sw,d2sh;
+ // Final dword
+ if (dwords & 1) *((int*)(buf)) = val;
+ }*/
- if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
+ //#define USE_SSE
- if(Sgn(w) != Sgn(sw))
+/*
+ void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
+ {
+ dwords <<= 2;
+ #ifdef USE_SSE
+ if(((uint32)buf) & 0x7F)
{
- w = Abs(w);
- sw = Abs(sw);
- flip = true;
+ for( ; ((uint32)buf) & 0x7F && dwords; buf++)
+ {
+ *buf = val;
+ dwords--;
+ }
}
+ if(dwords)
+ #endif
+ __asm
+ {
+ mov edi, buf
+ mov eax, val
+ mov ecx, dwords
- s2dw=(float)w / sw;
- s2dh=(float)h / sh;
- d2sw=(float)sw / w;
- d2sh=(float)sh / h;
+ mov edx,ecx
+ #ifdef USE_SSE
+ shr ecx,7
+ #else
+ shr ecx,6
+ #endif
+ mov ebx,ecx
+ #ifdef USE_SSE
+ shl ebx,7
+ #else
+ shl ebx,6
+ #endif
+ sub edx,ebx ; edx holds # of overflow bytes
- //Clip against the edges of the source
- if(sx<0)
- {
- dx+=(int)((0-sx) * s2dw);
- w-=(int)((0-sx) * s2dw);
- sw-=0-sx;
- sx=0;
- }
- if(sy<0)
- {
- dy+=(int)((0-sy) * s2dh);
- h-=(int)((0-sy) * s2dh);
+ #ifdef USE_SSE
+ mov [edi],eax
+ mov [edi+4],eax
+ mov [edi+8],eax
+ mov [edi+12],eax
+ movdqa xmm0, [edi]
+ #else
+ mov [edi],eax
+ mov [edi+4],eax
+ movq mm0, [edi]
+ #endif
+ cmp ecx,0
+ je doneloop
+ setloop:
- sh-=0-sy;
- sy=0;
- }
- if(sx+sw>src.width-1)
- {
- w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
- sw-=sx+sw-(src.width-1)-1;
- }
- if(sy+sh>(src.height-1))
- {
- h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
- sh-=sy+sh-(src.height-1)-1;
- }
- //Clip against the edges of the destination
- if(dx<surface.box.left)
- {
- if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
- sw-=(int)((surface.box.left-dx)*d2sw);
- w-=surface.box.left-dx;
- dx=surface.box.left;
- }
- if(dy<surface.box.top)
- {
- sy+=(int)((surface.box.top-dy)*d2sh);
- sh-=(int)((surface.box.top-dy)*d2sh);
- h-=surface.box.top-dy;
- dy=surface.box.top;
- }
- if((dx+w)>surface.box.right)
+ #ifdef USE_SSE
+ movdqa [edi],xmm0
+ movdqa [edi+16],xmm0
+ movdqa [edi+32],xmm0
+ movdqa [edi+48],xmm0
+ movdqa [edi+64],xmm0
+ movdqa [edi+80],xmm0
+ movdqa [edi+96],xmm0
+ movdqa [edi+112],xmm0
+ add edi,8*16
+ #else
+ movq [edi],mm0
+ movq [edi+8],mm0
+ movq [edi+16],mm0
+ movq [edi+24],mm0
+ movq [edi+32],mm0
+ movq [edi+40],mm0
+ movq [edi+48],mm0
+ movq [edi+56],mm0
+ add edi,8*8
+ #endif
+ dec ecx
+ jnz setloop
+
+ doneloop:
+ mov ecx,edx
+ shr ecx,2
+ rep stosd
+
+ emms
+ };
+ }
+ void memset_32(void *buf, uint32 val, uint32 dwords)
+ {
+ int align = 0;
+ if ((uint32)(buf) & 3)
{
- if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
- sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
- w-=((dx+w)-surface.box.right-1);
+ align = 4;
+ dwords--;
+
+ if (((uint32)(buf) & 1))
+ {
+ *(byte *)(buf) = (byte)(val&0xFF);
+ buf = ((byte *)(buf))+1;
+ val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
+ align --;
+ }
+ if (((uint32)(buf) & 2))
+ {
+ *(uint16 *)(buf) = (uint16)(val&0xFFFF);
+ buf = ((uint16 *)(buf))+1;
+ val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
+ align-=2;
+ }
}
- if((dy+h)>surface.box.bottom)
+ memset_32_aligned(buf,val,dwords);
+ if (align)
{
- sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
- h-=((dy+h)-surface.box.bottom-1);
+ if (align == 1)
+ {
+ *(byte *)(buf) = (byte)(val&0xFF);
+ }
+ else
+ {
+ *(uint16 *)(buf) = (uint16)(val&0xFFFF);
+ if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
+ }
}
- if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
+ }
+ */
+ #endif
- dx+=surface.offset.x;
- dy+=surface.offset.y;
+ void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
+ {
+ LFBSurface lfbSurface = surface.driverData;
+ uint32 color = lfbSurface.background;
- if(lfbSurface.bitmap.picture)
+ if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
{
- AlphaWriteMode alphaWrite = surface.alphaWrite;
- if(src.alphaBlend && surface.blend)
- {
- uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
- ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
- ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
- float scaleX = (float)sw / w;
- float scaleY = (float)sh / h;
- /*if(flip < 0)
- {
- dest += w-1;
- adddest += w;
- }
- else*/
- adddest -= w;
- if (w > sw && h > sh)
- {
- int y;
- for (y = 0; y < h; y++)
- {
- int y0 = y * sh / h;
- int y1 = Min(y0 + 1, sh - 1);
- float alpha = y * scaleY - y0;
- int x;
- for(x = 0; x < w; x++, dest += 1)
- {
- int x0 = x * sw / w;
- int x1 = Min(x0 + 1, sw - 1);
- float beta = x * scaleX - x0;
- ColorAlpha src00, src01, src10, src11;
- float a1,r1,g1,b1,a2,r2,g2,b2;
- float a,r,g,b;
- src00 = source[y0 * src.stride + x0];
- src01 = source[y0 * src.stride + x1];
- src10 = source[y1 * src.stride + x0];
- src11 = source[y1 * src.stride + x1];
- a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
- r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
- g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
- b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
- a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
- r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
- g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
- b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
- a = a1 * (1.0f - alpha) + a2 * alpha;
- r = r1 * (1.0f - alpha) + r2 * alpha;
- g = g1 * (1.0f - alpha) + g2 * alpha;
- b = b1 * (1.0f - alpha) + b2 * alpha;
- {
- ColorAlpha dst = *dest;
- int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
- int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
- int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
- if(cr > 255) cr = 255;
- if(cg > 255) cg = 255;
- if(cb > 255) cb = 255;
- dest->color = { (byte)cr, (byte)cg, (byte)cb };
+ color |= lfbSurface.foreground | lfbSurface.drawingChar;
+ x1 /= textCellW;
+ x2 /= textCellW;
+ y1 /= textCellH;
+ y2 /= textCellH;
+ }
+ if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
+
+ if(x1<surface.box.left) x1=surface.box.left;
+ if(x2>surface.box.right) x2=surface.box.right;
+ if(y1<surface.box.top) y1=surface.box.top;
+ if(y2>surface.box.bottom) y2=surface.box.bottom;
- if(alphaWrite == blend)
- {
- int ca = (int)(a + ((255 - a) * dst.a / 255));
- if(ca > 255) ca = 255;
- dest->a = (byte)ca;
- }
- else if(alphaWrite)
- dest->a = (byte)a;
- }
- }
- dest += adddest;
+ if(x2>=x1 && y2>=y1)
+ {
+ int w,y;
+ byte * theOffset;
+
+ w = x2-x1+1;
+ if(w<1) return;
+
+ x1 += surface.offset.x;
+ x2 += surface.offset.x;
+ y1 += surface.offset.y;
+ y2 += surface.offset.y;
+ if(lfbSurface.bitmap.picture)
+ {
+ if(!surface.writeColor)
+ {
+ ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
+ for(y = y1; y<= y2; y++)
+ {
+ int c;
+ for(c = 0; c < w; c++, picture++)
+ if(!picture->a)
+ picture->a = (byte)((color & 0xFF000000) >> 24);
+ picture += lfbSurface.bitmap.stride - w;
}
}
else
{
- int y;
- for (y = 0; y < h; y++)
+ if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
{
- int y0 = Min((int)((y + 1) * scaleY), sh - 1);
- int y1 = Min(y0 + 1, sh - 1);
- int x;
- for (x = 0; x < w; x++, dest += 1)
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
{
- int x0 = Min((int)((x + 1) * scaleX), sw - 1);
- int x1 = Min(x0 + 1, sw - 1);
- float a = 0, r = 0, g = 0, b = 0;
- int numPixels = 0;
- int i, j;
- for (i = y0; i <= y1; i++)
- for (j = x0; j <= x1; j++)
+ case 0:
+ theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
+ for(y = y1; y<= y2; y++)
{
- ColorAlpha pixel = source[i * src.stride + j];
- a += pixel.a;
- r += pixel.color.r;
- g += pixel.color.g;
- b += pixel.color.b;
- numPixels++;
+ FillBytes(theOffset,(byte)color,w);
+ theOffset += lfbSurface.bitmap.stride;
}
- a /= numPixels;
- r /= numPixels;
- g /= numPixels;
- b /= numPixels;
+ break;
+ case 1:
+ theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
+ for(y = y1; y<= y2; y++)
+ {
+ FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
+ theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
+ }
+ break;
+ case 2:
+ theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
+ for(y = y1; y<= y2; y++)
+ {
+ #if defined(__GNUC__)
+ FillBytesBy4((uint32 *) theOffset,color,w);
+ #else
+ memset_32((uint32 *) theOffset,color,w);
+ #endif
+ theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
+
+ }
+ /*
+ y = y2-y1+1;
+ {
+ int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
+ //memset_32((uint32 *) theOffset,color,w);
+ /-*_asm
+ {
+ push edi
+ push ecx
+ push eax
+ push ebx
+ push edx
+
+ mov ebx,bla
+
+ mov edi,theOffset
+ mov eax,color
+ mov edx,y
+ mov ecx,w
+
+ start:
+ push ecx
+
+ rep stosd
+ add edi,ebx
+ pop ecx
+ dec edx
+ jnz start
+ pop edx
+ pop ebx
+ pop eax
+ pop ecx
+ pop edi
+ };
+ break;
+ }*/
+ }
+ }
+ else
+ {
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
+ {
+ case 0:
+ theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
+ for(y = y1; y<= y2; y++)
+ {
+ // TODO: IMPLEMENT THIS
+ FillBytes(theOffset,(byte)color,w);
+ theOffset += lfbSurface.bitmap.stride;
+ }
+ break;
+ case 1:
{
- ColorAlpha dst = *dest;
- int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
- int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
- int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
- if(cr > 255) cr = 255;
- if(cg > 255) cg = 255;
- if(cb > 255) cb = 255;
- dest->color = { (byte)cr, (byte)cg, (byte)cb };
- if(alphaWrite == blend)
+ uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
+ ColorAlpha c = surface.background;
+ int a = c.a;
+ int cr = c.color.r;
+ int cg = c.color.g;
+ int cb = c.color.b;
+ PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
+
+ for(y = y1; y <= y2; y++)
{
- int ca = (int)(a + ((255 - a) * dst.a / 255));
- if(ca > 255) ca = 255;
- dest->a = (byte)ca;
+ int c;
+ for(c = 0; c < w; c++, dest++)
+ {
+ Color destColor = 0;
+ if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
+ else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
+ else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
+ {
+ int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
+ int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
+ int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
+
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+
+ destColor = { (byte)r, (byte)g, (byte)b };
+
+ if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
+ else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
+ else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
+ }
+ }
+ dest += (lfbSurface.bitmap.stride - w);
+ }
+ break;
+ }
+ case 2:
+ {
+ ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
+ AlphaWriteMode alphaWrite = surface.alphaWrite;
+ ColorAlpha c = surface.background;
+ int a = c.a;
+ int cr = c.color.r;
+ int cg = c.color.g;
+ int cb = c.color.b;
+ for(y = y1; y <= y2; y++)
+ {
+ int c;
+ for(c = 0; c < w; c++, dest++)
+ {
+ int dr = dest->color.r;
+ int dg = dest->color.g;
+ int db = dest->color.b;
+ int r = a * cr / 255 + ((255 - a) * dr / 255);
+ int g = a * cg / 255 + ((255 - a) * dg / 255);
+ int b = a * cb / 255 + ((255 - a) * db / 255);
+
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+ dest->color = { (byte)r, (byte)g, (byte)b };
+
+ if(alphaWrite == blend)
+ {
+ int ca = (int)(a + ((255 - a) * dest->a / 255));
+ if(ca > 255) ca = 255;
+ dest->a = (byte)ca;
+ }
+ else if(alphaWrite)
+ dest->a = (byte)a;
+ }
+ dest += (lfbSurface.bitmap.stride - w);
}
- else if(alphaWrite)
- dest->a = (byte)a;
}
}
- dest += adddest;
}
}
}
- else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
- filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
- // Fail back on Stretch
- else if(src.paletteShades)
- shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
- else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
- stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
- else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
- stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
}
}
-
- void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
- {
- Blit(display, surface, src, dx, dy, sx, sy, w, h);
- }
-
- void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
- {
- Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
- }
-
- void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+ void Clear(Display display, Surface surface, ClearType type)
{
- Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
- }
+ LFBSurface lfbSurface = surface.driverData;
- void UnloadFont(DisplaySystem displaySystem, Font font)
- {
- if(font)
+ lfbSurface.clearing = true;
+ if(surface.offset.x == 0 && surface.offset.y == 0 &&
+ surface.box.left == 0 && surface.box.top == 0 &&
+ surface.box.right == surface.width-1 &&
+ surface.box.bottom == surface.height-1)
{
-#if !defined(ECERE_NOTRUETYPE)
- int entry;
- for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
+ uint32 color = /*0xFF000000 | */lfbSurface.background;
+ if(type != depthBuffer)
{
- FontEntry fontEntry = font.fontEntries[entry];
- if(fontEntry)
+ if(lfbSurface.bitmap.stride != surface.width)
+ Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
+ else
{
- fontEntry.used--;
- if(!fontEntry.used)
+ switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
{
- loadedFonts.Remove(fontEntry);
- delete fontEntry;
+ case 0:
+ FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
+ break;
+ case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
+ case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
}
}
}
-#endif
- delete font;
+ /*
+ if((flags & CLEAR_Z) && zbuffer)
+ FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
+ */
+ }
+ else
+ {
+ if(type != depthBuffer)
+ Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
+ /*
+ if((flags & CLEAR_Z))
+ {
+ int y;
+ uint32 w = surface.box.right-surface.box.left+1;
+ float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
+ + surface.box.left+surface.offset.x;
+ for(y = surface.box.top; y<= surface.box.bottom; y++)
+ {
+ FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
+ offset += DISPLAY.Width;
+ }
+ }
+ */
}
+ lfbSurface.clearing = false;
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
{
- void * result = null;
+ LFBSurface lfbSurface = surface.driverData;
+ bool flip = false;
-#if !defined(ECERE_NOTRUETYPE)
- Font font = Font { };
- if(font)
- {
- char fileName[MAX_LOCATION];
- bool fakeItalic = flags.italic;
- int fontID = 0;
-#if !defined(__WIN32__)
- File linkCfg;
-#endif
- const char * ecereFonts = getenv("ECERE_FONTS");
- if(!ecereFonts) ecereFonts = "<:ecere>";
-#if !defined(__WIN32__)
- {
- char linkCfgPath[MAX_LOCATION];
+ if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
- strcpy(linkCfgPath, ecereFonts);
- PathCat(linkCfgPath, "linking.cfg");
- linkCfg = FileOpen(linkCfgPath, read);
- }
-#endif
- strcpy(fileName, faceName);
- strcpy(font.faceName, faceName);
- font.flags = flags;
- font.displaySystem = displaySystem;
+ if(w < 0) { w = -w; flip = true; }
- if(!FileExists(fileName))
- {
- strcpy(fileName, ecereFonts);
- PathCat(fileName, faceName);
- if(flags.bold && flags.italic) strcat(fileName, "bi");
- else if(flags.bold) strcat(fileName, "bd");
- else if(flags.italic) strcat(fileName, "i");
- strcat(fileName, ".ttf");
- strlwr(fileName);
- fakeItalic = false;
-
- if(flags.italic && !FileExists(fileName))
- {
- strcpy(fileName, ecereFonts);
- PathCat(fileName, faceName);
- if(flags.bold) strcat(fileName, "bd");
- strcat(fileName, ".ttf");
- strlwr(fileName);
- fakeItalic = true;
- }
+ //Clip against the edges of the source
+ if(sx<0)
+ {
+ dx+=-sx;
+ w-=-sx;
+ sx=0;
+ }
+ if(sy<0)
+ {
+ dy+=0-sy;
+ h-=0-sy;
+ sy=0;
+ }
+ if(sx+w>src.width-1)
+ w-=sx+w-(src.width-1)-1;
+ if(sy+h>src.height-1)
+ h-=sy+h-(src.height-1)-1;
+ //Clip against the edges of the destination
+ if(dx<surface.box.left)
+ {
+ if(!flip) sx+=surface.box.left-dx;
+ w-=surface.box.left-dx;
+ dx=surface.box.left;
+ }
+ if(dy<surface.box.top)
+ {
+ sy+=surface.box.top-dy;
+ h-=surface.box.top-dy;
+ dy=surface.box.top;
+ }
+ if((dx+w)>surface.box.right)
+ {
+ if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
+ w-=((uint32)(dx+w)-surface.box.right-1);
+ }
+ if((dy+h)>surface.box.bottom)
+ h-=((dy+h)-surface.box.bottom-1);
+ if((w<=0)||(h<=0))
+ return;
- // Search in current working directory
- if(!FileExists(fileName))
- {
- strcpy(fileName, faceName);
- if(flags.bold && flags.italic) strcat(fileName, "bi");
- else if(flags.bold) strcat(fileName, "bd");
- else if(flags.italic) strcat(fileName, "i");
- strcat(fileName, ".ttf");
- strlwr(fileName);
- fakeItalic = false;
-
- if(flags.italic && !FileExists(fileName))
- {
- strcpy(fileName, faceName);
- if(flags.bold) strcat(fileName, "bd");
- strcat(fileName, ".ttf");
- strlwr(fileName);
- fakeItalic = true;
- }
- }
+ dx += surface.offset.x;
+ dy += surface.offset.y;
- #if defined(__WIN32__)
- if(!FileExists(fileName))
+ if(lfbSurface.bitmap.picture)
+ {
+ AlphaWriteMode alphaWrite = surface.alphaWrite;
+ if(src.alphaBlend && surface.blend)
+ {
+ int x, y;
+ if(src.pixelFormat == pixelFormatAlpha)
{
- FontData fontData = { { 0 } };
- LOGFONT logFont = { 0 };
- HDC hdc = GetDC(0);
-
- fakeItalic = false;
-
- logFont.lfCharSet = DEFAULT_CHARSET;
- strcpy(logFont.lfFaceName, faceName);
- fontData.flags = flags;
-
- EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
- if(!fontData.fileName[0] && flags.bold)
+ if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
{
- fontData.forgive = true;
- EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
+ ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
+ byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
+ ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++, picture++, source++)
+ {
+ int a = *source * color.a;
+ ColorAlpha dest = *picture;
+ int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
+ int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
+ int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+ picture->color = { (byte)r, (byte)g, (byte)b };
+ if(alphaWrite == blend)
+ {
+ int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
+ if(ca > 255) ca = 255;
+ picture->a = (byte)ca;
+ }
+ else if(alphaWrite)
+ picture->a = (byte)(a / 255);
+ }
+ picture += lfbSurface.bitmap.stride - w;
+ source += src.stride - w;
+ }
}
- if(!fontData.fileName[0])
+ else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
{
- // Fake italic
- fontData.flags.italic = false;
- EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
- fakeItalic = true;
+ Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
+ byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
+ ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++, picture++, source++)
+ {
+ int a = *source * color.a;
+ Color dest = *picture;
+ int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
+ int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
+ int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+ *picture = Color { (byte)r, (byte)g, (byte)b };
+ }
+ picture += lfbSurface.bitmap.stride - w;
+ source += src.stride - w;
+ }
}
-
- if(fontData.fileName[0])
+ else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
{
- GetWindowsDirectory(fileName, MAX_LOCATION);
- PathCat(fileName, "fonts");
- PathCat(fileName, fontData.fileName);
+ Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
+ byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
+ ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++, picture++, source++)
+ {
+ int a = *source * color.a;
+ Color dest = *picture;
+ int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
+ int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
+ int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+ *picture = Color { (byte)r, (byte)g, (byte)b };
+ }
+ picture += lfbSurface.bitmap.stride - w;
+ source += src.stride - w;
+ }
}
- ReleaseDC(0, hdc);
}
- #elif !defined(ECERE_NOFONTCONFIG)
+ else
{
- char * fileName2;
- FcResult result = 0;
- FcPattern * pattern;
- FcPattern * matched;
- char * family;
- unichar testChar = 0;
- FcCharSet * charSet;
- if(!fcConfig)
- fcConfig = FcInitLoadConfigAndFonts();
-
- charSet = FcCharSetCreate();
-
- if(!strcmpi(faceName, "Mangal"))
- {
- testChar = 0x905;
- }
-
- if(testChar)
- FcCharSetAddChar(charSet, testChar);
-
- pattern = FcPatternBuild(null,
- //FC_SOURCE, FcTypeString, "freetype",
- FC_FAMILY, FcTypeString, faceName,
- //FC_SCALABLE, FcTypeBool, 1,
- FC_SIZE, FcTypeDouble, (double)size,
- FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
- FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
- testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
- null);
- FcDefaultSubstitute(pattern);
- FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
-
- matched = FcFontMatch (0, pattern, &result);
- // printf("Locating %s\n", faceName);
- if(matched)
- {
- FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
- //printf("Fontconfig returned %s\n", family);
- }
- if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
+ ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
+ if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
{
- double fontSize;
- FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
- FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
- FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
- strcpy(fileName, fileName2);
- // size = (float)fontSize;
-
- //printf("Matched to %s, %f\n", fileName, size);
+ ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++, picture++, source++)
+ {
+ ColorAlpha src = *source;
+ ColorAlpha dest = *picture;
+ int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
+ int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
+ int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+ picture->color = { (byte)r, (byte)g, (byte)b };
+ if(alphaWrite == blend)
+ {
+ int a = src.a + ((255 - src.a) * dest.a / 255);
+ if(a > 255) a = 255;
+ picture->a = (byte)a;
+ }
+ else if(alphaWrite)
+ picture->a = src.a;
+ }
+ picture += lfbSurface.bitmap.stride - w;
+ source += src.stride - w;
+ }
}
- else
+ else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
{
- //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
+ Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++, picture++, source++)
+ {
+ ColorAlpha src = *source;
+ Color565 dest = *picture;
+ int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
+ int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
+ int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
+ if(r > 255 * 31) r = 255 * 31;
+ if(g > 255 * 63) g = 255 * 63;
+ if(b > 255 * 31) b = 255 * 31;
+ *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
+ }
+ picture += lfbSurface.bitmap.stride - w;
+ source += src.stride - w;
+ }
}
- if(pattern) FcPatternDestroy(pattern);
- if(matched) FcPatternDestroy(matched);
- if(charSet) FcCharSetDestroy(charSet);
- }
- #endif
- }
-
- if(!FileExists(fileName))
- ChangeExtension(fileName, "otf", fileName);
- if(!FileExists(fileName))
- ChangeExtension(fileName, "ttc", fileName);
-
- //if(FileExists(fileName))
- {
- int entry = 0;
- char links[1024] = "";
- int linksPos = 0;
-#if defined(__WIN32__)
- HKEY key;
- links[0] = 0;
- if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
- !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
- {
- // int value = 0;
- DWORD type;
- DWORD size = 1024;
- RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
- memset(links + size, 0, 1024 - size);
- RegCloseKey(key);
- }
-#else
- links[0] = 0;
- if(linkCfg)
- {
- char line[512];
- while(linkCfg.GetLine(line, sizeof(line)))
+ else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
{
- int len = strlen(faceName);
- if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
+ Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
+ for(y = 0; y < h; y++)
{
- while(linkCfg.GetLine(line, sizeof(line)))
+ for(x = 0; x < w; x++, picture++, source++)
{
- TrimLSpaces(line, line);
- if(!line[0] || line[0] == '[')
- break;
- len = strlen(line);
- memcpy(links + linksPos, line, len);
- linksPos += len;
- links[linksPos] = 0;
- linksPos++;
+ ColorAlpha psrc = *source;
+ Color555 dest = *picture;
+ int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
+ int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
+ int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
+ if(r > 255 * 31) r = 255 * 31;
+ if(g > 255 * 31) g = 255 * 31;
+ if(b > 255 * 31) b = 255 * 31;
+ *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
}
+ picture += lfbSurface.bitmap.stride - w;
+ source += src.stride - w;
}
}
- linksPos = 0;
}
-#endif
- while(entry < MAX_FONT_LINK_ENTRIES)
- {
- FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
- if(!fontEntry)
- {
- File file = FileOpen/*Buffered*/(fileName, read);
- if(file)
- {
- FileSize fileSize = file.GetSize();
- FT_Open_Args args = { 0 };
- FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
- FT_Stream stream = new0 FT_StreamRec[1];
+ }
+ else if(src.paletteShades)
+ shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
+ else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
+ blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
+ else if(src.pixelFormat == pixelFormat8)
+ blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
+ }
+ }
- if(!ftLibrary)
- FT_Init_FreeType( &ftLibrary );
+ bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
+ {
+ bool result = false;
+ LFBDisplay lfbDisplay = display.driverData;
- fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
- fontEntry.stream = stream;
+ if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
+ {
+ bitmap.Free();
+ bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
+ (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
+ }
+ if(bitmap)
+ {
+ Surface surface = bitmap.GetSurface(0,0,null);
+ if(surface)
+ {
+ Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
+ if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
+ CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
+ delete surface;
+ }
+ result = true;
+ }
+ return result;
+ }
- /*
- fontEntry.buffer = new byte[fileSize];
- file.Read(fontEntry.buffer, 1, fileSize);
- */
+ void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+ {
+ LFBSurface lfbSurface = surface.driverData;
+ bool flip = false;
- //args.num_params = 1;
- args.params = ¶m;
+ float s2dw,s2dh,d2sw,d2sh;
- stream->size = fileSize;
- stream->descriptor.pointer = file;
- stream->read = FT_stream_load;
- stream->close = FT_stream_close;
+ if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
- args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
- args.stream = stream;
- //args.pathname = fileName;
- //args.memory_base = fontEntry.buffer;
- //args.memory_size = fileSize;
+ if(Sgn(w) != Sgn(sw))
+ {
+ w = Abs(w);
+ sw = Abs(sw);
+ flip = true;
+ }
- // printf("Opening: %s\n", fileName);
- FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
+ s2dw=(float)w / sw;
+ s2dh=(float)h / sh;
+ d2sw=(float)sw / w;
+ d2sh=(float)sh / h;
- // delete file;
- if(fontEntry.face)
- {
- fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
- fontEntry.hbFont.klass = &hb_fontClass;
- fontEntry.hbFont.userData = fontEntry; //.face;
+ //Clip against the edges of the source
+ if(sx<0)
+ {
+ dx+=(int)((0-sx) * s2dw);
+ w-=(int)((0-sx) * s2dw);
+ sw-=0-sx;
+ sx=0;
+ }
+ if(sy<0)
+ {
+ dy+=(int)((0-sy) * s2dh);
+ h-=(int)((0-sy) * s2dh);
- numFonts++;
- loadedFonts.Add(fontEntry);
- }
- else
- {
- delete fontEntry;
- // printf("Error opening font %s\n", fileName);
- }
- }
- }
- if(fontEntry)
- {
- if(!entry)
- {
- FT_Matrix matrix;
- FT_Vector pen = { 0, 0 };
- if(fakeItalic)
- {
- matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
- matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
- matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
- matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
- }
- else
- {
- matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
- matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
- matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
- matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
- }
- FT_Set_Transform(fontEntry.face, &matrix, &pen );
- FaceSetCharSize(fontEntry.face, size);
- font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
- // printf("Font height is %d\n", font.height);
- font.fakeItalic = fakeItalic;
- font.size = size;
- result = font;
- }
- font.fontEntries[entry++] = fontEntry;
- fontEntry.used++;
- }
+ sh-=0-sy;
+ sy=0;
+ }
+ if(sx+sw>src.width-1)
+ {
+ w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
+ sw-=sx+sw-(src.width-1)-1;
+ }
+ if(sy+sh>(src.height-1))
+ {
+ h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
+ sh-=sy+sh-(src.height-1)-1;
+ }
+ //Clip against the edges of the destination
+ if(dx<surface.box.left)
+ {
+ if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
+ sw-=(int)((surface.box.left-dx)*d2sw);
+ w-=surface.box.left-dx;
+ dx=surface.box.left;
+ }
+ if(dy<surface.box.top)
+ {
+ sy+=(int)((surface.box.top-dy)*d2sh);
+ sh-=(int)((surface.box.top-dy)*d2sh);
+ h-=surface.box.top-dy;
+ dy=surface.box.top;
+ }
+ if((dx+w)>surface.box.right)
+ {
+ if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
+ sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
+ w-=((dx+w)-surface.box.right-1);
+ }
+ if((dy+h)>surface.box.bottom)
+ {
+ sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
+ h-=((dy+h)-surface.box.bottom-1);
+ }
+ if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
+
+ dx+=surface.offset.x;
+ dy+=surface.offset.y;
+ if(lfbSurface.bitmap.picture)
+ {
+ AlphaWriteMode alphaWrite = surface.alphaWrite;
+ if(src.alphaBlend && surface.blend)
+ {
+ int x, y;
+ uint xerr,yerr;
+ uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
+ ColorAlpha * backsrc;
+ ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
+ ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
+ if(flip) source += sw-1;
+ adddest -= w;
+ yerr = 0;
+ for(y=0; y<sh; y++)
+ {
+ yerr+=h;
+ backsrc = source;
+ while(yerr >= sh)
{
- int c;
- char ch;
- char fontName[1024];
- if(!links[linksPos]) break;
- for(c = 0; (ch = links[linksPos + c]); c++)
- {
- fontName[c] = ch;
- if(ch == ',') break;
- }
- fontName[c] = 0;
- if(fontName[0] || ch == ',')
+ yerr-=sh;
+ xerr = 0;
+ for(x=0; x<sw; x++)
{
-#if defined(__WIN32__)
- GetWindowsDirectory(fileName, MAX_LOCATION);
- PathCat(fileName, "fonts");
- PathCat(fileName, fontName);
-#elif !defined(ECERE_NOFONTCONFIG)
- if(getenv("ECERE_FONTS"))
- {
- strcpy(fileName, ecereFonts);
- PathCat(fileName, fontName);
- }
- else
+ xerr+=w;
+ while(xerr>=sw)
{
+ xerr-=sw;
{
- char * fileName2;
- FcResult result = 0;
- FcPattern * pattern;
- FcPattern * matched;
- char * family;
- pattern = FcPatternBuild(null,
- //FC_SOURCE, FcTypeString, "freetype",
- //FC_SCALABLE, FcTypeBool, 1,
- FC_FAMILY, FcTypeString, links + linksPos + c + 1,
- FC_SIZE, FcTypeDouble, (double)size,
- FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
- FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
- null);
- FcDefaultSubstitute(pattern);
- FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
-
- //printf("Locating %s\n", links + linksPos + c + 1);
- matched = FcFontMatch (0, pattern, &result);
- if(matched)
- {
- FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
- // printf("Fontconfig returned %s\n", family);
- }
- if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
- FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
- {
- double fontSize;
- FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
- FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
- FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
- strcpy(fileName, fileName2);
- //size = (float)fontSize;
- // printf("Matched to %s, %f\n", fileName, size);
- }
- else
+ ColorAlpha src = *source;
+ ColorAlpha dst = *dest;
+ int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
+ int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
+ int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
+ dest->color = { (byte)r, (byte)g, (byte)b };
+ if(alphaWrite == blend)
{
- // 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);
+ int a = src.a + ((255 - src.a) * dst.a / 255);
+ if(a > 255) a = 255;
+ dest->a = (byte)a;
}
- if(pattern) FcPatternDestroy(pattern);
- if(matched) FcPatternDestroy(matched);
+ else if(alphaWrite)
+ dest->a = src.a;
}
+ dest++;
}
-#endif
-
+ source ++;
}
- linksPos += c;
- while(links[linksPos] && links[linksPos] != ',') linksPos++;
- linksPos++;
+ dest+=adddest;
+ source = backsrc;
}
+ source += addsource;
}
}
+ else if(src.paletteShades)
+ shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
+ stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
+ stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ }
+ }
- if(!result)
- UnloadFont(displaySystem, font);
- else
- {
- font.asciiPack.Render(font, 0, displaySystem);
- }
-#if !defined(__WIN32__)
- delete linkCfg;
-#endif
+ void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+ {
+ LFBSurface lfbSurface = surface.driverData;
+ bool flip = false;
+
+ float s2dw,s2dh,d2sw,d2sh;
+
+ if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
+
+ if(Sgn(w) != Sgn(sw))
+ {
+ w = Abs(w);
+ sw = Abs(sw);
+ flip = true;
+ }
+
+ s2dw=(float)w / sw;
+ s2dh=(float)h / sh;
+ d2sw=(float)sw / w;
+ d2sh=(float)sh / h;
+
+ //Clip against the edges of the source
+ if(sx<0)
+ {
+ dx+=(int)((0-sx) * s2dw);
+ w-=(int)((0-sx) * s2dw);
+ sw-=0-sx;
+ sx=0;
+ }
+ if(sy<0)
+ {
+ dy+=(int)((0-sy) * s2dh);
+ h-=(int)((0-sy) * s2dh);
+
+ sh-=0-sy;
+ sy=0;
+ }
+ if(sx+sw>src.width-1)
+ {
+ w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
+ sw-=sx+sw-(src.width-1)-1;
+ }
+ if(sy+sh>(src.height-1))
+ {
+ h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
+ sh-=sy+sh-(src.height-1)-1;
+ }
+ //Clip against the edges of the destination
+ if(dx<surface.box.left)
+ {
+ if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
+ sw-=(int)((surface.box.left-dx)*d2sw);
+ w-=surface.box.left-dx;
+ dx=surface.box.left;
+ }
+ if(dy<surface.box.top)
+ {
+ sy+=(int)((surface.box.top-dy)*d2sh);
+ sh-=(int)((surface.box.top-dy)*d2sh);
+ h-=surface.box.top-dy;
+ dy=surface.box.top;
}
- #endif
- return result;
- }
+ if((dx+w)>surface.box.right)
+ {
+ if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
+ sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
+ w-=((dx+w)-surface.box.right-1);
+ }
+ if((dy+h)>surface.box.bottom)
+ {
+ sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
+ h-=((dy+h)-surface.box.bottom-1);
+ }
+ if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
-#if !defined(ECERE_NOTRUETYPE)
- void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
- void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
- Surface surface, Display display, int * x, int y)
- {
- if(font && font.fontEntries && font.fontEntries[0])
- {
- LFBSurface lfbSurface = surface ? surface.driverData : null;
- int previousGlyph = 0;
- FT_Face previousFace = 0;
- int c, nb, glyphIndex = 0;
- unichar lastPack = lfbSurface && lfbSurface.writingOutline ? -1 : 0;
- GlyphPack pack = font.asciiPack, outline = null;
- int wc = 0;
- uint * glyphs = null;
- int numGlyphs = 0;
- bool rightToLeft = false;
- int fontEntryNum = 0;
- int glyphScript = 0;
- FontEntry curFontEntry;
- GlyphInfo * lastGlyph = null;
- int lastAX = 0;
-
- pack.bitmap.alphaBlend = true;
-
- for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
+ dx+=surface.offset.x;
+ dy+=surface.offset.y;
+
+ if(lfbSurface.bitmap.picture)
+ {
+ AlphaWriteMode alphaWrite = surface.alphaWrite;
+ if(src.alphaBlend && surface.blend)
{
- uint glyphNo = 0;
- uint packNo;
- if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
+ uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
+ ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
+ ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
+ float scaleX = (float)sw / w;
+ float scaleY = (float)sh / h;
+ /*if(flip < 0)
{
- glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
- rightToLeft ? glyphIndex-- : glyphIndex++;
+ dest += w-1;
+ adddest += w;
}
- else
+ else*/
+ adddest -= w;
+ if (w > sw && h > sh)
{
- HB_Script curScript = HB_Script_Common;
- const byte * scriptStart = text + c;
- //unichar nonASCIIch = 0;
- unichar ch;
- unichar ahead = 0;
- unichar testChar = 0;
-#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
- const char * testLang = null;
-#endif
-
- while(true)
+ int y;
+ for (y = 0; y < h; y++)
{
- HB_Script script = HB_Script_Common;
- ch = UTF8GetChar((const char *)text + c, &nb);
- //if(ch > 127) nonASCIIch = ch;
- if(!nb) break;
- if(ch == 32 && curScript)
+ int y0 = y * sh / h;
+ int y1 = Min(y0 + 1, sh - 1);
+ float alpha = y * scaleY - y0;
+ int x;
+ for(x = 0; x < w; x++, dest += 1)
{
- if(ahead)
- script = curScript;
- else
+ int x0 = x * sw / w;
+ int x1 = Min(x0 + 1, sw - 1);
+ float beta = x * scaleX - x0;
+ ColorAlpha src00, src01, src10, src11;
+ float a1,r1,g1,b1,a2,r2,g2,b2;
+ float a,r,g,b;
+ src00 = source[y0 * src.stride + x0];
+ src01 = source[y0 * src.stride + x1];
+ src10 = source[y1 * src.stride + x0];
+ src11 = source[y1 * src.stride + x1];
+ a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
+ r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
+ g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
+ b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
+ a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
+ r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
+ g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
+ b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
+ a = a1 * (1.0f - alpha) + a2 * alpha;
+ r = r1 * (1.0f - alpha) + r2 * alpha;
+ g = g1 * (1.0f - alpha) + g2 * alpha;
+ b = b1 * (1.0f - alpha) + b2 * alpha;
{
- int a;
- for(a = c + 1; a < c + len; a++)
- {
- if(text[a] != 32)
- break;
- }
- if(a < c + len)
+ ColorAlpha dst = *dest;
+ int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
+ int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
+ int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
+ if(cr > 255) cr = 255;
+ if(cg > 255) cg = 255;
+ if(cb > 255) cb = 255;
+ dest->color = { (byte)cr, (byte)cg, (byte)cb };
+
+ if(alphaWrite == blend)
{
- int nb;
- unichar ahead = UTF8GetChar((const char *)text + a, &nb);
- if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
- script = curScript;
+ int ca = (int)(a + ((255 - a) * dst.a / 255));
+ if(ca > 255) ca = 255;
+ dest->a = (byte)ca;
}
- else
- script = curScript;
- }
- }
- else if(ch < 0x370)
- script = HB_Script_Common;
- else if(ch <= 0x11FF)
- {
- switch(ch & 0xFF00)
- {
- case 0x300: script = HB_Script_Greek; break;
- case 0x400: script = HB_Script_Cyrillic; break;
- case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
- case 0x600: script = HB_Script_Arabic; break;
- case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
- case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
- case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
- case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
- case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
- case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
- case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
- case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
- case 0xF00: script = HB_Script_Tibetan; break;
- case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
- case 0x1100: script = HB_Script_Hangul; break;
+ else if(alphaWrite)
+ dest->a = (byte)a;
}
}
- else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
- else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
- script = HB_Script_Hangul;
- else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
- else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
- else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
- else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
- else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
- //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
- else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
- else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
- else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
- if(curScript)
- {
- if(!script || (script != curScript))
- break;
- c += nb;
- if(c >= len)
- break;
- }
- else
- {
- if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
- if(!script) { c += nb; break; }
- curScript = script;
- }
- }
- if(!nb) break;
- fontEntryNum = 0;
-
- if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
- {
- rightToLeft = false;
- glyphNo = ch;
- theCurrentScript = 0;
- }
- else
- {
- int len = c - (int)(scriptStart - text);
- int max = len * 2 + 1;
- if(max > utf16BufferSize)
- {
- utf16 = renew utf16 uint16[max];
- utf16BufferSize = max;
- }
- wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
- theCurrentScript = glyphScript = curScript;
- }
- switch(curScript)
- {
- case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
- //printf("Arabic ");
- break;
- case HB_Script_Devanagari: testChar = 0x905;
-#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
- testLang = "sa";
-#endif
- //printf("Devanagari ");
- break;
- case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
- //printf("Hebrew ");
- break;
- default:
- testChar = (ch == '\t') ? ' ' : ch;
- /*
- case 60: testChar = 'あ'; break;
- case 61: testChar = 0x3400; break; //'愛'; break;
- */
- }
-
- if(testChar)
- {
- // printf("Testing for char %x\n", testChar);
- for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
- {
- if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
- break;
- /*if(font.fontEntries[fontEntryNum])
- printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
- }
+ dest += adddest;
}
-
- if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
+ }
+ else
+ {
+ int y;
+ for (y = 0; y < h; y++)
{
-#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
- int fontID = 0;
- double fontSize = font.size;
- FcResult result = 0;
- FcPattern * pattern;
- FcPattern * matched;
- FcCharSet * charSet;
- char * family;
- FontEntry fontEntry;
- char * fileName = null;
- for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
- if(!font.fontEntries[fontEntryNum])
- break;
- if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
-#endif
- continue;
-
-#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
- {
- charSet = FcCharSetCreate();
- FcCharSetAddChar(charSet, testChar);
- //printf("Loading with char %x\n", testChar);
-
- pattern = FcPatternBuild(null,
- //FC_SOURCE, FcTypeString, "freetype",
- //FC_SCALABLE, FcTypeBool, 1,
- FC_FAMILY, FcTypeString, font.faceName,
- FC_SIZE, FcTypeDouble, (double)font.size,
- FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
- FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
- FC_CHARSET,FcTypeCharSet, charSet,
- testLang ? FC_LANG : 0, FcTypeString,testLang,
- null);
- FcDefaultSubstitute(pattern);
- FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
-
- //printf("Locating %s for script %d\n", font.faceName, curScript);
- matched = FcFontMatch (0, pattern, &result);
- if(matched)
- {
- FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
- //printf("Fontconfig returned %s\n", family);
- }
- if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
- {
- FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName);
- FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
- FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
- // printf("\nMatched to %s, %f\n", fileName, fontSize);
- }
- else
- {
- //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);
- }
- }
- if(fileName)
+ int y0 = Min((int)((y + 1) * scaleY), sh - 1);
+ int y1 = Min(y0 + 1, sh - 1);
+ int x;
+ for (x = 0; x < w; x++, dest += 1)
{
- fontEntry = (FontEntry)loadedFonts.FindString(fileName);
- if(!fontEntry)
- {
- File file = FileOpen(fileName, read);
- if(file)
+ int x0 = Min((int)((x + 1) * scaleX), sw - 1);
+ int x1 = Min(x0 + 1, sw - 1);
+ float a = 0, r = 0, g = 0, b = 0;
+ int numPixels = 0;
+ int i, j;
+ for (i = y0; i <= y1; i++)
+ for (j = x0; j <= x1; j++)
{
- FileSize fileSize = file.GetSize();
- FT_Open_Args args = { 0 };
- FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
- FT_Stream stream = new0 FT_StreamRec[1];
-
- if(!ftLibrary)
- FT_Init_FreeType( &ftLibrary );
-
- fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
- fontEntry.stream = stream;
-
- //args.num_params = 1;
- args.params = ¶m;
-
- stream->size = fileSize;
- stream->descriptor.pointer = file;
- stream->read = FT_stream_load;
- stream->close = FT_stream_close;
-
- args.flags = FT_OPEN_STREAM;
- args.stream = stream;
- //args.pathname = fileName;
- //args.memory_base = fontEntry.buffer;
- //args.memory_size = fileSize;
-
- // printf("Opening: %s\n", fileName);
- FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
-
- // delete file;
- if(fontEntry.face)
- {
- fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
- fontEntry.hbFont.klass = &hb_fontClass;
- fontEntry.hbFont.userData = fontEntry; //.face;
-
- numFonts++;
- loadedFonts.Add(fontEntry);
- }
- else
- {
- delete fontEntry;
- // printf("Error opening font %s\n", fileName);
- }
+ ColorAlpha pixel = source[i * src.stride + j];
+ a += pixel.a;
+ r += pixel.color.r;
+ g += pixel.color.g;
+ b += pixel.color.b;
+ numPixels++;
}
- }
- if(fontEntry)
+ a /= numPixels;
+ r /= numPixels;
+ g /= numPixels;
+ b /= numPixels;
{
- FaceSetCharSize(fontEntry.face, font.size);
-
- font.fontEntries[fontEntryNum] = fontEntry;
- fontEntry.used++;
+ ColorAlpha dst = *dest;
+ int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
+ int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
+ int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
+ if(cr > 255) cr = 255;
+ if(cg > 255) cg = 255;
+ if(cb > 255) cb = 255;
+ dest->color = { (byte)cr, (byte)cg, (byte)cb };
+ if(alphaWrite == blend)
+ {
+ int ca = (int)(a + ((255 - a) * dst.a / 255));
+ if(ca > 255) ca = 255;
+ dest->a = (byte)ca;
+ }
+ else if(alphaWrite)
+ dest->a = (byte)a;
}
}
- if(pattern) FcPatternDestroy(pattern);
- if(matched) FcPatternDestroy(matched);
- if(charSet) FcCharSetDestroy(charSet);
-#endif
- }
- if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
- if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
- {
- font.fontEntries[fontEntryNum].font = font;
- glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
- if(!numGlyphs)
- continue;
-
- glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
- glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
- rightToLeft ? glyphIndex-- : glyphIndex++;
- }
- }
-
- curFontEntry = font.fontEntries[fontEntryNum];
-
- packNo = glyphNo & 0xFFFFFF80;
-
- if(packNo != lastPack)
- {
- if(glyphNo < 128)
- pack = font.asciiPack;
- else
- {
- pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
- if(!pack)
- {
- pack = GlyphPack { key = (uintptr)packNo };
- font.glyphPacks.Add(pack);
- pack.Render(font, fontEntryNum, displaySystem);
- }
- }
- pack.bitmap.alphaBlend = true;
- lastPack = packNo;
-#if !defined(ECERE_VANILLA)
- if(lfbSurface && lfbSurface.writingOutline)
- {
- uint outlineNo = (((uint)surface.outline.size) << 16) | (uint16)(Min(surface.outline.fade, 257.0f) * 255);
- outline = (GlyphPack)pack.outlines.Find(outlineNo);
- if(!outline)
- {
- outline = { key = outlineNo };
- pack.outlines.Add(outline);
- pack.RenderOutline(outline, font, displaySystem);
- }
+ dest += adddest;
}
-#endif
}
- if(pack)
- {
- int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
- GlyphInfo * glyph = &(outline ? outline : pack).glyphs[glyphNo & 0x7F];
-
- int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
- int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
- int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
-
- ax += offset;
+ }
+ else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
+ filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ // Fail back on Stretch
+ else if(src.paletteShades)
+ shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
+ stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
+ stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
+ }
+ }
- if(previousGlyph && curFontEntry.face == previousFace)
- {
- FT_Vector delta = { 0, 0 };
- FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
- if(delta.x < 0) delta.x += (-delta.x) % 64;
- else if(delta.x) delta.x += 64 - (delta.x % 64);
- *x += delta.x * glyph->scale;
- }
- else
- FaceSetCharSize(curFontEntry.face, font.size);
+ void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
+ {
+ Blit(display, surface, src, dx, dy, sx, sy, w, h);
+ }
- previousGlyph = glyph->glyphNo;
- previousFace = curFontEntry.face;
+ void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+ {
+ Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+ }
- if(callback)
- callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, (outline ? outline : pack).bitmap);
- *x += ax;
+ void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+ {
+ Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+ }
- lastGlyph = glyph;
- lastAX = ax;
- }
- if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
- numGlyphs = 0;
- }
- if(lastGlyph)
- {
- int w = (lastGlyph->w + lastGlyph->left) * (1 << 6);
- // Fix for advance != width + left (e.g. italic fonts)
- if(w > lastAX)
- *x += w - lastAX;
- }
- }
- if(surface)
- {
- LFBSurface lfbSurface = surface.driverData;
- lfbSurface.xOffset = 0;
- }
+ void UnloadFont(DisplaySystem displaySystem, Font font)
+ {
+ delete font;
}
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ {
+#ifndef ECERE_NOTRUETYPE
+ return Font::Load(displaySystem, faceName, size, flags);
+#else
+ return { };
#endif
+ }
+
void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
{
if(displaySystem && displaySystem.flags.text && len)
}
if(height) *height = textCellH;
}
+#if !defined(ECERE_NOTRUETYPE)
else if(font && len)
{
if(width)
{
int w = 0;
-#if !defined(ECERE_NOTRUETYPE)
- ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
-#endif
+ font.ProcessString(displaySystem, (const byte *)text, len, null, null, null, &w, 0);
//*width = (w + 64 - w % 64) >> 6;
*width = w >> 6;
}
if(height)
*height = font.height;
}
+#endif
else
{
if(width) *width = 0;
}
#if !defined(ECERE_NOTRUETYPE)
- void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
+ void ::OutputGlyph(Surface surface, Display display, int x, int y, Glyph glyph, Bitmap bitmap)
{
- surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
+ surface.driver.Blit(display, surface, bitmap, x + glyph.left, y + glyph.top, glyph.x, glyph.y, glyph.w, glyph.h);
}
#endif
lfbSurface.writingText = true;
#if !defined(ECERE_NOTRUETYPE)
x <<= 6;
- ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
+ lfbSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
#endif
lfbSurface.writingText = false;
}
--- /dev/null
+namespace gfx;
+
+import "fontManagement"
+
+#if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
+#define ECERE_NOTRUETYPE
+#endif
+
+#undef __BLOCKS__
+#define uint _uint
+#define strlen _strlen
+#if !defined(ECERE_NOTRUETYPE)
+ #include <ft2build.h>
+ #include FT_FREETYPE_H
+ #include FT_TRUETYPE_TABLES_H
+ #include FT_UNPATENTED_HINTING_H
+ #define property _property
+ #include "harfbuzz.h"
+ #undef property
+#endif
+#undef uint
+#undef strlen
+
+#if !defined(ECERE_NOTRUETYPE)
+static int utf16BufferSize = 0;
+static uint16 * utf16 = null;
+#endif
+
+#if !defined(ECERE_NOTRUETYPE)
+
+#if !defined(ECERE_VANILLA)
+import "edtaa3func"
+
+static void ComputeOutline(byte *out, byte *src, uint w, uint h, float size, float fade)
+{
+ uint i, numPixels = w * h;
+ short * distx = new short[2 * numPixels], * disty = distx + numPixels;
+ float * data = new0 float[4 * numPixels], * gx = data + numPixels, * gy = gx + numPixels, * dist = gy + numPixels;
+ float rb = Max(1.5f, size), ra = rb - (rb-1)*fade*4 - 1;
+ float inv_rw = 1/(rb-ra);
+
+ for(i = 0; i < numPixels; i++)
+ data[i] = src[i] / 255.0f;
+
+ computegradient(data, w, h, gx, gy);
+ edtaa3(data, gx, gy, w, h, distx, disty, dist);
+
+ for(i = 0; i < numPixels; i++)
+ {
+ float value = 1 - Max(0.0f, Min(1.0f, (dist[i]-ra)*inv_rw));
+ out[i] = (byte)(255 * value * value);
+ }
+ delete distx;
+ delete data;
+}
+
+static void BlitOutline(byte * dst, int dx, int dy, int w, int h, byte * src, int sx, int sy, int sw, int sh, int srcStride)
+{
+ sh = Min(h - dy, sh);
+ sw = Min(w - dx, sw);
+ if(sw > 0 && sh > 0)
+ {
+ int y;
+ for(y = 0; y < sh; y++)
+ memcpy(dst + w * (dy+y) + dx, src + srcStride * (sy+y) + sx, sw);
+ }
+}
+
+static void MeasureOutline(byte * image, int w, int h, int * _x1, int * _y1, int * _x2, int * _y2)
+{
+ int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
+ int x, y;
+ for(x = 0; x < w && x1 == MAXINT; x++)
+ {
+ for(y = 0; y < h; y++)
+ if(image[(y*w)+x])
+ {
+ x1 = x;
+ break;
+ }
+ }
+ for(x = w-1; x >= 0 && x2 == MININT; x--)
+ {
+ for(y = 0; y < h; y++)
+ if(image[(y*w)+x])
+ {
+ x2 = x;
+ break;
+ }
+ }
+ for(y = 0; y < h && y1 == MAXINT; y++)
+ {
+ for(x = 0; x < w; x++)
+ if(image[(y*w)+x])
+ {
+ y1 = y;
+ break;
+ }
+ }
+ for(y = h-1; y >= 0 && y2 == MININT; y--)
+ {
+ for(x = 0; x < w; x++)
+ if(image[(y*w)+x])
+ {
+ y2 = y;
+ break;
+ }
+ }
+ *_x1 = x1;
+ *_y1 = y1;
+ *_x2 = x2;
+ *_y2 = y2;
+}
+
+#endif
+
+#define MAX_FONT_LINK_ENTRIES 10
+
+static HB_Script theCurrentScript;
+
+static unichar UTF16GetChar(const uint16 *string, int * nw)
+{
+ unichar ch;
+ if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
+ {
+ ch = HB_SurrogateToUcs4(string[0], string[1]);
+ *nw = 2;
+ }
+ else
+ {
+ ch = *string;
+ *nw = 1;
+ }
+ return ch;
+}
+
+static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
+{
+ FT_Face face = ((FontEntry)font->userData).face;
+ int glyph_pos = 0;
+ int c, nw;
+
+ if (length > *numGlyphs)
+ return 0;
+
+ for (c = 0; c < length; c += nw)
+ {
+ unichar ch = UTF16GetChar(string + c, &nw);
+ glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
+ }
+ *numGlyphs = glyph_pos;
+ return 1;
+}
+
+static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
+{
+ FontEntry entry = font->userData;
+ Font glFont = entry.font;
+ int c;
+ uint lastPack = 0;
+ GlyphPack pack = glFont.asciiPack;
+ int fontEntryNum;
+ for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
+ {
+ if(glFont.fontEntries[fontEntryNum] == entry)
+ break;
+ }
+
+ for(c = 0; c < numGlyphs; c++)
+ {
+ Glyph * glyph;
+ uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
+ uint packNo = glyphNo & 0xFFFFFF80;
+ if(packNo != lastPack)
+ {
+ pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
+ if(!pack)
+ {
+ glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
+ pack.Render(glFont, fontEntryNum, glFont.displaySystem);
+ pack.bitmap.alphaBlend = true;
+ }
+ lastPack = packNo;
+ }
+ glyph = &pack.glyphs[glyphNo & 0x7F];
+ advances[c] = glyph->ax;
+ }
+}
+
+static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
+{
+ FT_Face face = ((FontEntry)font->userData).face;
+ int c, nw;
+
+ for (c = 0; c < length; c += nw)
+ {
+ unichar ch = UTF16GetChar(string + c, &nw);
+ if(!FT_Get_Char_Index(face, ch))
+ return 0;
+ }
+ return 1;
+}
+
+static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
+{
+ FT_Face face = (FT_Face)font;
+ FT_ULong ftlen = *length;
+ FT_Error error = 0;
+
+ if (!FT_IS_SFNT(face))
+ return HB_Err_Invalid_Argument;
+
+ error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
+ *length = (uint)ftlen;
+ return (HB_Error)error;
+}
+
+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)
+{
+ HB_Error error = HB_Err_Ok;
+ FT_Face face = (FT_Face)font->userData;
+
+ int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
+
+ if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
+ return error;
+
+ if (face->glyph->format != ft_glyph_format_outline)
+ return (HB_Error)HB_Err_Invalid_SubTable;
+
+ *nPoints = face->glyph->outline.n_points;
+ if (!(*nPoints))
+ return HB_Err_Ok;
+
+ if (point > *nPoints)
+ return (HB_Error)HB_Err_Invalid_SubTable;
+
+ *xpos = (int)face->glyph->outline.points[point].x;
+ *ypos = (int)face->glyph->outline.points[point].y;
+
+ return HB_Err_Ok;
+}
+
+static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
+{
+ FontEntry entry = font->userData;
+ Font glFont = entry.font;
+ uint lastPack = 0;
+ GlyphPack pack = glFont.asciiPack;
+ int fontEntryNum;
+ for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
+ {
+ if(glFont.fontEntries[fontEntryNum] == entry)
+ break;
+ }
+ {
+ Glyph * glyph;
+ uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
+ uint packNo = glyphNo & 0xFFFFFF80;
+ if(packNo != lastPack)
+ {
+ pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
+ if(!pack)
+ {
+ pack = { key = (uintptr)packNo };
+ glFont.glyphPacks.Add(pack);
+ pack.Render(glFont, fontEntryNum, glFont.displaySystem);
+ pack.bitmap.alphaBlend = true;
+ }
+ lastPack = packNo;
+ }
+ glyph = &pack.glyphs[glyphNo & 0x7F];
+
+ metrics->x = glyph->ax;
+ metrics->y = 0;
+ metrics->width = glyph->w;
+ metrics->height = glyph->h;
+ metrics->xOffset = glyph->bx;
+ metrics->yOffset = glyph->by;
+ }
+}
+
+static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
+{
+ FontEntry entry = font->userData;
+ FT_Face face = entry.face;
+
+ // Note that we aren't scanning the VDMX table which we probably would in
+ // an ideal world.
+ if(metric == HB_FontAscent)
+ return face->ascender;
+ return 0;
+}
+
+static HB_FontClass hb_fontClass =
+{
+ hb_stringToGlyphs, hb_getAdvances, hb_canRender,
+ hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
+};
+
+static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
+{
+ File f = stream->descriptor.pointer;
+ f.Seek((int)offset, start);
+ return count ? f.Read(buffer, 1, (uint)count) : 0;
+}
+
+static void FT_stream_close(FT_Stream stream)
+{
+ File f = stream->descriptor.pointer;
+ delete f;
+ delete stream;
+}
+
+static FT_Library ftLibrary;
+static int numFonts;
+#undef CompareString
+static BinaryTree loadedFonts
+{
+ CompareKey = (void *)BinaryTree::CompareString
+};
+
+class FontEntry : BTNode
+{
+ FT_Face face;
+ HB_FontRec hbFont;
+ HB_Face hbFace;
+
+ int used;
+ byte * buffer;
+
+ //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
+ FT_Stream stream;
+ Font font;
+ float scale;
+
+ ~FontEntry()
+ {
+ delete (char *)key;
+ delete buffer;
+ if(hbFace)
+ HB_FreeFace(hbFace);
+ if(face)
+ {
+ FT_Done_Face(face);
+ numFonts--;
+ if(!numFonts)
+ {
+ FT_Done_FreeType(ftLibrary);
+ ftLibrary = null;
+ }
+ }
+ }
+
+ FontEntry ::Load(FaceInfo info)
+ {
+ FontEntry fontEntry = (FontEntry)loadedFonts.FindString(info.fileName);
+ if(!fontEntry)
+ {
+ File file = FileOpen/*Buffered*/(info.fileName, read);
+ if(file)
+ {
+ FileSize fileSize = file.GetSize();
+ FT_Open_Args args = { 0 };
+ FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
+ FT_Stream stream = new0 FT_StreamRec[1];
+
+ if(!ftLibrary)
+ FT_Init_FreeType( &ftLibrary );
+
+ fontEntry = FontEntry { key = (uintptr)CopyString(info.fileName) };
+ fontEntry.stream = stream;
+
+ /*
+ fontEntry.buffer = new byte[fileSize];
+ file.Read(fontEntry.buffer, 1, fileSize);
+ */
+
+ //args.num_params = 1;
+ args.params = ¶m;
+
+ stream->size = fileSize;
+ stream->descriptor.pointer = file;
+ stream->read = FT_stream_load;
+ stream->close = FT_stream_close;
+
+ args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
+ args.stream = stream;
+ //args.pathname = fileName;
+ //args.memory_base = fontEntry.buffer;
+ //args.memory_size = fileSize;
+
+ // printf("Opening: %s\n", fileName);
+ FT_Open_Face( ftLibrary, &args, info.fontID, &fontEntry.face );
+
+ // delete file;
+ if(fontEntry.face)
+ {
+ fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
+ fontEntry.hbFont.klass = &hb_fontClass;
+ fontEntry.hbFont.userData = fontEntry; //.face;
+
+ numFonts++;
+ loadedFonts.Add(fontEntry);
+ }
+ else
+ {
+ delete fontEntry;
+ // printf("Error opening font %s\n", fileName);
+ }
+ }
+ }
+ return fontEntry;
+ }
+}
+
+static float FaceSetCharSize(FT_Face face, float size)
+{
+ float scale = 1;
+ if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
+ {
+ if(face->num_fixed_sizes)
+ {
+ int c;
+ int bestDiff = MAXINT, best = 0;
+ FT_Bitmap_Size * sizes = face->available_sizes;
+ int wishedHeight = (int)(size * 96 / 72);
+ for(c = 0; c < face->num_fixed_sizes; c++)
+ {
+ int diff = abs(sizes[c].height - wishedHeight);
+ if(diff < bestDiff)
+ {
+ best = c;
+ bestDiff = diff;
+ }
+ }
+ FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
+
+ if(!face->ascender)
+ face->ascender = sizes[best].height;
+ scale = (float)wishedHeight / sizes[best].height;
+ }
+ }
+ return scale;
+}
+
+#endif
+
+struct Glyph
+{
+ int ax, ay;
+ int x, y;
+ int w, h;
+ int left, top;
+ int bx, by;
+ int glyphNo;
+ float scale;
+};
+
+class GlyphPack : BTNode
+{
+ Glyph glyphs[256];
+ Bitmap bitmap { };
+ BinaryTree outlines { };
+ int cellWidth, cellHeight;
+
+ void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
+ {
+#if !defined(ECERE_NOTRUETYPE)
+ unichar c;
+ int maxWidth, maxHeight;
+ int cellWidth, cellHeight;
+ int width, height;
+ FontEntry fontEntry = null;
+ FT_Face faces[128];
+ float scales[128];
+ bool isGlyph = ((uint)key & 0x80000000) != 0;
+ //int curScript = ((uint)key & 0x7F000000) >> 24;
+ unichar testChar = 0;
+ /*
+ if(isGlyph)
+ {
+ switch(curScript)
+ {
+ case HB_Script_Arabic:
+ testChar = 0x621;
+ // printf("\nRendering arabic in %s (%d)\n", faceName, key & 0xFFFFFF);
+ break;
+ case HB_Script_Devanagari:
+ testChar = 0x905;
+ break;
+ case 60: testChar = 'あ'; break;
+ case 61: testChar = 0x3400; break;
+ }
+ }
+ */
+ /*
+ FT_GlyphSlot slot;
+ FT_Matrix matrix;
+ FT_Vector pen = { 0, 0 };
+ if(fakeItalic)
+ {
+ matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
+ matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
+ matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
+ matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
+ FT_Set_Transform( fontEntry.face, &matrix, &pen );
+ }
+ FT_Set_Char_Size( fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
+ */
+
+ maxWidth = 0;
+ maxHeight = 0;
+
+ for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
+ {
+ fontEntry = font.fontEntries[c];
+ if(fontEntry)
+ {
+ FT_Matrix matrix;
+ FT_Vector pen = { 0, 0 };
+
+ if(font.fakeItalic)
+ {
+ matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
+ matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
+ matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
+ matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
+ FT_Set_Transform(fontEntry.face, &matrix, &pen);
+ }
+ //FT_Set_Char_Size(fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
+ fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
+ if(!font.scale)
+ font.scale = fontEntry.scale;
+ if(!c)
+ {
+ if(!fontEntry.face->units_per_EM)
+ font.ascent = (int)((double)fontEntry.face->ascender);
+ else
+ font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
+ }
+
+ fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
+ fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
+ fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
+ fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
+ }
+ }
+
+ fontEntry = null;
+ for(c = 0; c < 128; c++)
+ {
+ int entry = 0;
+ if(isGlyph)
+ {
+ uint glyph = ((uint)key | c) & 0xFFFFFF;
+ for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
+ {
+ fontEntry = font.fontEntries[entry];
+ if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
+ {
+ if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
+ {
+ //printf("%s: Accepted entry %d ", faceName, entry);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ for(entry = startFontEntry; ; entry++)
+ {
+ uint glyph;
+ fontEntry = font.fontEntries[entry];
+ if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
+ {
+ if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
+ break;
+ }
+ }
+ }
+ scales[c] = fontEntry.scale;
+ faces[c] = fontEntry.face;
+ maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
+ maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
+ //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
+ }
+ this.cellWidth = cellWidth = maxWidth;
+ this.cellHeight = cellHeight = maxHeight;
+
+ width = maxWidth * 16;
+ height = maxHeight * 8;
+
+ if(true)
+ {
+ width = pow2i(width);
+ height = pow2i(height);
+ }
+
+ if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
+ {
+ Bitmap bitmap = this.bitmap;
+
+ bitmap.transparent = true;
+
+ for(c = 0; c < 128; c++)
+ {
+ FT_Int i, j, p, q;
+ FT_Int xMax, yMax;
+ int sx = (c % 16) * cellWidth;
+ int sy = (c / 16) * cellHeight;
+ int x, y;
+ byte * picture = (byte *)bitmap.picture;
+ Glyph * glyph = &glyphs[c];
+ FT_GlyphSlot slot = faces[c]->glyph;
+ double em_size = 1.0 * faces[c]->units_per_EM;
+ //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
+ double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
+ double ascender = faces[c]->ascender * y_scale;
+ int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
+
+ 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
+
+ FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
+
+ x = sx;
+ y = sy;
+ //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
+
+ glyph->left = slot->bitmap_left;
+ // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + height - (faces[c]->size->metrics.height >> 6);
+ // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (height - maxHeight);
+ //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - height);
+ //glyph->top = (int)(ascender - slot->bitmap_top) + (height - (faces[c]->size->metrics.height >> 6));
+
+ //glyph->top = (int)(ascender + (height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
+ //glyph->top = (int)(ascender + (height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
+
+ //glyph->top = (int)((ascender - slot->bitmap_top) + (height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
+
+ //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (height - (faces[c]->size->metrics.height >> 6));
+ //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (height - (faces[c]->size->metrics.height >> 6));
+
+ //glyph->top = (int)(ascender - slot->bitmap_top);// + (height - maxHeight);
+ glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
+
+ // 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);
+ xMax = x + slot->bitmap.width;
+ yMax = y + slot->bitmap.rows;
+
+ {
+ int total = 0;
+ int numPixels = 0;
+ //int max;
+ if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
+ {
+ for(j = y, q = 0; j<yMax; j++)
+ {
+ for(p = 0, i = x; i<xMax; i++)
+ {
+ byte value = ((byte *)slot->bitmap.buffer)[q + p++];
+ if(value > 32)
+ {
+ total += value;
+ numPixels++;
+ }
+ }
+ q += slot->bitmap.pitch;
+ }
+ }
+ //max = numPixels ? (total / numPixels) : 1;
+
+ for(j = y, q = 0; j<yMax; j++)
+ {
+ int bit = 0x80;
+ for(p = 0, i = x; i<xMax; i++)
+ {
+ if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
+ {
+ picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
+ bit >>= 1;
+ if(!bit) { bit = 0x80; p++; }
+ }
+ else
+ {
+ byte value = ((byte *)slot->bitmap.buffer)[q + p++];
+ picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
+ }
+ }
+ q += slot->bitmap.pitch;
+ }
+ }
+ glyph->x = sx;
+ glyph->y = sy;
+ glyph->w = slot->bitmap.width;
+ glyph->h = slot->bitmap.rows;
+ glyph->glyphNo = glyphNo;
+ glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
+ glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
+ glyph->scale = scales[c];
+
+ glyph->ax = (int)slot->advance.x;
+ glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
+ }
+ #if 0
+ {
+ int c;
+ char fileName[256];
+ static int fid = 0;
+ for(c = 0; c<256; c++)
+ bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
+ bitmap.pixelFormat = pixelFormat8;
+
+ /*
+ //strcpy(fileName, faceName);
+ if(flags)
+ strcat(fileName, "Bold");
+ */
+ sprintf(fileName, "font%d", fid++);
+ ChangeExtension(fileName, "pcx", fileName);
+
+ bitmap.Save(fileName, null, 0);
+ bitmap.pixelFormat = pixelFormatAlpha;
+ }
+ #endif
+
+ if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
+ {
+ bitmap.keepData = true; // For outlines
+ displaySystem.Lock();
+#if defined(__WIN32__)
+ // Is this check still required?
+ if(displaySystem.driver == class(OpenGLDisplayDriver)
+
+#if !defined(_GLES) && !defined(ECERE_STATIC)
+ || displaySystem.driver == class(Direct3D8DisplayDriver)
+ || displaySystem.driver == class(Direct3D9DisplayDriver)
+#endif
+
+ )
+#endif
+ bitmap.MakeDD(displaySystem);
+ displaySystem.Unlock();
+ }
+ }
+#endif
+ }
+
+ void RenderOutline(GlyphPack outline, Font font, DisplaySystem displaySystem)
+ {
+#if !defined(ECERE_NOTRUETYPE) && !defined(ECERE_VANILLA)
+ unichar c;
+ int pCellWidth = this.cellWidth, pCellHeight = this.cellHeight;
+ int cellWidth, cellHeight;
+ int width, height;
+ uintptr key = outline.key;
+ float outlineSize = (float)(key >> 16);
+ float fade = ((uint32)key & 0xFFFF) / 255.f;
+ Glyph * widest = null, * highest = null;
+ uint widestIndex = 0, highestIndex = 0;
+ Glyph * glyph;
+ int minX1 = MAXINT, minY1 = MAXINT;
+ int maxX2 = MININT, maxY2 = MININT;
+ int timesBigger = 2;
+ byte * bigger = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
+ byte * field = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
+ int ox, oy;
+
+ // Test biggest glyphs to determine cell width & height:
+ for(c = 0; c < 128; c++)
+ {
+ glyph = &glyphs[c];
+ if(glyph->w > (widest ? widest->w : 0))
+ widest = glyph, widestIndex = c;
+ if(glyph->h > (highest ? highest->h : 0))
+ highest = glyph, highestIndex = c;
+ }
+
+ cellWidth = 0;
+ cellHeight = 0;
+ for(glyph = widest; glyph; glyph = (glyph == widest && glyph != highest) ? highest : null)
+ {
+ int index = (glyph == widest) ? widestIndex : highestIndex;
+ int x = (index & 0xF) * pCellWidth, y = (index >> 4) * pCellHeight;
+ int w = pCellWidth * timesBigger, h = pCellHeight * timesBigger;
+ int x1,y1,x2,y2;
+
+ memset(bigger, 0, w * h);
+ BlitOutline(bigger, (w - pCellWidth)/2, (h - pCellHeight)/2, w, h, bitmap.picture, x, y, pCellWidth, pCellHeight, bitmap.width);
+ ComputeOutline(field, bigger, w, h, outlineSize, fade);
+ MeasureOutline(field, w, h, &x1, &y1, &x2, &y2);
+ minX1 = Min(minX1, x1);
+ minY1 = Min(minY1, y1);
+ maxX2 = Max(maxX2, x2);
+ maxY2 = Max(maxY2, y2);
+ }
+ {
+ int x1 = (timesBigger*pCellWidth - pCellWidth) / 2, x2 = x1 + pCellWidth-1;
+ int y1 = (timesBigger*pCellHeight - pCellHeight) / 2, y2 = y1 + pCellHeight-1;
+ ox = -Max(0, x1 - minX1);
+ oy = -Max(0, y1 - minY1);
+ cellWidth = pCellWidth - ox + Max(0, (maxX2 > x2) ? (maxX2 - x2) : 0);
+ cellHeight = pCellHeight - oy + Max(0, (maxY2 > y2) ? (maxY2 - y2) : 0);
+ }
+
+ width = cellWidth * 16;
+ height = cellHeight * 8;
+ if(true) //TEXTURES_MUST_BE_POWER_OF_2)
+ {
+ width = pow2i(width);
+ height = pow2i(height);
+ }
+
+ if(outline.bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false))
+ {
+ Bitmap bitmap = outline.bitmap;
+ byte * picture = (byte *)bitmap.picture;
+ memset(picture, 0, width * height);
+
+ for(c = 0; c < 128; c++)
+ {
+ Glyph * glyph = &outline.glyphs[c];
+ int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
+ int w = 0, h = 0;
+ memset(bigger, 0, cellWidth * cellHeight);
+ BlitOutline(bigger, -ox, -oy, cellWidth, cellHeight,
+ this.bitmap.picture,
+ (c & 0xF) * pCellWidth, (c >> 4) * pCellHeight,
+ pCellWidth, pCellHeight,
+ this.bitmap.width);
+
+ // Don't waste time on empty glyphs
+ if(glyphs[c].w)
+ {
+ ComputeOutline(field, bigger, cellWidth, cellHeight, outlineSize, fade);
+ MeasureOutline(field, cellWidth, cellHeight, &x1, &y1, &x2, &y2);
+ if(x2 > x1) w = x2-x1+1;
+ if(y2 > y1) h = y2-y1+1;
+ }
+ else
+ memset(field, 0, cellWidth * cellHeight);
+
+ glyph->x = (c & 0xF) * cellWidth;
+ glyph->y = (c >> 4) * cellHeight;
+ BlitOutline(picture, glyph->x, glyph->y, width, height, field, 0, 0, cellWidth, cellHeight, cellWidth);
+
+ glyph->glyphNo = glyphs[c].glyphNo;
+ glyph->scale = glyphs[c].scale;
+ glyph->left = glyphs[c].left + ox;
+ glyph->top = glyphs[c].top + oy;
+ if(w) { glyph->x += x1; glyph->left += x1; }
+ if(h) { glyph->y += y1; glyph->top += y1; }
+ glyph->w = w;
+ glyph->h = h;
+ glyph->bx = glyphs[c].bx;
+ glyph->by = glyphs[c].by;
+ glyph->ax = glyphs[c].ax;
+ glyph->ay = glyphs[c].ay;
+ }
+
+ #if 0
+ {
+ int c;
+ char fileName[256];
+ static int fid = 0;
+ for(c = 0; c<256; c++)
+ outline.bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
+ outline.bitmap.pixelFormat = pixelFormat8;
+
+ /*
+ //strcpy(fileName, faceName);
+ if(flags)
+ strcat(fileName, "Bold");
+ */
+ sprintf(fileName, "outline%d", fid++);
+ ChangeExtension(fileName, "pcx", fileName);
+
+ outline.bitmap.Save(fileName, null, 0);
+ outline.bitmap.pixelFormat = pixelFormatAlpha;
+ }
+
+ /*{
+ static int num = 0;
+ char fileName[MAX_LOCATION];
+
+ sprintf(fileName, "template%03d.png", num);
+ bitmap.Save(fileName, null, 0);
+ sprintf(fileName, "outline%03d.png", num++);
+ outline.bitmap.Save(fileName, null, 0);
+ }*/
+ #endif
+ if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
+ {
+ displaySystem.Lock();
+#if defined(__WIN32__)
+ // Is this check still required?
+ if(displaySystem.driver == class(OpenGLDisplayDriver)
+
+#if !defined(_GLES) && !defined(ECERE_STATIC)
+ || displaySystem.driver == class(Direct3D8DisplayDriver)
+ || displaySystem.driver == class(Direct3D9DisplayDriver)
+#endif
+ )
+#endif
+ bitmap.MakeDD(displaySystem);
+ displaySystem.Unlock();
+ }
+ }
+ delete bigger;
+ delete field;
+#endif
+ }
+}
+
+#if !defined(ECERE_NOTRUETYPE)
+static HB_ShaperItem shaper_item;
+
+static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
+{
+ static uint maxGlyphs = 0;
+ HB_Glyph * glyphs = shaper_item.glyphs;
+
+ shaper_item.kerning_applied = 0;
+ shaper_item.string = string;
+ shaper_item.stringLength = len;
+ shaper_item.item.script = script;
+ shaper_item.item.pos = 0;
+ shaper_item.item.length = shaper_item.stringLength;
+ if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
+ shaper_item.item.bidiLevel = 1;
+ else
+ shaper_item.item.bidiLevel = 0;
+ shaper_item.shaperFlags = 0;
+ shaper_item.font = &entry.hbFont;
+ shaper_item.face = entry.hbFace;
+ shaper_item.num_glyphs = shaper_item.item.length;
+ shaper_item.glyphIndicesPresent = 0;
+ shaper_item.initialGlyphCount = 0;
+ shaper_item.num_glyphs = 0;
+ shaper_item.glyphs = null;
+
+ while(!HB_ShapeItem(&shaper_item))
+ {
+ if(shaper_item.num_glyphs > maxGlyphs)
+ {
+ maxGlyphs = shaper_item.num_glyphs;
+ glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
+ shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
+ shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
+ shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
+ shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
+ }
+ else
+ {
+ shaper_item.glyphs = glyphs;
+ shaper_item.num_glyphs = maxGlyphs;
+ }
+ }
+
+ *numGlyphs = shaper_item.num_glyphs;
+ *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
+ return shaper_item.glyphs;
+}
+
+/*
+ delete shaper_item.glyphs;
+ delete shaper_item.attributes;
+ delete shaper_item.advances;
+ delete shaper_item.offsets;
+ delete shaper_item.log_clusters;
+*/
+#endif
+
+public class Font : struct
+{
+ BinaryTree glyphPacks { };
+ GlyphPack asciiPack { };
+ float size;
+ bool fakeItalic;
+ int height;
+ FontFlags flags;
+ char faceName[512];
+ DisplaySystem displaySystem;
+ int ascent;
+ float scale;
+ int numEntries;
+#if !defined(ECERE_NOTRUETYPE)
+ FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
+#endif
+
+ ~Font()
+ {
+ int entry;
+
+#if !defined(ECERE_NOTRUETYPE)
+ GlyphPack pack;
+ while((pack = (GlyphPack)glyphPacks.root))
+ {
+ glyphPacks.Remove(pack);
+ delete pack;
+ }
+#endif
+
+#if !defined(ECERE_NOTRUETYPE)
+ for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
+ {
+ FontEntry fontEntry = fontEntries[entry];
+ if(fontEntry)
+ {
+ fontEntry.used--;
+ if(!fontEntry.used)
+ {
+ loadedFonts.Remove(fontEntry);
+ delete fontEntry;
+ }
+ }
+ }
+#endif
+ }
+ public property int ascent
+ {
+ get { return (int)(this ? ascent * scale : 0); }
+ }
+
+ void Setup(DisplaySystem displaySystem, const String faceName, float size, FontFlags flags)
+ {
+ strcpy(this.faceName, faceName);
+ this.flags = flags;
+ this.displaySystem = displaySystem;
+ this.size = size;
+ }
+
+ bool LoadEntry(FaceInfo info)
+ {
+ bool result = false;
+ if(numEntries < MAX_FONT_LINK_ENTRIES)
+ {
+ FontEntry fontEntry = FontEntry::Load(info);
+ if(fontEntry)
+ {
+ if(!numEntries)
+ {
+ FT_Matrix matrix;
+ FT_Vector pen = { 0, 0 };
+ if(fakeItalic)
+ {
+ matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
+ matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
+ matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
+ matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
+ }
+ else
+ {
+ matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
+ matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
+ matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
+ matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
+ }
+ FT_Set_Transform(fontEntry.face, &matrix, &pen );
+ FaceSetCharSize(fontEntry.face, size);
+ height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
+ // printf("Font height is %d\n", height);
+ this.fakeItalic = info.fakeItalic;
+ }
+ fontEntries[numEntries++] = fontEntry;
+ fontEntry.used++;
+
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ Font ::Load(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ {
+ Font result = null;
+ Array<FaceInfo> infos = ResolveFont(faceName, size, flags);
+ if(infos)
+ {
+ Font font { };
+ bool success = false;
+ font.Setup(displaySystem, faceName, size, flags);
+ for(f : infos)
+ success |= font.LoadEntry(f);
+ if(success)
+ {
+ font.asciiPack.Render(font, 0, displaySystem);
+ result = font;
+ }
+ else
+ delete font;
+ infos.Free();
+ delete infos;
+ }
+ return result;
+ }
+
+ void ProcessString(DisplaySystem displaySystem, const byte * text, int len,
+ void (* callback)(Surface surface, Display display, int x, int y, Glyph glyph, Bitmap bitmap),
+ Surface surface, Display display, int * x, int y)
+ {
+#if !defined(ECERE_NOTRUETYPE)
+ if(this && fontEntries[0])
+ {
+ LFBSurface lfbSurface = surface ? surface.driverData : null;
+ int previousGlyph = 0;
+ FT_Face previousFace = 0;
+ int c, nb, glyphIndex = 0;
+ unichar lastPack = lfbSurface && lfbSurface.writingOutline ? -1 : 0;
+ GlyphPack pack = asciiPack, outline = null;
+ int wc = 0;
+ uint * glyphs = null;
+ int numGlyphs = 0;
+ bool rightToLeft = false;
+ int fontEntryNum = 0;
+ int glyphScript = 0;
+ FontEntry curFontEntry;
+ Glyph * lastGlyph = null;
+ int lastAX = 0;
+
+ pack.bitmap.alphaBlend = true;
+
+ for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
+ {
+ uint glyphNo = 0;
+ uint packNo;
+ if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
+ {
+ glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
+ rightToLeft ? glyphIndex-- : glyphIndex++;
+ }
+ else
+ {
+ HB_Script curScript = HB_Script_Common;
+ const byte * scriptStart = text + c;
+ //unichar nonASCIIch = 0;
+ unichar ch;
+ unichar ahead = 0;
+ unichar testChar = 0;
+ const String testLang = null;
+
+ while(true)
+ {
+ HB_Script script = HB_Script_Common;
+ ch = UTF8GetChar((const char *)text + c, &nb);
+ //if(ch > 127) nonASCIIch = ch;
+ if(!nb) break;
+ if(ch == 32 && curScript)
+ {
+ if(ahead)
+ script = curScript;
+ else
+ {
+ int a;
+ for(a = c + 1; a < c + len; a++)
+ {
+ if(text[a] != 32)
+ break;
+ }
+ if(a < c + len)
+ {
+ int nb;
+ unichar ahead = UTF8GetChar((const char *)text + a, &nb);
+ if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
+ script = curScript;
+ }
+ else
+ script = curScript;
+ }
+ }
+ else if(ch < 0x370)
+ script = HB_Script_Common;
+ else if(ch <= 0x11FF)
+ {
+ switch(ch & 0xFF00)
+ {
+ case 0x300: script = HB_Script_Greek; break;
+ case 0x400: script = HB_Script_Cyrillic; break;
+ case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
+ case 0x600: script = HB_Script_Arabic; break;
+ case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
+ case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
+ case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
+ case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
+ case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
+ case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
+ case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
+ case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
+ case 0xF00: script = HB_Script_Tibetan; break;
+ case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
+ case 0x1100: script = HB_Script_Hangul; break;
+ }
+ }
+ else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
+ else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
+ script = HB_Script_Hangul;
+ else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
+ else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
+ else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
+ else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
+ else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
+ //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
+ else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
+ else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
+ else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
+ if(curScript)
+ {
+ if(!script || (script != curScript))
+ break;
+ c += nb;
+ if(c >= len)
+ break;
+ }
+ else
+ {
+ if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
+ if(!script) { c += nb; break; }
+ curScript = script;
+ }
+ }
+ if(!nb) break;
+ fontEntryNum = 0;
+
+ if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
+ {
+ rightToLeft = false;
+ glyphNo = ch;
+ theCurrentScript = 0;
+ }
+ else
+ {
+ int len = c - (int)(scriptStart - text);
+ int max = len * 2 + 1;
+ if(max > utf16BufferSize)
+ {
+ utf16 = renew utf16 uint16[max];
+ utf16BufferSize = max;
+ }
+ wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
+ theCurrentScript = glyphScript = curScript;
+ }
+ switch(curScript)
+ {
+ case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
+ //printf("Arabic ");
+ break;
+ case HB_Script_Devanagari: testChar = 0x905;
+ testLang = "sa";
+ //printf("Devanagari ");
+ break;
+ case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
+ //printf("Hebrew ");
+ break;
+ default:
+ testChar = (ch == '\t') ? ' ' : ch;
+ /*
+ case 60: testChar = 'あ'; break;
+ case 61: testChar = 0x3400; break; //'愛'; break;
+ */
+ }
+
+ if(testChar)
+ {
+ // printf("Testing for char %x\n", testChar);
+ for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
+ {
+ if(fontEntries[fontEntryNum] && FT_Get_Char_Index(fontEntries[fontEntryNum].face, testChar))
+ break;
+ /*if(fontEntries[fontEntryNum])
+ printf("Not found in %s\n", (char *)fontEntries[fontEntryNum].key);*/
+ }
+ }
+
+ if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
+ {
+ FaceInfo info;
+ // Do we still have room to add an entry?
+ for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
+ if(!fontEntries[fontEntryNum])
+ break;
+ if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
+ continue;
+
+ if((info = ResolveCharFont(faceName, size, flags, testLang, testChar)))
+ {
+ FontEntry fontEntry = FontEntry::Load(info);
+ if(fontEntry)
+ {
+ FaceSetCharSize(fontEntry.face, size);
+ fontEntries[fontEntryNum] = fontEntry;
+ fontEntry.used++;
+ }
+ delete info;
+ }
+ }
+ if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
+ if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
+ {
+ fontEntries[fontEntryNum].font = this;
+ glyphs = shaping(fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
+ if(!numGlyphs)
+ continue;
+
+ glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
+ glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
+ rightToLeft ? glyphIndex-- : glyphIndex++;
+ }
+ }
+
+ curFontEntry = fontEntries[fontEntryNum];
+
+ packNo = glyphNo & 0xFFFFFF80;
+
+ if(packNo != lastPack)
+ {
+ if(glyphNo < 128)
+ pack = asciiPack;
+ else
+ {
+ pack = (GlyphPack)glyphPacks.Find((uintptr)packNo);
+ if(!pack)
+ {
+ pack = GlyphPack { key = (uintptr)packNo };
+ glyphPacks.Add(pack);
+ pack.Render(this, fontEntryNum, displaySystem);
+ }
+ }
+ pack.bitmap.alphaBlend = true;
+ lastPack = packNo;
+ #if !defined(ECERE_VANILLA)
+ if(lfbSurface && lfbSurface.writingOutline)
+ {
+ uint outlineNo = (((uint)surface.outline.size) << 16) | (uint16)(Min(surface.outline.fade, 257.0f) * 255);
+ outline = (GlyphPack)pack.outlines.Find(outlineNo);
+ if(!outline)
+ {
+ outline = { key = outlineNo };
+ pack.outlines.Add(outline);
+ pack.RenderOutline(outline, this, displaySystem);
+ }
+ }
+ #endif
+ }
+ if(pack)
+ {
+ int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
+ Glyph * glyph = &(outline ? outline : pack).glyphs[glyphNo & 0x7F];
+
+ int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
+ int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
+ int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
+
+ ax += offset;
+
+ if(previousGlyph && curFontEntry.face == previousFace)
+ {
+ FT_Vector delta = { 0, 0 };
+ FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
+ if(delta.x < 0) delta.x += (-delta.x) % 64;
+ else if(delta.x) delta.x += 64 - (delta.x % 64);
+ *x += delta.x * glyph->scale;
+ }
+ else
+ FaceSetCharSize(curFontEntry.face, size);
+
+ previousGlyph = glyph->glyphNo;
+ previousFace = curFontEntry.face;
+
+ if(callback)
+ callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, (outline ? outline : pack).bitmap);
+ *x += ax;
+
+ lastGlyph = glyph;
+ lastAX = ax;
+ }
+ if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
+ numGlyphs = 0;
+ }
+ if(lastGlyph)
+ {
+ int w = (lastGlyph->w + lastGlyph->left) * (1 << 6);
+ // Fix for advance != width + left (e.g. italic fonts)
+ if(w > lastAX)
+ *x += w - lastAX;
+ }
+ }
+ if(surface)
+ {
+ LFBSurface lfbSurface = surface.driverData;
+ lfbSurface.xOffset = 0;
+ }
+#endif
+ }
+};