Fixing font rendering bugs, harfbuzz still doesn't work right

This commit is contained in:
MattTuttle
2014-07-31 17:16:59 -05:00
parent 200e953641
commit 4503100713
8 changed files with 253 additions and 167 deletions

View File

@@ -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;
};

View File

@@ -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:

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}
}