signed distance field font support

This commit is contained in:
Juan Linietsky 2015-03-21 00:43:33 -03:00
parent 90a84b4ddb
commit acc6f3b285
11 changed files with 64 additions and 9 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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