#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 <freetype/ttunpat.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>
#endif
#undef uint
+#undef strlen
#ifdef __MSC__
#pragma warning(disable:4244)
#if !defined(ECERE_NOTRUETYPE)
-static unichar UTF16GetChar(uint16 *string, int * nw)
+#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]))
return ch;
}
-static HB_Bool hb_stringToGlyphs(HB_Font font, uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
+static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
{
- FT_Face face = (FT_Face)font->userData;
+ FT_Face face = ((FontEntry)font->userData).face;
int glyph_pos = 0;
int c, nw;
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++)
- advances[c] = 0; // ### not tested right now
+ {
+ GlyphInfo * 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, uint16 * string, uint length)
+static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
{
- FT_Face face = (FT_Face)font->userData;
+ FT_Face face = ((FontEntry)font->userData).face;
int c, nw;
for (c = 0; c < length; c += nw)
return HB_Err_Invalid_Argument;
error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
- *length = ftlen;
+ *length = (uint)ftlen;
return (HB_Error)error;
}
return error;
if (face->glyph->format != ft_glyph_format_outline)
- return (HB_Error)HB_Err_Invalid_GPOS_SubTable;
+ 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_GPOS_SubTable;
+ return (HB_Error)HB_Err_Invalid_SubTable;
- *xpos = face->glyph->outline.points[point].x;
- *ypos = face->glyph->outline.points[point].y;
+ *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 glyph, HB_GlyphMetrics *metrics)
+static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
{
- // ###
- metrics->x = metrics->y = metrics->width = metrics->height = metrics->xOffset = metrics->yOffset = 0;
+ 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)
+ {
+ 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)
{
- return 0; // ####
+ 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_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
};
-static uint FT_stream_load(FT_Stream stream, uint offset, byte * buffer, uint count)
+static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
{
File f = stream->descriptor.pointer;
- f.Seek(offset, start);
- return count ? f.Read(buffer, 1, count) : 0;
+ f.Seek((int)offset, start);
+ return count ? f.Read(buffer, 1, (uint)count) : 0;
}
static void FT_stream_close(FT_Stream stream)
#undef CompareString
static BinaryTree loadedFonts
{
- CompareKey = (void *)BinaryTree::CompareString
+ CompareKey = (void *)BinaryTree::CompareString
};
class FontEntry : BTNode
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()
{
- char * fileName = (char *)key;
- delete fileName;
+ delete (char *)key;
delete buffer;
if(hbFace)
HB_FreeFace(hbFace);
}
}
}
+
+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 GlyphInfo
int x, y;
int w, h;
int left, top;
+ int bx, by;
int glyphNo;
+ float scale;
};
-#define MAX_FONT_LINK_ENTRIES 10
-
class GlyphPack : BTNode
{
GlyphInfo glyphs[256];
int width, height;
FontEntry fontEntry = null;
FT_Face faces[128];
- bool isGlyph = key & 0x80000000;
- int curScript = (key & 0x7F000000) >> 24;
+ float scales[128];
+ bool isGlyph = ((uint)key & 0x80000000) != 0;
+ //int curScript = ((uint)key & 0x7F000000) >> 24;
unichar testChar = 0;
/*
if(isGlyph)
// printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
break;
case HB_Script_Devanagari:
- testChar = 0x905;
+ testChar = 0x905;
break;
case 60: testChar = 'あ'; break;
case 61: testChar = 0x3400; break;
FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
*/
- maxWidth = 0;
+ maxWidth = 0;
maxHeight = 0;
for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
{
FT_Matrix matrix;
FT_Vector pen = { 0, 0 };
-
+
if(font.fakeItalic)
{
matrix.xx = (FT_Fixed)( 1.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);
+ //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)
+ {
+ 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 = fontEntry.face->size->metrics.x_scale;
- fontEntry.hbFont.y_scale = fontEntry.face->size->metrics.y_scale;
+ fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
+ fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
}
}
int entry = 0;
if(isGlyph)
{
- uint glyph = (key | c) & 0xFFFFFF;
+ uint glyph = ((uint)key | c) & 0xFFFFFF;
for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
{
fontEntry = font.fontEntries[entry];
{
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 ", font.faceName, entry);
break;
}
{
uint glyph;
fontEntry = font.fontEntries[entry];
- if((glyph = FT_Get_Char_Index(fontEntry.face, (key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
+ 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));
+ 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));
}
cellWidth = maxWidth;
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 = faces[c]->size->metrics.y_ppem / em_size;
+ //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 ? ((key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], key | c);
+ 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); // + ((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));
-
+
//glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
- glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6)) / 2;
+ 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;
{
int total = 0;
int numPixels = 0;
- int max;
+ //int max;
if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
{
for(j = y, q = 0; j<yMax; j++)
q += slot->bitmap.pitch;
}
}
- max = numPixels ? (total / numPixels) : 1;
+ //max = numPixels ? (total / numPixels) : 1;
for(j = y, q = 0; j<yMax; j++)
{
{
picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
bit >>= 1;
- if(!bit) { bit = 0x80; p++; }
+ if(!bit) { bit = 0x80; p++; }
}
else
{
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 = slot->advance.x;
- glyph->ay = slot->advance.y + (64 - slot->advance.y % 64);
+ glyph->ax = (int)slot->advance.x;
+ glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
}
#if 0
{
char fileName[256];
static int fid = 0;
for(c = 0; c<256; c++)
- bitmap.palette[c] = ColorAlpha { 255, { c,c,c } };
+ bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
bitmap.pixelFormat = pixelFormat8;
-
+
/*
//strcpy(fileName, faceName);
if(flags)
}
#if !defined(ECERE_NOTRUETYPE)
-default:
-HB_LineBreakClass HB_GetLineBreakClass(unichar ch)
-{
- return 0; //(HB_LineBreakClass)QUnicodeTables::lineBreakClass(ch);
-}
-
-void HB_GetUnicodeCharProperties(unichar ch, HB_CharCategory *category, int *combiningClass)
-{
- *category = GetCharCategory(ch); //(HB_CharCategory)QChar::category(ch);
- *combiningClass = 0; //QChar::combiningClass(ch);
-}
-
-HB_CharCategory HB_GetUnicodeCharCategory(unichar ch)
-{
- return GetCharCategory(ch);
-}
-
-int HB_GetUnicodeCharCombiningClass(unichar ch)
-{
- return 0; // QChar::combiningClass(ch);
-}
-
-uint16 HB_GetMirroredChar(uint16 ch)
-{
- return 0; //QChar::mirroredChar(ch);
-}
-private:
-
static HB_ShaperItem shaper_item;
static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
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;
+ 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;
+ 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.glyphs = glyphs;
shaper_item.num_glyphs = maxGlyphs;
- }
+ }
}
*numGlyphs = shaper_item.num_glyphs;
- *rightToLeft = shaper_item.item.bidiLevel % 2;
+ *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
return shaper_item.glyphs;
}
int height;
FontFlags flags;
char faceName[512];
+ DisplaySystem displaySystem;
+ int ascent;
+ float scale;
~Font()
{
}
#endif
}
+ public property int ascent
+ {
+ get { return (int)(this ? ascent * scale : 0); }
+ }
};
public class LFBDisplay : struct
{
char fileName[MAX_FILENAME];
FontFlags flags;
+ bool forgive;
};
static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
{
- if(fontType == TRUETYPE_FONTTYPE)
+ //if(fontType == TRUETYPE_FONTTYPE)
{
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(weight == font->elfLogFont.lfWeight && italic == (font->elfLogFont.lfItalic != 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];
- uint32 type;
- int size = 1024;
- int sizeFileName = 1024;
+ DWORD type;
+ DWORD size = 1024;
+ DWORD sizeFileName = 1024;
char * occurence;
- if(RegEnumValue(key, value++, entryName, &size, null, &type, fontFileName, &sizeFileName) != ERROR_SUCCESS)
+ if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
break;
- if((occurence = SearchString(entryName, 0, font->elfFullName, false, false)))
+ if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
{
int c;
for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
else if(ch != ' ') break;
}
if(c >= 0) continue;
- for(c = (int)(occurence - entryName) + strlen(font->elfFullName); ; c++)
+ for(c = (int)(occurence - 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;
strcpy(fileName, fontFileName);
RegCloseKey(key);
return 0;
- }
+ }
}
RegCloseKey(key);
return 1;
}
}
}
- return 1;
+ return 1;
}
#endif
+#if !defined(ECERE_NOTRUETYPE)
static int utf16BufferSize = 0;
static uint16 * utf16 = null;
+#endif
public class LFBDisplayDriver : DisplayDriver
{
case 2: stride = width; break;
}
}
- bitmap.stride = stride;
+ bitmap.stride = stride;
bitmap.width = width;
bitmap.height = height;
bitmap.size = (uint32) stride * (uint32)height;
}
bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
- {
+ {
bool result = false;
LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
/*
DWORD c;
DWORD * picture = (DWORD *)src.picture;
-
+
for(c = 0; c<src.size; c++, picture++)
{
if(*picture & 0xFFFFFF)
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;
LFBDisplay lfbDisplay = display ? display.driverData : null;
LFBSurface lfbSurface = surface.driverData;
uint index;
- if(display) color = color /*& 0xFFFFFF*/;
+ //if(display) color = color & 0xFFFFFF;
lfbSurface.foregroundRgb = color;
if(lfbSurface.font && lfbDisplay)
case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
case pixelFormat888: lfbSurface.foreground = color; break;
case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
- case pixelFormatText:
+ case pixelFormatText:
if(display)
lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
else
{
LFBDisplay lfbDisplay = display ? display.driverData : null;
LFBSurface lfbSurface = surface.driverData;
- color = color /*& 0xFFFFFF*/;
+ //color = color & 0xFFFFFF;
switch(lfbSurface.bitmap.pixelFormat)
{
case pixelFormat8:
case pixelFormat565: lfbSurface.background = (Color565)color; break;
case pixelFormat888: lfbSurface.background = color; break;
case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
- case pixelFormatText:
+ case pixelFormatText:
if(display)
lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
else
((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
else
{
- ((uint16 *)lfbSurface.bitmap.picture)[offset] =
+ ((uint16 *)lfbSurface.bitmap.picture)[offset] =
(((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
}
}
break;
}
}
- else
+ else
{
if(x2 >= x1)
{
void memset_32_aligned(void *buf, int val, int dwords)
{
// Qword align
- if ((int)(buf) & 4)
+ if ((int)(buf) & 4)
{
*((uint32 *)(buf)) = val;
buf = ((uint32 *)(buf))+1;
dwords--;
}
-
- if (dwords > 1)
+
+ if (dwords > 1)
{
__asm {
cld
emms
};
}
-
+
// Final dword
if (dwords & 1) *((int*)(buf)) = val;
}*/
void memset_32(void *buf, uint32 val, uint32 dwords)
{
int align = 0;
- if ((uint32)(buf) & 3)
+ if ((uint32)(buf) & 3)
{
align = 4;
dwords--;
-
+
if (((uint32)(buf) & 1))
{
- *(byte *)(buf) = (byte)(val&0xFF);
+ *(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);
+ *(uint16 *)(buf) = (uint16)(val&0xFFFF);
buf = ((uint16 *)(buf))+1;
val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
align-=2;
{
if (align == 1)
{
- *(byte *)(buf) = (byte)(val&0xFF);
+ *(byte *)(buf) = (byte)(val&0xFF);
}
else
{
- *(uint16 *)(buf) = (uint16)(val&0xFFFF);
- if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
+ *(uint16 *)(buf) = (uint16)(val&0xFFFF);
+ if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
}
}
}
{
int w,y;
byte * theOffset;
-
+
w = x2-x1+1;
if(w<1) return;
}
else
{
- if(surface.background.a == 255 || lfbSurface.clearing)
+ if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
{
switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
{
{
int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
//memset_32((uint32 *) theOffset,color,w);
- /*_asm
+ /-*_asm
{
push edi
push ecx
mov eax,color
mov edx,y
mov ecx,w
-
+
start:
push ecx
-
+
rep stosd
add edi,ebx
pop ecx
- dec edx
+ dec edx
jnz start
pop edx
pop ebx
{
int c;
for(c = 0; c < w; c++, dest++)
- {
- Color destColor;
+ {
+ 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 c;
for(c = 0; c < w; c++, dest++)
- {
+ {
int dr = dest->color.r;
int dg = dest->color.g;
int db = dest->color.b;
if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
{
bitmap.Free();
- bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
+ bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
(lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
}
if(bitmap)
{
w = Abs(w);
sw = Abs(sw);
- flip = true;
+ flip = true;
}
s2dw=(float)w / sw;
ColorAlpha * backsrc;
ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
- if(flip < 0) source += sw-1;
+ if(flip) source += sw-1;
adddest -= w;
yerr = 0;
for(y=0; y<sh; y++)
{
w = Abs(w);
sw = Abs(sw);
- flip = true;
+ flip = true;
}
s2dw=(float)w / sw;
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;
float scaleX = (float)sw / w;
int x0 = x * sw / w;
int x1 = Min(x0 + 1, sw - 1);
float beta = x * scaleX - x0;
- ColorAlpha color;
ColorAlpha src00, src01, src10, src11;
float a1,r1,g1,b1,a2,r2,g2,b2;
float a,r,g,b;
else if(alphaWrite)
dest->a = (byte)a;
}
- }
+ }
dest += adddest;
}
}
- else
- {
+ else
+ {
int y;
for (y = 0; y < h; y++)
{
float a = 0, r = 0, g = 0, b = 0;
int numPixels = 0;
int i, j;
- ColorAlpha color;
for (i = y0; i <= y1; i++)
for (j = x0; j <= x1; j++)
{
g += pixel.color.g;
b += pixel.color.b;
numPixels++;
- }
+ }
a /= numPixels;
r /= numPixels;
g /= numPixels;
b /= numPixels;
{
- ColorAlpha src = *source;
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));
}
}
dest += adddest;
- }
+ }
}
}
else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
delete fontEntry;
}
}
- }
+ }
#endif
delete font;
}
}
- Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
{
void * result = null;
{
char fileName[MAX_LOCATION];
bool fakeItalic = flags.italic;
- char linkCfgPath[MAX_LOCATION];
int fontID = 0;
#if !defined(__WIN32__)
File linkCfg;
#endif
- char * ecereFonts = getenv("ECERE_FONTS");
+ const char * ecereFonts = getenv("ECERE_FONTS");
if(!ecereFonts) ecereFonts = "<:ecere>";
#if !defined(__WIN32__)
- strcpy(linkCfgPath, ecereFonts);
- PathCat(linkCfgPath, "linking.cfg");
- linkCfg = FileOpen(linkCfgPath, read);
+ {
+ char linkCfgPath[MAX_LOCATION];
+
+ 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(!FileExists(fileName))
{
strcat(fileName, ".ttf");
strlwr(fileName);
fakeItalic = false;
-
+
if(flags.italic && !FileExists(fileName))
{
strcpy(fileName, ecereFonts);
fakeItalic = true;
}
+ // 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;
+ }
+ }
+
#if defined(__WIN32__)
if(!FileExists(fileName))
{
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, (DWORD)&fontData, 0);
+
+ EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
+ if(!fontData.fileName[0] && flags.bold)
+ {
+ fontData.forgive = true;
+ EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
+ }
if(!fontData.fileName[0])
{
// Fake italic
fontData.flags.italic = false;
- EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (DWORD)&fontData, 0);
+ EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
fakeItalic = true;
}
-
+
if(fontData.fileName[0])
{
GetWindowsDirectory(fileName, MAX_LOCATION);
PathCat(fileName, fontData.fileName);
}
ReleaseDC(0, hdc);
- }
- #else
+ }
+ #elif !defined(ECERE_NOFONTCONFIG)
{
char * fileName2;
FcResult result = 0;
if(testChar)
FcCharSetAddChar(charSet, testChar);
-
+
pattern = FcPatternBuild(null,
//FC_SOURCE, FcTypeString, "freetype",
FC_FAMILY, FcTypeString, faceName,
// printf("Locating %s\n", faceName);
if(matched)
{
- FcPatternGetString(matched, FC_FAMILY, 0, &family);
+ FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
//printf("Fontconfig returned %s\n", family);
}
if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
{
double fontSize;
- FcPatternGetString (matched, FC_FILE, 0, &fileName2);
+ FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
strcpy(fileName, fileName2);
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;
- uint32 type;
- int size = 1024;
- RegQueryValueEx(key, faceName,null, &type, links, &size);
+ {
+ // 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
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 = (uint)CopyString(fileName) };
+ fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
fontEntry.stream = stream;
/*
{
fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
fontEntry.hbFont.klass = &hb_fontClass;
- fontEntry.hbFont.userData = fontEntry.face;
+ fontEntry.hbFont.userData = fontEntry; //.face;
numFonts++;
loadedFonts.Add(fontEntry);
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);
- font.height = ((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
+ 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;
GetWindowsDirectory(fileName, MAX_LOCATION);
PathCat(fileName, "fonts");
PathCat(fileName, fontName);
-#elif defined(ECERE_NOFONTCONFIG)
+#elif !defined(ECERE_NOFONTCONFIG)
if(getenv("ECERE_FONTS"))
{
strcpy(fileName, ecereFonts);
matched = FcFontMatch (0, pattern, &result);
if(matched)
{
- FcPatternGetString(matched, FC_FAMILY, 0, &family);
+ FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
// printf("Fontconfig returned %s\n", family);
}
if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
- FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
+ FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
{
double fontSize;
- FcPatternGetString (matched, FC_FILE, 0, &fileName2);
+ FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
strcpy(fileName, fileName2);
}
}
#endif
-
+
}
linksPos += c;
- while(links[linksPos]) linksPos++;
+ while(links[linksPos] && links[linksPos] != ',') linksPos++;
linksPos++;
}
}
}
-
+
if(!result)
UnloadFont(displaySystem, font);
else
}
#if !defined(ECERE_NOTRUETYPE)
- void ::ProcessString(Font font, DisplaySystem displaySystem, byte * text, int len,
- void (* callback)(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft),
+ 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])
{
int previousGlyph = 0;
+ FT_Face previousFace = 0;
int c, nb, glyphIndex = 0;
unichar lastPack = 0;
GlyphPack pack = font.asciiPack;
- int wc;
- uint * glyphs;
+ int wc = 0;
+ uint * glyphs = null;
int numGlyphs = 0;
bool rightToLeft = false;
- int rightToLeftOffset = 0;
int fontEntryNum = 0;
- bool foundArabic = false;
int glyphScript = 0;
-
+ FontEntry curFontEntry;
+
pack.bitmap.alphaBlend = true;
- for(c = 0; c < len || glyphIndex < numGlyphs;)
+ for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
{
- uint glyphNo;
+ uint glyphNo = 0;
uint packNo;
- if(glyphIndex < numGlyphs)
+ if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
{
- glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
+ glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
+ rightToLeft ? glyphIndex-- : glyphIndex++;
}
else
{
HB_Script curScript = HB_Script_Common;
- byte * scriptStart = text + c;
+ const byte * scriptStart = text + c;
+ //unichar nonASCIIch = 0;
unichar ch;
unichar ahead = 0;
unichar testChar = 0;
- char * testLang = null;
-
+#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
+ const char * testLang = null;
+#endif
+
while(true)
{
HB_Script script = HB_Script_Common;
- ch = UTF8GetChar(text + c, &nb);
+ ch = UTF8GetChar((const char *)text + c, &nb);
+ //if(ch > 127) nonASCIIch = ch;
if(!nb) break;
if(ch == 32 && curScript)
{
if(a < c + len)
{
int nb;
- unichar ahead = UTF8GetChar(text + a, &nb);
+ unichar ahead = UTF8GetChar((const char *)text + a, &nb);
if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
- script = curScript;
+ script = curScript;
}
else
script = curScript;
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 >= 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;
if(c >= len)
break;
}
- else
+ else
{
if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
if(!script) { c += nb; break; }
{
rightToLeft = false;
glyphNo = ch;
+ theCurrentScript = 0;
}
else
{
utf16 = renew utf16 uint16[max];
utf16BufferSize = max;
}
- wc = UTF8toUTF16BufferLen(scriptStart, utf16, max, len);
- glyphScript = curScript;
+ 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";
+ 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;
+ testChar = (ch == '\t') ? ' ' : ch;
/*
case 60: testChar = 'あ'; break;
case 61: testChar = 0x3400; break; //'愛'; break;
printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
}
}
-
- if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
+
+ if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
{
-#if !defined(__WIN32__)
+#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
int fontID = 0;
double fontSize = font.size;
FcResult result = 0;
char * family;
FontEntry fontEntry;
char * fileName = null;
- bool fakeItalic = false;
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__)
+
+#if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
{
charSet = FcCharSetCreate();
FcCharSetAddChar(charSet, testChar);
matched = FcFontMatch (0, pattern, &result);
if(matched)
{
- FcPatternGetString(matched, FC_FAMILY, 0, &family);
+ FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
//printf("Fontconfig returned %s\n", family);
}
- if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, &family) == FcResultMatch)
+ if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
{
- FcPatternGetString (matched, FC_FILE, 0, &fileName);
+ 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);
if(file)
{
FileSize fileSize = file.GetSize();
- FT_Open_Args args = { 0 };
+ 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 = (uint)CopyString(fileName) };
+ fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
fontEntry.stream = stream;
-
+
//args.num_params = 1;
args.params = ¶m;
// delete file;
if(fontEntry.face)
{
- fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
+ fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
fontEntry.hbFont.klass = &hb_fontClass;
- fontEntry.hbFont.userData = fontEntry.face;
+ fontEntry.hbFont.userData = fontEntry; //.face;
numFonts++;
loadedFonts.Add(fontEntry);
}
if(fontEntry)
{
- FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
+ FaceSetCharSize(fontEntry.face, font.size);
font.fontEntries[fontEntryNum] = fontEntry;
fontEntry.used++;
}
}
- if(pattern) FcPatternDestroy(pattern);
+ 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)
{
- int c;
+ font.fontEntries[fontEntryNum].font = font;
glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
if(!numGlyphs)
continue;
- if(rightToLeft /*&& surface*/)
- {
- int c;
- rightToLeftOffset = 0;
- for(c = 0; c<numGlyphs; c++)
- {
- GlyphInfo * glyph;
- glyphNo = glyphs[c] | 0x80000000 | (glyphScript << 24);
- packNo = glyphNo & 0xFFFFFF80;
- if(packNo != lastPack)
- {
- pack = (GlyphPack)font.glyphPacks.Find(packNo);
- if(!pack)
- {
- pack = GlyphPack { key = packNo };
- font.glyphPacks.Add(pack);
- pack.Render(font, fontEntryNum, displaySystem);
- }
- pack.bitmap.alphaBlend = true;
- lastPack = packNo;
- }
- glyph = &pack.glyphs[glyphNo & 0x7F];
-
- rightToLeftOffset += (int)glyph->ax - glyph->left;
- }
- *x += rightToLeftOffset;
- }
- glyphIndex = 0;
- glyphNo = glyphs[glyphIndex++] | 0x80000000 | (glyphScript << 24);
+ 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)
+ if(glyphNo < 128)
pack = font.asciiPack;
else
{
- pack = (GlyphPack)font.glyphPacks.Find(packNo);
+ pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
if(!pack)
{
- pack = GlyphPack { key = packNo };
+ pack = GlyphPack { key = (uintptr)packNo };
font.glyphPacks.Add(pack);
pack.Render(font, fontEntryNum, displaySystem);
}
}
if(pack)
{
+ int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
GlyphInfo * glyph = &pack.glyphs[glyphNo & 0x7F];
- /*if(previousGlyph)
+ 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;
- FT_Get_Kerning(font.fontEntries[fontEntryNum].face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
- *x += delta.x;
+ 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;
}
- previousGlyph = glyph->glyphNo;*/
- callback(surface, display, x, y, glyph, pack.bitmap, rightToLeft);
+ else
+ FaceSetCharSize(curFontEntry.face, font.size);
+
+ previousGlyph = glyph->glyphNo;
+ previousFace = curFontEntry.face;
+
+ if(callback)
+ callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
+ *x += ax;
}
- if(numGlyphs && glyphIndex == numGlyphs)
- {
- *x += rightToLeftOffset;
+ if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
numGlyphs = 0;
- }
}
}
if(surface)
}
}
- void ::AddWidth(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
- {
- if(rightToLeft)
- {
- *x -= (int)glyph->ax - glyph->left;
- }
- else
- {
- *x += glyph->ax;
- }
- }
#endif
- void FontExtent(DisplaySystem displaySystem, Font font, byte * text, int len, int * width, int * height)
+ void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
{
if(displaySystem && displaySystem.flags.text && len)
{
- if(width)
+ if(width)
{
int num = len;
*width = num * textCellW;
{
int w = 0;
#if !defined(ECERE_NOTRUETYPE)
- ProcessString(font, displaySystem, text, len, AddWidth, null, null, &w, 0);
+ ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
#endif
//*width = (w + 64 - w % 64) >> 6;
*width = w >> 6;
}
#if !defined(ECERE_NOTRUETYPE)
- void ::OutputGlyph(Surface surface, Display display, int * x, int y, GlyphInfo * glyph, Bitmap bitmap, bool rightToLeft)
+ void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
{
- LFBSurface lfbSurface = surface.driverData;
- //lfbSurface.xOffset = (*x & 0x3F);
- if(rightToLeft)
- {
- surface.driver.Blit(display, surface, bitmap, (*x >> 6) - glyph->w, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
- *x -= (int)glyph->ax - glyph->left;
- }
- else
- {
- surface.driver.Blit(display, surface, bitmap, (*x >> 6) + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
- *x += glyph->ax;
- }
+ surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
}
#endif
- void WriteText(Display display, Surface surface, int x, int y, byte * text, int len)
+ void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
{
LFBSurface lfbSurface = surface.driverData;
if(display && display.displaySystem.flags.text)
x /= textCellW;
y /= textCellH;
- if(y > surface.box.bottom || y < surface.box.top)
+ if(y > surface.box.bottom || y < surface.box.top)
return;
coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
*coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
}
}
- else
+ else
{
lfbSurface.writingText = true;
#if !defined(ECERE_NOTRUETYPE)
x <<= 6;
- ProcessString(lfbSurface.font, surface.displaySystem, text, len, OutputGlyph, surface, display, &x, y);
+ ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
#endif
lfbSurface.writingText = false;
}
}
-
+
void TextFont(Display display, Surface surface, Font font)
{
LFBSurface lfbSurface = surface.driverData;
void TextOpacity(Display display, Surface surface, bool opaque)
{
- LFBSurface lfbSurface = surface.driverData;
}
- void TextExtent(Display display, Surface surface, byte * text, int len, int * width, int * height)
+ void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
{
LFBSurface lfbSurface = surface.driverData;
FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
delete mesh.texCoords;
}
- bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
+ bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
{
bool result = false;
-
- if((!mesh.flags.vertices || mesh.vertices || (mesh.vertices = new Vector3Df[mesh.nVertices])) &&
- (!mesh.flags.normals || mesh.normals || (mesh.normals = new Vector3Df[mesh.nVertices])) &&
- (!mesh.flags.texCoords1 || mesh.texCoords || (mesh.texCoords = new Pointf [mesh.nVertices])))
+ if(mesh.nVertices == nVertices)
+ {
+ result = true;
+ // Same number of vertices, adding features (Leaves the other features pointers alone)
+ if(mesh.flags != flags)
+ {
+ if(!mesh.flags.vertices && flags.vertices)
+ {
+ if(flags.doubleVertices)
+ {
+ mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
+ }
+ else
+ mesh.vertices = new Vector3Df[nVertices];
+ }
+ if(!mesh.flags.normals && flags.normals)
+ {
+ if(flags.doubleNormals)
+ {
+ mesh.normals = (Vector3Df *)new Vector3D[nVertices];
+ }
+ else
+ mesh.normals = new Vector3Df[nVertices];
+ }
+ if(!mesh.flags.texCoords1 && flags.texCoords1)
+ mesh.texCoords = new Pointf[nVertices];
+ if(!mesh.flags.colors && flags.colors)
+ mesh.colors = new ColorRGBAf[nVertices];
+ }
+ }
+ else
+ {
result = true;
+ // New number of vertices, reallocate all current and new features
+ flags |= mesh.flags;
+ if(flags.vertices)
+ {
+ if(flags.doubleVertices)
+ {
+ mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
+ }
+ else
+ mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
+ }
+ if(flags.normals)
+ {
+ if(flags.doubleNormals)
+ {
+ mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
+ }
+ else
+ mesh.normals = renew mesh.normals Vector3Df[nVertices];
+ }
+ if(flags.texCoords1)
+ mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
+ if(flags.colors)
+ mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
+ }
return result;
}