From acc6f3b285f058104fd6431bed2c4cfe4dc05a58 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 21 Mar 2015 00:43:33 -0300 Subject: [PATCH] signed distance field font support --- drivers/gles2/rasterizer_gles2.cpp | 12 ++++++++++++ drivers/gles2/shaders/canvas.glsl | 10 +++++++++- scene/gui/label.cpp | 4 +++- scene/resources/font.cpp | 17 +++++++++++++++++ scene/resources/font.h | 4 ++++ servers/visual/rasterizer.h | 3 ++- servers/visual/visual_server_raster.cpp | 8 ++++++++ servers/visual/visual_server_raster.h | 1 + servers/visual/visual_server_wrap_mt.h | 1 + servers/visual_server.h | 1 + .../io_plugins/editor_font_import_plugin.cpp | 12 ++++++------ 11 files changed, 64 insertions(+), 9 deletions(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index a21b0775e91..05c977f3441 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -9127,8 +9127,10 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const canvas_use_modulate=p_modulate!=Color(1,1,1,1); canvas_modulate=p_modulate; canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false); bool reset_modulate=false; + bool prev_distance_field=false; while(p_item_list) { @@ -9144,12 +9146,22 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const canvas_use_modulate=p_modulate!=Color(1,1,1,1); canvas_modulate=p_modulate; canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false); + prev_distance_field=false; rebind_shader=true; reset_modulate=true; } + if (prev_distance_field!=ci->distance_field) { + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,ci->distance_field); + prev_distance_field=ci->distance_field; + rebind_shader=true; + } + + if (current_clip!=ci->final_clip_owner) { current_clip=ci->final_clip_owner; diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 0e19736fd53..e6d25699775 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -191,8 +191,16 @@ void main() { vec3 normal = vec3(0.0,0.0,1.0); #endif - +#ifdef USE_DISTANCE_FIELD + const float smoothing = 1.0/32.0; + float distance = texture2D(texture, uv_interp).a; + color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance); +#else color *= texture2D( texture, uv_interp ); + +#endif + + #if defined(ENABLE_SCREEN_UV) vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; #endif diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index d2e1e7f0b98..892e4c9bc7c 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -72,6 +72,7 @@ void Label::_notification(int p_what) { if (clip && !autowrap) VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + if (word_cache_dirty) regenerate_word_cache(); @@ -87,7 +88,8 @@ void Label::_notification(int p_what) { bool use_outlinde = get_constant("shadow_as_outline"); Point2 shadow_ofs(get_constant("shadow_offset_x"),get_constant("shadow_offset_y")); - + VisualServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(),font.is_valid() && font->is_distance_field_hint()); + int font_h = font->get_height(); int line_from=(int)get_val(); // + p_exposed.pos.y / font_h; int lines_visible = size.y/font_h; diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 49ee3ee017f..24d413ed60c 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -398,6 +398,17 @@ int Font::get_kerning_pair(CharType p_A,CharType p_B) const { return 0; } +void Font::set_distance_field_hint(bool p_distance_field) { + + distance_field_hint=p_distance_field; + emit_changed(); +} + +bool Font::is_distance_field_hint() const{ + + return distance_field_hint; +} + void Font::clear() { @@ -406,6 +417,7 @@ void Font::clear() { char_map.clear(); textures.clear(); kerning_map.clear(); + distance_field_hint=false; } Size2 Font::get_string_size(const String& p_string) const { @@ -514,6 +526,9 @@ void Font::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_char_size","char","next"),&Font::get_char_size,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("get_string_size","string"),&Font::get_string_size); + ObjectTypeDB::bind_method(_MD("set_distance_field_hint","enable"),&Font::set_distance_field_hint); + ObjectTypeDB::bind_method(_MD("is_distance_field_hint"),&Font::is_distance_field_hint); + ObjectTypeDB::bind_method(_MD("clear"),&Font::clear); ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","string","modulate","clip_w"),&Font::draw,DEFVAL(Color(1,1,1)),DEFVAL(-1)); @@ -535,12 +550,14 @@ void Font::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,1" ), _SCS("set_height"), _SCS("get_height") ); ADD_PROPERTY( PropertyInfo( Variant::REAL, "ascent", PROPERTY_HINT_RANGE,"-1024,1024,1" ), _SCS("set_ascent"), _SCS("get_ascent") ); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "distance_field" ), _SCS("set_distance_field_hint"), _SCS("is_distance_field_hint") ); } Font::Font() { clear(); + } diff --git a/scene/resources/font.h b/scene/resources/font.h index a64ec1ef7a4..498bc6863a5 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -75,6 +75,7 @@ private: float height; float ascent; + bool distance_field_hint; void _set_chars(const DVector& p_chars); DVector _get_chars() const; @@ -116,6 +117,9 @@ public: Size2 get_string_size(const String& p_string) const; void clear(); + + void set_distance_field_hint(bool p_distance_field); + bool is_distance_field_hint() const; void draw(RID p_canvas_item, const Point2& p_pos, const String& p_text,const Color& p_modulate=Color(1,1,1),int p_clip_w=-1) const; void draw_halign(RID p_canvas_item, const Point2& p_pos, HAlign p_align,float p_width,const String& p_text,const Color& p_modulate=Color(1,1,1)) const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 8c89ddd5b7e..ebc210fe3d2 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -783,6 +783,7 @@ public: CanvasItem* final_clip_owner; CanvasItem* material_owner; ViewportRender *vp_render; + bool distance_field; Rect2 global_rect_cache; @@ -910,7 +911,7 @@ public: } void clear() { for (int i=0;iclip=p_clip; } +void VisualServerRaster::canvas_item_set_distance_field_mode(RID p_item, bool p_distance_field) { + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->distance_field=p_distance_field; +} + void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index b1970c55b33..72af7932789 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1128,6 +1128,7 @@ public: //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect); virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform); virtual void canvas_item_set_clip(RID p_item, bool p_clip); + virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2()); virtual void canvas_item_set_opacity(RID p_item, float p_opacity); virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 562b9ffeb00..ded4c6fc00e 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -1109,6 +1109,7 @@ public: //FUNC(canvas_item_set_rect,RID, const Rect2& p_rect); FUNC2(canvas_item_set_transform,RID, const Matrix32& ); FUNC2(canvas_item_set_clip,RID, bool ); + FUNC2(canvas_item_set_distance_field_mode,RID, bool ); FUNC3(canvas_item_set_custom_rect,RID, bool ,const Rect2&); FUNC2(canvas_item_set_opacity,RID, float ); FUNC2RC(float,canvas_item_get_opacity,RID, float ); diff --git a/servers/visual_server.h b/servers/visual_server.h index c748839d1e7..b6d354454ee 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -969,6 +969,7 @@ public: virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform)=0; virtual void canvas_item_set_clip(RID p_item, bool p_clip)=0; + virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable)=0; virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2())=0; virtual void canvas_item_set_opacity(RID p_item, float p_opacity)=0; virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const=0; diff --git a/tools/editor/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp index 05a42218a29..05621531995 100644 --- a/tools/editor/io_plugins/editor_font_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -984,7 +984,7 @@ Ref EditorFontImportPlugin::generate_font(const Refglyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono ); if (error) { @@ -1016,7 +1016,8 @@ Ref EditorFontImportPlugin::generate_font(const Refbitmap.width; int h = slot->bitmap.rows; int p = slot->bitmap.pitch; - print_line("pitch "+itos(slot->bitmap.pitch)); + + print_line("W: "+itos(w)+" P: "+itos(slot->bitmap.pitch)); if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) { @@ -1049,8 +1050,6 @@ Ref EditorFontImportPlugin::generate_font(const Refadvance=slot->advance.x/float(1<<6); - fdata->advance/=scaler; - if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) { fdata->halign = fdata->halign / scaler - 1.5; @@ -1150,7 +1149,7 @@ Ref EditorFontImportPlugin::generate_font(const Refofs_x=0; spd->ofs_y=0; - if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, ft_render_mode_normal )) { + if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono )) { spd->advance = slot->advance.x>>6; //round to nearest or store as float spd->advance/=scaler; @@ -1498,7 +1497,7 @@ Ref EditorFontImportPlugin::generate_font(const Ref atlast = memnew( ImageTexture ); atlast->create_from_image(atlas); @@ -1531,6 +1530,7 @@ Ref EditorFontImportPlugin::generate_font(const Refclear(); font->set_height(height+bottom_space+top_space); font->set_ascent(ascent+top_space); + font->set_distance_field_hint(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD); //register texures {