Adding loadRange to Font

This commit is contained in:
MattTuttle
2014-07-30 17:08:16 -05:00
parent 83bb9d9b66
commit 200e953641
6 changed files with 157 additions and 68 deletions

View File

@@ -27,6 +27,10 @@ typedef GlyphData = {
@:autoBuild(lime.Assets.embedFont()) @:autoBuild(lime.Assets.embedFont())
class Font { class Font {
public var image:Image;
public var glyphRects:StringMap<GlyphRect>;
#if js #if js
private static var __canvas:CanvasElement; private static var __canvas:CanvasElement;
@@ -52,9 +56,54 @@ class Font {
} }
public function loadGlyphData (size:Int, glyphs:String="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. "):GlyphData { public function createImage ():Image {
var glyphRects = new StringMap<GlyphRect>(); glyphRects = new StringMap<GlyphRect>();
#if (cpp || neko)
var data = lime_font_create_image (handle);
if (data == null) {
return null;
} else {
for (glyph in cast (data.glyphs, Array<Dynamic>)) {
glyphRects.set (glyph.char, {
x: glyph.x,
y: glyph.y,
xOffset: glyph.xOffset,
yOffset: glyph.yOffset,
advance: glyph.advance,
width: glyph.width,
height: glyph.height,
});
}
glyphRects = data.glyphRects;
return new Image (new UInt8Array (data.image.data), data.image.width, data.image.height, data.image.bpp);
}
#end
}
public function loadRange (size:Int, start:Int, end:Int) {
#if (cpp || neko)
lime_font_load_range (handle, size, start, end);
#end
}
public function loadGlyphs (size:Int, glyphs:String="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. ") {
#if js #if js
@@ -212,34 +261,6 @@ class Font {
#elseif (cpp || neko) #elseif (cpp || neko)
lime_font_load_glyphs (handle, size, glyphs); lime_font_load_glyphs (handle, size, glyphs);
var data = lime_font_create_image (handle);
if (data == null) {
return null;
} else {
for (glyph in cast (data.glyphs, Array<Dynamic>)) {
glyphRects.set (glyph.char, {
x: glyph.x,
y: glyph.y,
xOffset: glyph.xOffset,
yOffset: glyph.yOffset,
advance: glyph.advance,
width: glyph.width,
height: glyph.height,
});
}
return {
glyphs: glyphRects,
image: new Image (new UInt8Array (data.image.data), data.image.width, data.image.height, data.image.bpp)
};
}
#end #end
@@ -248,6 +269,7 @@ class Font {
#if (cpp || neko) #if (cpp || neko)
private static var lime_font_load = System.load ("lime", "lime_font_load", 1); private static var lime_font_load = System.load ("lime", "lime_font_load", 1);
private static var lime_font_load_glyphs = System.load ("lime", "lime_font_load_glyphs", 3); private static var lime_font_load_glyphs = System.load ("lime", "lime_font_load_glyphs", 3);
private static var lime_font_load_range = System.load ("lime", "lime_font_load_range", 4);
private static var lime_font_create_image = System.load ("lime", "lime_font_create_image", 1); private static var lime_font_create_image = System.load ("lime", "lime_font_create_image", 1);
#end #end

View File

@@ -174,11 +174,11 @@ class Text {
} }
public function fromString (font:Font, text:String) { public function fromString (font:Font, size:Int, text:String) {
#if (cpp || neko) #if (cpp || neko)
return lime_text_from_string (handle, font.handle, text); return lime_text_from_string (handle, font.handle, size, text);
#end #end
@@ -186,7 +186,7 @@ class Text {
#if (cpp || neko) #if (cpp || neko)
private static var lime_text_create = System.load ("lime", "lime_text_create", 3); private static var lime_text_create = System.load ("lime", "lime_text_create", 3);
private static var lime_text_from_string = System.load ("lime", "lime_text_from_string", 3); private static var lime_text_from_string = System.load ("lime", "lime_text_from_string", 4);
#end #end
} }

View File

@@ -17,6 +17,7 @@ namespace lime {
typedef struct { typedef struct {
unsigned long codepoint; unsigned long codepoint;
unsigned int size;
FT_UInt index; FT_UInt index;
FT_Pos height; FT_Pos height;
@@ -29,13 +30,16 @@ namespace lime {
public: public:
Font (const char *fontFace); Font (const char *fontFace);
void LoadGlyphs (int size, const char *glyphs); void LoadGlyphs (size_t size, const char *glyphs);
value createImage (Image *image); void LoadRange (size_t size, unsigned long start, unsigned long end);
value renderToImage (Image *image);
FT_Face face; FT_Face face;
private: private:
bool InsertCodepoint (unsigned long codepoint, size_t size);
std::list<GlyphInfo> glyphList; std::list<GlyphInfo> glyphList;

View File

@@ -30,7 +30,6 @@
#include <ui/TouchEvent.h> #include <ui/TouchEvent.h>
#include <ui/Window.h> #include <ui/Window.h>
#include <ui/WindowEvent.h> #include <ui/WindowEvent.h>
#include <utils/CFFIValue.h>
#include <vm/NekoVM.h> #include <vm/NekoVM.h>
@@ -168,13 +167,25 @@ namespace lime {
} }
value lime_font_load_range (value fontHandle, value size, value start, value end) {
#ifdef LIME_FREETYPE
Font *font = (Font*)(intptr_t)val_float (fontHandle);
font->LoadRange (val_int (size), val_int (start), val_int (end));
#endif
return alloc_null ();
}
value lime_font_create_image (value fontHandle) { value lime_font_create_image (value fontHandle) {
#ifdef LIME_FREETYPE #ifdef LIME_FREETYPE
Image image; Image image;
Font *font = (Font*)(intptr_t)val_float (fontHandle); Font *font = (Font*)(intptr_t)val_float (fontHandle);
value data = alloc_empty_object (); value data = alloc_empty_object ();
alloc_field (data, val_id ("glyphs"), font->createImage (&image)); alloc_field (data, val_id ("glyphs"), font->renderToImage (&image));
alloc_field (data, val_id ("image"), image.Value ()); alloc_field (data, val_id ("image"), image.Value ());
return data; return data;
#else #else
@@ -207,7 +218,7 @@ namespace lime {
} }
value lime_text_from_string (value textHandle, value fontHandle, value textString) { value lime_text_from_string (value textHandle, value fontHandle, value size, value textString) {
#if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ)
Image image; Image image;
@@ -368,9 +379,10 @@ namespace lime {
DEFINE_PRIM (lime_image_load, 1); DEFINE_PRIM (lime_image_load, 1);
DEFINE_PRIM (lime_font_load, 1); DEFINE_PRIM (lime_font_load, 1);
DEFINE_PRIM (lime_font_load_glyphs, 3); DEFINE_PRIM (lime_font_load_glyphs, 3);
DEFINE_PRIM (lime_font_load_range, 4);
DEFINE_PRIM (lime_font_create_image, 1); DEFINE_PRIM (lime_font_create_image, 1);
DEFINE_PRIM (lime_text_create, 3); DEFINE_PRIM (lime_text_create, 3);
DEFINE_PRIM (lime_text_from_string, 3); DEFINE_PRIM (lime_text_from_string, 4);
DEFINE_PRIM (lime_key_event_manager_register, 2); DEFINE_PRIM (lime_key_event_manager_register, 2);
DEFINE_PRIM (lime_lzma_encode, 1); DEFINE_PRIM (lime_lzma_encode, 1);
DEFINE_PRIM (lime_lzma_decode, 1); DEFINE_PRIM (lime_lzma_decode, 1);

View File

@@ -134,7 +134,7 @@ namespace lime {
bool CompareGlyphCodepoint (const GlyphInfo &a, const GlyphInfo &b) { bool CompareGlyphCodepoint (const GlyphInfo &a, const GlyphInfo &b) {
return a.codepoint < b.codepoint; return a.codepoint < b.codepoint || a.size < b.size;
} }
@@ -188,8 +188,59 @@ namespace lime {
} }
bool Font::InsertCodepoint (unsigned long codepoint, size_t size) {
void Font::LoadGlyphs (int size, const char *glyphs) { GlyphInfo info;
info.codepoint = codepoint;
// 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)) {
info.size = size;
info.index = FT_Get_Char_Index (face, codepoint);
if (FT_Load_Glyph (face, info.index, FT_LOAD_DEFAULT) != 0) return false;
info.height = face->glyph->metrics.height;
glyphList.insert (first, info);
return true;
}
return false;
}
void Font::LoadRange (size_t size, unsigned long start, unsigned long end) {
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);
for (unsigned long codepoint = start; codepoint < end; codepoint++) {
InsertCodepoint (codepoint, size);
}
}
void Font::LoadGlyphs (size_t size, const char *glyphs) {
size_t hdpi = 72; size_t hdpi = 72;
size_t vdpi = 72; size_t vdpi = 72;
@@ -207,29 +258,13 @@ namespace lime {
char *g = (char*)glyphs; char *g = (char*)glyphs;
while (*g != 0) { while (*g != 0) {
GlyphInfo info; InsertCodepoint (readNextChar(g), size);
bool found = false;
info.codepoint = readNextChar(g);
std::list<GlyphInfo>::iterator first = glyphList.begin ();
first = std::lower_bound (first, glyphList.end (), info, CompareGlyphCodepoint);
if (info.codepoint < (*first).codepoint) {
info.index = FT_Get_Char_Index (face, info.codepoint);
if (FT_Load_Glyph (face, info.index, FT_LOAD_DEFAULT) != 0) continue;
info.height = face->glyph->metrics.height;
glyphList.insert (first, info);
}
} }
} }
value Font::createImage (Image *image) { value Font::renderToImage (Image *image) {
if (!init) { if (!init) {
@@ -254,8 +289,22 @@ namespace lime {
value rects = alloc_array (glyphList.size()); value rects = alloc_array (glyphList.size());
int rectsIndex = 0; int rectsIndex = 0;
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)
};
for (std::list<GlyphInfo>::iterator it = glyphList.begin(); it != glyphList.end(); it++) { for (std::list<GlyphInfo>::iterator it = glyphList.begin(); it != glyphList.end(); it++) {
// recalculate the character size for each glyph since it will vary
FT_Set_Char_Size (face, 0, (int)((*it).size*64), (int)(hdpi * hres), vdpi);
FT_Set_Transform (face, &matrix, NULL);
FT_Load_Glyph (face, (*it).index, FT_LOAD_DEFAULT); FT_Load_Glyph (face, (*it).index, FT_LOAD_DEFAULT);
if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL) != 0) continue; if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL) != 0) continue;

View File

@@ -30,21 +30,23 @@ class Main extends Application {
var text:Text; var text:Text;
var font = new Font ("assets/amiri-regular.ttf"); var font = new Font ("assets/amiri-regular.ttf");
font.loadRange (16, 32, 128);
font.loadGlyphs (32, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.");
font.loadGlyphs (32, "صِفخَلقخودكَمثلالشمسإذبَزَغتيحظىالضَجيعُبهانَلاءَمِعطار ");
var image = font.createImage ();
text = new Text (RightToLeft, ScriptArabic, "ar"); text = new Text (RightToLeft, ScriptArabic, "ar");
text.fromString (font, "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ"); text.fromString (font, 32, "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ");
var data = font.loadGlyphData (16, "صِفخَلقخودكَمثلالشمسإذبَزَغتيحظىالضَجيعُبهانَلاءَمِعطار ");
var image = data.image;
text = new Text (LeftToRight, ScriptLatin, "en"); text = new Text (LeftToRight, ScriptLatin, "en");
var data = font.loadGlyphData (32, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ."); text.fromString (font, 16, "The quick brown fox jumps over the lazy dog.");
text.fromString (font, "The quick brown fox jumps over the lazy dog.");
font = new Font ("assets/fireflysung.ttf"); font = new Font ("assets/fireflysung.ttf");
text = new Text (TopToBottom, ScriptHan, "ch"); font.loadGlyphs (32, "");
text.fromString (font, ""); // var image = font.createImage ();
var chinese = font.loadGlyphData (64, ""); text = new Text (TopToBottom, ScriptHan, "ch");
text.fromString (font, 32, "");
switch (context) { switch (context) {