diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index 67b811a7d7..5d43b90170 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -125,6 +125,8 @@
+
+
Returns [TextServer] RID of the font cache for specific variation.
@@ -226,6 +228,26 @@
Returns [Dictionary] with OpenType font name strings (localized font names, version, description, license information, sample text, etc.).
+
+
+
+
+ Returns the array in the predefined color palette at [param index]. Palette contains all colors used to render font glyphs. Each palette has the same number of colors. Colors can be overridden using [FontVariation].
+
+
+
+
+
+ Returns the number of predefined color palettes. Palette contains all colors used to render font glyphs. Each palette has the same number of colors.
+
+
+
+
+
+
+ Returns the name of the predefined color palette at [param index]. Palette contains all colors used to render font glyphs. Each palette has the same number of colors.
+
+
diff --git a/doc/classes/FontVariation.xml b/doc/classes/FontVariation.xml
index 08c2ec9a4f..4945cc2e92 100644
--- a/doc/classes/FontVariation.xml
+++ b/doc/classes/FontVariation.xml
@@ -52,6 +52,12 @@
A set of OpenType feature tags. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
+
+ An array of colors to override predefined palette. Use [code]Color(0, 0, 0, 0)[/code], to keep predefined palette color at specific position.
+
+
+ A palette index.
+
Extra spacing at the bottom of the line in pixels.
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 4d66c19812..759bdfbe00 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -406,6 +406,36 @@
Returns oversampling factor override. If set to a positive value, overrides the oversampling factor of the viewport this font is used in. See [member Viewport.oversampling]. This value doesn't override the [code skip-lint]oversampling[/code] parameter of [code skip-lint]draw_*[/code] methods. Used by dynamic fonts only.
+
+
+
+
+
+ Returns the array in the predefined color palette at [param index]. Palette contains all colors used to render font glyphs. Each palette has the same number of colors. Colors can be overridden using [method font_set_palette_custom_colors].
+
+
+
+
+
+
+ Returns the number of predefined color palettes. Palette contains all colors used to render font glyphs. Each palette has the same number of colors.
+
+
+
+
+
+
+ Returns array of custom colors to override predefined palette.
+
+
+
+
+
+
+
+ Returns the name of the predefined color palette at [param index]. Palette contains all colors used to render font glyphs. Each palette has the same number of colors.
+
+
@@ -542,6 +572,13 @@
Returns thickness of the underline in pixels.
+
+
+
+
+ Returns used palette index.
+
+
@@ -882,7 +919,7 @@
-
+
If set to [code]true[/code], color modulation is applied when drawing colored glyphs, otherwise it's applied to the monochrome glyphs only.
@@ -936,6 +973,14 @@
If set to a positive value, overrides the oversampling factor of the viewport this font is used in. See [member Viewport.oversampling]. This value doesn't override the [code skip-lint]oversampling[/code] parameter of [code skip-lint]draw_*[/code] methods. Used by dynamic fonts only.
+
+
+
+
+
+ Sets array of custom colors to override predefined palette. Set to empty array to reset overrides. Use [code]Color(0, 0, 0, 0)[/code], to keep predefined palette color at specific position.
+
+
@@ -1044,6 +1089,14 @@
Sets thickness of the underline in pixels.
+
+
+
+
+
+ Sets used palette index.
+
+
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index 92bc817027..cfc8313c47 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -384,6 +384,36 @@
Returns oversampling factor override. If set to a positive value, overrides the oversampling factor of the viewport this font is used in. See [member Viewport.oversampling]. This value doesn't override the [code skip-lint]oversampling[/code] parameter of [code skip-lint]draw_*[/code] methods. Used by dynamic fonts only.
+
+
+
+
+
+ Returns the array in the predefined color palette at [param index]. Palette contains all colors used to render font glyphs. Each palette has the same number of colors. Colors can be overridden using [method _font_set_palette_custom_colors].
+
+
+
+
+
+
+ Returns the number of predefined color palettes. Palette contains all colors used to render font glyphs. Each palette has the same number of colors.
+
+
+
+
+
+
+ Returns array of custom colors to override predefined palette.
+
+
+
+
+
+
+
+ Returns the name of the predefined color palette at [param index]. Palette contains all colors used to render font glyphs. Each palette has the same number of colors.
+
+
@@ -520,6 +550,13 @@
Returns thickness of the underline in pixels.
+
+
+
+
+ Returns used palette index.
+
+
@@ -919,6 +956,14 @@
If set to a positive value, overrides the oversampling factor of the viewport this font is used in. See [member Viewport.oversampling]. This value doesn't override the [code skip-lint]oversampling[/code] parameter of [code skip-lint]draw_*[/code] methods. Used by dynamic fonts only.
+
+
+
+
+
+ Sets array of custom colors to override predefined palette. Set to empty array to reset overrides. Use [code]Color(0, 0, 0, 0)[/code], to keep predefined palette color at specific position.
+
+
@@ -1024,6 +1069,14 @@
Sets thickness of the underline in pixels.
+
+
+
+
+
+ Sets used palette index.
+
+
diff --git a/editor/inspector/editor_property_name_processor.cpp b/editor/inspector/editor_property_name_processor.cpp
index 8c0d6b0624..270a23bd2c 100644
--- a/editor/inspector/editor_property_name_processor.cpp
+++ b/editor/inspector/editor_property_name_processor.cpp
@@ -167,6 +167,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["bptc"] = "BPTC";
capitalize_string_remaps["bvh"] = "BVH";
capitalize_string_remaps["ca"] = "CA";
+ capitalize_string_remaps["colr"] = "COLR";
capitalize_string_remaps["ccdik"] = "CCDIK";
capitalize_string_remaps["cd"] = "CD";
capitalize_string_remaps["cpu"] = "CPU";
diff --git a/misc/extension_api_validation/4.1-stable_4.2-stable/GH-80954.txt b/misc/extension_api_validation/4.1-stable_4.2-stable/GH-80954.txt
index a18b428c07..3d80724457 100644
--- a/misc/extension_api_validation/4.1-stable_4.2-stable/GH-80954.txt
+++ b/misc/extension_api_validation/4.1-stable_4.2-stable/GH-80954.txt
@@ -1,5 +1,5 @@
GH-80954
--------
-Validate extension JSON: Error: Field 'classes/Font/methods/find_variation/arguments': size changed value in new API, from 4 to 9.
+Validate extension JSON: Error: Field 'classes/Font/methods/find_variation/arguments': size changed value in new API, from 4 to 11.
Added optional arguments. Compatibility method registered.
diff --git a/misc/extension_api_validation/4.2-stable_4.3-stable/GH-87668.txt b/misc/extension_api_validation/4.2-stable_4.3-stable/GH-87668.txt
index 282a83be35..aea01b1472 100644
--- a/misc/extension_api_validation/4.2-stable_4.3-stable/GH-87668.txt
+++ b/misc/extension_api_validation/4.2-stable_4.3-stable/GH-87668.txt
@@ -1,5 +1,5 @@
GH-87668
--------
-Validate extension JSON: Error: Field 'classes/Font/methods/find_variation/arguments': size changed value in new API, from 8 to 9.
+Validate extension JSON: Error: Field 'classes/Font/methods/find_variation/arguments': size changed value in new API, from 8 to 11.
Added optional "baseline_offset" argument. Compatibility method registered.
diff --git a/misc/extension_api_validation/4.6-stable/GH-117149.txt b/misc/extension_api_validation/4.6-stable/GH-117149.txt
new file mode 100644
index 0000000000..54b67b0ae6
--- /dev/null
+++ b/misc/extension_api_validation/4.6-stable/GH-117149.txt
@@ -0,0 +1,5 @@
+GH-117149
+---------
+Validate extension JSON: Error: Field 'classes/Font/methods/find_variation/arguments': size changed value in new API, from 9 to 11.
+
+Optional "palette_index" and "custom_colors" arguments added. Compatibility method registered.
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 2c1fed6cf7..1111612788 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -99,6 +99,7 @@ if env["builtin_harfbuzz"]:
# "src/hb-subset-cff-common.cc",
# "src/hb-subset-cff1.cc",
# "src/hb-subset-cff2.cc",
+ # "src/hb-subset-cff2-to-cff1.cc",
# "src/hb-subset-input.cc",
# "src/hb-subset-instancer-iup.cc",
# "src/hb-subset-instancer-solver.cc",
@@ -109,9 +110,30 @@ if env["builtin_harfbuzz"]:
# "src/hb-subset-table-layout.cc",
# "src/hb-subset-table-other.cc",
# "src/hb-subset-table-var.cc",
+ "src/hb-raster.cc",
+ "src/hb-raster-draw.cc",
+ "src/hb-raster-image.cc",
+ "src/hb-raster-paint.cc",
+ "src/hb-raster-svg-base.cc",
+ "src/hb-raster-svg-bbox.cc",
+ "src/hb-raster-svg-color.cc",
+ "src/hb-raster-svg-clip.cc",
+ "src/hb-raster-svg-defs.cc",
+ "src/hb-raster-svg-defs-scan.cc",
+ "src/hb-raster-svg-gradient.cc",
+ "src/hb-raster-svg-fill.cc",
+ "src/hb-raster-svg-render.cc",
+ "src/hb-raster-svg-parse.cc",
+ "src/hb-raster-svg-use.cc",
+ "src/hb-vector-svg-draw.cc",
+ "src/hb-vector-svg-paint.cc",
+ "src/hb-vector-svg-path.cc",
+ "src/hb-vector-svg-subset.cc",
+ "src/hb-vector-svg-utils.cc",
"src/hb-subset.cc",
"src/hb-ucd.cc",
"src/hb-unicode.cc",
+ "src/hb-zlib.cc",
# "src/hb-uniscribe.cc",
"src/OT/Var/VARC/VARC.cc",
]
@@ -128,7 +150,7 @@ if env["builtin_harfbuzz"]:
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
- env_harfbuzz.Append(CPPDEFINES=["HAVE_ICU"])
+ env_harfbuzz.Append(CPPDEFINES=["HAVE_ICU", "HAVE_ZLIB", "HAVE_PNG"])
if env["builtin_icu4c"]:
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
env_harfbuzz.Append(
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index e0a0cd53e8..366520d590 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1085,6 +1085,72 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
#endif
#ifdef MODULE_FREETYPE_ENABLED
+#if HB_VERSION_ATLEAST(13, 0, 0)
+_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_hb_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, hb_raster_image_t *p_image, const hb_raster_extents_t &p_ext, const Vector2 &p_advance, bool p_bgra) const {
+ FontGlyph chr;
+ chr.advance = p_advance * p_data->scale;
+ chr.found = true;
+
+ int w = p_ext.width;
+ int h = p_ext.height;
+
+ if (w == 0 || h == 0 || p_image == nullptr) {
+ chr.texture_idx = -1;
+ chr.uv_rect = Rect2();
+ chr.rect = Rect2();
+ return chr;
+ }
+
+ int color_size = p_bgra ? 4 : 2;
+
+ int mw = w + p_rect_margin * 4;
+ int mh = h + p_rect_margin * 4;
+
+ ERR_FAIL_COND_V(mw > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+
+ Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
+
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
+ ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
+
+ const uint8_t *img_src = hb_raster_image_get_buffer(p_image);
+
+ // Fit character in char texture.
+ ShelfPackTexture &tex = p_data->textures.write[tex_pos.index];
+
+ {
+ uint8_t *wr = tex.image->ptrw();
+
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * color_size;
+ ERR_FAIL_COND_V(ofs >= tex.image->get_data_size(), FontGlyph());
+ if (p_bgra) {
+ int ofs_color = i * p_ext.stride + (j << 2);
+ wr[ofs + 2] = img_src[ofs_color + 0];
+ wr[ofs + 1] = img_src[ofs_color + 1];
+ wr[ofs + 0] = img_src[ofs_color + 2];
+ wr[ofs + 3] = img_src[ofs_color + 3];
+ } else {
+ wr[ofs + 0] = 255; // grayscale as 1
+ wr[ofs + 1] = img_src[i * p_ext.stride + j];
+ }
+ }
+ }
+ }
+
+ tex.dirty = true;
+
+ chr.texture_idx = tex_pos.index;
+
+ chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2);
+ chr.rect.position = Vector2(p_ext.x_origin - p_rect_margin, p_ext.y_origin - p_rect_margin) * p_data->scale;
+ chr.rect.size = chr.uv_rect.size * p_data->scale;
+ return chr;
+}
+#endif
+
_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap p_bitmap, int p_yofs, int p_xofs, const Vector2 &p_advance, bool p_bgra) const {
FontGlyph chr;
chr.advance = p_advance * p_data->scale;
@@ -1093,7 +1159,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
int w = p_bitmap.width;
int h = p_bitmap.rows;
- if (w == 0 || h == 0) {
+ if (w == 0 || h == 0 || p_bitmap.buffer == nullptr) {
chr.texture_idx = -1;
chr.uv_rect = Rect2();
chr.rect = Rect2();
@@ -1335,21 +1401,85 @@ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, const Vector2i
}
FT_GlyphSlot slot = p_font_data->face->glyph;
- bool from_svg = (slot->format == FT_GLYPH_FORMAT_SVG); // Need to check before FT_Render_Glyph as it will change format to bitmap.
+ bool fix_edge = (slot->format == FT_GLYPH_FORMAT_SVG); // Need to check before FT_Render_Glyph as it will change format to bitmap.
+ bool from_bitmap = (slot->format == FT_GLYPH_FORMAT_BITMAP);
if (!outline) {
- if (!p_font_data->msdf) {
- error = FT_Render_Glyph(slot, aa_mode);
- }
- if (!error) {
- if (p_font_data->msdf) {
+ if (p_font_data->msdf) {
#ifdef MODULE_MSDFGEN_ENABLED
- gl = rasterize_msdf(p_font_data, fd, p_font_data->msdf_range, rect_range, &slot->outline, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0);
+ gl = rasterize_msdf(p_font_data, fd, p_font_data->msdf_range, rect_range, &slot->outline, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0);
#else
- fd->glyph_map[p_glyph] = FontGlyph();
- ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!");
+ fd->glyph_map[p_glyph] = FontGlyph();
+ ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!");
#endif
+ } else {
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ if (hb_rdr && hb_mono && p_font_data->antialiasing == FONT_ANTIALIASING_GRAY && !from_bitmap) {
+ bool is_rasterized = false;
+ float xshift = 0.0;
+ if ((p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && p_size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE * 64)) {
+ xshift = float((int)((p_glyph >> 27) & 3) << 4);
+ } else if ((p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && p_size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE * 64)) {
+ xshift = float((int)((p_glyph >> 27) & 3) << 5);
+ }
+ xshift += (p_font_data->embolden * double(p_size.x) / 64.0);
+ fix_edge = false;
+ if (fd->color_paint) {
+ hb_raster_paint_reset(hb_rdr);
+ if (p_font_data->transform != Transform2D()) {
+ hb_raster_paint_set_transform(hb_rdr, p_font_data->transform[0][0], p_font_data->transform[1][0], p_font_data->transform[0][1], -p_font_data->transform[1][1], 0.f, 0.f);
+ } else {
+ hb_raster_paint_set_transform(hb_rdr, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f);
+ }
+ hb_raster_paint_set_scale_factor(hb_rdr, 64.0, 64.0);
+ hb_raster_paint_clear_custom_palette_colors(hb_rdr);
+ if (!p_font_data->palette_custom_colors_hb.is_empty()) {
+ for (int col = 0; col < p_font_data->palette_custom_colors_hb.size(); col++) {
+ if (p_font_data->palette_custom_colors_hb[col] != 0) {
+ hb_raster_paint_set_custom_palette_color(hb_rdr, col, p_font_data->palette_custom_colors_hb[col]);
+ }
+ }
+ }
+ bool ok = hb_raster_paint_glyph(hb_rdr, fd->hb_handle, (hb_codepoint_t)glyph_index, xshift, 0, p_font_data->palette_index, (hb_color_t)0xFFFFFFFF);
+ if (ok) {
+ is_rasterized = true;
+ hb_raster_image_t *img = hb_raster_paint_render(hb_rdr);
+ hb_raster_extents_t ext = { 0, 0, 0, 0, 0 };
+ if (img) {
+ hb_raster_image_get_extents(img, &ext);
+ gl = rasterize_hb_bitmap(fd, rect_range, img, ext, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, true);
+ hb_raster_paint_recycle_image(hb_rdr, img);
+ } else {
+ gl = rasterize_hb_bitmap(fd, rect_range, nullptr, ext, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, true);
+ }
+ }
+ }
+ if (!is_rasterized) {
+ hb_raster_draw_reset(hb_mono);
+ if (p_font_data->transform != Transform2D()) {
+ hb_raster_draw_set_transform(hb_mono, p_font_data->transform[0][0], p_font_data->transform[1][0], p_font_data->transform[0][1], -p_font_data->transform[1][1], 0.f, 0.f);
+ } else {
+ hb_raster_draw_set_transform(hb_mono, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f);
+ }
+ hb_raster_draw_set_scale_factor(hb_mono, 64.0, 64.0);
+ hb_raster_draw_glyph(hb_mono, fd->hb_handle, (hb_codepoint_t)glyph_index, xshift, 0);
+ hb_raster_image_t *img = hb_raster_draw_render(hb_mono);
+ hb_raster_extents_t ext = { 0, 0, 0, 0, 0 };
+ if (img) {
+ hb_raster_image_get_extents(img, &ext);
+ gl = rasterize_hb_bitmap(fd, rect_range, img, ext, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, false);
+ hb_raster_draw_recycle_image(hb_mono, img);
+ } else {
+ gl = rasterize_hb_bitmap(fd, rect_range, nullptr, ext, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, false);
+ }
+ }
} else {
- gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra);
+#else
+ {
+#endif
+ error = FT_Render_Glyph(slot, aa_mode);
+ if (!error) {
+ gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra);
+ }
}
}
} else {
@@ -1380,7 +1510,7 @@ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, const Vector2i
cleanup_stroker:
FT_Stroker_Done(stroker);
}
- gl.from_svg = from_svg;
+ gl.fix_edge = fix_edge;
E = fd->glyph_map.insert(p_glyph, gl);
r_glyph = E->value;
return gl.found;
@@ -1501,6 +1631,10 @@ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_font_data, const
fd->hb_handle = hb_ft_font_create(p_font_data->face, nullptr);
+ if (p_font_data->embolden != 0.0) {
+ hb_font_set_synthetic_bold(fd->hb_handle, p_font_data->embolden / 16.0, p_font_data->embolden / 16.0, true);
+ }
+
fd->ascent = (p_font_data->face->size->metrics.ascender / 64.0) * fd->scale;
fd->descent = (-p_font_data->face->size->metrics.descender / 64.0) * fd->scale;
fd->underline_position = (-FT_MulFix(p_font_data->face->underline_position, p_font_data->face->size->metrics.y_scale) / 64.0) * fd->scale;
@@ -1512,16 +1646,56 @@ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_font_data, const
#ifndef _MSC_VER
#warning Building with HarfBuzz < 3.3.0, synthetic slant offset correction disabled.
#endif
+#endif
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ fd->hb_face = hb_font_get_face(fd->hb_handle);
+ fd->color_paint = (hb_ot_color_has_paint(fd->hb_face) || hb_ot_color_has_layers(fd->hb_face));
#endif
if (!p_font_data->face_init) {
+ const static hb_language_t english = hb_language_from_string("en", -1);
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ hb_face_t *hb_face = fd->hb_face;
+
+ p_font_data->palette_names.clear();
+ p_font_data->palette_colors.clear();
+
+ unsigned int pal_count = hb_ot_color_palette_get_count(hb_face);
+ for (unsigned int pal = 0; pal < pal_count; pal++) {
+ String pal_name;
+ Vector pal_colors;
+ // Get name.
+ hb_ot_name_id_t name_id = hb_ot_color_palette_get_name_id(hb_face, pal);
+ if (name_id == HB_OT_NAME_ID_INVALID) {
+ pal_name = vformat("Palette %d", pal + 1);
+ } else {
+ unsigned int text_size = hb_ot_name_get_utf32(hb_face, name_id, english, nullptr, nullptr) + 1;
+ pal_name.resize_uninitialized(text_size);
+ hb_ot_name_get_utf32(hb_face, name_id, english, &text_size, (uint32_t *)pal_name.ptrw());
+ }
+ // Get colors.
+ unsigned int color_count = 0;
+ color_count = hb_ot_color_palette_get_colors(hb_face, pal, 0, &color_count, nullptr);
+ Vector pal_colors_hb;
+ pal_colors_hb.resize_uninitialized(color_count);
+ hb_ot_color_palette_get_colors(hb_face, pal, 0, &color_count, pal_colors_hb.ptrw());
+ for (unsigned int col = 0; col < color_count; col++) {
+ Color c = Color::from_rgba8(hb_color_get_red(pal_colors_hb[col]), hb_color_get_green(pal_colors_hb[col]), hb_color_get_blue(pal_colors_hb[col]), hb_color_get_alpha(pal_colors_hb[col]));
+ pal_colors.push_back(c);
+ }
+
+ p_font_data->palette_names.push_back(pal_name);
+ p_font_data->palette_colors.push_back(pal_colors);
+ }
+#else
+ hb_face_t *hb_face = hb_font_get_face(fd->hb_handle);
+#endif
// When a font does not provide a `family_name`, FreeType tries to synthesize one based on other names.
// FreeType automatically converts non-ASCII characters to "?" in the synthesized name.
// To avoid that behavior, use the format-specific name directly if available.
- hb_face_t *hb_face = hb_font_get_face(fd->hb_handle);
+
unsigned int num_entries = 0;
const hb_ot_name_entry_t *names = hb_ot_name_list_names(hb_face, &num_entries);
- const hb_language_t english = hb_language_from_string("en", -1);
for (unsigned int i = 0; i < num_entries; i++) {
if (names[i].name_id != HB_OT_NAME_ID_FONT_FAMILY) {
continue;
@@ -2603,6 +2777,90 @@ bool TextServerAdvanced::_font_is_modulate_color_glyphs(const RID &p_font_rid) c
return fd->modulate_color_glyphs;
}
+int64_t TextServerAdvanced::_font_get_palette_count(const RID &p_font_rid) const {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, 0);
+
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ return fd->palette_names.size();
+#else
+ return 0;
+#endif
+}
+
+String TextServerAdvanced::_font_get_palette_name(const RID &p_font_rid, int64_t p_index) const {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, String());
+
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ ERR_FAIL_INDEX_V(p_index, fd->palette_names.size(), String());
+ return fd->palette_names[p_index];
+#else
+ return String();
+#endif
+}
+
+Vector TextServerAdvanced::_font_get_palette_colors(const RID &p_font_rid, int64_t p_index) const {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, Vector());
+
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ ERR_FAIL_INDEX_V(p_index, fd->palette_names.size(), Vector());
+ return fd->palette_colors[p_index];
+#else
+ return Vector();
+#endif
+}
+
+void TextServerAdvanced::_font_set_palette_custom_colors(const RID &p_font_rid, const Vector &p_colors) {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL(fd);
+
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ if (fd->palette_custom_colors != p_colors) {
+ fd->palette_custom_colors = p_colors;
+ fd->palette_custom_colors_hb.resize_uninitialized(p_colors.size());
+ for (int col = 0; col < fd->palette_custom_colors.size(); col++) {
+ const Color &c = fd->palette_custom_colors[col];
+ fd->palette_custom_colors_hb.write[col] = HB_COLOR(c.get_b8(), c.get_g8(), c.get_r8(), c.get_a8());
+ }
+ _font_clear_cache(fd);
+ }
+#endif
+}
+
+Vector TextServerAdvanced::_font_get_palette_custom_colors(const RID &p_font_rid) const {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, Vector());
+
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ return fd->palette_custom_colors;
+#else
+ return Vector();
+#endif
+}
+
+int64_t TextServerAdvanced::_font_get_used_palette(const RID &p_font_rid) const {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, 0);
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ return fd->palette_index;
+#else
+ return 0;
+#endif
+}
+
+void TextServerAdvanced::_font_set_used_palette(const RID &p_font_rid, int64_t p_index) {
+ FontAdvanced *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL(fd);
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ if (fd->palette_index != p_index) {
+ fd->palette_index = p_index;
+ _font_clear_cache(fd);
+ }
+#endif
+}
+
void TextServerAdvanced::_font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
FontAdvanced *fd = _get_font_data(p_font_rid);
ERR_FAIL_NULL(fd);
@@ -3508,7 +3766,7 @@ RID TextServerAdvanced::_font_get_glyph_texture_rid(const RID &p_font_rid, const
if (ffsd->textures[fgl.texture_idx].dirty) {
ShelfPackTexture &tex = ffsd->textures.write[fgl.texture_idx];
Ref img = tex.image;
- if (fgl.from_svg) {
+ if (fgl.fix_edge) {
// Same as the "fix alpha border" process option when importing SVGs
img->fix_alpha_edges();
}
@@ -3558,7 +3816,7 @@ Size2 TextServerAdvanced::_font_get_glyph_texture_size(const RID &p_font_rid, co
if (ffsd->textures[fgl.texture_idx].dirty) {
ShelfPackTexture &tex = ffsd->textures.write[fgl.texture_idx];
Ref img = tex.image;
- if (fgl.from_svg) {
+ if (fgl.fix_edge) {
// Same as the "fix alpha border" process option when importing SVGs
img->fix_alpha_edges();
}
@@ -4034,7 +4292,7 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
if (ffsd->textures[fgl.texture_idx].dirty) {
ShelfPackTexture &tex = ffsd->textures.write[fgl.texture_idx];
Ref img = tex.image;
- if (fgl.from_svg) {
+ if (fgl.fix_edge) {
// Same as the "fix alpha border" process option when importing SVGs
img->fix_alpha_edges();
}
@@ -8119,7 +8377,10 @@ void TextServerAdvanced::_update_settings() {
TextServerAdvanced::TextServerAdvanced() {
os_locale = OS::get_singleton()->get_locale();
-
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ hb_rdr = hb_raster_paint_create_or_fail();
+ hb_mono = hb_raster_draw_create_or_fail();
+#endif
_insert_feature_sets();
_bmp_create_font_funcs();
_update_settings();
@@ -8144,6 +8405,14 @@ void TextServerAdvanced::_cleanup() {
TextServerAdvanced::~TextServerAdvanced() {
_bmp_free_font_funcs();
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ if (hb_rdr != nullptr) {
+ hb_raster_paint_destroy(hb_rdr);
+ }
+ if (hb_mono != nullptr) {
+ hb_raster_draw_destroy(hb_mono);
+ }
+#endif
#ifdef MODULE_FREETYPE_ENABLED
if (ft_library != nullptr) {
FT_Done_FreeType(ft_library);
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 564bcbe47a..30b82b2cfb 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -91,6 +91,9 @@ GODOT_CLANG_WARNING_POP
#include
#include
+#if HB_VERSION_ATLEAST(13, 0, 0)
+#include
+#endif
/*************************************************************************/
@@ -228,7 +231,7 @@ class TextServerAdvanced : public TextServerExtension {
Rect2 rect;
Rect2 uv_rect;
Vector2 advance;
- bool from_svg = false;
+ bool fix_edge = false;
};
struct FontAdvanced;
@@ -249,6 +252,10 @@ class TextServerAdvanced : public TextServerExtension {
HashMap glyph_map;
HashMap kerning_map;
hb_font_t *hb_handle = nullptr;
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ hb_face_t *hb_face = nullptr;
+ bool color_paint = false;
+#endif
#ifdef MODULE_FREETYPE_ENABLED
FT_Size fsize = nullptr;
@@ -311,6 +318,14 @@ class TextServerAdvanced : public TextServerExtension {
HashMap cache;
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ Vector palette_names;
+ Vector palette_colors;
+ PackedColorArray palette_custom_colors;
+ Vector palette_custom_colors_hb;
+ unsigned int palette_index = 0;
+#endif
+
bool face_init = false;
HashSet supported_scripts;
Dictionary supported_features;
@@ -350,6 +365,9 @@ class TextServerAdvanced : public TextServerExtension {
#endif
#ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap p_bitmap, int p_yofs, int p_xofs, const Vector2 &p_advance, bool p_bgra) const;
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ _FORCE_INLINE_ FontGlyph rasterize_hb_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, hb_raster_image_t *p_image, const hb_raster_extents_t &p_ext, const Vector2 &p_advance, bool p_bgra) const;
+#endif
#endif
bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph, FontGlyph &r_glyph, uint32_t p_oversampling = 0) const;
bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size, FontForSizeAdvanced *&r_cache_for_size, bool p_silent = false, uint32_t p_oversampling = 0) const;
@@ -555,6 +573,11 @@ class TextServerAdvanced : public TextServerExtension {
mutable RID_PtrOwner font_owner;
mutable RID_PtrOwner shaped_owner;
+#if HB_VERSION_ATLEAST(13, 0, 0)
+ hb_raster_paint_t *hb_rdr = nullptr;
+ hb_raster_draw_t *hb_mono = nullptr;
+#endif
+
_FORCE_INLINE_ FontAdvanced *_get_font_data(const RID &p_font_rid) const {
RID rid = p_font_rid;
FontAdvancedLinkedVariation *fdv = font_var_owner.get_or_null(rid);
@@ -870,6 +893,14 @@ public:
MODBIND2(font_set_modulate_color_glyphs, const RID &, bool);
MODBIND1RC(bool, font_is_modulate_color_glyphs, const RID &);
+ MODBIND1RC(int64_t, font_get_palette_count, const RID &);
+ MODBIND2RC(String, font_get_palette_name, const RID &, int64_t);
+ MODBIND2RC(Vector, font_get_palette_colors, const RID &, int64_t);
+ MODBIND2(font_set_palette_custom_colors, const RID &, const Vector &);
+ MODBIND1RC(Vector, font_get_palette_custom_colors, const RID &);
+ MODBIND1RC(int64_t, font_get_used_palette, const RID &);
+ MODBIND2(font_set_used_palette, const RID &, int64_t);
+
MODBIND2(font_set_subpixel_positioning, const RID &, SubpixelPositioning);
MODBIND1RC(SubpixelPositioning, font_get_subpixel_positioning, const RID &);
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 2209ddb954..447fc62783 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -1549,6 +1549,51 @@ bool TextServerFallback::_font_is_modulate_color_glyphs(const RID &p_font_rid) c
return fd->modulate_color_glyphs;
}
+int64_t TextServerFallback::_font_get_palette_count(const RID &p_font_rid) const {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, 0);
+
+ return 0;
+}
+
+String TextServerFallback::_font_get_palette_name(const RID &p_font_rid, int64_t p_index) const {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, String());
+
+ return String();
+}
+
+Vector TextServerFallback::_font_get_palette_colors(const RID &p_font_rid, int64_t p_index) const {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, Vector());
+
+ return Vector();
+}
+
+void TextServerFallback::_font_set_palette_custom_colors(const RID &p_font_rid, const Vector &p_colors) {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL(fd);
+}
+
+Vector TextServerFallback::_font_get_palette_custom_colors(const RID &p_font_rid) const {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, Vector());
+
+ return Vector();
+}
+
+int64_t TextServerFallback::_font_get_used_palette(const RID &p_font_rid) const {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL_V(fd, 0);
+
+ return 0;
+}
+
+void TextServerFallback::_font_set_used_palette(const RID &p_font_rid, int64_t p_index) {
+ FontFallback *fd = _get_font_data(p_font_rid);
+ ERR_FAIL_NULL(fd);
+}
+
void TextServerFallback::_font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
FontFallback *fd = _get_font_data(p_font_rid);
ERR_FAIL_NULL(fd);
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 88731e1981..f3310a35f6 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -649,6 +649,14 @@ public:
MODBIND2(font_set_modulate_color_glyphs, const RID &, bool);
MODBIND1RC(bool, font_is_modulate_color_glyphs, const RID &);
+ MODBIND1RC(int64_t, font_get_palette_count, const RID &);
+ MODBIND2RC(String, font_get_palette_name, const RID &, int64_t);
+ MODBIND2RC(Vector, font_get_palette_colors, const RID &, int64_t);
+ MODBIND2(font_set_palette_custom_colors, const RID &, const Vector &);
+ MODBIND1RC(Vector, font_get_palette_custom_colors, const RID &);
+ MODBIND1RC(int64_t, font_get_used_palette, const RID &);
+ MODBIND2(font_set_used_palette, const RID &, int64_t);
+
MODBIND2(font_set_subpixel_positioning, const RID &, SubpixelPositioning);
MODBIND1RC(SubpixelPositioning, font_get_subpixel_positioning, const RID &);
diff --git a/scene/resources/font.compat.inc b/scene/resources/font.compat.inc
index 45bda9aff7..daac8b3f5c 100644
--- a/scene/resources/font.compat.inc
+++ b/scene/resources/font.compat.inc
@@ -59,11 +59,15 @@ real_t Font::_draw_char_outline_bind_compat_104872(RID p_canvas_item, const Poin
}
RID Font::_find_variation_bind_compat_80954(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform) const {
- return find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, 0, 0, 0, 0, 0.0);
+ return find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, 0, 0, 0, 0, 0.0, 0, Vector());
}
RID Font::_find_variation_bind_compat_87668(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph) const {
- return find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, 0.0);
+ return find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, 0.0, 0, Vector());
+}
+
+RID Font::_find_variation_bind_compat_117149(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
+ return find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset, 0, Vector());
}
void Font::_bind_compatibility_methods() {
@@ -78,6 +82,7 @@ void Font::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform"), &Font::_find_variation_bind_compat_80954, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()));
ClassDB::bind_compatibility_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform", "spacing_top", "spacing_bottom", "spacing_space", "spacing_glyph"), &Font::_find_variation_bind_compat_87668, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0));
+ ClassDB::bind_compatibility_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform", "spacing_top", "spacing_bottom", "spacing_space", "spacing_glyph", "baseline_offset"), &Font::_find_variation_bind_compat_117149, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0.0));
}
#endif // DISABLE_DEPRECATED
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 4abfe35596..11535d9e21 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -53,7 +53,7 @@ void Font::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_fallbacks"), &Font::get_fallbacks);
// Output.
- ClassDB::bind_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform", "spacing_top", "spacing_bottom", "spacing_space", "spacing_glyph", "baseline_offset"), &Font::find_variation, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform", "spacing_top", "spacing_bottom", "spacing_space", "spacing_glyph", "baseline_offset", "palette_index", "custom_colors"), &Font::find_variation, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0.0), DEFVAL(0), DEFVAL(Vector()));
ClassDB::bind_method(D_METHOD("get_rids"), &Font::get_rids);
// Font metrics.
@@ -70,6 +70,10 @@ void Font::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_font_weight"), &Font::get_font_weight);
ClassDB::bind_method(D_METHOD("get_font_stretch"), &Font::get_font_stretch);
+ ClassDB::bind_method(D_METHOD("get_palette_count"), &Font::get_palette_count);
+ ClassDB::bind_method(D_METHOD("get_palette_name", "index"), &Font::get_palette_name);
+ ClassDB::bind_method(D_METHOD("get_palette_colors", "index"), &Font::get_palette_colors);
+
ClassDB::bind_method(D_METHOD("get_spacing", "spacing"), &Font::get_spacing);
ClassDB::bind_method(D_METHOD("get_opentype_features"), &Font::get_opentype_features);
@@ -270,6 +274,18 @@ String Font::get_font_name() const {
return TS->font_get_name(_get_rid());
}
+int64_t Font::get_palette_count() const {
+ return TS->font_get_palette_count(_get_rid());
+}
+
+String Font::get_palette_name(int64_t p_index) const {
+ return TS->font_get_palette_name(_get_rid(), p_index);
+}
+
+Vector Font::get_palette_colors(int64_t p_index) const {
+ return TS->font_get_palette_colors(_get_rid(), p_index);
+}
+
Dictionary Font::get_ot_name_strings() const {
return TS->font_get_ot_name_strings(_get_rid());
}
@@ -2366,7 +2382,7 @@ real_t FontFile::get_oversampling() const {
return oversampling_override;
}
-RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
+RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset, int64_t p_palette_index, const Vector &p_custom_colors) const {
// Find existing variation cache.
const Dictionary &supported_coords = get_supported_variation_list();
int make_linked_from = -1;
@@ -2378,6 +2394,8 @@ RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_fa
match = match && (TS->font_get_face_index(cache[i]) == p_face_index);
match = match && (TS->font_get_embolden(cache[i]) == p_strength);
match = match && (TS->font_get_transform(cache[i]) == p_transform);
+ match = match && (TS->font_get_used_palette(cache[i]) == p_palette_index);
+ match = match && (TS->font_get_palette_custom_colors(cache[i]) == p_custom_colors);
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_TOP) == p_spacing_top);
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_BOTTOM) == p_spacing_bottom);
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_SPACE) == p_spacing_space);
@@ -2427,6 +2445,8 @@ RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_fa
TS->font_set_spacing(cache[idx], TextServer::SPACING_SPACE, p_spacing_space);
TS->font_set_spacing(cache[idx], TextServer::SPACING_GLYPH, p_spacing_glyph);
TS->font_set_baseline_offset(cache[idx], p_baseline_offset);
+ TS->font_set_used_palette(cache[idx], p_palette_index);
+ TS->font_set_palette_custom_colors(cache[idx], p_custom_colors);
} else {
_ensure_rid(idx);
TS->font_set_variation_coordinates(cache[idx], p_variation_coordinates);
@@ -2438,6 +2458,8 @@ RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_fa
TS->font_set_spacing(cache[idx], TextServer::SPACING_SPACE, p_spacing_space);
TS->font_set_spacing(cache[idx], TextServer::SPACING_GLYPH, p_spacing_glyph);
TS->font_set_baseline_offset(cache[idx], p_baseline_offset);
+ TS->font_set_used_palette(cache[idx], p_palette_index);
+ TS->font_set_palette_custom_colors(cache[idx], p_custom_colors);
}
return cache[idx];
}
@@ -2905,6 +2927,12 @@ void FontVariation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_baseline_offset", "baseline_offset"), &FontVariation::set_baseline_offset);
ClassDB::bind_method(D_METHOD("get_baseline_offset"), &FontVariation::get_baseline_offset);
+ ClassDB::bind_method(D_METHOD("get_palette_index"), &FontVariation::get_palette_index);
+ ClassDB::bind_method(D_METHOD("set_palette_index", "palette_index"), &FontVariation::set_palette_index);
+
+ ClassDB::bind_method(D_METHOD("get_palette_custom_colors"), &FontVariation::get_palette_custom_colors);
+ ClassDB::bind_method(D_METHOD("set_palette_custom_colors", "colors"), &FontVariation::set_palette_custom_colors);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_font", PROPERTY_HINT_RESOURCE_TYPE, Font::get_class_static()), "set_base_font", "get_base_font");
ADD_GROUP("Variation", "variation_");
@@ -2924,6 +2952,46 @@ void FontVariation::_bind_methods() {
ADD_GROUP("Baseline", "baseline_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "baseline_offset", PROPERTY_HINT_RANGE, "-2,2,0.005"), "set_baseline_offset", "get_baseline_offset");
+
+ ADD_GROUP("Palette", "palette_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "palette_index", PROPERTY_HINT_NONE, ""), "set_palette_index", "get_palette_index");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "palette_custom_colors", PROPERTY_HINT_NONE, ""), "set_palette_custom_colors", "get_palette_custom_colors");
+}
+
+void FontVariation::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "palette_custom_colors") {
+ Ref f = _get_base_font_or_default();
+ if (f.is_valid()) {
+ int64_t pal_count = f->get_palette_count();
+ if (pal_count == 0 || f->get_palette_colors(0).is_empty()) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ } else {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ } else if (p_property.name == "palette_index") {
+ Ref f = _get_base_font_or_default();
+ if (f.is_valid()) {
+ p_property.hint = PROPERTY_HINT_ENUM;
+ p_property.hint_string = String();
+
+ int64_t pal_count = f->get_palette_count();
+ if (pal_count == 0) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ } else {
+ for (int64_t i = 0; i < pal_count; i++) {
+ if (!p_property.hint_string.is_empty()) {
+ p_property.hint_string += ",";
+ }
+ p_property.hint_string += f->get_palette_name(i);
+ }
+ }
+ } else {
+ p_property.hint = PROPERTY_HINT_NONE;
+ p_property.hint_string = String();
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
}
void FontVariation::_update_rids() const {
@@ -2965,6 +3033,8 @@ void FontVariation::reset_state() {
extra_spacing[i] = 0;
}
baseline_offset = 0.0;
+ palette_index = 0;
+ custom_colors.clear();
Font::reset_state();
}
@@ -3120,10 +3190,32 @@ float FontVariation::get_baseline_offset() const {
return baseline_offset;
}
-RID FontVariation::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
+void FontVariation::set_palette_index(int64_t p_palette_index) {
+ if (palette_index != p_palette_index) {
+ palette_index = p_palette_index;
+ _invalidate_rids();
+ }
+}
+
+int64_t FontVariation::get_palette_index() const {
+ return palette_index;
+}
+
+void FontVariation::set_palette_custom_colors(const Vector &p_colors) {
+ if (custom_colors != p_colors) {
+ custom_colors = p_colors;
+ _invalidate_rids();
+ }
+}
+
+Vector FontVariation::get_palette_custom_colors() const {
+ return custom_colors;
+}
+
+RID FontVariation::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset, int64_t p_palette_index, const Vector &p_custom_colors) const {
Ref f = _get_base_font_or_default();
if (f.is_valid()) {
- return f->find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset);
+ return f->find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset, p_palette_index, p_custom_colors);
}
return RID();
}
@@ -3131,7 +3223,7 @@ RID FontVariation::find_variation(const Dictionary &p_variation_coordinates, int
RID FontVariation::_get_rid() const {
Ref f = _get_base_font_or_default();
if (f.is_valid()) {
- return f->find_variation(variation.opentype, variation.face_index, variation.embolden, variation.transform, extra_spacing[TextServer::SPACING_TOP], extra_spacing[TextServer::SPACING_BOTTOM], extra_spacing[TextServer::SPACING_SPACE], extra_spacing[TextServer::SPACING_GLYPH], baseline_offset);
+ return f->find_variation(variation.opentype, variation.face_index, variation.embolden, variation.transform, extra_spacing[TextServer::SPACING_TOP], extra_spacing[TextServer::SPACING_BOTTOM], extra_spacing[TextServer::SPACING_SPACE], extra_spacing[TextServer::SPACING_GLYPH], baseline_offset, palette_index, custom_colors);
}
return RID();
}
@@ -3651,7 +3743,7 @@ int SystemFont::get_spacing(TextServer::SpacingType p_spacing) const {
}
}
-RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
+RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset, int64_t p_palette_index, const Vector &p_custom_colors) const {
Ref f = _get_base_font_or_default();
if (f.is_valid()) {
Dictionary var = p_variation_coordinates;
@@ -3667,9 +3759,9 @@ RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_
if (!face_indices.is_empty()) {
int face_index = CLAMP(p_face_index, 0, face_indices.size() - 1);
- return f->find_variation(var, face_indices[face_index], p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset);
+ return f->find_variation(var, face_indices[face_index], p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset, p_palette_index, p_custom_colors);
} else {
- return f->find_variation(var, 0, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset);
+ return f->find_variation(var, 0, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset, p_palette_index, p_custom_colors);
}
}
return RID();
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 02252210f1..996e6922fc 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -108,6 +108,7 @@ protected:
real_t _draw_char_outline_bind_compat_104872(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size = DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const;
RID _find_variation_bind_compat_80954(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D()) const;
RID _find_variation_bind_compat_87668(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0) const;
+ RID _find_variation_bind_compat_117149(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0) const;
static void _bind_compatibility_methods();
#endif
@@ -123,7 +124,7 @@ public:
virtual TypedArray get_fallbacks() const;
// Output.
- virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0) const { return RID(); }
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0, int64_t p_palette_index = 0, const Vector &p_custom_colors = Vector()) const { return RID(); }
virtual RID _get_rid() const { return RID(); }
virtual TypedArray get_rids() const;
@@ -141,6 +142,10 @@ public:
virtual int get_font_weight() const;
virtual int get_font_stretch() const;
+ virtual int64_t get_palette_count() const;
+ virtual String get_palette_name(int64_t p_index) const;
+ virtual Vector get_palette_colors(int64_t p_index) const;
+
virtual int get_spacing(TextServer::SpacingType p_spacing) const { return 0; }
virtual Dictionary get_opentype_features() const;
@@ -300,7 +305,7 @@ public:
virtual real_t get_oversampling() const;
// Cache.
- virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0) const override;
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0, int64_t p_palette_index = 0, const Vector &p_custom_colors = Vector()) const override;
virtual RID _get_rid() const override;
virtual int get_cache_count() const;
@@ -427,9 +432,12 @@ class FontVariation : public Font {
Dictionary opentype_features;
int extra_spacing[TextServer::SPACING_MAX];
float baseline_offset = 0.0;
+ int64_t palette_index = 0;
+ Vector custom_colors;
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
virtual void _update_rids() const override;
@@ -461,8 +469,14 @@ public:
virtual float get_baseline_offset() const;
virtual void set_baseline_offset(float p_baseline_offset);
+ virtual int64_t get_palette_index() const;
+ virtual void set_palette_index(int64_t p_palette_index);
+
+ virtual Vector get_palette_custom_colors() const;
+ virtual void set_palette_custom_colors(const Vector &p_colors);
+
// Output.
- virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0) const override;
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0, int64_t p_palette_index = 0, const Vector &p_custom_colors = Vector()) const override;
virtual RID _get_rid() const override;
FontVariation();
@@ -568,7 +582,7 @@ public:
virtual int get_spacing(TextServer::SpacingType p_spacing) const override;
- virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0) const override;
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D(), int p_spacing_top = 0, int p_spacing_bottom = 0, int p_spacing_space = 0, int p_spacing_glyph = 0, float p_baseline_offset = 0.0, int64_t p_palette_index = 0, const Vector &p_custom_colors = Vector()) const override;
virtual RID _get_rid() const override;
int64_t get_face_count() const override;
diff --git a/servers/text/text_server.cpp b/servers/text/text_server.cpp
index d66f7fbc41..12a408b7c2 100644
--- a/servers/text/text_server.cpp
+++ b/servers/text/text_server.cpp
@@ -276,9 +276,17 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font_rid", "force_autohinter"), &TextServer::font_set_force_autohinter);
ClassDB::bind_method(D_METHOD("font_is_force_autohinter", "font_rid"), &TextServer::font_is_force_autohinter);
- ClassDB::bind_method(D_METHOD("font_set_modulate_color_glyphs", "font_rid", "force_autohinter"), &TextServer::font_set_modulate_color_glyphs);
+ ClassDB::bind_method(D_METHOD("font_set_modulate_color_glyphs", "font_rid", "modulate"), &TextServer::font_set_modulate_color_glyphs);
ClassDB::bind_method(D_METHOD("font_is_modulate_color_glyphs", "font_rid"), &TextServer::font_is_modulate_color_glyphs);
+ ClassDB::bind_method(D_METHOD("font_get_palette_count", "font_rid"), &TextServer::font_get_palette_count);
+ ClassDB::bind_method(D_METHOD("font_get_palette_name", "font_rid", "index"), &TextServer::font_get_palette_name);
+ ClassDB::bind_method(D_METHOD("font_get_palette_colors", "font_rid", "index"), &TextServer::font_get_palette_colors);
+ ClassDB::bind_method(D_METHOD("font_set_palette_custom_colors", "font_rid", "colors"), &TextServer::font_set_palette_custom_colors);
+ ClassDB::bind_method(D_METHOD("font_get_palette_custom_colors", "font_rid"), &TextServer::font_get_palette_custom_colors);
+ ClassDB::bind_method(D_METHOD("font_get_used_palette", "font_rid"), &TextServer::font_get_used_palette);
+ ClassDB::bind_method(D_METHOD("font_set_used_palette", "font_rid", "index"), &TextServer::font_set_used_palette);
+
ClassDB::bind_method(D_METHOD("font_set_hinting", "font_rid", "hinting"), &TextServer::font_set_hinting);
ClassDB::bind_method(D_METHOD("font_get_hinting", "font_rid"), &TextServer::font_get_hinting);
diff --git a/servers/text/text_server.h b/servers/text/text_server.h
index 89c9b5ef62..f2da4fc3e7 100644
--- a/servers/text/text_server.h
+++ b/servers/text/text_server.h
@@ -332,6 +332,14 @@ public:
virtual void font_set_modulate_color_glyphs(const RID &p_font_rid, bool p_modulate) = 0;
virtual bool font_is_modulate_color_glyphs(const RID &p_font_rid) const = 0;
+ virtual int64_t font_get_palette_count(const RID &p_font_rid) const = 0;
+ virtual String font_get_palette_name(const RID &p_font_rid, int64_t p_index) const = 0;
+ virtual Vector font_get_palette_colors(const RID &p_font_rid, int64_t p_index) const = 0;
+ virtual void font_set_palette_custom_colors(const RID &p_font_rid, const Vector &p_colors) = 0;
+ virtual Vector font_get_palette_custom_colors(const RID &p_font_rid) const = 0;
+ virtual int64_t font_get_used_palette(const RID &p_font_rid) const = 0;
+ virtual void font_set_used_palette(const RID &p_font_rid, int64_t p_index) = 0;
+
virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) = 0;
virtual Hinting font_get_hinting(const RID &p_font_rid) const = 0;
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index a95d233ca1..49b3e1ec6c 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -115,6 +115,14 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_modulate_color_glyphs, "font_rid", "modulate");
GDVIRTUAL_BIND(_font_is_modulate_color_glyphs, "font_rid");
+ GDVIRTUAL_BIND(_font_get_palette_count, "font_rid");
+ GDVIRTUAL_BIND(_font_get_palette_name, "font_rid", "index");
+ GDVIRTUAL_BIND(_font_get_palette_colors, "font_rid", "index");
+ GDVIRTUAL_BIND(_font_set_palette_custom_colors, "font_rid", "colors");
+ GDVIRTUAL_BIND(_font_get_palette_custom_colors, "font_rid");
+ GDVIRTUAL_BIND(_font_get_used_palette, "font_rid");
+ GDVIRTUAL_BIND(_font_set_used_palette, "font_rid", "index");
+
GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting");
GDVIRTUAL_BIND(_font_get_hinting, "font_rid");
@@ -690,6 +698,43 @@ bool TextServerExtension::font_is_modulate_color_glyphs(const RID &p_font_rid) c
return ret;
}
+int64_t TextServerExtension::font_get_palette_count(const RID &p_font_rid) const {
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_palette_count, p_font_rid, ret);
+ return ret;
+}
+
+String TextServerExtension::font_get_palette_name(const RID &p_font_rid, int64_t p_index) const {
+ String ret;
+ GDVIRTUAL_CALL(_font_get_palette_name, p_font_rid, p_index, ret);
+ return ret;
+}
+Vector TextServerExtension::font_get_palette_colors(const RID &p_font_rid, int64_t p_index) const {
+ Vector ret;
+ GDVIRTUAL_CALL(_font_get_palette_colors, p_font_rid, p_index, ret);
+ return ret;
+}
+
+void TextServerExtension::font_set_palette_custom_colors(const RID &p_font_rid, const Vector &p_colors) {
+ GDVIRTUAL_CALL(_font_set_palette_custom_colors, p_font_rid, p_colors);
+}
+
+Vector TextServerExtension::font_get_palette_custom_colors(const RID &p_font_rid) const {
+ Vector ret;
+ GDVIRTUAL_CALL(_font_get_palette_custom_colors, p_font_rid, ret);
+ return ret;
+}
+
+int64_t TextServerExtension::font_get_used_palette(const RID &p_font_rid) const {
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_used_palette, p_font_rid, ret);
+ return ret;
+}
+
+void TextServerExtension::font_set_used_palette(const RID &p_font_rid, int64_t p_index) {
+ GDVIRTUAL_CALL(_font_set_used_palette, p_font_rid, p_index);
+}
+
void TextServerExtension::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
GDVIRTUAL_CALL(_font_set_hinting, p_font_rid, p_hinting);
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index b0556ee512..407aa55c07 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -213,6 +213,21 @@ public:
GDVIRTUAL2(_font_set_modulate_color_glyphs, RID, bool);
GDVIRTUAL1RC(bool, _font_is_modulate_color_glyphs, RID);
+ virtual int64_t font_get_palette_count(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(int64_t, _font_get_palette_count, const RID &);
+ virtual String font_get_palette_name(const RID &p_font_rid, int64_t p_index) const override;
+ GDVIRTUAL2RC(String, _font_get_palette_name, const RID &, int64_t);
+ virtual Vector font_get_palette_colors(const RID &p_font_rid, int64_t p_index) const override;
+ GDVIRTUAL2RC(Vector, _font_get_palette_colors, const RID &, int64_t);
+ virtual void font_set_palette_custom_colors(const RID &p_font_rid, const Vector &p_colors) override;
+ GDVIRTUAL2(_font_set_palette_custom_colors, const RID &, const Vector &);
+ virtual Vector font_get_palette_custom_colors(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(Vector, _font_get_palette_custom_colors, const RID &);
+ virtual int64_t font_get_used_palette(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(int64_t, _font_get_used_palette, const RID &);
+ virtual void font_set_used_palette(const RID &p_font_rid, int64_t p_index) override;
+ GDVIRTUAL2(_font_set_used_palette, const RID &, int64_t);
+
virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) override;
virtual Hinting font_get_hinting(const RID &p_font_rid) const override;
GDVIRTUAL2(_font_set_hinting, RID, Hinting);
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 1f127f7928..cd511ac308 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -468,7 +468,7 @@ Patches:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 12.3.2 (b42511e071162fe76102f613a6ccc009726c99af, 2026)
+- Version: 13.1.1 (70b812d8d2fb4a2b6386c04bfd8565a0fcc05f9b, 2026)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
index 63d59af6ca..e8c73ffaab 100644
--- a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
+++ b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
@@ -1814,10 +1814,7 @@ struct ClipList
{
auto *rec = clips.as_array ().bsearch (gid);
if (rec)
- {
- rec->get_extents (extents, this, instancer);
- return true;
- }
+ return rec->get_extents (extents, this, instancer);
return false;
}
diff --git a/thirdparty/harfbuzz/src/OT/Color/svg/svg.hh b/thirdparty/harfbuzz/src/OT/Color/svg/svg.hh
index d6aca4a60e..d6fb71832b 100644
--- a/thirdparty/harfbuzz/src/OT/Color/svg/svg.hh
+++ b/thirdparty/harfbuzz/src/OT/Color/svg/svg.hh
@@ -27,7 +27,12 @@
#include "../../../hb-open-type.hh"
#include "../../../hb-blob.hh"
+#include "../../../hb-limits.hh"
+#include "../../../hb-map.hh"
#include "../../../hb-paint.hh"
+#include "../../../hb-zlib.hh"
+#include
+#include
/*
* SVG -- SVG (Scalable Vector Graphics)
@@ -39,12 +44,62 @@
namespace OT {
+static inline hb_blob_t *
+hb_ot_svg_reference_normalized_blob (hb_blob_t *image,
+ const char **svg,
+ unsigned *len)
+{
+ hb_blob_t *blob = hb_blob_reference (image);
+ unsigned data_len = 0;
+ const char *data = hb_blob_get_data (blob, &data_len);
+
+ if (!data || !data_len)
+ goto fail;
+
+ if (hb_blob_is_gzip (data, data_len))
+ {
+ uint32_t expected_size = 0;
+ if (hb_gzip_get_uncompressed_size (data, data_len, &expected_size) &&
+ unlikely ((size_t) expected_size > (size_t) HB_SVG_MAX_DOCUMENT_SIZE))
+ goto fail;
+
+ hb_blob_t *uncompressed = hb_blob_decompress_gzip (blob,
+ HB_SVG_MAX_DOCUMENT_SIZE);
+ if (!uncompressed)
+ goto fail;
+
+ hb_blob_destroy (blob);
+ blob = uncompressed;
+ data = hb_blob_get_data (blob, &data_len);
+ if (!data || !data_len)
+ goto fail;
+ }
+
+ if (unlikely ((size_t) data_len > (size_t) HB_SVG_MAX_DOCUMENT_SIZE))
+ goto fail;
+
+ if (svg) *svg = data;
+ if (len) *len = data_len;
+ return blob;
+
+fail:
+ hb_blob_destroy (blob);
+ if (svg) *svg = nullptr;
+ if (len) *len = 0;
+ return nullptr;
+}
struct SVGDocumentIndexEntry
{
int cmp (hb_codepoint_t g) const
{ return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
+ hb_codepoint_t get_start_glyph () const
+ { return startGlyphID; }
+
+ hb_codepoint_t get_end_glyph () const
+ { return endGlyphID; }
+
hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
{
return hb_blob_create_sub_blob (svg_blob,
@@ -78,13 +133,50 @@ struct SVG
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
+ struct svg_id_span_t
+ {
+ const char *p;
+ unsigned len;
+
+ bool operator == (const svg_id_span_t &o) const
+ {
+ return len == o.len && !memcmp (p, o.p, len);
+ }
+
+ uint32_t hash () const
+ {
+ uint32_t h = hb_hash (len);
+ for (unsigned i = 0; i < len; i++)
+ h = h * 33u + (unsigned char) p[i];
+ return h;
+ }
+ };
+
+ struct svg_defs_entry_t
+ {
+ svg_id_span_t id;
+ unsigned start;
+ unsigned end;
+ };
+
+ struct svg_doc_cache_t
+ {
+ hb_blob_t *blob = nullptr;
+ const char *svg = nullptr;
+ unsigned len = 0;
+ hb_vector_t defs_entries;
+ hb_codepoint_t start_glyph = HB_CODEPOINT_INVALID;
+ hb_codepoint_t end_glyph = HB_CODEPOINT_INVALID;
+ hb_vector_t> glyph_spans;
+ hb_hashmap_t> id_spans;
+ };
+
bool has_data () const { return svgDocEntries; }
struct accelerator_t
{
- accelerator_t (hb_face_t *face)
- { table = hb_sanitize_context_t ().reference_table