diff --git a/lime/text/Font.hx b/lime/text/Font.hx index 0a071a80d..91767ae83 100644 --- a/lime/text/Font.hx +++ b/lime/text/Font.hx @@ -255,6 +255,17 @@ class Font { } + public function getGlyphMetrics (glyphs:GlyphSet):Array { + + #if (cpp || neko || nodejs) + return lime_font_get_glyph_metrics (__handle, glyphs); + #else + return null; + #end + + } + + public function loadRange (size:Int, start:Int, end:Int) { #if (flash || js) @@ -426,6 +437,7 @@ class Font { private static var lime_font_get_ascender = System.load ("lime", "lime_font_get_ascender", 1); private static var lime_font_get_descender = System.load ("lime", "lime_font_get_descender", 1); private static var lime_font_get_family_name = System.load ("lime", "lime_font_get_family_name", 1); + private static var lime_font_get_glyph_metrics = System.load ("lime", "lime_font_get_glyph_metrics", 2); private static var lime_font_get_height = System.load ("lime", "lime_font_get_height", 1); private static var lime_font_get_num_glyphs = System.load ("lime", "lime_font_get_num_glyphs", 1); private static var lime_font_get_underline_position = System.load ("lime", "lime_font_get_underline_position", 1); diff --git a/lime/text/GlyphMetrics.hx b/lime/text/GlyphMetrics.hx new file mode 100644 index 000000000..884c0b74c --- /dev/null +++ b/lime/text/GlyphMetrics.hx @@ -0,0 +1,15 @@ +package lime.text; + +/** + * ... + * @author ... + */ +class GlyphMetrics +{ + + public function new() + { + + } + +} \ No newline at end of file diff --git a/lime/text/GlyphSet.hx b/lime/text/GlyphSet.hx new file mode 100644 index 000000000..306ea3fd1 --- /dev/null +++ b/lime/text/GlyphSet.hx @@ -0,0 +1,62 @@ +package lime.text; + + +class GlyphSet { + + + public var glyphs:String; + public var ranges:Array; + + + public function new (glyphs:String = null, rangeStart:Int = -1, rangeEnd:Int = -1) { + + ranges = new Array (); + + if (glyphs != null) { + + addGlyphs (glyphs); + + } + + if (rangeStart > -1) { + + addRange (rangeStart, rangeEnd); + + } + + } + + + public function addGlyphs (glyphs:String):Void { + + this.glyphs += glyphs; + + } + + + public function addRange (start:Int = 0, end:Int = -1) { + + ranges.push (new GlyphRange (start, end)); + + } + + +} + + +private class GlyphRange { + + + public var end:Int; + public var start:Int; + + + public function new (start:Int, end:Int) { + + this.start = start; + this.end = end; + + } + + +} \ No newline at end of file diff --git a/lime/text/TextLayout.hx b/lime/text/TextEngine.hx similarity index 74% rename from lime/text/TextLayout.hx rename to lime/text/TextEngine.hx index 83a477b0d..4941fce47 100644 --- a/lime/text/TextLayout.hx +++ b/lime/text/TextEngine.hx @@ -6,7 +6,7 @@ import lime.system.System; @:access(lime.text.Font) -class TextLayout { +class TextEngine { public var direction (default, null):TextDirection; @@ -25,7 +25,7 @@ class TextLayout { this.language = language; #if (cpp || neko || nodejs) - __handle = lime_text_layout_create (direction, script, language); + __handle = lime_text_engine_create (direction, script, language); #end this.direction = direction; @@ -38,7 +38,7 @@ class TextLayout { #if (cpp || neko || nodejs) if (font.__handle == null) throw "Uninitialized font handle."; - return lime_text_layout_layout (__handle, font.__handle, size, text); + return lime_text_engine_layout (__handle, font.__handle, size, text); #else @@ -50,8 +50,8 @@ class TextLayout { #if (cpp || neko || nodejs) - private static var lime_text_layout_create = System.load ("lime", "lime_text_layout_create", 3); - private static var lime_text_layout_layout = System.load ("lime", "lime_text_layout_layout", 4); + private static var lime_text_engine_create = System.load ("lime", "lime_text_engine_create", 3); + private static var lime_text_engine_layout = System.load ("lime", "lime_text_engine_layout", 4); #end diff --git a/lime/text/TextFormat.hx b/lime/text/TextFormat.hx deleted file mode 100644 index 800bd964d..000000000 --- a/lime/text/TextFormat.hx +++ /dev/null @@ -1,65 +0,0 @@ -package lime.text; - - -import lime.system.System; - -@:access(lime.text.Font) - - -class TextLayout { - - - public var direction(default, null):TextDirection; - - #if (cpp || neko || nodejs) - public var handle:Dynamic; - #end - - - public function new (direction:TextDirection, script:TextScript, language:String) { - - #if (cpp || neko || nodejs) - handle = lime_text_create (direction, script, language); - #end - - this.direction = direction; - - } - - - public function fromString (font:Font, size:Int, text:String):Array { - - #if (cpp || neko || nodejs) - - if (font.__handle == null) throw "Uninitialized font handle."; - return lime_text_from_string (handle, font.__handle, size, text); - - #else - - return null; - - #end - - } - - - #if (cpp || neko || nodejs) - 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", 4); - #end - - -} - - -typedef Point = { - var x:Float; - var y:Float; -}; - - -typedef PosInfo = { - var codepoint:UInt; - var advance:Point; - var offset:Point; -}; \ No newline at end of file diff --git a/project/Build.xml b/project/Build.xml index 7be2f259d..9bec1b9d4 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -60,13 +60,14 @@ +
- +
diff --git a/project/include/text/Font.h b/project/include/text/Font.h index fcaee015d..b54fac338 100644 --- a/project/include/text/Font.h +++ b/project/include/text/Font.h @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -11,9 +12,6 @@ namespace lime { - class Image; - - typedef struct { unsigned long codepoint; @@ -37,6 +35,7 @@ namespace lime { int GetAscender (); int GetDescender (); wchar_t *GetFamilyName (); + value GetGlyphMetrics (GlyphSet *glyphSet); int GetHeight (); int GetNumGlyphs (); int GetUnderlinePosition (); diff --git a/project/include/text/GlyphSet.h b/project/include/text/GlyphSet.h new file mode 100644 index 000000000..d09467a09 --- /dev/null +++ b/project/include/text/GlyphSet.h @@ -0,0 +1,44 @@ +#ifndef LIME_TEXT_GLYPH_SET_H +#define LIME_TEXT_GLYPH_SET_H + + +#include +#include +#include + + +namespace lime { + + + struct GlyphRange { + + unsigned long start, end; + + GlyphRange () : start (-1), end (-1) {} + GlyphRange (unsigned long start, unsigned long end) : start (start), end (end) {} + + }; + + + class GlyphSet { + + + public: + + GlyphSet (std::wstring glyphs = NULL, unsigned long rangeStart = -1, unsigned long rangeEnd = -1); + GlyphSet (value glyphSet); + + void AddGlyphs (std::wstring glyphs); + void AddRange (unsigned long start = 0, unsigned long end = -1); + + std::wstring glyphs; + QuickVec ranges; + + + }; + + +} + + +#endif diff --git a/project/include/text/TextLayout.h b/project/include/text/TextEngine.h similarity index 62% rename from project/include/text/TextLayout.h rename to project/include/text/TextEngine.h index 521ebc79b..cc0737bea 100644 --- a/project/include/text/TextLayout.h +++ b/project/include/text/TextEngine.h @@ -1,5 +1,5 @@ -#ifndef LIME_TEXT_TEXT_LAYOUT_H -#define LIME_TEXT_TEXT_LAYOUT_H +#ifndef LIME_TEXT_TEXT_ENGINE_H +#define LIME_TEXT_TEXT_ENGINE_H #include @@ -9,13 +9,13 @@ namespace lime { - class TextLayout { + class TextEngine { public: - TextLayout (int direction, const char *script, const char *language); - ~TextLayout (); + TextEngine (int direction, const char *script, const char *language); + ~TextEngine (); value Layout (Font *font, size_t size, const char *text); diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index beb0cd054..131d39b73 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -180,6 +181,19 @@ namespace lime { } + value lime_font_get_glyph_metrics (value fontHandle, value glyphSet) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)(intptr_t)val_float (fontHandle); + GlyphSet glyphs = GlyphSet (glyphSet); + return font->GetGlyphMetrics (&glyphs); + #else + return alloc_null (); + #endif + + } + + value lime_font_get_height (value fontHandle) { #ifdef LIME_FREETYPE @@ -261,7 +275,7 @@ namespace lime { if (font) { value v = alloc_float ((intptr_t)font); - val_gc (v, lime_font_destroy); + //val_gc (v, lime_font_destroy); return v; } @@ -509,10 +523,10 @@ namespace lime { } - void lime_text_layout_destroy (value textHandle) { + void lime_text_engine_destroy (value textHandle) { #ifdef LIME_HARFBUZZ - TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); + TextEngine *text = (TextEngine*)(intptr_t)val_float (textHandle); delete text; text = 0; #endif @@ -520,13 +534,13 @@ namespace lime { } - value lime_text_layout_create (value direction, value script, value language) { + value lime_text_engine_create (value direction, value script, value language) { #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) - TextLayout *text = new TextLayout (val_int (direction), val_string (script), val_string (language)); + TextEngine *text = new TextEngine (val_int (direction), val_string (script), val_string (language)); value v = alloc_float ((intptr_t)text); - val_gc (v, lime_text_layout_destroy); + //val_gc (v, lime_text_engine_destroy); return v; #else @@ -538,11 +552,11 @@ namespace lime { } - value lime_text_layout_layout (value textHandle, value fontHandle, value size, value textString) { + value lime_text_engine_layout (value textHandle, value fontHandle, value size, value textString) { #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) - TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); + TextEngine *text = (TextEngine*)(intptr_t)val_float (textHandle); Font *font = (Font*)(intptr_t)val_float (fontHandle); return text->Layout (font, val_int (size), val_string (textString)); @@ -639,6 +653,7 @@ namespace lime { DEFINE_PRIM (lime_font_get_ascender, 1); DEFINE_PRIM (lime_font_get_descender, 1); DEFINE_PRIM (lime_font_get_family_name, 1); + DEFINE_PRIM (lime_font_get_glyph_metrics, 2); DEFINE_PRIM (lime_font_get_height, 1); DEFINE_PRIM (lime_font_get_num_glyphs, 1); DEFINE_PRIM (lime_font_get_underline_position, 1); @@ -663,8 +678,8 @@ namespace lime { DEFINE_PRIM (lime_renderer_flip, 1); DEFINE_PRIM (lime_render_event_manager_register, 2); DEFINE_PRIM (lime_system_gettimer, 0); - DEFINE_PRIM (lime_text_layout_create, 3); - DEFINE_PRIM (lime_text_layout_layout, 4); + DEFINE_PRIM (lime_text_engine_create, 3); + DEFINE_PRIM (lime_text_engine_layout, 4); DEFINE_PRIM (lime_touch_event_manager_register, 2); DEFINE_PRIM (lime_update_event_manager_register, 2); DEFINE_PRIM (lime_window_close, 1); diff --git a/project/src/text/Font.cpp b/project/src/text/Font.cpp index 0c70734a5..621697c15 100644 --- a/project/src/text/Font.cpp +++ b/project/src/text/Font.cpp @@ -271,8 +271,15 @@ namespace lime { static int id_codepoint; static int id_height; + static int id_horizontalAdvance; + static int id_horizontalBearingX; + static int id_horizontalBearingY; + static int id_index; static int id_offset; static int id_size; + static int id_verticalAdvance; + static int id_verticalBearingX; + static int id_verticalBearingY; static int id_width; static int id_x; static int id_y; @@ -293,6 +300,33 @@ namespace lime { } + static void initialize () { + + if (!init) { + + id_width = val_id ("width"); + id_height = val_id ("height"); + id_x = val_id ("x"); + id_y = val_id ("y"); + id_offset = val_id ("offset"); + id_size = val_id ("size"); + id_codepoint = val_id ("codepoint"); + + id_horizontalAdvance = val_id ("horizontalAdvance"); + id_horizontalBearingX = val_id ("horizontalBearingX"); + id_horizontalBearingY = val_id ("horizontalBearingY"); + id_index = val_id ("index"); + id_verticalAdvance = val_id ("verticalAdvance"); + id_verticalBearingX = val_id ("verticalBearingX"); + id_verticalBearingY = val_id ("verticalBearingY"); + + init = true; + + } + + } + + Font::Font (void* face) { this->face = face; @@ -451,11 +485,11 @@ namespace lime { FT_ULong char_code; FT_UInt glyph_index; - char_code = FT_Get_First_Char ((FT_Face)(FT_Face)face, &glyph_index); + char_code = FT_Get_First_Char ((FT_Face)face, &glyph_index); while (glyph_index != 0) { - if (FT_Load_Glyph ((FT_Face)(FT_Face)face, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_DEFAULT) == 0) { + if (FT_Load_Glyph ((FT_Face)face, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_DEFAULT) == 0) { glyph *g = new glyph; result = FT_Outline_Decompose (&((FT_Face)face)->glyph->outline, &ofn, g); @@ -662,6 +696,83 @@ namespace lime { } + void GetGlyphMetrics_Push (FT_Face face, FT_UInt glyphIndex, value glyphList) { + + if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_DEFAULT) == 0) { + + value metrics = alloc_empty_object (); + + alloc_field (metrics, id_height, alloc_int (((FT_Face)face)->glyph->metrics.height)); + alloc_field (metrics, id_horizontalBearingX, alloc_int (((FT_Face)face)->glyph->metrics.horiBearingX)); + alloc_field (metrics, id_horizontalBearingY, alloc_int (((FT_Face)face)->glyph->metrics.horiBearingY)); + alloc_field (metrics, id_horizontalAdvance, alloc_int (((FT_Face)face)->glyph->metrics.horiAdvance)); + alloc_field (metrics, id_index, alloc_int (glyphIndex)); + alloc_field (metrics, id_verticalBearingX, alloc_int (((FT_Face)face)->glyph->metrics.vertBearingX)); + alloc_field (metrics, id_verticalBearingY, alloc_int (((FT_Face)face)->glyph->metrics.vertBearingY)); + alloc_field (metrics, id_verticalAdvance, alloc_int (((FT_Face)face)->glyph->metrics.vertAdvance)); + + val_array_push (glyphList, metrics); + + } + + } + + + value Font::GetGlyphMetrics (GlyphSet *glyphSet) { + + initialize (); + + value glyphList = alloc_array (0); + + if (!glyphSet->glyphs.empty ()) { + + for (wchar_t& c : glyphSet->glyphs) { + + GetGlyphMetrics_Push ((FT_Face)face, FT_Get_Char_Index ((FT_Face)face, c), glyphList); + + } + + } + + for (GlyphRange range : glyphSet->ranges) { + + if (range.start == 0 && range.end == -1) { + + FT_UInt glyphIndex; + FT_ULong charCode = FT_Get_First_Char ((FT_Face)face, &glyphIndex); + + while (glyphIndex != 0) { + + GetGlyphMetrics_Push ((FT_Face)face, glyphIndex, glyphList); + charCode = FT_Get_Next_Char ((FT_Face)face, charCode, &glyphIndex); + + } + + } else { + + unsigned long end = range.end; + + if (end < 0) { + + end = ((FT_Face)face)->num_glyphs - 1; + + } + + for (unsigned long i = range.start; i <= end; i++) { + + GetGlyphMetrics_Push ((FT_Face)face, i, glyphList); + + } + + } + + } + + return glyphList; + + } + + int Font::GetHeight () { return ((FT_Face)face)->height; @@ -788,18 +899,7 @@ namespace lime { value Font::RenderToImage (ImageBuffer *image) { - if (!init) { - - id_width = val_id ("width"); - id_height = val_id ("height"); - id_x = val_id ("x"); - id_y = val_id ("y"); - id_offset = val_id ("offset"); - id_size = val_id ("size"); - id_codepoint = val_id ("codepoint"); - init = true; - - } + initialize (); glyphList.sort (CompareGlyphHeight); diff --git a/project/src/text/GlyphSet.cpp b/project/src/text/GlyphSet.cpp new file mode 100644 index 000000000..2c9660fb8 --- /dev/null +++ b/project/src/text/GlyphSet.cpp @@ -0,0 +1,89 @@ +#include + + +namespace lime { + + + static int id_end; + static int id_glyphs; + static int id_ranges; + static int id_start; + static bool init = false; + + + GlyphSet::GlyphSet (std::wstring glyphs, unsigned long rangeStart, unsigned long rangeEnd) { + + //this->glyphs = 0; + //ranges = new QuickVec (); + + if (!glyphs.empty ()) { + + AddGlyphs (glyphs); + + } + + if (rangeStart > -1) { + + AddRange (rangeStart, rangeEnd); + + } + + } + + + GlyphSet::GlyphSet (value glyphSet) { + + if (!init) { + + id_end = val_id ("end"); + id_glyphs = val_id ("glyphs"); + id_ranges = val_id ("ranges"); + id_start = val_id ("start"); + init = true; + + } + + if (!val_is_null (glyphSet)) { + + value glyphs = val_field (glyphSet, id_glyphs); + + if (!val_is_null (glyphs)) { + + this->glyphs = val_wstring (glyphs); + + } + + value ranges = val_field (glyphSet, id_ranges); + int length = val_array_size (ranges); + + for (int i = 0; i < length; i++) { + + value range = val_array_i (ranges, i); + AddRange (val_int (val_field (range, id_start)), val_int (val_field (range, id_end))); + + } + + } + + } + + + void GlyphSet::AddGlyphs (std::wstring glyphs) { + + if (!glyphs.empty ()) { + + this->glyphs += glyphs; + + } + + } + + + void GlyphSet::AddRange (unsigned long start, unsigned long end) { + + ranges.push_back (GlyphRange (start, end)); + + } + + +} \ No newline at end of file diff --git a/project/src/text/TextLayout.cpp b/project/src/text/TextEngine.cpp similarity index 92% rename from project/src/text/TextLayout.cpp rename to project/src/text/TextEngine.cpp index 350b48487..5809ffbeb 100644 --- a/project/src/text/TextLayout.cpp +++ b/project/src/text/TextEngine.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include FT_FREETYPE_H @@ -9,7 +9,7 @@ namespace lime { - TextLayout::TextLayout (int direction, const char *script, const char *language) { + TextEngine::TextEngine (int direction, const char *script, const char *language) { if (strlen (script) != 4) return; @@ -25,14 +25,14 @@ namespace lime { } - TextLayout::~TextLayout () { + TextEngine::~TextEngine () { hb_buffer_destroy ((hb_buffer_t*)mBuffer); } - value TextLayout::Layout (Font *font, size_t size, const char *text) { + value TextEngine::Layout (Font *font, size_t size, const char *text) { font->SetSize (size);