mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 21:51:22 +00:00 
			
		
		
		
	Support colored font
This commit is contained in:
		
							parent
							
								
									05b1843818
								
							
						
					
					
						commit
						c5e3acc29c
					
				
					 3 changed files with 59 additions and 22 deletions
				
			
		|  | @ -87,6 +87,6 @@ if env['builtin_freetype']: | ||||||
| 
 | 
 | ||||||
| # Godot source files | # Godot source files | ||||||
| env.add_source_files(env.modules_sources, "*.cpp") | env.add_source_files(env.modules_sources, "*.cpp") | ||||||
| env.Append(CCFLAGS=['-DFREETYPE_ENABLED']) | env.Append(CCFLAGS=['-DFREETYPE_ENABLED', '-DFT_CONFIG_OPTION_USE_PNG']) | ||||||
| 
 | 
 | ||||||
| Export('env') | Export('env') | ||||||
|  |  | ||||||
|  | @ -192,10 +192,25 @@ Error DynamicFontAtSize::_load() { | ||||||
| 		ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); | 		ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); | ||||||
| 	}*/ | 	}*/ | ||||||
| 
 | 
 | ||||||
|  | 	if (FT_HAS_COLOR(face)) { | ||||||
|  | 		int best_match = 0; | ||||||
|  | 		int diff = ABS(id.size - face->available_sizes[0].width); | ||||||
|  | 		scale_color_font = float(id.size) / face->available_sizes[0].width; | ||||||
|  | 		for (int i = 1; i < face->num_fixed_sizes; i++) { | ||||||
|  | 			int ndiff = ABS(id.size - face->available_sizes[i].width); | ||||||
|  | 			if (ndiff < diff) { | ||||||
|  | 				best_match = i; | ||||||
|  | 				diff = ndiff; | ||||||
|  | 				scale_color_font = float(id.size) / face->available_sizes[i].width; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		error = FT_Select_Size(face, best_match); | ||||||
|  | 	} else { | ||||||
| 		error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); | 		error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	ascent = (face->size->metrics.ascender >> 6) / oversampling; | 	ascent = (face->size->metrics.ascender >> 6) / oversampling * scale_color_font; | ||||||
| 	descent = (-face->size->metrics.descender >> 6) / oversampling; | 	descent = (-face->size->metrics.descender >> 6) / oversampling * scale_color_font; | ||||||
| 	linegap = 0; | 	linegap = 0; | ||||||
| 	texture_flags = 0; | 	texture_flags = 0; | ||||||
| 	if (id.mipmaps) | 	if (id.mipmaps) | ||||||
|  | @ -292,7 +307,6 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const V | ||||||
| 			ret.x += (delta.x >> 6) / oversampling; | 			ret.x += (delta.x >> 6) / oversampling; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -334,14 +348,18 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT | ||||||
| 
 | 
 | ||||||
| 			if (!ch->found) | 			if (!ch->found) | ||||||
| 				continue; | 				continue; | ||||||
| 
 |  | ||||||
| 			Point2 cpos = p_pos; | 			Point2 cpos = p_pos; | ||||||
| 			cpos.x += ch->h_align; | 			cpos.x += ch->h_align; | ||||||
| 			cpos.y -= get_ascent(); | 			cpos.y -= fb->get_ascent(); | ||||||
| 			cpos.y += ch->v_align; | 			cpos.y += ch->v_align; | ||||||
| 			ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0); | 			ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0); | ||||||
| 			if (ch->texture_idx != -1) | 			if (ch->texture_idx != -1) { | ||||||
| 				VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, p_modulate, false, RID(), false); | 				Color modulate = p_modulate; | ||||||
|  | 				if (FT_HAS_COLOR(fb->face)) { | ||||||
|  | 					modulate.r = modulate.g = modulate.b = 1; | ||||||
|  | 				} | ||||||
|  | 				VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size * Vector2(fb->scale_color_font, fb->scale_color_font)), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, modulate, false, RID(), false); | ||||||
|  | 			} | ||||||
| 			advance = ch->advance; | 			advance = ch->advance; | ||||||
| 			used_fallback = true; | 			used_fallback = true; | ||||||
| 			break; | 			break; | ||||||
|  | @ -362,8 +380,13 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT | ||||||
| 		cpos.y -= get_ascent(); | 		cpos.y -= get_ascent(); | ||||||
| 		cpos.y += c->v_align; | 		cpos.y += c->v_align; | ||||||
| 		ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0); | 		ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0); | ||||||
| 		if (c->texture_idx != -1) | 		if (c->texture_idx != -1) { | ||||||
| 			VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect_uv, p_modulate, false, RID(), false); | 			Color modulate = p_modulate; | ||||||
|  | 			if (FT_HAS_COLOR(face)) { | ||||||
|  | 				modulate.r = modulate.g = modulate.b = 1; | ||||||
|  | 			} | ||||||
|  | 			VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size * Vector2(scale_color_font, scale_color_font)), textures[c->texture_idx].texture->get_rid(), c->rect_uv, modulate, false, RID(), false); | ||||||
|  | 		} | ||||||
| 		advance = c->advance; | 		advance = c->advance; | ||||||
| 		//textures[c->texture_idx].texture->draw(p_canvas_item,Vector2());
 | 		//textures[c->texture_idx].texture->draw(p_canvas_item,Vector2());
 | ||||||
| 	} | 	} | ||||||
|  | @ -437,9 +460,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 		char_map[p_char] = ch; | 		char_map[p_char] = ch; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	int error = FT_Load_Char(face, p_char, FT_LOAD_RENDER | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); | 	int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); | ||||||
| 	if (!error) { | 	if (!error) { | ||||||
| 		error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); | 		error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); | ||||||
| 	} | 	} | ||||||
| 	if (error) { | 	if (error) { | ||||||
| 
 | 
 | ||||||
|  | @ -476,6 +499,8 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 
 | 
 | ||||||
| 	//find a texture to fit this...
 | 	//find a texture to fit this...
 | ||||||
| 
 | 
 | ||||||
|  | 	int color_size = slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; | ||||||
|  | 	Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; | ||||||
| 	int tex_index = -1; | 	int tex_index = -1; | ||||||
| 	int tex_x = 0; | 	int tex_x = 0; | ||||||
| 	int tex_y = 0; | 	int tex_y = 0; | ||||||
|  | @ -484,6 +509,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 
 | 
 | ||||||
| 		CharTexture &ct = textures[i]; | 		CharTexture &ct = textures[i]; | ||||||
| 
 | 
 | ||||||
|  | 		if (ct.texture->get_format() != require_format) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
| 		if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture
 | 		if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture
 | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -533,13 +561,13 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 
 | 
 | ||||||
| 		CharTexture tex; | 		CharTexture tex; | ||||||
| 		tex.texture_size = texsize; | 		tex.texture_size = texsize; | ||||||
| 		tex.imgdata.resize(texsize * texsize * 2); //grayscale alpha
 | 		tex.imgdata.resize(texsize * texsize * color_size); | ||||||
| 
 | 
 | ||||||
| 		{ | 		{ | ||||||
| 			//zero texture
 | 			//zero texture
 | ||||||
| 			PoolVector<uint8_t>::Write w = tex.imgdata.write(); | 			PoolVector<uint8_t>::Write w = tex.imgdata.write(); | ||||||
| 			ERR_FAIL_COND(texsize * texsize * 2 > tex.imgdata.size()); | 			ERR_FAIL_COND(texsize * texsize * color_size > tex.imgdata.size()); | ||||||
| 			for (int i = 0; i < texsize * texsize * 2; i++) { | 			for (int i = 0; i < texsize * texsize * color_size; i++) { | ||||||
| 				w[i] = 0; | 				w[i] = 0; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -561,7 +589,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 		for (int i = 0; i < h; i++) { | 		for (int i = 0; i < h; i++) { | ||||||
| 			for (int j = 0; j < w; j++) { | 			for (int j = 0; j < w; j++) { | ||||||
| 
 | 
 | ||||||
| 				int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * 2; | 				int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * color_size; | ||||||
| 				ERR_FAIL_COND(ofs >= tex.imgdata.size()); | 				ERR_FAIL_COND(ofs >= tex.imgdata.size()); | ||||||
| 				switch (slot->bitmap.pixel_mode) { | 				switch (slot->bitmap.pixel_mode) { | ||||||
| 					case FT_PIXEL_MODE_MONO: { | 					case FT_PIXEL_MODE_MONO: { | ||||||
|  | @ -574,7 +602,14 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 						wr[ofs + 0] = 255; //grayscale as 1
 | 						wr[ofs + 0] = 255; //grayscale as 1
 | ||||||
| 						wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j]; | 						wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j]; | ||||||
| 						break; | 						break; | ||||||
| 					// TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA
 | 					case FT_PIXEL_MODE_BGRA: { | ||||||
|  | 						int ofs_color = i * slot->bitmap.pitch + (j << 2); | ||||||
|  | 						wr[ofs + 2] = slot->bitmap.buffer[ofs_color + 0]; | ||||||
|  | 						wr[ofs + 1] = slot->bitmap.buffer[ofs_color + 1]; | ||||||
|  | 						wr[ofs + 0] = slot->bitmap.buffer[ofs_color + 2]; | ||||||
|  | 						wr[ofs + 3] = slot->bitmap.buffer[ofs_color + 3]; | ||||||
|  | 					} break; | ||||||
|  | 					// TODO: FT_PIXEL_MODE_LCD
 | ||||||
| 					default: | 					default: | ||||||
| 						ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode)); | 						ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode)); | ||||||
| 						ERR_FAIL(); | 						ERR_FAIL(); | ||||||
|  | @ -587,7 +622,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 	//blit to image and texture
 | 	//blit to image and texture
 | ||||||
| 	{ | 	{ | ||||||
| 
 | 
 | ||||||
| 		Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata)); | 		Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, require_format, tex.imgdata)); | ||||||
| 
 | 
 | ||||||
| 		if (tex.texture.is_null()) { | 		if (tex.texture.is_null()) { | ||||||
| 			tex.texture.instance(); | 			tex.texture.instance(); | ||||||
|  | @ -605,9 +640,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Character chr; | 	Character chr; | ||||||
| 	chr.h_align = xofs / oversampling; | 	chr.h_align = xofs * scale_color_font / oversampling; | ||||||
| 	chr.v_align = ascent - (yofs / oversampling); // + ascent - descent;
 | 	chr.v_align = ascent - (yofs * scale_color_font / oversampling); // + ascent - descent;
 | ||||||
| 	chr.advance = advance / oversampling; | 	chr.advance = advance * scale_color_font / oversampling; | ||||||
| 	chr.texture_idx = tex_index; | 	chr.texture_idx = tex_index; | ||||||
| 	chr.found = true; | 	chr.found = true; | ||||||
| 
 | 
 | ||||||
|  | @ -646,6 +681,7 @@ DynamicFontAtSize::DynamicFontAtSize() { | ||||||
| 	linegap = 1; | 	linegap = 1; | ||||||
| 	texture_flags = 0; | 	texture_flags = 0; | ||||||
| 	oversampling = font_oversampling; | 	oversampling = font_oversampling; | ||||||
|  | 	scale_color_font = 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DynamicFontAtSize::~DynamicFontAtSize() { | DynamicFontAtSize::~DynamicFontAtSize() { | ||||||
|  |  | ||||||
|  | @ -104,6 +104,7 @@ class DynamicFontAtSize : public Reference { | ||||||
| 	float linegap; | 	float linegap; | ||||||
| 	float rect_margin; | 	float rect_margin; | ||||||
| 	float oversampling; | 	float oversampling; | ||||||
|  | 	float scale_color_font; | ||||||
| 
 | 
 | ||||||
| 	uint32_t texture_flags; | 	uint32_t texture_flags; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 volzhs
						volzhs