Browse Source

signed distance field font support

Juan Linietsky 10 years ago
parent
commit
acc6f3b285

+ 12 - 0
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;

+ 9 - 1
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

+ 3 - 1
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;

+ 17 - 0
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();
+
 	
 
 }

+ 4 - 0
scene/resources/font.h

@@ -75,6 +75,7 @@ private:
 	
 	float height;
 	float ascent;
+	bool distance_field_hint;
 
 	void _set_chars(const DVector<int>& p_chars);
 	DVector<int> _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;

+ 2 - 1
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;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL;  material_owner=NULL;}
-		CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1;  blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; }
+		CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1;  blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; }
 		virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
 	};
 

+ 8 - 0
servers/visual/visual_server_raster.cpp

@@ -3411,6 +3411,14 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) {
 	canvas_item->clip=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) {
 

+ 1 - 0
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;

+ 1 - 0
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 );

+ 1 - 0
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;

+ 6 - 6
tools/editor/io_plugins/editor_font_import_plugin.cpp

@@ -984,7 +984,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 	{
 
 		bool skip=false;
-		error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
+		error = FT_Load_Char( face, charcode, font_mode==_EditorFontImportOptions::FONT_BITMAP?FT_LOAD_RENDER:FT_LOAD_MONOCHROME );
 		if (error) skip=true;
 		else error = FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono );
 		if (error) {
@@ -1016,7 +1016,8 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 		int w = slot->bitmap.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<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 		else
 			fdata->advance=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<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 	spd->ofs_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<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 		atlas.convert(Image::FORMAT_GRAYSCALE_ALPHA);
 	}
 
-	if (1) {
+	if (0) {
 		//debug the texture
 		Ref<ImageTexture> atlast = memnew( ImageTexture );
 		atlast->create_from_image(atlas);
@@ -1531,6 +1530,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 	font->clear();
 	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
 	{