From 1ee5ebe788bc323f84f3d79875d630c6daab1e2c Mon Sep 17 00:00:00 2001 From: Kane Wallmann Date: Thu, 21 May 2015 22:04:29 +1000 Subject: [PATCH] Work on Cairo FreeType implementation --- lime/graphics/cairo/Cairo.hx | 48 +++++++ lime/graphics/cairo/CairoFont.hx | 30 ++++ lime/graphics/cairo/CairoFontOptions.hx | 118 ++++++++++++++++ lime/graphics/cairo/CairoHintMetrics.hx | 10 ++ lime/graphics/cairo/CairoHintStyle.hx | 12 ++ lime/graphics/cairo/CairoSubpixelOrder.hx | 12 ++ lime/text/Font.hx | 5 +- lime/text/TextLayout.hx | 36 +++-- project/Build.xml | 1 + project/src/graphics/cairo/CairoBindings.cpp | 139 ++++++++++++++++++- project/src/text/Font.cpp | 12 +- project/src/text/TextLayout.cpp | 6 +- 12 files changed, 399 insertions(+), 30 deletions(-) create mode 100644 lime/graphics/cairo/CairoFont.hx create mode 100644 lime/graphics/cairo/CairoFontOptions.hx create mode 100644 lime/graphics/cairo/CairoHintMetrics.hx create mode 100644 lime/graphics/cairo/CairoHintStyle.hx create mode 100644 lime/graphics/cairo/CairoSubpixelOrder.hx diff --git a/lime/graphics/cairo/Cairo.hx b/lime/graphics/cairo/Cairo.hx index d38774ee3..feb3dcde5 100644 --- a/lime/graphics/cairo/Cairo.hx +++ b/lime/graphics/cairo/Cairo.hx @@ -369,6 +369,41 @@ class Cairo { } + public function setFontFace( face:CairoFont ) { + + #if lime_cairo + lime_cairo_set_font_face( handle, face.handle ); + #end + } + + public function setFontSize( size:Float ) { + + #if lime_cairo + lime_cairo_set_font_size( handle, size ); + #end + } + + public function getFontOptions ():CairoFontOptions { + + #if lime_cairo + return new CairoFontOptions( handle ); + #end + + return cast 0; + + } + + + public function setFontOptions (value:CairoFontOptions):CairoFontOptions { + + #if lime_cairo + lime_cairo_set_font_options (handle, value.handle); + #end + + return value; + + } + public function setSourceRGB (r:Float, g:Float, b:Float):Void { @@ -405,6 +440,14 @@ class Cairo { } + public function showText ( utf8:String ) { + + #if lime_cairo + lime_cairo_show_text( handle, utf8 ); + #end + + } + public function status ():CairoStatus { @@ -882,7 +925,11 @@ class Cairo { private static var lime_cairo_save = System.load ("lime", "lime_cairo_save", 1); private static var lime_cairo_set_antialias = System.load ("lime", "lime_cairo_set_antialias", 2); private static var lime_cairo_set_dash = System.load ("lime", "lime_cairo_set_dash", 2); + private static var lime_cairo_set_font_face = System.load ("lime", "lime_cairo_set_font_face", 2); + private static var lime_cairo_set_font_size = System.load ("lime", "lime_cairo_set_font_size", 2); private static var lime_cairo_set_fill_rule = System.load ("lime", "lime_cairo_set_fill_rule", 2); + private static var lime_cairo_set_font_options = System.load ("lime", "lime_cairo_set_font_options", 2); + private static var lime_cairo_get_font_options = System.load ("lime", "lime_cairo_get_font_options", 1); private static var lime_cairo_set_line_cap = System.load ("lime", "lime_cairo_set_line_cap", 2); private static var lime_cairo_set_line_join = System.load ("lime", "lime_cairo_set_line_join", 2); private static var lime_cairo_set_line_width = System.load ("lime", "lime_cairo_set_line_width", 2); @@ -895,6 +942,7 @@ class Cairo { private static var lime_cairo_set_source_surface = System.load ("lime", "lime_cairo_set_source_surface", 4); private static var lime_cairo_set_tolerance = System.load ("lime", "lime_cairo_set_tolerance", 2); private static var lime_cairo_show_page = System.load ("lime", "lime_cairo_show_page", 1); + private static var lime_cairo_show_text = System.load ("lime", "lime_cairo_show_text", 2); private static var lime_cairo_status = System.load ("lime", "lime_cairo_status", 1); private static var lime_cairo_stroke = System.load ("lime", "lime_cairo_stroke", 1); private static var lime_cairo_stroke_extents = System.load ("lime", "lime_cairo_stroke_extents", 5); diff --git a/lime/graphics/cairo/CairoFont.hx b/lime/graphics/cairo/CairoFont.hx new file mode 100644 index 000000000..dc3a31f64 --- /dev/null +++ b/lime/graphics/cairo/CairoFont.hx @@ -0,0 +1,30 @@ +package lime.graphics.cairo; +import lime.text.Font; +import lime.system.System; + +class CairoFont +{ + @:noCompletion public var handle:Dynamic; + + public var font(default,null):Font; + + public function new( font : Font ) { + + #if lime_cairo + this.font = font; + handle = lime_cairo_ft_font_face_create_for_ft_face( font.src, 0 ); + #end + } + + public function destroy() { + #if lime_cairo + lime_cairo_font_face_destroy (handle); + #end + } + + #if (cpp || neko || nodejs) + private static var lime_cairo_ft_font_face_create_for_ft_face = System.load ("lime", "lime_cairo_ft_font_face_create_for_ft_face", 2); + private static var lime_cairo_font_face_destroy = System.load ("lime", "lime_cairo_font_face_destroy", 1); + #end + +} \ No newline at end of file diff --git a/lime/graphics/cairo/CairoFontOptions.hx b/lime/graphics/cairo/CairoFontOptions.hx new file mode 100644 index 000000000..fa4a6402b --- /dev/null +++ b/lime/graphics/cairo/CairoFontOptions.hx @@ -0,0 +1,118 @@ +package lime.graphics.cairo; +import lime.graphics.cairo.CairoSubpixelOrder; +import lime.graphics.cairo.CairoSubpixelOrder; +import lime.graphics.cairo.CairoSubpixelOrder; +import lime.text.Font; +import lime.system.System; + +class CairoFontOptions +{ + public var antialias (get, set):CairoAntialias; + public var subpixelOrder (get, set):CairoSubpixelOrder; + public var hintStyle (get, set):CairoHintStyle; + public var hintMetrics (get, set):CairoHintMetrics; + + @:noCompletion public var handle:Dynamic; + + public function new( handle : Dynamic = null ) { + + #if lime_cairo + if ( handle == null ) + handle = lime_cairo_font_options_create(); + #end + + this.handle = handle; + } + + @:noCompletion private function get_antialias ():CairoAntialias { + + #if lime_cairo + return lime_cairo_font_options_get_antialias (handle); + #end + + return cast 0; + + } + + + @:noCompletion private function set_antialias (value:CairoAntialias):CairoAntialias { + + #if lime_cairo + lime_cairo_font_options_set_antialias (handle, value); + #end + + return value; + + } + + @:noCompletion private function get_subpixelOrder ():CairoSubpixelOrder { + + #if lime_cairo + return lime_cairo_font_options_get_subpixel_order (handle); + #end + + return cast 0; + + } + + + @:noCompletion private function set_subpixelOrder (value:CairoSubpixelOrder):CairoSubpixelOrder { + + #if lime_cairo + lime_cairo_font_options_set_subpixel_order (handle, value); + #end + + return value; + + } + + @:noCompletion private function get_hintStyle ():CairoHintStyle { + + #if lime_cairo + return lime_cairo_font_options_get_hint_style (handle); + #end + + return cast 0; + } + + + @:noCompletion private function set_hintStyle (value:CairoHintStyle):CairoHintStyle { + + #if lime_cairo + lime_cairo_font_options_set_hint_style (handle, value); + #end + + return value; + } + + @:noCompletion private function get_hintMetrics ():CairoHintMetrics { + + #if lime_cairo + return lime_cairo_font_options_get_hint_metrics (handle); + #end + + return cast 0; + } + + @:noCompletion private function set_hintMetrics (value:CairoHintMetrics):CairoHintMetrics { + + #if lime_cairo + lime_cairo_font_options_set_hint_metrics (handle, value); + #end + + return value; + } + + #if (cpp || neko || nodejs) + private static var lime_cairo_font_options_create = System.load ("lime", "lime_cairo_font_options_create", 0); + private static var lime_cairo_font_options_get_antialias = System.load ("lime", "lime_cairo_font_options_get_antialias", 1); + private static var lime_cairo_font_options_get_subpixel_order = System.load ("lime", "lime_cairo_font_options_get_subpixel_order", 1); + private static var lime_cairo_font_options_get_hint_style = System.load ("lime", "lime_cairo_font_options_get_hint_style", 1); + private static var lime_cairo_font_options_get_hint_metrics = System.load ("lime", "lime_cairo_font_options_get_hint_metrics", 1); + private static var lime_cairo_font_options_set_antialias = System.load ("lime", "lime_cairo_font_options_set_antialias", 2); + private static var lime_cairo_font_options_set_subpixel_order = System.load ("lime", "lime_cairo_font_options_set_subpixel_order", 2); + private static var lime_cairo_font_options_set_hint_style = System.load ("lime", "lime_cairo_font_options_set_hint_style", 2); + private static var lime_cairo_font_options_set_hint_metrics = System.load ("lime", "lime_cairo_font_options_set_hint_metrics", 2); + #end + +} \ No newline at end of file diff --git a/lime/graphics/cairo/CairoHintMetrics.hx b/lime/graphics/cairo/CairoHintMetrics.hx new file mode 100644 index 000000000..2f056a5a9 --- /dev/null +++ b/lime/graphics/cairo/CairoHintMetrics.hx @@ -0,0 +1,10 @@ +package lime.graphics.cairo; + + +@:enum abstract CairoHintMetrics(Int) from Int to Int { + + public var DEFAULT = 0; + public var OFF = 1; + public var ON = 2; + +} \ No newline at end of file diff --git a/lime/graphics/cairo/CairoHintStyle.hx b/lime/graphics/cairo/CairoHintStyle.hx new file mode 100644 index 000000000..971fbcf9d --- /dev/null +++ b/lime/graphics/cairo/CairoHintStyle.hx @@ -0,0 +1,12 @@ +package lime.graphics.cairo; + + +@:enum abstract CairoHintStyle(Int) from Int to Int { + + public var DEFAULT = 0; + public var NONE = 1; + public var SLIGHT = 2; + public var MEDIUM = 3; + public var FULL = 4; + +} \ No newline at end of file diff --git a/lime/graphics/cairo/CairoSubpixelOrder.hx b/lime/graphics/cairo/CairoSubpixelOrder.hx new file mode 100644 index 000000000..2dfce90ec --- /dev/null +++ b/lime/graphics/cairo/CairoSubpixelOrder.hx @@ -0,0 +1,12 @@ +package lime.graphics.cairo; + + +@:enum abstract CairoSubpixelOrder(Int) from Int to Int { + + public var DEFAULT = 0; + public var RGB = 1; + public var BGR = 2; + public var VRGB = 3; + public var VBGR = 4; + +} \ No newline at end of file diff --git a/lime/text/Font.hx b/lime/text/Font.hx index f153a77dd..e00e83fbd 100644 --- a/lime/text/Font.hx +++ b/lime/text/Font.hx @@ -174,7 +174,7 @@ class Font { return null; } - + public function renderGlyphs (glyphs:Array, fontSize:Int):Map { @@ -339,8 +339,7 @@ class Font { return null; } - - + @:noCompletion private function __fromBytes (bytes:ByteArray):Void { __fontPath = null; diff --git a/lime/text/TextLayout.hx b/lime/text/TextLayout.hx index b2d804905..572d9c674 100644 --- a/lime/text/TextLayout.hx +++ b/lime/text/TextLayout.hx @@ -15,11 +15,13 @@ class TextLayout { public var font (default, set):Font; public var glyphs (get, null):Array; public var language (get, set):String; - public var positions (default, null):Array; + @:isVar public var positions (get, null):Array; public var script (get, set):TextScript; public var size (default, set):Int; public var text (default, set):String; + private var __dirty:Bool; + @:noCompletion private var __buffer:ByteArray; @:noCompletion private var __direction:TextDirection; @:noCompletion private var __handle:Dynamic; @@ -36,12 +38,12 @@ class TextLayout { __script = script; __language = language; + positions = []; + __dirty = true; + #if (cpp || neko || nodejs) __handle = lime_text_layout_create (__direction, __script, __language); #end - - __position (); - } @@ -81,8 +83,7 @@ class TextLayout { } - } - + } } #end @@ -97,6 +98,17 @@ class TextLayout { + @:noCompletion private function get_positions ():Array { + + if ( __dirty ) + { + __dirty = false; + __position(); + } + + return positions; + } + @:noCompletion private function get_direction ():TextDirection { return __direction; @@ -114,7 +126,7 @@ class TextLayout { lime_text_layout_set_direction (__handle, value); #end - __position (); + __dirty = true; return value; @@ -126,7 +138,7 @@ class TextLayout { if (value == this.font) return value; this.font = value; - __position (); + __dirty = true; return value; } @@ -164,7 +176,7 @@ class TextLayout { lime_text_layout_set_language (__handle, value); #end - __position (); + __dirty = true; return value; @@ -188,7 +200,7 @@ class TextLayout { lime_text_layout_set_script (__handle, value); #end - __position (); + __dirty = true; return value; @@ -200,7 +212,7 @@ class TextLayout { if (value == this.size) return value; this.size = value; - __position (); + __dirty = true; return value; } @@ -211,7 +223,7 @@ class TextLayout { if (value == this.text) return value; this.text = value; - __position (); + __dirty = true; return value; } diff --git a/project/Build.xml b/project/Build.xml index d56b804e1..7053dc94d 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -48,6 +48,7 @@ + diff --git a/project/src/graphics/cairo/CairoBindings.cpp b/project/src/graphics/cairo/CairoBindings.cpp index c7a54fc6a..d38df5eff 100644 --- a/project/src/graphics/cairo/CairoBindings.cpp +++ b/project/src/graphics/cairo/CairoBindings.cpp @@ -1,11 +1,13 @@ #include +#include #include #include #include - +#include namespace lime { + void lime_cairo_font_options_destroy (value handle); value lime_cairo_arc (value *arg, int argCount) { @@ -119,7 +121,80 @@ namespace lime { } + value lime_cairo_font_face_destroy (value handle) { + + cairo_font_face_t* face = (cairo_font_face_t*)(intptr_t)val_float(handle); + cairo_font_face_destroy( face ); + return alloc_null (); + + } + value lime_cairo_font_options_create () { + + value options = alloc_float( (intptr_t)cairo_font_options_create() ); + val_gc( options, lime_cairo_font_options_destroy ); + return options; + + } + + void lime_cairo_font_options_destroy (value handle) { + + cairo_font_options_destroy( (cairo_font_options_t*)(intptr_t)val_float (handle) ); + + } + + value lime_cairo_font_options_get_antialias (value handle) { + + return alloc_int( cairo_font_options_get_antialias( (cairo_font_options_t*)(intptr_t)val_float (handle) ) ); + + } + + value lime_cairo_font_options_get_subpixel_order (value handle) { + + return alloc_int( cairo_font_options_get_subpixel_order( (cairo_font_options_t*)(intptr_t)val_float (handle) ) ); + + } + + value lime_cairo_font_options_get_hint_style (value handle) { + + return alloc_int( cairo_font_options_get_hint_style( (cairo_font_options_t*)(intptr_t)val_float (handle) ) ); + + } + + value lime_cairo_font_options_get_hint_metrics (value handle) { + + return alloc_int( cairo_font_options_get_hint_metrics( (cairo_font_options_t*)(intptr_t)val_float (handle) ) ); + + } + + value lime_cairo_font_options_set_antialias (value handle, value v) { + + cairo_font_options_set_antialias( (cairo_font_options_t*)(intptr_t)val_float (handle), (cairo_antialias_t)val_int( v ) ); + return alloc_null(); + + } + + value lime_cairo_font_options_set_subpixel_order (value handle, value v) { + + cairo_font_options_set_subpixel_order( (cairo_font_options_t*)(intptr_t)val_float (handle), (cairo_subpixel_order_t)val_int( v ) ); + return alloc_null(); + + } + + value lime_cairo_font_options_set_hint_style (value handle, value v) { + + cairo_font_options_set_hint_style( (cairo_font_options_t*)(intptr_t)val_float (handle), (cairo_hint_style_t)val_int( v ) ); + return alloc_null(); + + } + + value lime_cairo_font_options_set_hint_metrics (value handle, value v) { + + cairo_font_options_set_hint_metrics( (cairo_font_options_t*)(intptr_t)val_float (handle), (cairo_hint_metrics_t)val_int( v ) ); + return alloc_null(); + + } + value lime_cairo_get_antialias (value handle) { return alloc_int (cairo_get_antialias ((cairo_t*)(intptr_t)val_float (handle))); @@ -172,6 +247,15 @@ namespace lime { return alloc_int (cairo_get_fill_rule ((cairo_t*)(intptr_t)val_float (handle))); } + + value lime_cairo_get_font_options (value handle) { + + cairo_font_options_t* options = (cairo_font_options_t*)(intptr_t)lime_cairo_font_options_create(); + + cairo_get_font_options ((cairo_t*)(intptr_t)val_float (handle), options); + + return alloc_float ((intptr_t)options); + } value lime_cairo_get_group_target (value handle) { @@ -616,6 +700,26 @@ namespace lime { } + value lime_cairo_set_font_face (value handle, value face) { + + cairo_set_font_face ((cairo_t*)(intptr_t)val_float (handle), (cairo_font_face_t*)(intptr_t)val_float (face) ); + return alloc_null (); + + } + + value lime_cairo_set_font_size (value handle, value size) { + + cairo_set_font_size ((cairo_t*)(intptr_t)val_float (handle), val_number(size) ); + return alloc_null (); + + } + + value lime_cairo_set_font_options (value handle, value options) { + + cairo_set_font_options ((cairo_t*)(intptr_t)val_float (handle), (cairo_font_options_t*)(intptr_t)val_float (options) ); + return alloc_null (); + + } value lime_cairo_set_fill_rule (value handle, value cap) { @@ -725,6 +829,13 @@ namespace lime { } + value lime_cairo_show_text (value handle, value text) { + + cairo_show_text( (cairo_t*)(intptr_t)val_float (handle), (char*)val_string(text) ); + return alloc_null (); + + } + value lime_cairo_status (value handle) { @@ -825,6 +936,16 @@ namespace lime { } + #ifdef LIME_FREETYPE + value lime_cairo_ft_font_face_create_for_ft_face( value face, value flags ) { + + Font *font = (Font*)(intptr_t)val_float (face); + + return alloc_float ((intptr_t)cairo_ft_font_face_create_for_ft_face( (FT_Face)(font->face), val_int( flags ) )); + + } + #endif + DEFINE_PRIM_MULT (lime_cairo_arc); DEFINE_PRIM_MULT (lime_cairo_arc_negative); @@ -839,11 +960,23 @@ namespace lime { DEFINE_PRIM (lime_cairo_fill, 1); DEFINE_PRIM (lime_cairo_fill_extents, 5); DEFINE_PRIM (lime_cairo_fill_preserve, 1); + DEFINE_PRIM (lime_cairo_ft_font_face_create_for_ft_face, 2); + DEFINE_PRIM (lime_cairo_font_face_destroy, 1); + DEFINE_PRIM (lime_cairo_font_options_create, 0); + DEFINE_PRIM (lime_cairo_font_options_get_antialias, 1); + DEFINE_PRIM (lime_cairo_font_options_get_subpixel_order, 1); + DEFINE_PRIM (lime_cairo_font_options_get_hint_style, 1); + DEFINE_PRIM (lime_cairo_font_options_get_hint_metrics, 1); + DEFINE_PRIM (lime_cairo_font_options_set_antialias, 2); + DEFINE_PRIM (lime_cairo_font_options_set_subpixel_order, 2); + DEFINE_PRIM (lime_cairo_font_options_set_hint_style, 2); + DEFINE_PRIM (lime_cairo_font_options_set_hint_metrics, 2); DEFINE_PRIM (lime_cairo_get_antialias, 1); DEFINE_PRIM (lime_cairo_get_current_point, 1); DEFINE_PRIM (lime_cairo_get_dash, 1); DEFINE_PRIM (lime_cairo_get_dash_count, 1); DEFINE_PRIM (lime_cairo_get_fill_rule, 1); + DEFINE_PRIM (lime_cairo_get_font_options, 1); DEFINE_PRIM (lime_cairo_get_group_target, 1); DEFINE_PRIM (lime_cairo_get_line_cap, 1); DEFINE_PRIM (lime_cairo_get_line_join, 1); @@ -901,6 +1034,9 @@ namespace lime { DEFINE_PRIM (lime_cairo_set_antialias, 2); DEFINE_PRIM (lime_cairo_set_dash, 2); DEFINE_PRIM (lime_cairo_set_fill_rule, 2); + DEFINE_PRIM (lime_cairo_set_font_face, 2); + DEFINE_PRIM (lime_cairo_set_font_size, 2); + DEFINE_PRIM (lime_cairo_set_font_options, 2); DEFINE_PRIM (lime_cairo_set_line_cap, 2); DEFINE_PRIM (lime_cairo_set_line_join, 2); DEFINE_PRIM (lime_cairo_set_line_width, 2); @@ -913,6 +1049,7 @@ namespace lime { DEFINE_PRIM (lime_cairo_set_source_surface, 4); DEFINE_PRIM (lime_cairo_set_tolerance, 2); DEFINE_PRIM (lime_cairo_show_page, 1); + DEFINE_PRIM (lime_cairo_show_text, 2); DEFINE_PRIM (lime_cairo_status, 1); DEFINE_PRIM (lime_cairo_stroke, 1); DEFINE_PRIM (lime_cairo_stroke_extents, 5); diff --git a/project/src/text/Font.cpp b/project/src/text/Font.cpp index 0ccce7b5a..f0a53b835 100644 --- a/project/src/text/Font.cpp +++ b/project/src/text/Font.cpp @@ -866,19 +866,9 @@ namespace lime { 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 ((FT_Face)face, 0, (int)(size*64), (int)(hdpi * hres), vdpi); - FT_Set_Transform ((FT_Face)face, &matrix, NULL); + FT_Set_Char_Size ((FT_Face)face, (int)(size*64), (int)(size*64), hdpi, vdpi); mSize = size; - } diff --git a/project/src/text/TextLayout.cpp b/project/src/text/TextLayout.cpp index 0fb89d114..e215d357b 100644 --- a/project/src/text/TextLayout.cpp +++ b/project/src/text/TextLayout.cpp @@ -52,7 +52,7 @@ namespace lime { 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; + //float hres = 100; int posIndex = 0; int glyphSize = sizeof(GlyphPosition); @@ -79,9 +79,9 @@ namespace lime { data = (GlyphPosition*)(bytesPosition); data->index = glyph_info[i].codepoint; - data->advanceX = (float)(pos.x_advance / (float)(hres * 64)); + data->advanceX = (float)(pos.x_advance / (float)(64)); data->advanceY = (float)(pos.y_advance / (float)64); - data->offsetX = (float)(pos.x_offset / (float)(hres * 64)); + data->offsetX = (float)(pos.x_offset / (float)(64)); data->offsetY = (float)(pos.y_offset / (float)64); bytesPosition += glyphSize;