Add Font.getTextMetrics, rename TextLayout->TextEngine

This commit is contained in:
Joshua Granick
2015-03-09 08:09:09 -07:00
parent a406401848
commit 0f6f022dab
13 changed files with 380 additions and 108 deletions

View File

@@ -255,6 +255,17 @@ class Font {
}
public function getGlyphMetrics (glyphs:GlyphSet):Array<GlyphMetrics> {
#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);

15
lime/text/GlyphMetrics.hx Normal file
View File

@@ -0,0 +1,15 @@
package lime.text;
/**
* ...
* @author ...
*/
class GlyphMetrics
{
public function new()
{
}
}

62
lime/text/GlyphSet.hx Normal file
View File

@@ -0,0 +1,62 @@
package lime.text;
class GlyphSet {
public var glyphs:String;
public var ranges:Array<GlyphRange>;
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;
}
}

View File

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

View File

@@ -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<PosInfo> {
#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;
};

View File

@@ -60,13 +60,14 @@
<compilerflag value="-DLIME_FREETYPE" />
<file name="src/text/Font.cpp" />
<file name="src/text/GlyphSet.cpp" />
<section if="LIME_HARFBUZZ">
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/harfbuzz/src" />
<compilerflag value="-DLIME_HARFBUZZ" />
<file name="src/text/TextLayout.cpp" />
<file name="src/text/TextEngine.cpp" />
</section>

View File

@@ -3,6 +3,7 @@
#include <graphics/ImageBuffer.h>
#include <text/GlyphSet.h>
#include <utils/Resource.h>
#include <hx/CFFI.h>
#include <list>
@@ -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 ();

View File

@@ -0,0 +1,44 @@
#ifndef LIME_TEXT_GLYPH_SET_H
#define LIME_TEXT_GLYPH_SET_H
#include <hx/CFFI.h>
#include <utils/QuickVec.h>
#include <string>
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<GlyphRange> ranges;
};
}
#endif

View File

@@ -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 <text/Font.h>
@@ -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);

View File

@@ -20,7 +20,8 @@
#include <graphics/RenderEvent.h>
#include <system/System.h>
#include <text/Font.h>
#include <text/TextLayout.h>
#include <text/GlyphSet.h>
#include <text/TextEngine.h>
#include <ui/KeyEvent.h>
#include <ui/Mouse.h>
#include <ui/MouseCursor.h>
@@ -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);

View File

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

View File

@@ -0,0 +1,89 @@
#include <text/GlyphSet.h>
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<GlyphRange> ();
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));
}
}

View File

@@ -1,4 +1,4 @@
#include <text/TextLayout.h>
#include <text/TextEngine.h>
#include <ft2build.h>
#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);