From 74592ed5bde475a58d1ef2f63fab6a5e0a135155 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 14 Mar 2015 23:50:15 -0700 Subject: [PATCH] Rename (and refactor) TextLayout, update GlyphMetrics --- lime/text/Font.hx | 10 +- lime/text/Glyph.hx | 2 +- lime/text/GlyphMetrics.hx | 12 +- lime/text/GlyphPosition.hx | 32 +++ lime/text/TextEngine.hx | 75 ------ lime/text/TextLayout.hx | 224 ++++++++++++++++++ project/Build.xml | 3 +- project/include/text/Font.h | 1 - project/include/text/GlyphSet.h | 44 ---- project/include/text/TextEngine.h | 35 --- project/include/text/TextLayout.h | 49 ++++ project/src/ExternalInterface.cpp | 60 ++++- project/src/text/GlyphSet.cpp | 89 ------- .../text/{TextEngine.cpp => TextLayout.cpp} | 72 ++++-- 14 files changed, 415 insertions(+), 293 deletions(-) create mode 100644 lime/text/GlyphPosition.hx delete mode 100644 lime/text/TextEngine.hx create mode 100644 lime/text/TextLayout.hx delete mode 100644 project/include/text/GlyphSet.h delete mode 100644 project/include/text/TextEngine.h create mode 100644 project/include/text/TextLayout.h delete mode 100644 project/src/text/GlyphSet.cpp rename project/src/text/{TextEngine.cpp => TextLayout.cpp} (53%) diff --git a/lime/text/Font.hx b/lime/text/Font.hx index 3cb702762..2178632b9 100644 --- a/lime/text/Font.hx +++ b/lime/text/Font.hx @@ -3,6 +3,7 @@ package lime.text; import lime.graphics.Image; import lime.graphics.ImageBuffer; +import lime.math.Vector2; import lime.utils.ByteArray; import lime.utils.UInt8Array; import lime.system.System; @@ -101,13 +102,10 @@ class Font { var value = lime_font_get_glyph_metrics (__handle, glyph); var metrics = new GlyphMetrics (); + metrics.advance = new Vector2 (value.horizontalAdvance, value.verticalAdvance); metrics.height = value.height; - metrics.horizontalAdvance = value.horizontalAdvance; - metrics.horizontalBearingX = value.horizontalBearingX; - metrics.horizontalBearingY = value.horizontalBearingY; - metrics.verticalAdvance = value.verticalAdvance; - metrics.verticalBearingX = value.verticalBearingX; - metrics.verticalBearingY = value.verticalBearingY; + metrics.horizontalBearing = new Vector2 (value.horizontalBearingX, value.horizontalBearingY); + metrics.verticalBearing = new Vector2 (value.verticalBearingX, value.verticalBearingY); return metrics; #else diff --git a/lime/text/Glyph.hx b/lime/text/Glyph.hx index e406cb471..3fcebadec 100644 --- a/lime/text/Glyph.hx +++ b/lime/text/Glyph.hx @@ -1,7 +1,7 @@ package lime.text; -abstract Glyph(Int) from Int to Int { +abstract Glyph(Int) from Int to Int from UInt to UInt { public function new (i:Int) { diff --git a/lime/text/GlyphMetrics.hx b/lime/text/GlyphMetrics.hx index 2e4b1ce2e..faf9714ad 100644 --- a/lime/text/GlyphMetrics.hx +++ b/lime/text/GlyphMetrics.hx @@ -1,16 +1,16 @@ package lime.text; +import lime.math.Vector2; + + class GlyphMetrics { + public var advance:Vector2; public var height:Int; - public var horizontalAdvance:Int; - public var horizontalBearingX:Int; - public var horizontalBearingY:Int; - public var verticalAdvance:Int; - public var verticalBearingX:Int; - public var verticalBearingY:Int; + public var horizontalBearing:Vector2; + public var verticalBearing:Vector2; public function new () { diff --git a/lime/text/GlyphPosition.hx b/lime/text/GlyphPosition.hx new file mode 100644 index 000000000..b61531691 --- /dev/null +++ b/lime/text/GlyphPosition.hx @@ -0,0 +1,32 @@ +package lime.text; + + +import lime.math.Vector2; + + +class GlyphPosition { + + + public var advance:Vector2; + public var glyph:Glyph; + public var offset:Vector2; + + + public function new (glyph:Glyph, advance:Vector2, offset:Vector2 = null) { + + this.glyph = glyph; + this.advance = advance; + + if (offset != null) { + + this.offset = offset; + + } else { + + this.offset = new Vector2 (); + + } + + } + +} \ No newline at end of file diff --git a/lime/text/TextEngine.hx b/lime/text/TextEngine.hx deleted file mode 100644 index 4941fce47..000000000 --- a/lime/text/TextEngine.hx +++ /dev/null @@ -1,75 +0,0 @@ -package lime.text; - - -import lime.system.System; - -@:access(lime.text.Font) - - -class TextEngine { - - - public var direction (default, null):TextDirection; - public var language (default, null):String; - public var script (default, null):TextScript; - - #if (cpp || neko || nodejs) - private var __handle:Dynamic; - #end - - - public function new (direction:TextDirection = LEFT_TO_RIGHT, script:TextScript = COMMON, language:String = "") { - - this.direction = direction; - this.script = script; - this.language = language; - - #if (cpp || neko || nodejs) - __handle = lime_text_engine_create (direction, script, language); - #end - - this.direction = direction; - - } - - - public function layout (font:Font, size:Int, text:String):Array { - - #if (cpp || neko || nodejs) - - if (font.__handle == null) throw "Uninitialized font handle."; - return lime_text_engine_layout (__handle, font.__handle, size, text); - - #else - - return null; - - #end - - } - - - #if (cpp || neko || nodejs) - 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 - - -} - - -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/lime/text/TextLayout.hx b/lime/text/TextLayout.hx new file mode 100644 index 000000000..d855c77a0 --- /dev/null +++ b/lime/text/TextLayout.hx @@ -0,0 +1,224 @@ +package lime.text; + + +import lime.math.Vector2; +import lime.system.System; +import lime.utils.ByteArray; + +@:access(lime.text.Font) + + +class TextLayout { + + + public var direction (get, set):TextDirection; + public var font (default, set):Font; + public var glyphs (get, null):Array; + public var language (get, set):String; + public var positions (default, null):Array; + public var script (get, set):TextScript; + public var size (default, set):Int; + public var text (default, set):String; + + @:noCompletion private var __buffer:ByteArray; + @:noCompletion private var __direction:TextDirection; + @:noCompletion private var __handle:Dynamic; + @:noCompletion private var __language:String; + @:noCompletion private var __script:TextScript; + + + public function new (text:String = "", font:Font = null, size:Int = 12, direction:TextDirection = LEFT_TO_RIGHT, script:TextScript = COMMON, language:String = "en") { + + this.text = text; + this.font = font; + this.size = size; + __direction = direction; + __script = script; + __language = language; + + #if (cpp || neko || nodejs) + __handle = lime_text_layout_create (__direction, __script, __language); + #end + + __position (); + + } + + + @:noCompletion private function __position ():Void { + + positions = []; + + #if (cpp || neko || nodejs) + + if (__handle != null && text != null && text != "" && font != null && font.__handle != null) { + + if (__buffer == null) { + + __buffer = new ByteArray (); + __buffer.bigEndian = false; + + } + + lime_text_layout_position (__handle, font.__handle, size, text, __buffer); + + if (__buffer.length > 4) { + + __buffer.position = 0; + + var count = __buffer.readUnsignedInt (); + var index, advanceX, advanceY, offsetX, offsetY; + + for (i in 0...count) { + + index = __buffer.readUnsignedInt (); + advanceX = __buffer.readFloat (); + advanceY = __buffer.readFloat (); + offsetX = __buffer.readFloat (); + offsetY = __buffer.readFloat (); + + positions.push (new GlyphPosition (index, new Vector2 (advanceX, advanceY), new Vector2 (offsetX, offsetY))); + + } + + } + + } + + #end + + } + + + + + // Get & Set Methods + + + + + @:noCompletion private function get_direction ():TextDirection { + + return __direction; + + } + + + @:noCompletion private function set_direction (value:TextDirection):TextDirection { + + __direction = value; + + #if (cpp || neko || nodejs) + lime_text_layout_set_direction (__handle, value); + #end + + __position (); + + return value; + + } + + + @:noCompletion private function set_font (value:Font):Font { + + this.font = value; + __position (); + return value; + + } + + + @:noCompletion private function get_glyphs ():Array { + + var glyphs = []; + + for (position in positions) { + + glyphs.push (position.glyph); + + } + + return glyphs; + + } + + + @:noCompletion private function get_language ():String { + + return __language; + + } + + + @:noCompletion private function set_language (value:String):String { + + __language = value; + + #if (cpp || neko || nodejs) + lime_text_layout_set_language (__handle, value); + #end + + __position (); + + return value; + + } + + + @:noCompletion private function get_script ():TextScript { + + return __script; + + } + + + @:noCompletion private function set_script (value:TextScript):TextScript { + + __script = value; + + #if (cpp || neko || nodejs) + lime_text_layout_set_script (__handle, value); + #end + + __position (); + + return value; + + } + + + @:noCompletion private function set_size (value:Int):Int { + + this.size = value; + __position (); + return value; + + } + + + @:noCompletion private function set_text (value:String):String { + + this.text = value; + __position (); + return value; + + } + + + + + // Native Methods + + + + + #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_position = System.load ("lime", "lime_text_layout_position", 5); + private static var lime_text_layout_set_direction = System.load ("lime", "lime_text_layout_set_direction", 2); + private static var lime_text_layout_set_language = System.load ("lime", "lime_text_layout_set_language", 2); + private static var lime_text_layout_set_script = System.load ("lime", "lime_text_layout_set_script", 2); + #end + + +} \ No newline at end of file diff --git a/project/Build.xml b/project/Build.xml index 9bec1b9d4..7be2f259d 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -60,14 +60,13 @@ -
- +
diff --git a/project/include/text/Font.h b/project/include/text/Font.h index a48e5a5c7..16b1c0990 100644 --- a/project/include/text/Font.h +++ b/project/include/text/Font.h @@ -4,7 +4,6 @@ #include #include -#include #include #include diff --git a/project/include/text/GlyphSet.h b/project/include/text/GlyphSet.h deleted file mode 100644 index d09467a09..000000000 --- a/project/include/text/GlyphSet.h +++ /dev/null @@ -1,44 +0,0 @@ -#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/TextEngine.h b/project/include/text/TextEngine.h deleted file mode 100644 index cc0737bea..000000000 --- a/project/include/text/TextEngine.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef LIME_TEXT_TEXT_ENGINE_H -#define LIME_TEXT_TEXT_ENGINE_H - - -#include -#include - - -namespace lime { - - - class TextEngine { - - - public: - - TextEngine (int direction, const char *script, const char *language); - ~TextEngine (); - - value Layout (Font *font, size_t size, const char *text); - - private: - - void *mBuffer; - long mDirection; - long mScript; - long mLanguage; - - }; - - -} - - -#endif diff --git a/project/include/text/TextLayout.h b/project/include/text/TextLayout.h new file mode 100644 index 000000000..f33368db2 --- /dev/null +++ b/project/include/text/TextLayout.h @@ -0,0 +1,49 @@ +#ifndef LIME_TEXT_TEXT_LAYOUT_H +#define LIME_TEXT_TEXT_LAYOUT_H + + +#include +#include + + +namespace lime { + + + typedef struct { + + uint32_t index; + float advanceX; + float advanceY; + float offsetX; + float offsetY; + + } GlyphPosition; + + + class TextLayout { + + + public: + + TextLayout (int direction, const char *script, const char *language); + ~TextLayout (); + + void Position (Font *font, size_t size, const char *text, ByteArray *bytes); + void SetDirection (int direction); + void SetLanguage (const char* language); + void SetScript (const char* script); + + private: + + void *mBuffer; + long mDirection; + long mScript; + long mLanguage; + + }; + + +} + + +#endif diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index e0eb61df1..36b0ff17c 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -20,8 +20,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -542,10 +541,10 @@ namespace lime { } - void lime_text_engine_destroy (value textHandle) { + void lime_text_layout_destroy (value textHandle) { #ifdef LIME_HARFBUZZ - TextEngine *text = (TextEngine*)(intptr_t)val_float (textHandle); + TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); delete text; text = 0; #endif @@ -553,13 +552,13 @@ namespace lime { } - value lime_text_engine_create (value direction, value script, value language) { + value lime_text_layout_create (value direction, value script, value language) { #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) - TextEngine *text = new TextEngine (val_int (direction), val_string (script), val_string (language)); + TextLayout *text = new TextLayout (val_int (direction), val_string (script), val_string (language)); value v = alloc_float ((intptr_t)text); - val_gc (v, lime_text_engine_destroy); + val_gc (v, lime_text_layout_destroy); return v; #else @@ -571,19 +570,51 @@ namespace lime { } - value lime_text_engine_layout (value textHandle, value fontHandle, value size, value textString) { + value lime_text_layout_position (value textHandle, value fontHandle, value size, value textString, value data) { #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) - TextEngine *text = (TextEngine*)(intptr_t)val_float (textHandle); + TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); Font *font = (Font*)(intptr_t)val_float (fontHandle); - return text->Layout (font, val_int (size), val_string (textString)); + ByteArray bytes = ByteArray (data); + text->Position (font, val_int (size), val_string (textString), &bytes); - #else + #endif return alloc_null (); + } + + + value lime_text_layout_set_direction (value textHandle, value direction) { + + #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) + TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); + text->SetDirection (val_int (direction)); #endif + return alloc_null (); + + } + + + value lime_text_layout_set_language (value textHandle, value direction) { + + #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) + TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); + text->SetLanguage (val_string (direction)); + #endif + return alloc_null (); + + } + + + value lime_text_layout_set_script (value textHandle, value direction) { + + #if defined(LIME_FREETYPE) && defined(LIME_HARFBUZZ) + TextLayout *text = (TextLayout*)(intptr_t)val_float (textHandle); + text->SetScript (val_string (direction)); + #endif + return alloc_null (); } @@ -699,8 +730,11 @@ 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_engine_create, 3); - DEFINE_PRIM (lime_text_engine_layout, 4); + DEFINE_PRIM (lime_text_layout_create, 3); + DEFINE_PRIM (lime_text_layout_position, 5); + DEFINE_PRIM (lime_text_layout_set_direction, 2); + DEFINE_PRIM (lime_text_layout_set_language, 2); + DEFINE_PRIM (lime_text_layout_set_script, 2); 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/GlyphSet.cpp b/project/src/text/GlyphSet.cpp deleted file mode 100644 index 2c9660fb8..000000000 --- a/project/src/text/GlyphSet.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#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/TextEngine.cpp b/project/src/text/TextLayout.cpp similarity index 53% rename from project/src/text/TextEngine.cpp rename to project/src/text/TextLayout.cpp index cd40e23ba..0fb89d114 100644 --- a/project/src/text/TextEngine.cpp +++ b/project/src/text/TextLayout.cpp @@ -1,4 +1,5 @@ -#include +#include +#include #include #include FT_FREETYPE_H @@ -9,7 +10,7 @@ namespace lime { - TextEngine::TextEngine (int direction, const char *script, const char *language) { + TextLayout::TextLayout (int direction, const char *script, const char *language) { if (strlen (script) != 4) return; @@ -25,14 +26,14 @@ namespace lime { } - TextEngine::~TextEngine () { + TextLayout::~TextLayout () { hb_buffer_destroy ((hb_buffer_t*)mBuffer); } - value TextEngine::Layout (Font *font, size_t size, const char *text) { + void TextLayout::Position (Font *font, size_t size, const char *text, ByteArray *bytes) { font->SetSize (size); @@ -47,39 +48,68 @@ namespace lime { hb_font_t *hb_font = hb_ft_font_create ((FT_Face)font->face, NULL); hb_shape (hb_font, (hb_buffer_t*)mBuffer, NULL, 0); - unsigned int glyph_count; + uint32_t glyph_count; hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos ((hb_buffer_t*)mBuffer, &glyph_count); hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions ((hb_buffer_t*)mBuffer, &glyph_count); float hres = 100; - value pos_info = alloc_array (glyph_count); int posIndex = 0; + int glyphSize = sizeof(GlyphPosition); + uint32_t dataSize = 4 + (glyph_count * glyphSize); + + if (bytes->Size() < dataSize) { + + bytes->Resize (dataSize); + + } + + unsigned char* bytesPosition = bytes->Bytes (); + + *(bytesPosition) = glyph_count; + bytesPosition += 4; + + hb_glyph_position_t pos; + GlyphPosition *data; + for (int i = 0; i < glyph_count; i++) { - //font->InsertCodepointFromIndex(glyph_info[i].codepoint); - hb_glyph_position_t pos = glyph_pos[i]; + pos = glyph_pos[i]; - value obj = alloc_empty_object (); - alloc_field (obj, val_id ("codepoint"), alloc_float (glyph_info[i].codepoint)); + data = (GlyphPosition*)(bytesPosition); - 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); + data->index = glyph_info[i].codepoint; + data->advanceX = (float)(pos.x_advance / (float)(hres * 64)); + data->advanceY = (float)(pos.y_advance / (float)64); + data->offsetX = (float)(pos.x_offset / (float)(hres * 64)); + data->offsetY = (float)(pos.y_offset / (float)64); - 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); + bytesPosition += glyphSize; } hb_font_destroy (hb_font); - return pos_info; + } + + + void TextLayout::SetDirection (int direction) { + + mDirection = (hb_direction_t)direction; + + } + + + void TextLayout::SetLanguage (const char* language) { + + mLanguage = (long)hb_language_from_string (language, strlen (language)); + + } + + + void TextLayout::SetScript (const char* script) { + + mScript = hb_script_from_string (script, -1); }