Fixing font rendering bugs, harfbuzz still doesn't work right
This commit is contained in:
@@ -17,7 +17,7 @@ namespace lime {
|
||||
typedef struct {
|
||||
|
||||
unsigned long codepoint;
|
||||
unsigned int size;
|
||||
size_t size;
|
||||
FT_UInt index;
|
||||
FT_Pos height;
|
||||
|
||||
@@ -30,17 +30,19 @@ namespace lime {
|
||||
public:
|
||||
|
||||
Font (const char *fontFace);
|
||||
void LoadGlyphs (size_t size, const char *glyphs);
|
||||
void LoadRange (size_t size, unsigned long start, unsigned long end);
|
||||
value renderToImage (Image *image);
|
||||
void LoadGlyphs (const char *glyphs);
|
||||
void LoadRange (unsigned long start, unsigned long end);
|
||||
void SetSize (size_t size);
|
||||
value RenderToImage (Image *image);
|
||||
|
||||
FT_Face face;
|
||||
|
||||
private:
|
||||
|
||||
bool InsertCodepoint (unsigned long codepoint, size_t size);
|
||||
bool InsertCodepoint (unsigned long codepoint);
|
||||
|
||||
std::list<GlyphInfo> glyphList;
|
||||
size_t mSize;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LIME_GRAPHICS_TEXT_H
|
||||
|
||||
|
||||
#include <hx/CFFI.h>
|
||||
#include <hb.h>
|
||||
|
||||
|
||||
@@ -19,7 +20,7 @@ namespace lime {
|
||||
Text (hb_tag_t direction, const char *script, const char *language);
|
||||
~Text ();
|
||||
|
||||
void fromString (Font *font, const char *text);
|
||||
value FromString (Font *font, size_t size, const char *text);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -159,7 +159,8 @@ namespace lime {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
font->LoadGlyphs (val_int (size), val_string (glyphs));
|
||||
font->SetSize (val_int (size));
|
||||
font->LoadGlyphs (val_string (glyphs));
|
||||
#endif
|
||||
|
||||
return alloc_null ();
|
||||
@@ -171,7 +172,8 @@ namespace lime {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
font->LoadRange (val_int (size), val_int (start), val_int (end));
|
||||
font->SetSize (val_int (size));
|
||||
font->LoadRange (val_int (start), val_int (end));
|
||||
#endif
|
||||
|
||||
return alloc_null ();
|
||||
@@ -185,7 +187,7 @@ namespace lime {
|
||||
Image image;
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
value data = alloc_empty_object ();
|
||||
alloc_field (data, val_id ("glyphs"), font->renderToImage (&image));
|
||||
alloc_field (data, val_id ("glyphs"), font->RenderToImage (&image));
|
||||
alloc_field (data, val_id ("image"), image.Value ());
|
||||
return data;
|
||||
#else
|
||||
@@ -221,11 +223,9 @@ namespace lime {
|
||||
value lime_text_from_string (value textHandle, value fontHandle, value size, value textString) {
|
||||
|
||||
#if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ)
|
||||
Image image;
|
||||
Text *text = (Text*)(intptr_t)val_float (textHandle);
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
text->fromString(font, val_string (textString));
|
||||
return alloc_null ();
|
||||
return text->FromString(font, val_int (size), val_string (textString));
|
||||
#else
|
||||
return alloc_null ();
|
||||
#endif
|
||||
|
||||
@@ -117,11 +117,10 @@ namespace lime {
|
||||
|
||||
static int id_x;
|
||||
static int id_y;
|
||||
static int id_x_offset;
|
||||
static int id_y_offset;
|
||||
static int id_advance;
|
||||
static int id_offset;
|
||||
static int id_width;
|
||||
static int id_height;
|
||||
static int id_size;
|
||||
static int id_codepoint;
|
||||
static bool init = false;
|
||||
|
||||
@@ -134,7 +133,7 @@ namespace lime {
|
||||
|
||||
bool CompareGlyphCodepoint (const GlyphInfo &a, const GlyphInfo &b) {
|
||||
|
||||
return a.codepoint < b.codepoint || a.size < b.size;
|
||||
return a.codepoint < b.codepoint && a.size < b.size;
|
||||
|
||||
}
|
||||
|
||||
@@ -188,20 +187,20 @@ namespace lime {
|
||||
|
||||
}
|
||||
|
||||
bool Font::InsertCodepoint (unsigned long codepoint, size_t size) {
|
||||
bool Font::InsertCodepoint (unsigned long codepoint) {
|
||||
|
||||
GlyphInfo info;
|
||||
info.codepoint = codepoint;
|
||||
info.size = mSize;
|
||||
|
||||
// search for duplicates, if any
|
||||
std::list<GlyphInfo>::iterator first = glyphList.begin ();
|
||||
first = std::lower_bound (first, glyphList.end (), info, CompareGlyphCodepoint);
|
||||
|
||||
// skip duplicates unless they are different sizes
|
||||
if (codepoint < (*first).codepoint ||
|
||||
(codepoint == (*first).codepoint && size != (*first).size)) {
|
||||
// if (codepoint < (*first).codepoint ||
|
||||
// (codepoint == (*first).codepoint && mSize != (*first).size)) {
|
||||
|
||||
info.size = size;
|
||||
info.index = FT_Get_Char_Index (face, codepoint);
|
||||
|
||||
if (FT_Load_Glyph (face, info.index, FT_LOAD_DEFAULT) != 0) return false;
|
||||
@@ -210,13 +209,14 @@ namespace lime {
|
||||
glyphList.insert (first, info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void Font::LoadRange (size_t size, unsigned long start, unsigned long end) {
|
||||
void Font::SetSize (size_t size) {
|
||||
|
||||
size_t hdpi = 72;
|
||||
size_t vdpi = 72;
|
||||
@@ -231,40 +231,34 @@ namespace lime {
|
||||
FT_Set_Char_Size (face, 0, (int)(size*64), (int)(hdpi * hres), vdpi);
|
||||
FT_Set_Transform (face, &matrix, NULL);
|
||||
|
||||
mSize = size;
|
||||
|
||||
}
|
||||
|
||||
void Font::LoadRange (unsigned long start, unsigned long end) {
|
||||
|
||||
for (unsigned long codepoint = start; codepoint < end; codepoint++) {
|
||||
|
||||
InsertCodepoint (codepoint, size);
|
||||
InsertCodepoint (codepoint);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Font::LoadGlyphs (size_t size, const char *glyphs) {
|
||||
|
||||
size_t hdpi = 72;
|
||||
size_t vdpi = 72;
|
||||
size_t hres = 100;
|
||||
FT_Matrix matrix = {
|
||||
(int)((1.0/hres) * 0x10000L),
|
||||
(int)((0.0) * 0x10000L),
|
||||
(int)((0.0) * 0x10000L),
|
||||
(int)((1.0) * 0x10000L)
|
||||
};
|
||||
|
||||
FT_Set_Char_Size (face, 0, (int)(size*64), (int)(hdpi * hres), vdpi);
|
||||
FT_Set_Transform (face, &matrix, NULL);
|
||||
void Font::LoadGlyphs (const char *glyphs) {
|
||||
|
||||
char *g = (char*)glyphs;
|
||||
|
||||
while (*g != 0) {
|
||||
|
||||
InsertCodepoint (readNextChar(g), size);
|
||||
InsertCodepoint (readNextChar (g));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
value Font::renderToImage (Image *image) {
|
||||
value Font::RenderToImage (Image *image) {
|
||||
|
||||
if (!init) {
|
||||
|
||||
@@ -272,9 +266,8 @@ namespace lime {
|
||||
id_height = val_id ("height");
|
||||
id_x = val_id ("x");
|
||||
id_y = val_id ("y");
|
||||
id_x_offset = val_id ("xOffset");
|
||||
id_y_offset = val_id ("yOffset");
|
||||
id_advance = val_id ("advance");
|
||||
id_offset = val_id ("offset");
|
||||
id_size = val_id ("size");
|
||||
id_codepoint = val_id ("codepoint");
|
||||
init = true;
|
||||
|
||||
@@ -369,12 +362,16 @@ namespace lime {
|
||||
value v = alloc_empty_object ();
|
||||
alloc_field (v, id_x, alloc_int (x));
|
||||
alloc_field (v, id_y, alloc_int (y));
|
||||
alloc_field (v, id_x_offset, alloc_int (face->glyph->metrics.horiBearingX / 64));
|
||||
alloc_field (v, id_y_offset, alloc_int (face->glyph->metrics.horiBearingY / 64));
|
||||
alloc_field (v, id_advance, alloc_int (face->glyph->metrics.horiAdvance / 64));
|
||||
alloc_field (v, id_width, alloc_int (bitmap.width));
|
||||
alloc_field (v, id_height, alloc_int (bitmap.rows));
|
||||
|
||||
value offset = alloc_empty_object ();
|
||||
alloc_field (offset, id_x, alloc_int (face->glyph->bitmap_left));
|
||||
alloc_field (offset, id_y, alloc_int (face->glyph->bitmap_top));
|
||||
alloc_field (v, id_offset, offset);
|
||||
|
||||
alloc_field (v, id_codepoint, alloc_int ((*it).codepoint));
|
||||
alloc_field (v, id_size, alloc_int ((*it).size));
|
||||
val_array_set_i (rects, rectsIndex++, v);
|
||||
|
||||
x += bitmap.width + 1;
|
||||
|
||||
@@ -11,23 +11,28 @@ namespace lime {
|
||||
|
||||
if (strlen(script) != 4) return;
|
||||
|
||||
hb_script_t tag = (hb_script_t)HB_TAG (script[0], script[1], script[2], script[3]);
|
||||
|
||||
buffer = hb_buffer_create ();
|
||||
hb_buffer_set_direction (buffer, (hb_direction_t)direction);
|
||||
hb_buffer_set_script (buffer, (hb_script_t)HB_TAG (script[0], script[1], script[2], script[3]));
|
||||
hb_buffer_set_script (buffer, tag);
|
||||
hb_buffer_set_language (buffer, hb_language_from_string (language, strlen (language)));
|
||||
|
||||
}
|
||||
|
||||
Text::~Text () {
|
||||
|
||||
hb_buffer_reset (buffer);
|
||||
hb_buffer_destroy (buffer);
|
||||
|
||||
}
|
||||
|
||||
void Text::fromString (Font *font, const char *text) {
|
||||
value Text::FromString (Font *font, size_t size, const char *text) {
|
||||
|
||||
font->SetSize (size);
|
||||
|
||||
// layout the text
|
||||
size_t len = strlen (text);
|
||||
int len = strlen (text);
|
||||
hb_buffer_add_utf8 (buffer, text, len, 0, len);
|
||||
hb_font_t *hb_font = hb_ft_font_create (font->face, NULL);
|
||||
hb_shape (hb_font, buffer, NULL, 0);
|
||||
@@ -35,21 +40,37 @@ namespace lime {
|
||||
unsigned int glyph_count;
|
||||
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos (buffer, &glyph_count);
|
||||
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions (buffer, &glyph_count);
|
||||
hb_direction_t direction = hb_buffer_get_direction (buffer);
|
||||
|
||||
float hres = 16.0;
|
||||
float hres = 100;
|
||||
value pos_info = alloc_array (glyph_count);
|
||||
int posIndex = 0;
|
||||
|
||||
for (int i = 0; i < glyph_count; i++) {
|
||||
|
||||
int codepoint = glyph_info[i].codepoint;
|
||||
float x_advance = glyph_pos[i].x_advance / (float)(hres * 64);
|
||||
float x_offset = glyph_pos[i].x_offset / (float)(hres * 64);
|
||||
float y_advance = glyph_pos[i].y_advance / (float)(64);
|
||||
float y_offset = glyph_pos[i].y_offset / (float)(64);
|
||||
hb_glyph_position_t pos = glyph_pos[i];
|
||||
|
||||
value obj = alloc_empty_object ();
|
||||
alloc_field (obj, val_id ("codepoint"), alloc_float (glyph_info[i].codepoint));
|
||||
|
||||
value advance = alloc_empty_object ();
|
||||
alloc_field (advance, val_id ("x"), alloc_float (pos.x_advance / (float)(hres * 64)));
|
||||
alloc_field (advance, val_id ("y"), alloc_float (pos.y_advance / (float)64));
|
||||
alloc_field (obj, val_id ("advance"), advance);
|
||||
|
||||
value offset = alloc_empty_object ();
|
||||
alloc_field (offset, val_id ("x"), alloc_float (pos.x_offset / (float)(hres * 64)));
|
||||
alloc_field (offset, val_id ("y"), alloc_float (pos.y_offset / (float)64));
|
||||
alloc_field (obj, val_id ("offset"), offset);
|
||||
|
||||
val_array_set_i (pos_info, posIndex++, obj);
|
||||
|
||||
}
|
||||
|
||||
hb_font_destroy (hb_font);
|
||||
|
||||
return pos_info;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user