|
@@ -328,6 +328,7 @@ void DynamicFontAtSize::set_texture_flags(uint32_t p_flags) {
|
|
|
texture_flags = p_flags;
|
|
|
for (int i = 0; i < textures.size(); i++) {
|
|
|
Ref<ImageTexture> &tex = textures.write[i].texture;
|
|
|
+ textures.write[i].dirty = true;
|
|
|
if (!tex.is_null()) {
|
|
|
tex->set_flags(p_flags);
|
|
|
}
|
|
@@ -358,6 +359,17 @@ RID DynamicFontAtSize::get_char_texture(CharType p_char, CharType p_next, const
|
|
|
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), RID());
|
|
|
|
|
|
if (ch->texture_idx != -1) {
|
|
|
+ if (font->textures[ch->texture_idx].dirty) {
|
|
|
+ ShelfPackTexture &tex = font->textures.write[ch->texture_idx];
|
|
|
+ Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, tex.format, tex.imgdata));
|
|
|
+ if (tex.texture.is_null()) {
|
|
|
+ tex.texture.instance();
|
|
|
+ tex.texture->create_from_image(img, Texture::FLAG_VIDEO_SURFACE | texture_flags);
|
|
|
+ } else {
|
|
|
+ tex.texture->set_data(img); //update
|
|
|
+ }
|
|
|
+ tex.dirty = false;
|
|
|
+ }
|
|
|
return font->textures[ch->texture_idx].texture->get_rid();
|
|
|
}
|
|
|
}
|
|
@@ -388,6 +400,17 @@ Size2 DynamicFontAtSize::get_char_texture_size(CharType p_char, CharType p_next,
|
|
|
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), Size2());
|
|
|
|
|
|
if (ch->texture_idx != -1) {
|
|
|
+ if (font->textures[ch->texture_idx].dirty) {
|
|
|
+ ShelfPackTexture &tex = font->textures.write[ch->texture_idx];
|
|
|
+ Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, tex.format, tex.imgdata));
|
|
|
+ if (tex.texture.is_null()) {
|
|
|
+ tex.texture.instance();
|
|
|
+ tex.texture->create_from_image(img, Texture::FLAG_VIDEO_SURFACE | texture_flags);
|
|
|
+ } else {
|
|
|
+ tex.texture->set_data(img); //update
|
|
|
+ }
|
|
|
+ tex.dirty = false;
|
|
|
+ }
|
|
|
return font->textures[ch->texture_idx].texture->get_size();
|
|
|
}
|
|
|
}
|
|
@@ -518,6 +541,17 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
|
|
|
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), 0);
|
|
|
|
|
|
if (!p_advance_only && ch->texture_idx != -1) {
|
|
|
+ if (font->textures[ch->texture_idx].dirty) {
|
|
|
+ ShelfPackTexture &tex = font->textures.write[ch->texture_idx];
|
|
|
+ Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, tex.format, tex.imgdata));
|
|
|
+ if (tex.texture.is_null()) {
|
|
|
+ tex.texture.instance();
|
|
|
+ tex.texture->create_from_image(img, Texture::FLAG_VIDEO_SURFACE | texture_flags);
|
|
|
+ } else {
|
|
|
+ tex.texture->set_data(img); //update
|
|
|
+ }
|
|
|
+ tex.dirty = false;
|
|
|
+ }
|
|
|
Point2 cpos = p_pos;
|
|
|
cpos.x += ch->h_align;
|
|
|
cpos.y -= font->get_ascent();
|
|
@@ -595,57 +629,29 @@ DynamicFontAtSize::Character DynamicFontAtSize::Character::not_found() {
|
|
|
return ch;
|
|
|
}
|
|
|
|
|
|
-DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyph(int p_color_size, Image::Format p_image_format, int p_width, int p_height) {
|
|
|
- TexturePosition ret;
|
|
|
- ret.index = -1;
|
|
|
- ret.x = 0;
|
|
|
- ret.y = 0;
|
|
|
+DynamicFontAtSize::FontTexturePosition DynamicFontAtSize::_find_texture_pos_for_glyph(int p_color_size, Image::Format p_image_format, int p_width, int p_height) {
|
|
|
+ FontTexturePosition ret;
|
|
|
|
|
|
int mw = p_width;
|
|
|
int mh = p_height;
|
|
|
|
|
|
- for (int i = 0; i < textures.size(); i++) {
|
|
|
- const CharTexture &ct = textures[i];
|
|
|
-
|
|
|
- if (ct.texture->get_format() != p_image_format) {
|
|
|
+ ShelfPackTexture *ct = textures.ptrw();
|
|
|
+ for (int32_t i = 0; i < textures.size(); i++) {
|
|
|
+ if (ct[i].format != p_image_format) {
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
- if (mw > ct.texture_size || mh > ct.texture_size) { //too big for this texture
|
|
|
+ if (mw > ct[i].texture_size || mh > ct[i].texture_size) { // Too big for this texture.
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- ret.y = 0x7FFFFFFF;
|
|
|
- ret.x = 0;
|
|
|
-
|
|
|
- for (int j = 0; j < ct.texture_size - mw; j++) {
|
|
|
- int max_y = 0;
|
|
|
-
|
|
|
- for (int k = j; k < j + mw; k++) {
|
|
|
- int y = ct.offsets[k];
|
|
|
- if (y > max_y) {
|
|
|
- max_y = y;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (max_y < ret.y) {
|
|
|
- ret.y = max_y;
|
|
|
- ret.x = j;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (ret.y == 0x7FFFFFFF || ret.y + mh > ct.texture_size) {
|
|
|
- continue; //fail, could not fit it here
|
|
|
+ ret = ct[i].pack_rect(i, mh, mw);
|
|
|
+ if (ret.index != -1) {
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
- ret.index = i;
|
|
|
- break;
|
|
|
}
|
|
|
|
|
|
if (ret.index == -1) {
|
|
|
//could not find texture to fit, create one
|
|
|
- ret.x = 0;
|
|
|
- ret.y = 0;
|
|
|
|
|
|
int texsize = MAX(id.size * oversampling * 8, 256);
|
|
|
if (mw > texsize) {
|
|
@@ -659,8 +665,8 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp
|
|
|
|
|
|
texsize = MIN(texsize, 4096);
|
|
|
|
|
|
- CharTexture tex;
|
|
|
- tex.texture_size = texsize;
|
|
|
+ ShelfPackTexture tex = ShelfPackTexture(texsize);
|
|
|
+ tex.format = p_image_format;
|
|
|
tex.imgdata.resize(texsize * texsize * p_color_size); //grayscale alpha
|
|
|
|
|
|
{
|
|
@@ -684,13 +690,9 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- tex.offsets.resize(texsize);
|
|
|
- for (int i = 0; i < texsize; i++) { //zero offsets
|
|
|
- tex.offsets.write[i] = 0;
|
|
|
- }
|
|
|
-
|
|
|
textures.push_back(tex);
|
|
|
- ret.index = textures.size() - 1;
|
|
|
+ int32_t idx = textures.size() - 1;
|
|
|
+ ret = textures.write[idx].pack_rect(idx, mh, mw);
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
@@ -709,13 +711,13 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b
|
|
|
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
|
|
|
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
|
|
|
|
|
|
- TexturePosition tex_pos = _find_texture_pos_for_glyph(color_size, require_format, mw, mh);
|
|
|
+ FontTexturePosition tex_pos = _find_texture_pos_for_glyph(color_size, require_format, mw, mh);
|
|
|
ERR_FAIL_COND_V(tex_pos.index < 0, Character::not_found());
|
|
|
|
|
|
//fit character in char texture
|
|
|
|
|
|
- CharTexture &tex = textures.write[tex_pos.index];
|
|
|
-
|
|
|
+ ShelfPackTexture &tex = textures.write[tex_pos.index];
|
|
|
+ tex.dirty = true;
|
|
|
{
|
|
|
PoolVector<uint8_t>::Write wr = tex.imgdata.write();
|
|
|
|
|
@@ -750,24 +752,6 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //blit to image and texture
|
|
|
- {
|
|
|
- Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, require_format, tex.imgdata));
|
|
|
-
|
|
|
- if (tex.texture.is_null()) {
|
|
|
- tex.texture.instance();
|
|
|
- tex.texture->create_from_image(img, Texture::FLAG_VIDEO_SURFACE | texture_flags);
|
|
|
- } else {
|
|
|
- tex.texture->set_data(img); //update
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // update height array
|
|
|
-
|
|
|
- for (int k = tex_pos.x; k < tex_pos.x + mw; k++) {
|
|
|
- tex.offsets.write[k] = tex_pos.y + mh;
|
|
|
- }
|
|
|
-
|
|
|
Character chr;
|
|
|
chr.h_align = xofs * scale_color_font / oversampling;
|
|
|
chr.v_align = ascent - (yofs * scale_color_font / oversampling); // + ascent - descent;
|