diff options
author | volzhs <volzhs@gmail.com> | 2018-01-16 22:22:59 +0900 |
---|---|---|
committer | volzhs <volzhs@gmail.com> | 2018-01-16 22:56:54 +0900 |
commit | c5e3acc29c44e11e5416c66cad8f93b82c93e6b9 (patch) | |
tree | e40066395708f3c4d457c71a2575dbcf6472f252 /scene/resources | |
parent | 05b1843818fd07f084816ec506ec505e24f8f02c (diff) |
Support colored font
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/dynamic_font.cpp | 78 | ||||
-rw-r--r-- | scene/resources/dynamic_font.h | 1 |
2 files changed, 58 insertions, 21 deletions
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index b35a9ae963..f4d114e4ba 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -192,10 +192,25 @@ Error DynamicFontAtSize::_load() { ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); }*/ - error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); + 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); + } - ascent = (face->size->metrics.ascender >> 6) / oversampling; - descent = (-face->size->metrics.descender >> 6) / oversampling; + ascent = (face->size->metrics.ascender >> 6) / oversampling * scale_color_font; + descent = (-face->size->metrics.descender >> 6) / oversampling * scale_color_font; linegap = 0; texture_flags = 0; 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; } } - return ret; } @@ -334,14 +348,18 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT if (!ch->found) continue; - Point2 cpos = p_pos; cpos.x += ch->h_align; - cpos.y -= get_ascent(); + cpos.y -= fb->get_ascent(); cpos.y += ch->v_align; ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0); - 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); + if (ch->texture_idx != -1) { + 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; used_fallback = true; break; @@ -362,8 +380,13 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT cpos.y -= get_ascent(); cpos.y += c->v_align; ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0); - 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); + if (c->texture_idx != -1) { + 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; //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; 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) { - error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); } if (error) { @@ -476,6 +499,8 @@ void DynamicFontAtSize::_update_char(CharType p_char) { //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_x = 0; int tex_y = 0; @@ -484,6 +509,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { 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 continue; @@ -533,13 +561,13 @@ void DynamicFontAtSize::_update_char(CharType p_char) { CharTexture tex; tex.texture_size = texsize; - tex.imgdata.resize(texsize * texsize * 2); //grayscale alpha + tex.imgdata.resize(texsize * texsize * color_size); { //zero texture PoolVector<uint8_t>::Write w = tex.imgdata.write(); - ERR_FAIL_COND(texsize * texsize * 2 > tex.imgdata.size()); - for (int i = 0; i < texsize * texsize * 2; i++) { + ERR_FAIL_COND(texsize * texsize * color_size > tex.imgdata.size()); + for (int i = 0; i < texsize * texsize * color_size; i++) { w[i] = 0; } } @@ -561,7 +589,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { for (int i = 0; i < h; i++) { 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()); switch (slot->bitmap.pixel_mode) { 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 + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j]; 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: ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode)); ERR_FAIL(); @@ -587,7 +622,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { //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()) { tex.texture.instance(); @@ -605,9 +640,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { } Character chr; - chr.h_align = xofs / oversampling; - chr.v_align = ascent - (yofs / oversampling); // + ascent - descent; - chr.advance = advance / oversampling; + chr.h_align = xofs * scale_color_font / oversampling; + chr.v_align = ascent - (yofs * scale_color_font / oversampling); // + ascent - descent; + chr.advance = advance * scale_color_font / oversampling; chr.texture_idx = tex_index; chr.found = true; @@ -646,6 +681,7 @@ DynamicFontAtSize::DynamicFontAtSize() { linegap = 1; texture_flags = 0; oversampling = font_oversampling; + scale_color_font = 1; } DynamicFontAtSize::~DynamicFontAtSize() { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index a949892086..50fc70551c 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -104,6 +104,7 @@ class DynamicFontAtSize : public Reference { float linegap; float rect_margin; float oversampling; + float scale_color_font; uint32_t texture_flags; |