Implement support for loading system fonts on Linux, macOS / iOS and Windows.
This commit is contained in:
parent
3e0e84a54c
commit
36ef8f29dc
|
@ -115,7 +115,7 @@ jobs:
|
|||
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
|
||||
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev \
|
||||
libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip \
|
||||
llvm libspeechd-dev speech-dispatcher
|
||||
llvm libspeechd-dev speech-dispatcher fontconfig libfontconfig-dev
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
|
|
|
@ -231,6 +231,14 @@ void OS::crash(const String &p_message) {
|
|||
CRASH_NOW_MSG(p_message);
|
||||
}
|
||||
|
||||
Vector<String> OS::get_system_fonts() const {
|
||||
return ::OS::get_singleton()->get_system_fonts();
|
||||
}
|
||||
|
||||
String OS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
|
||||
return ::OS::get_singleton()->get_system_font_path(p_font_name, p_bold, p_italic);
|
||||
}
|
||||
|
||||
String OS::get_executable_path() const {
|
||||
return ::OS::get_singleton()->get_executable_path();
|
||||
}
|
||||
|
@ -589,6 +597,8 @@ void OS::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_processor_count"), &OS::get_processor_count);
|
||||
ClassDB::bind_method(D_METHOD("get_processor_name"), &OS::get_processor_name);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_system_fonts"), &OS::get_system_fonts);
|
||||
ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "bold", "italic"), &OS::get_system_font_path, DEFVAL(false), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
|
||||
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false));
|
||||
|
|
|
@ -170,6 +170,8 @@ public:
|
|||
void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
void crash(const String &p_message);
|
||||
|
||||
Vector<String> get_system_fonts() const;
|
||||
String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const;
|
||||
String get_executable_path() const;
|
||||
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
|
||||
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
|
||||
|
|
|
@ -142,6 +142,8 @@ public:
|
|||
virtual void set_low_processor_usage_mode_sleep_usec(int p_usec);
|
||||
virtual int get_low_processor_usage_mode_sleep_usec() const;
|
||||
|
||||
virtual Vector<String> get_system_fonts() const { return Vector<String>(); };
|
||||
virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const { return String(); };
|
||||
virtual String get_executable_path() const;
|
||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) = 0;
|
||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="FontFile" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
FontFile source data and prerendered glyph cache, imported from dynamic or bitmap font.
|
||||
Font source data and prerendered glyph cache, imported from dynamic or bitmap font.
|
||||
</brief_description>
|
||||
<description>
|
||||
[FontFile] contains a set of glyphs to represent Unicode characters imported from a font file, as well as a cache of rasterized glyphs, and a set of fallback [Font]s to use.
|
||||
|
|
|
@ -385,6 +385,23 @@
|
|||
[b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories. Shared directories have additional restrictions on Android.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_system_font_path" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="font_name" type="String" />
|
||||
<argument index="1" name="bold" type="bool" default="false" />
|
||||
<argument index="2" name="italic" type="bool" default="false" />
|
||||
<description>
|
||||
Returns path to the system font file with [code]font_name[/code] and style. Return empty string if no matching fonts found.
|
||||
[b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_system_fonts" qualifiers="const">
|
||||
<return type="PackedStringArray" />
|
||||
<description>
|
||||
Returns list of font family names available.
|
||||
[b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_thread_caller_id" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="SystemFont" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
Font loaded from a system font.
|
||||
[b]Note:[/b] This class is implemented on iOS, Linux, macOS and Windows, on other platforms it will fallback to default theme font.
|
||||
</brief_description>
|
||||
<description>
|
||||
[SystemFont] loads a font from a system font with the first matching name from [member font_names].
|
||||
It will attempt to match font style, but it's not guaranteed.
|
||||
The returned font might be part of a font collection or be a variable font with OpenType "weight" and/or "italic" features set.
|
||||
You can create [FontVariation] of the system font for fine control over its features.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true">
|
||||
If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled.
|
||||
</member>
|
||||
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
|
||||
Array of fallback [Font]s.
|
||||
</member>
|
||||
<member name="font_names" type="PackedStringArray" setter="set_font_names" getter="get_font_names" default="PackedStringArray()">
|
||||
Array of font family names to search, first matching font found is used.
|
||||
</member>
|
||||
<member name="font_style" type="int" setter="set_font_style" getter="get_font_style" enum="TextServer.FontStyle" default="0">
|
||||
Font style flags, see [enum TextServer.FontStyle].
|
||||
</member>
|
||||
<member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false">
|
||||
If set to [code]true[/code], auto-hinting is supported and preferred over font built-in hinting.
|
||||
</member>
|
||||
<member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="get_generate_mipmaps" default="false">
|
||||
If set to [code]true[/code], generate mipmaps for the font textures.
|
||||
</member>
|
||||
<member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="TextServer.Hinting" default="1">
|
||||
Font hinting mode.
|
||||
</member>
|
||||
<member name="oversampling" type="float" setter="set_oversampling" getter="get_oversampling" default="0.0">
|
||||
Font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead.
|
||||
</member>
|
||||
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
|
||||
Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
|
@ -81,10 +81,7 @@ class EditorPropertyArray : public EditorProperty {
|
|||
GDCLASS(EditorPropertyArray, EditorProperty);
|
||||
|
||||
PopupMenu *change_type = nullptr;
|
||||
bool updating = false;
|
||||
bool dropping = false;
|
||||
|
||||
Ref<EditorPropertyArrayObject> object;
|
||||
int page_length = 20;
|
||||
int page_index = 0;
|
||||
int changing_type_index;
|
||||
|
@ -106,29 +103,35 @@ class EditorPropertyArray : public EditorProperty {
|
|||
Button *reorder_selected_button = nullptr;
|
||||
|
||||
void _page_changed(int p_page);
|
||||
void _length_changed(double p_page);
|
||||
void _add_element();
|
||||
void _edit_pressed();
|
||||
void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
|
||||
void _change_type(Object *p_button, int p_index);
|
||||
void _change_type_menu(int p_index);
|
||||
|
||||
void _object_id_selected(const StringName &p_property, ObjectID p_id);
|
||||
void _remove_pressed(int p_index);
|
||||
|
||||
void _button_draw();
|
||||
bool _is_drop_valid(const Dictionary &p_drag_data) const;
|
||||
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
|
||||
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
|
||||
|
||||
void _reorder_button_gui_input(const Ref<InputEvent> &p_event);
|
||||
void _reorder_button_down(int p_index);
|
||||
void _reorder_button_up();
|
||||
|
||||
protected:
|
||||
Ref<EditorPropertyArrayObject> object;
|
||||
|
||||
bool updating = false;
|
||||
bool dropping = false;
|
||||
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
virtual void _add_element();
|
||||
virtual void _length_changed(double p_page);
|
||||
virtual void _edit_pressed();
|
||||
virtual void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
|
||||
virtual void _change_type(Object *p_button, int p_index);
|
||||
virtual void _change_type_menu(int p_index);
|
||||
|
||||
virtual void _object_id_selected(const StringName &p_property, ObjectID p_id);
|
||||
virtual void _remove_pressed(int p_index);
|
||||
|
||||
virtual void _button_draw();
|
||||
virtual bool _is_drop_valid(const Dictionary &p_drag_data) const;
|
||||
virtual bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
|
||||
virtual void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
|
||||
|
||||
public:
|
||||
void setup(Variant::Type p_array_type, const String &p_hint_string = "");
|
||||
virtual void update_property() override;
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 1v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V3h2a1 1 0 0 1 1 1h1V1h-6Z" fill="#e0e0e0"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6Z" fill="#ff5f5f"/></svg>
|
||||
<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 7.5h-1a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5h-.5V9a1 1 0 0 1-1 1v1H8V9.854A1 1 0 0 1 7.5 9V7.5zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg>
|
||||
|
|
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 401 B |
|
@ -1 +1 @@
|
|||
<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M2.437 1 1.379 4h1A.84 1.192 50 0 1 3.73 3h2L3.615 9a.84 1.192 50 0 1-1.352 1l-.353 1h4l.353-1a.84 1.192 50 0 1-.648-1l2.116-6h2a.84 1.192 50 0 1 .648 1h1l1.058-3h-6Z" fill="#e0e0e0"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6Z" fill="#ff5f5f"/></svg>
|
||||
<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M5.975 11 7.21 7.5H5.916a.478.478 0 0 0-.113.016.837.837 0 0 0-.127.043c-.044.018-.089.04-.133.066l-.043.027V9a1 1 0 0 1-1 1v1h1.475zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6z" fill="#ff5f5f"/></svg>
|
||||
|
|
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 552 B |
|
@ -0,0 +1 @@
|
|||
<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:#e0e0e0;fill-opacity:1;stroke-width:.714755" d="m5.787 1-.402 1.613c-.352.265-.71.122-1.012-.111l-.904-.541L2.46 2.973l.853 1.425c-.058.438-.412.586-.79.635-.343.065-.674.216-1.024.213V6.72c.367 0 .715.157 1.074.224.371.032.716.243.727.65l-.84 1.4 1.008 1.01c.443-.266.895-.53 1.33-.802.349-.044.675.139.674.506l.314 1.258c.459-.059 1.099.115 1.45-.082.117-.475.242-.954.35-1.428A.67.67 0 0 1 8 9.195V7.5H6.5a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5H4v-4h5.75c-.005-.22.107-.434.254-.625l.543-.902L9.535 1.96l-1.426.853c-.437-.058-.588-.412-.636-.79L7.217 1h-1.43z"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg>
|
After Width: | Height: | Size: 797 B |
|
@ -895,17 +895,45 @@ void FontPreview::_notification(int p_what) {
|
|||
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
|
||||
Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
|
||||
font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color);
|
||||
|
||||
// Draw font preview.
|
||||
Vector2 pos = Vector2(0, font->get_height(font_size)) + (get_size() - Vector2(0, font->get_height(font_size)) - line->get_size()) / 2;
|
||||
line->draw(get_canvas_item(), pos, text_color);
|
||||
bool prev_ok = true;
|
||||
if (prev_font.is_valid()) {
|
||||
if (prev_font->get_font_name().is_empty()) {
|
||||
prev_ok = false;
|
||||
} else {
|
||||
String name;
|
||||
if (prev_font->get_font_style_name().is_empty()) {
|
||||
name = prev_font->get_font_name();
|
||||
} else {
|
||||
name = vformat("%s (%s)", prev_font->get_font_name(), prev_font->get_font_style_name());
|
||||
}
|
||||
if (prev_font->is_class("FontVariation")) {
|
||||
name += " " + TTR(" - Variation");
|
||||
}
|
||||
font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color);
|
||||
|
||||
// Draw font baseline.
|
||||
Color line_color = text_color;
|
||||
line_color.a *= 0.6;
|
||||
draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color);
|
||||
draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color);
|
||||
String sample;
|
||||
static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀";
|
||||
for (int i = 0; i < sample_base.length(); i++) {
|
||||
if (prev_font->has_char(sample_base[i])) {
|
||||
sample += sample_base[i];
|
||||
}
|
||||
}
|
||||
if (sample.is_empty()) {
|
||||
sample = prev_font->get_supported_chars().substr(0, 6);
|
||||
}
|
||||
if (sample.is_empty()) {
|
||||
prev_ok = false;
|
||||
} else {
|
||||
prev_font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + prev_font->get_height(50)), sample, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, 50, text_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!prev_ok) {
|
||||
text_color.a *= 0.5;
|
||||
font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), TTR("Unable to preview font"), HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -917,30 +945,11 @@ Size2 FontPreview::get_minimum_size() const {
|
|||
}
|
||||
|
||||
void FontPreview::set_data(const Ref<Font> &p_f) {
|
||||
line->clear();
|
||||
if (p_f.is_valid()) {
|
||||
name = vformat("%s (%s)", p_f->get_font_name(), p_f->get_font_style_name());
|
||||
if (p_f->is_class("FontVariation")) {
|
||||
name += " " + TTR(" - Variation");
|
||||
}
|
||||
String sample;
|
||||
static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀";
|
||||
for (int i = 0; i < sample_base.length(); i++) {
|
||||
if (p_f->has_char(sample_base[i])) {
|
||||
sample += sample_base[i];
|
||||
}
|
||||
}
|
||||
if (sample.is_empty()) {
|
||||
sample = p_f->get_supported_chars().substr(0, 6);
|
||||
}
|
||||
line->add_string(sample, p_f, 50);
|
||||
}
|
||||
|
||||
prev_font = p_f;
|
||||
update();
|
||||
}
|
||||
|
||||
FontPreview::FontPreview() {
|
||||
line.instantiate();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -964,6 +973,71 @@ bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Va
|
|||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* EditorPropertyFontNamesArray */
|
||||
/*************************************************************************/
|
||||
|
||||
void EditorPropertyFontNamesArray::_add_element() {
|
||||
Size2 size = get_size();
|
||||
menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
}
|
||||
|
||||
void EditorPropertyFontNamesArray::_add_font(int p_option) {
|
||||
if (updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
Variant array = object->get_array();
|
||||
int previous_size = array.call("size");
|
||||
|
||||
array.call("resize", previous_size + 1);
|
||||
array.set(previous_size, menu->get_item_text(p_option));
|
||||
|
||||
emit_changed(get_edited_property(), array, "", false);
|
||||
object->set_array(array);
|
||||
update_property();
|
||||
}
|
||||
|
||||
EditorPropertyFontNamesArray::EditorPropertyFontNamesArray() {
|
||||
menu = memnew(PopupMenu);
|
||||
menu->add_item("Sans-Serif", 0);
|
||||
menu->add_item("Serif", 1);
|
||||
menu->add_item("Monospace", 2);
|
||||
menu->add_item("Fantasy", 3);
|
||||
menu->add_item("Cursive", 4);
|
||||
|
||||
menu->add_separator();
|
||||
|
||||
if (OS::get_singleton()) {
|
||||
Vector<String> fonts = OS::get_singleton()->get_system_fonts();
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
menu->add_item(fonts[i], i + 6);
|
||||
}
|
||||
}
|
||||
add_child(menu);
|
||||
menu->connect("id_pressed", callable_mp(this, &EditorPropertyFontNamesArray::_add_font));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* EditorInspectorPluginSystemFont */
|
||||
/*************************************************************************/
|
||||
|
||||
bool EditorInspectorPluginSystemFont::can_handle(Object *p_object) {
|
||||
return Object::cast_to<SystemFont>(p_object) != nullptr;
|
||||
}
|
||||
|
||||
bool EditorInspectorPluginSystemFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
|
||||
if (p_path == "font_names") {
|
||||
EditorPropertyFontNamesArray *editor = memnew(EditorPropertyFontNamesArray);
|
||||
editor->setup(p_type, p_hint_text);
|
||||
add_property_editor(p_path, editor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FontEditorPlugin */
|
||||
/*************************************************************************/
|
||||
|
@ -973,6 +1047,10 @@ FontEditorPlugin::FontEditorPlugin() {
|
|||
fc_plugin.instantiate();
|
||||
EditorInspector::add_inspector_plugin(fc_plugin);
|
||||
|
||||
Ref<EditorInspectorPluginSystemFont> fs_plugin;
|
||||
fs_plugin.instantiate();
|
||||
EditorInspector::add_inspector_plugin(fs_plugin);
|
||||
|
||||
Ref<EditorInspectorPluginFontPreview> fp_plugin;
|
||||
fp_plugin.instantiate();
|
||||
EditorInspector::add_inspector_plugin(fp_plugin);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/io/marshalls.h"
|
||||
#include "editor/editor_plugin.h"
|
||||
#include "editor/editor_properties.h"
|
||||
#include "editor/editor_properties_array_dict.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
|
@ -225,8 +226,7 @@ protected:
|
|||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
String name;
|
||||
Ref<TextLine> line;
|
||||
Ref<Font> prev_font;
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
|
@ -249,6 +249,33 @@ public:
|
|||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyFontNamesArray : public EditorPropertyArray {
|
||||
GDCLASS(EditorPropertyFontNamesArray, EditorPropertyArray);
|
||||
|
||||
PopupMenu *menu = nullptr;
|
||||
|
||||
protected:
|
||||
virtual void _add_element() override;
|
||||
|
||||
void _add_font(int p_option);
|
||||
static void _bind_methods(){};
|
||||
|
||||
public:
|
||||
EditorPropertyFontNamesArray();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorInspectorPluginSystemFont : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginSystemFont, EditorInspectorPlugin);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class FontEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(FontEditorPlugin, EditorPlugin);
|
||||
|
||||
|
|
|
@ -92,6 +92,9 @@ public:
|
|||
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||
|
||||
virtual Vector<String> get_system_fonts() const override;
|
||||
virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
|
||||
|
||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#import "view_controller.h"
|
||||
|
||||
#import <AudioToolbox/AudioServices.h>
|
||||
#import <CoreText/CoreText.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <dlfcn.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
@ -302,6 +303,80 @@ String OS_IOS::get_processor_name() const {
|
|||
ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
|
||||
}
|
||||
|
||||
Vector<String> OS_IOS::get_system_fonts() const {
|
||||
HashSet<String> font_names;
|
||||
CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames();
|
||||
if (fonts) {
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) {
|
||||
CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i);
|
||||
if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) {
|
||||
NSString *ns_name = (__bridge NSString *)cf_name;
|
||||
font_names.insert(String::utf8([ns_name UTF8String]));
|
||||
}
|
||||
}
|
||||
CFRelease(fonts);
|
||||
}
|
||||
|
||||
Vector<String> ret;
|
||||
for (const String &E : font_names) {
|
||||
ret.push_back(E);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String OS_IOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
|
||||
String ret;
|
||||
|
||||
String font_name = p_font_name;
|
||||
if (font_name.to_lower() == "sans-serif") {
|
||||
font_name = "Helvetica";
|
||||
} else if (font_name.to_lower() == "serif") {
|
||||
font_name = "Times";
|
||||
} else if (font_name.to_lower() == "monospace") {
|
||||
font_name = "Courier";
|
||||
} else if (font_name.to_lower() == "fantasy") {
|
||||
font_name = "Papyrus";
|
||||
} else if (font_name.to_lower() == "cursive") {
|
||||
font_name = "Apple Chancery";
|
||||
};
|
||||
|
||||
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
|
||||
|
||||
CTFontSymbolicTraits traits = 0;
|
||||
if (p_bold) {
|
||||
traits |= kCTFontBoldTrait;
|
||||
}
|
||||
if (p_italic) {
|
||||
traits |= kCTFontItalicTrait;
|
||||
}
|
||||
|
||||
CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
|
||||
CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
|
||||
CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
|
||||
|
||||
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
|
||||
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
|
||||
CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
|
||||
|
||||
CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
|
||||
if (font) {
|
||||
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute);
|
||||
if (url) {
|
||||
NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
|
||||
ret = String::utf8([font_path UTF8String]);
|
||||
CFRelease(url);
|
||||
}
|
||||
CFRelease(font);
|
||||
}
|
||||
|
||||
CFRelease(attributes);
|
||||
CFRelease(traits_dict);
|
||||
CFRelease(sym_traits);
|
||||
CFRelease(name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void OS_IOS::vibrate_handheld(int p_duration_ms) {
|
||||
if (ios->supports_haptic_engine()) {
|
||||
ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f);
|
||||
|
|
|
@ -298,6 +298,12 @@ def configure(env):
|
|||
|
||||
## Flags
|
||||
|
||||
if os.system("pkg-config --exists fontconfig") == 0: # 0 means found
|
||||
env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
|
||||
env.ParseConfig("pkg-config fontconfig --cflags --libs")
|
||||
else:
|
||||
print("Warning: fontconfig libraries not found. Disabling the system fonts support.")
|
||||
|
||||
if os.system("pkg-config --exists alsa") == 0: # 0 means found
|
||||
env["alsa"] = True
|
||||
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef FONTCONFIG_ENABLED
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#endif
|
||||
|
||||
void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
|
||||
const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
|
||||
|
||||
|
@ -327,6 +331,91 @@ uint64_t OS_LinuxBSD::get_embedded_pck_offset() const {
|
|||
return off;
|
||||
}
|
||||
|
||||
Vector<String> OS_LinuxBSD::get_system_fonts() const {
|
||||
#ifdef FONTCONFIG_ENABLED
|
||||
HashSet<String> font_names;
|
||||
Vector<String> ret;
|
||||
|
||||
FcConfig *config = FcInitLoadConfigAndFonts();
|
||||
ERR_FAIL_COND_V(!config, ret);
|
||||
|
||||
FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, nullptr);
|
||||
ERR_FAIL_COND_V(!object_set, ret);
|
||||
|
||||
static const char *allowed_formats[] = { "TrueType", "CFF" };
|
||||
for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) {
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
ERR_CONTINUE(!pattern);
|
||||
|
||||
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
|
||||
FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i]));
|
||||
|
||||
FcFontSet *font_set = FcFontList(config, pattern, object_set);
|
||||
if (font_set) {
|
||||
for (int j = 0; j < font_set->nfont; j++) {
|
||||
char *family_name = nullptr;
|
||||
if (FcPatternGetString(font_set->fonts[j], FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
|
||||
if (family_name) {
|
||||
font_names.insert(String::utf8(family_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
FcFontSetDestroy(font_set);
|
||||
}
|
||||
FcPatternDestroy(pattern);
|
||||
}
|
||||
FcObjectSetDestroy(object_set);
|
||||
|
||||
for (const String &E : font_names) {
|
||||
ret.push_back(E);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
ERR_FAIL_COND_V_MSG(Vector<String>(), "Godot was compiled without fontconfig, system font support is disabled.")
|
||||
#endif
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
|
||||
#ifdef FONTCONFIG_ENABLED
|
||||
String ret;
|
||||
|
||||
FcConfig *config = FcInitLoadConfigAndFonts();
|
||||
ERR_FAIL_COND_V(!config, ret);
|
||||
|
||||
FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, FC_FILE, nullptr);
|
||||
ERR_FAIL_COND_V(!object_set, ret);
|
||||
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
if (pattern) {
|
||||
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
|
||||
FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT, p_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL);
|
||||
FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
|
||||
|
||||
FcConfigSubstitute(0, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
FcResult result;
|
||||
FcPattern *match = FcFontMatch(0, pattern, &result);
|
||||
if (match) {
|
||||
char *file_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
|
||||
if (file_name) {
|
||||
ret = String::utf8(file_name);
|
||||
}
|
||||
}
|
||||
|
||||
FcPatternDestroy(match);
|
||||
}
|
||||
FcPatternDestroy(pattern);
|
||||
}
|
||||
FcObjectSetDestroy(object_set);
|
||||
#else
|
||||
ERR_FAIL_COND_V_MSG(Vector<String>(), "Godot was compiled without fontconfig, system font support is disabled.")
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_config_path() const {
|
||||
if (has_environment("XDG_CONFIG_HOME")) {
|
||||
if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
|
||||
|
|
|
@ -80,6 +80,9 @@ public:
|
|||
|
||||
virtual uint64_t get_embedded_pck_offset() const override;
|
||||
|
||||
virtual Vector<String> get_system_fonts() const override;
|
||||
virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
|
||||
|
||||
virtual String get_config_path() const override;
|
||||
virtual String get_data_path() const override;
|
||||
virtual String get_cache_path() const override;
|
||||
|
|
|
@ -97,6 +97,8 @@ public:
|
|||
|
||||
virtual String get_locale() const override;
|
||||
|
||||
virtual Vector<String> get_system_fonts() const override;
|
||||
virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
|
||||
virtual String get_executable_path() const override;
|
||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
|
||||
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
||||
|
|
|
@ -303,6 +303,80 @@ String OS_MacOS::get_locale() const {
|
|||
return String([locale_code UTF8String]).replace("-", "_");
|
||||
}
|
||||
|
||||
Vector<String> OS_MacOS::get_system_fonts() const {
|
||||
HashSet<String> font_names;
|
||||
CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames();
|
||||
if (fonts) {
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) {
|
||||
CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i);
|
||||
if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) {
|
||||
NSString *ns_name = (__bridge NSString *)cf_name;
|
||||
font_names.insert(String::utf8([ns_name UTF8String]));
|
||||
}
|
||||
}
|
||||
CFRelease(fonts);
|
||||
}
|
||||
|
||||
Vector<String> ret;
|
||||
for (const String &E : font_names) {
|
||||
ret.push_back(E);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String OS_MacOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
|
||||
String ret;
|
||||
|
||||
String font_name = p_font_name;
|
||||
if (font_name.to_lower() == "sans-serif") {
|
||||
font_name = "Helvetica";
|
||||
} else if (font_name.to_lower() == "serif") {
|
||||
font_name = "Times";
|
||||
} else if (font_name.to_lower() == "monospace") {
|
||||
font_name = "Courier";
|
||||
} else if (font_name.to_lower() == "fantasy") {
|
||||
font_name = "Papyrus";
|
||||
} else if (font_name.to_lower() == "cursive") {
|
||||
font_name = "Apple Chancery";
|
||||
};
|
||||
|
||||
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
|
||||
|
||||
CTFontSymbolicTraits traits = 0;
|
||||
if (p_bold) {
|
||||
traits |= kCTFontBoldTrait;
|
||||
}
|
||||
if (p_italic) {
|
||||
traits |= kCTFontItalicTrait;
|
||||
}
|
||||
|
||||
CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
|
||||
CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
|
||||
CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
|
||||
|
||||
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
|
||||
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
|
||||
CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
|
||||
|
||||
CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
|
||||
if (font) {
|
||||
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute);
|
||||
if (url) {
|
||||
NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
|
||||
ret = String::utf8([font_path UTF8String]);
|
||||
CFRelease(url);
|
||||
}
|
||||
CFRelease(font);
|
||||
}
|
||||
|
||||
CFRelease(attributes);
|
||||
CFRelease(traits_dict);
|
||||
CFRelease(sym_traits);
|
||||
CFRelease(name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
String OS_MacOS::get_executable_path() const {
|
||||
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
|
||||
int pid = getpid();
|
||||
|
|
|
@ -270,6 +270,7 @@ def configure_msvc(env, manual_msvc_config):
|
|||
"bcrypt",
|
||||
"Avrt",
|
||||
"dwmapi",
|
||||
"dwrite",
|
||||
]
|
||||
|
||||
if env["vulkan"]:
|
||||
|
@ -441,6 +442,7 @@ def configure_mingw(env):
|
|||
"avrt",
|
||||
"uuid",
|
||||
"dwmapi",
|
||||
"dwrite",
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <avrt.h>
|
||||
#include <bcrypt.h>
|
||||
#include <direct.h>
|
||||
#include <dwrite.h>
|
||||
#include <knownfolders.h>
|
||||
#include <process.h>
|
||||
#include <regstr.h>
|
||||
|
@ -621,6 +622,135 @@ Error OS_Windows::set_cwd(const String &p_cwd) {
|
|||
return OK;
|
||||
}
|
||||
|
||||
Vector<String> OS_Windows::get_system_fonts() const {
|
||||
Vector<String> ret;
|
||||
HashSet<String> font_names;
|
||||
|
||||
ComAutoreleaseRef<IDWriteFactory> dwrite_factory;
|
||||
HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory.reference));
|
||||
ERR_FAIL_COND_V(FAILED(hr) || dwrite_factory.is_null(), ret);
|
||||
|
||||
ComAutoreleaseRef<IDWriteFontCollection> font_collection;
|
||||
hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false);
|
||||
ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), ret);
|
||||
|
||||
UINT32 family_count = font_collection->GetFontFamilyCount();
|
||||
for (UINT32 i = 0; i < family_count; i++) {
|
||||
ComAutoreleaseRef<IDWriteFontFamily> family;
|
||||
hr = font_collection->GetFontFamily(i, &family.reference);
|
||||
ERR_CONTINUE(FAILED(hr) || family.is_null());
|
||||
|
||||
ComAutoreleaseRef<IDWriteLocalizedStrings> family_names;
|
||||
hr = family->GetFamilyNames(&family_names.reference);
|
||||
ERR_CONTINUE(FAILED(hr) || family_names.is_null());
|
||||
|
||||
UINT32 index = 0;
|
||||
BOOL exists = false;
|
||||
UINT32 length = 0;
|
||||
Char16String name;
|
||||
|
||||
hr = family_names->FindLocaleName(L"en-us", &index, &exists);
|
||||
ERR_CONTINUE(FAILED(hr));
|
||||
|
||||
hr = family_names->GetStringLength(index, &length);
|
||||
ERR_CONTINUE(FAILED(hr));
|
||||
|
||||
name.resize(length + 1);
|
||||
hr = family_names->GetString(index, (WCHAR *)name.ptrw(), length + 1);
|
||||
ERR_CONTINUE(FAILED(hr));
|
||||
|
||||
font_names.insert(String::utf16(name.ptr(), length));
|
||||
}
|
||||
|
||||
for (const String &E : font_names) {
|
||||
ret.push_back(E);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
|
||||
String font_name = p_font_name;
|
||||
if (font_name.to_lower() == "sans-serif") {
|
||||
font_name = "Arial";
|
||||
} else if (font_name.to_lower() == "serif") {
|
||||
font_name = "Times New Roman";
|
||||
} else if (font_name.to_lower() == "monospace") {
|
||||
font_name = "Courier New";
|
||||
} else if (font_name.to_lower() == "cursive") {
|
||||
font_name = "Comic Sans MS";
|
||||
} else if (font_name.to_lower() == "fantasy") {
|
||||
font_name = "Gabriola";
|
||||
}
|
||||
|
||||
ComAutoreleaseRef<IDWriteFactory> dwrite_factory;
|
||||
HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory.reference));
|
||||
ERR_FAIL_COND_V(FAILED(hr) || dwrite_factory.is_null(), String());
|
||||
|
||||
ComAutoreleaseRef<IDWriteFontCollection> font_collection;
|
||||
hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false);
|
||||
ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), String());
|
||||
|
||||
UINT32 index = 0;
|
||||
BOOL exists = false;
|
||||
font_collection->FindFamilyName((const WCHAR *)font_name.utf16().get_data(), &index, &exists);
|
||||
if (FAILED(hr)) {
|
||||
return String();
|
||||
}
|
||||
|
||||
ComAutoreleaseRef<IDWriteFontFamily> family;
|
||||
hr = font_collection->GetFontFamily(index, &family.reference);
|
||||
if (FAILED(hr) || family.is_null()) {
|
||||
return String();
|
||||
}
|
||||
|
||||
ComAutoreleaseRef<IDWriteFont> dwrite_font;
|
||||
hr = family->GetFirstMatchingFont(p_bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, p_italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, &dwrite_font.reference);
|
||||
if (FAILED(hr) || dwrite_font.is_null()) {
|
||||
return String();
|
||||
}
|
||||
|
||||
ComAutoreleaseRef<IDWriteFontFace> dwrite_face;
|
||||
hr = dwrite_font->CreateFontFace(&dwrite_face.reference);
|
||||
if (FAILED(hr) || dwrite_face.is_null()) {
|
||||
return String();
|
||||
}
|
||||
|
||||
UINT32 number_of_files = 0;
|
||||
hr = dwrite_face->GetFiles(&number_of_files, nullptr);
|
||||
if (FAILED(hr)) {
|
||||
return String();
|
||||
}
|
||||
Vector<ComAutoreleaseRef<IDWriteFontFile>> files;
|
||||
files.resize(number_of_files);
|
||||
hr = dwrite_face->GetFiles(&number_of_files, (IDWriteFontFile **)files.ptrw());
|
||||
if (FAILED(hr)) {
|
||||
return String();
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < number_of_files; i++) {
|
||||
void const *reference_key = nullptr;
|
||||
UINT32 reference_key_size = 0;
|
||||
ComAutoreleaseRef<IDWriteLocalFontFileLoader> loader;
|
||||
|
||||
hr = files.write[i]->GetLoader((IDWriteFontFileLoader **)&loader.reference);
|
||||
if (FAILED(hr) || loader.is_null()) {
|
||||
continue;
|
||||
}
|
||||
hr = files.write[i]->GetReferenceKey(&reference_key, &reference_key_size);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WCHAR file_path[MAX_PATH];
|
||||
hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], MAX_PATH);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
return String::utf16((const char16_t *)&file_path[0]);
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
String OS_Windows::get_executable_path() const {
|
||||
WCHAR bufname[4096];
|
||||
GetModuleFileNameW(nullptr, bufname, 4096);
|
||||
|
|
|
@ -62,6 +62,26 @@
|
|||
#define WINDOWS_DEBUG_OUTPUT_ENABLED
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class ComAutoreleaseRef {
|
||||
public:
|
||||
T *reference = nullptr;
|
||||
|
||||
_FORCE_INLINE_ T *operator->() { return reference; }
|
||||
_FORCE_INLINE_ const T *operator->() const { return reference; }
|
||||
_FORCE_INLINE_ T *operator*() { return reference; }
|
||||
_FORCE_INLINE_ const T *operator*() const { return reference; }
|
||||
_FORCE_INLINE_ bool is_valid() const { return reference != nullptr; }
|
||||
_FORCE_INLINE_ bool is_null() const { return reference == nullptr; }
|
||||
ComAutoreleaseRef() {}
|
||||
~ComAutoreleaseRef() {
|
||||
if (reference != nullptr) {
|
||||
reference->Release();
|
||||
reference = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class JoypadWindows;
|
||||
class OS_Windows : public OS {
|
||||
#ifdef STDOUT_FILE
|
||||
|
@ -147,6 +167,9 @@ public:
|
|||
virtual String get_environment(const String &p_var) const override;
|
||||
virtual bool set_environment(const String &p_var, const String &p_value) const override;
|
||||
|
||||
virtual Vector<String> get_system_fonts() const override;
|
||||
virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
|
||||
|
||||
virtual String get_executable_path() const override;
|
||||
|
||||
virtual String get_locale() const override;
|
||||
|
|
|
@ -443,8 +443,10 @@ void TextEdit::_notification(int p_what) {
|
|||
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_TRANSLATION_CHANGED:
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
_update_caches();
|
||||
_update_wrap_at_column(true);
|
||||
if (is_inside_tree()) {
|
||||
_update_caches();
|
||||
_update_wrap_at_column(true);
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
|
||||
|
|
|
@ -870,6 +870,7 @@ void register_scene_types() {
|
|||
GDREGISTER_ABSTRACT_CLASS(Font);
|
||||
GDREGISTER_CLASS(FontFile);
|
||||
GDREGISTER_CLASS(FontVariation);
|
||||
GDREGISTER_CLASS(SystemFont);
|
||||
|
||||
GDREGISTER_CLASS(Curve);
|
||||
|
||||
|
|
|
@ -2693,3 +2693,374 @@ FontVariation::FontVariation() {
|
|||
FontVariation::~FontVariation() {
|
||||
reset_state();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* SystemFont */
|
||||
/*************************************************************************/
|
||||
|
||||
void SystemFont::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &SystemFont::set_antialiased);
|
||||
ClassDB::bind_method(D_METHOD("is_antialiased"), &SystemFont::is_antialiased);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps);
|
||||
ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &SystemFont::set_force_autohinter);
|
||||
ClassDB::bind_method(D_METHOD("is_force_autohinter"), &SystemFont::is_force_autohinter);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &SystemFont::set_hinting);
|
||||
ClassDB::bind_method(D_METHOD("get_hinting"), &SystemFont::get_hinting);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &SystemFont::set_subpixel_positioning);
|
||||
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &SystemFont::get_subpixel_positioning);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &SystemFont::set_oversampling);
|
||||
ClassDB::bind_method(D_METHOD("get_oversampling"), &SystemFont::get_oversampling);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_font_names"), &SystemFont::get_font_names);
|
||||
ClassDB::bind_method(D_METHOD("set_font_names", "names"), &SystemFont::set_font_names);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_font_style", "style"), &SystemFont::set_font_style);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), "set_subpixel_positioning", "get_subpixel_positioning");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), "set_oversampling", "get_oversampling");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks");
|
||||
}
|
||||
|
||||
void SystemFont::_update_rids() const {
|
||||
Ref<Font> f = _get_base_font_or_default();
|
||||
|
||||
rids.clear();
|
||||
if (fallbacks.is_empty() && f.is_valid()) {
|
||||
RID rid = _get_rid();
|
||||
if (rid.is_valid()) {
|
||||
rids.push_back(rid);
|
||||
}
|
||||
|
||||
const TypedArray<Font> &base_fallbacks = f->get_fallbacks();
|
||||
for (int i = 0; i < base_fallbacks.size(); i++) {
|
||||
_update_rids_fb(base_fallbacks[i], 0);
|
||||
}
|
||||
} else {
|
||||
_update_rids_fb(const_cast<SystemFont *>(this), 0);
|
||||
}
|
||||
dirty_rids = false;
|
||||
}
|
||||
|
||||
void SystemFont::_update_base_font() {
|
||||
if (base_font.is_valid()) {
|
||||
base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
|
||||
base_font.unref();
|
||||
}
|
||||
|
||||
face_indeces.clear();
|
||||
ftr_weight = 0;
|
||||
ftr_italic = 0;
|
||||
for (const String &E : names) {
|
||||
if (E.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String path = OS::get_singleton()->get_system_font_path(E, style & TextServer::FONT_BOLD, style & TextServer::FONT_ITALIC);
|
||||
if (path.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
Ref<FontFile> file;
|
||||
file.instantiate();
|
||||
Error err = file->load_dynamic_font(path);
|
||||
if (err != OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it's a font collection check all faces to match requested style.
|
||||
for (int i = 0; i < file->get_face_count(); i++) {
|
||||
file->set_face_index(0, i);
|
||||
if (((file->get_font_style() & TextServer::FONT_BOLD) == (style & TextServer::FONT_BOLD)) && ((file->get_font_style() & TextServer::FONT_ITALIC) == (style & TextServer::FONT_ITALIC))) {
|
||||
face_indeces.push_back(i);
|
||||
}
|
||||
}
|
||||
if (face_indeces.is_empty()) {
|
||||
face_indeces.push_back(0);
|
||||
}
|
||||
file->set_face_index(0, face_indeces[0]);
|
||||
|
||||
// If it's a variable font, apply weight and italic coordinates to match requested style.
|
||||
Dictionary ftr = file->get_supported_variation_list();
|
||||
if ((style & TextServer::FONT_BOLD) && ftr.has(TS->name_to_tag("weight"))) {
|
||||
ftr_weight = 700;
|
||||
}
|
||||
if ((style & TextServer::FONT_ITALIC) && ftr.has(TS->name_to_tag("italic"))) {
|
||||
ftr_italic = 1;
|
||||
}
|
||||
|
||||
// Apply font rendering settings.
|
||||
file->set_antialiased(antialiased);
|
||||
file->set_generate_mipmaps(mipmaps);
|
||||
file->set_force_autohinter(force_autohinter);
|
||||
file->set_hinting(hinting);
|
||||
file->set_subpixel_positioning(subpixel_positioning);
|
||||
file->set_oversampling(oversampling);
|
||||
|
||||
base_font = file;
|
||||
}
|
||||
|
||||
if (base_font.is_valid()) {
|
||||
base_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
_invalidate_rids();
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
void SystemFont::reset_state() {
|
||||
if (base_font.is_valid()) {
|
||||
base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
|
||||
base_font.unref();
|
||||
}
|
||||
|
||||
if (theme_font.is_valid()) {
|
||||
theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
|
||||
theme_font.unref();
|
||||
}
|
||||
|
||||
names.clear();
|
||||
face_indeces.clear();
|
||||
ftr_weight = 0;
|
||||
ftr_italic = 0;
|
||||
style = 0;
|
||||
antialiased = true;
|
||||
mipmaps = false;
|
||||
force_autohinter = false;
|
||||
hinting = TextServer::HINTING_LIGHT;
|
||||
subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
|
||||
oversampling = 0.f;
|
||||
|
||||
Font::reset_state();
|
||||
}
|
||||
|
||||
Ref<Font> SystemFont::_get_base_font_or_default() const {
|
||||
if (theme_font.is_valid()) {
|
||||
theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids));
|
||||
theme_font.unref();
|
||||
}
|
||||
|
||||
if (base_font.is_valid()) {
|
||||
return base_font;
|
||||
}
|
||||
|
||||
// Check the project-defined Theme resource.
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
List<StringName> theme_types;
|
||||
Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
|
||||
|
||||
for (const StringName &E : theme_types) {
|
||||
if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
|
||||
Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
|
||||
if (f.is_valid()) {
|
||||
theme_font = f;
|
||||
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly, fall back on the items defined in the default Theme, if they exist.
|
||||
if (Theme::get_default().is_valid()) {
|
||||
List<StringName> theme_types;
|
||||
Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
|
||||
|
||||
for (const StringName &E : theme_types) {
|
||||
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
|
||||
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
|
||||
if (f.is_valid()) {
|
||||
theme_font = f;
|
||||
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
// If they don't exist, use any type to return the default/empty value.
|
||||
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
|
||||
if (f.is_valid()) {
|
||||
theme_font = f;
|
||||
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
return Ref<Font>();
|
||||
}
|
||||
|
||||
void SystemFont::set_antialiased(bool p_antialiased) {
|
||||
if (antialiased != p_antialiased) {
|
||||
antialiased = p_antialiased;
|
||||
if (base_font.is_valid()) {
|
||||
base_font->set_antialiased(antialiased);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemFont::is_antialiased() const {
|
||||
return antialiased;
|
||||
}
|
||||
|
||||
void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) {
|
||||
if (mipmaps != p_generate_mipmaps) {
|
||||
mipmaps = p_generate_mipmaps;
|
||||
if (base_font.is_valid()) {
|
||||
base_font->set_generate_mipmaps(mipmaps);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemFont::get_generate_mipmaps() const {
|
||||
return mipmaps;
|
||||
}
|
||||
|
||||
void SystemFont::set_force_autohinter(bool p_force_autohinter) {
|
||||
if (force_autohinter != p_force_autohinter) {
|
||||
force_autohinter = p_force_autohinter;
|
||||
if (base_font.is_valid()) {
|
||||
base_font->set_force_autohinter(force_autohinter);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemFont::is_force_autohinter() const {
|
||||
return force_autohinter;
|
||||
}
|
||||
|
||||
void SystemFont::set_hinting(TextServer::Hinting p_hinting) {
|
||||
if (hinting != p_hinting) {
|
||||
hinting = p_hinting;
|
||||
if (base_font.is_valid()) {
|
||||
base_font->set_hinting(hinting);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
TextServer::Hinting SystemFont::get_hinting() const {
|
||||
return hinting;
|
||||
}
|
||||
|
||||
void SystemFont::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
|
||||
if (subpixel_positioning != p_subpixel) {
|
||||
subpixel_positioning = p_subpixel;
|
||||
if (base_font.is_valid()) {
|
||||
base_font->set_subpixel_positioning(subpixel_positioning);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
TextServer::SubpixelPositioning SystemFont::get_subpixel_positioning() const {
|
||||
return subpixel_positioning;
|
||||
}
|
||||
|
||||
void SystemFont::set_oversampling(real_t p_oversampling) {
|
||||
if (oversampling != p_oversampling) {
|
||||
oversampling = p_oversampling;
|
||||
if (base_font.is_valid()) {
|
||||
base_font->set_oversampling(oversampling);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
real_t SystemFont::get_oversampling() const {
|
||||
return oversampling;
|
||||
}
|
||||
|
||||
void SystemFont::set_font_names(const PackedStringArray &p_names) {
|
||||
if (names != p_names) {
|
||||
names = p_names;
|
||||
_update_base_font();
|
||||
}
|
||||
}
|
||||
|
||||
PackedStringArray SystemFont::get_font_names() const {
|
||||
return names;
|
||||
}
|
||||
|
||||
void SystemFont::set_font_style(BitField<TextServer::FontStyle> p_style) {
|
||||
if (style != p_style) {
|
||||
style = p_style;
|
||||
_update_base_font();
|
||||
}
|
||||
}
|
||||
|
||||
BitField<TextServer::FontStyle> SystemFont::get_font_style() const {
|
||||
return style;
|
||||
}
|
||||
|
||||
int SystemFont::get_spacing(TextServer::SpacingType p_spacing) const {
|
||||
if (base_font.is_valid()) {
|
||||
return base_font->get_spacing(p_spacing);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform) const {
|
||||
Ref<Font> f = _get_base_font_or_default();
|
||||
if (f.is_valid()) {
|
||||
Dictionary var = p_variation_coordinates;
|
||||
if (ftr_weight > 0 && !var.has(TS->name_to_tag("weight"))) {
|
||||
var[TS->name_to_tag("weight")] = ftr_weight;
|
||||
}
|
||||
if (ftr_italic > 0 && !var.has(TS->name_to_tag("italic"))) {
|
||||
var[TS->name_to_tag("italic")] = ftr_italic;
|
||||
}
|
||||
|
||||
if (!face_indeces.is_empty()) {
|
||||
int face_index = CLAMP(p_face_index, 0, face_indeces.size() - 1);
|
||||
return f->find_variation(var, face_indeces[face_index], p_strength, p_transform);
|
||||
} else {
|
||||
return f->find_variation(var, 0, p_strength, p_transform);
|
||||
}
|
||||
}
|
||||
return RID();
|
||||
}
|
||||
|
||||
RID SystemFont::_get_rid() const {
|
||||
Ref<Font> f = _get_base_font_or_default();
|
||||
if (f.is_valid()) {
|
||||
if (!face_indeces.is_empty()) {
|
||||
Dictionary var;
|
||||
if (ftr_weight > 0) {
|
||||
var[TS->name_to_tag("weight")] = ftr_weight;
|
||||
}
|
||||
if (ftr_italic > 0) {
|
||||
var[TS->name_to_tag("italic")] = ftr_italic;
|
||||
}
|
||||
return f->find_variation(var, face_indeces[0]);
|
||||
} else {
|
||||
return f->_get_rid();
|
||||
}
|
||||
}
|
||||
return RID();
|
||||
}
|
||||
|
||||
int64_t SystemFont::get_face_count() const {
|
||||
return face_indeces.size();
|
||||
}
|
||||
|
||||
SystemFont::SystemFont() {
|
||||
/* NOP */
|
||||
}
|
||||
|
||||
SystemFont::~SystemFont() {
|
||||
reset_state();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class TextLine;
|
|||
class TextParagraph;
|
||||
|
||||
/*************************************************************************/
|
||||
/* Font */
|
||||
/* Font */
|
||||
/*************************************************************************/
|
||||
|
||||
class Font : public Resource {
|
||||
|
@ -381,4 +381,74 @@ public:
|
|||
~FontVariation();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* SystemFont */
|
||||
/*************************************************************************/
|
||||
|
||||
class SystemFont : public Font {
|
||||
GDCLASS(SystemFont, Font);
|
||||
|
||||
PackedStringArray names;
|
||||
BitField<TextServer::FontStyle> style = 0;
|
||||
|
||||
mutable Ref<Font> theme_font;
|
||||
|
||||
Ref<FontFile> base_font;
|
||||
Vector<int> face_indeces;
|
||||
int ftr_weight = 0;
|
||||
int ftr_italic = 0;
|
||||
|
||||
bool antialiased = true;
|
||||
bool mipmaps = false;
|
||||
bool force_autohinter = false;
|
||||
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
|
||||
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
|
||||
real_t oversampling = 0.f;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _update_base_font();
|
||||
virtual void _update_rids() const override;
|
||||
|
||||
virtual void reset_state() override;
|
||||
|
||||
public:
|
||||
virtual Ref<Font> _get_base_font_or_default() const;
|
||||
|
||||
virtual void set_antialiased(bool p_antialiased);
|
||||
virtual bool is_antialiased() const;
|
||||
|
||||
virtual void set_generate_mipmaps(bool p_generate_mipmaps);
|
||||
virtual bool get_generate_mipmaps() const;
|
||||
|
||||
virtual void set_force_autohinter(bool p_force_autohinter);
|
||||
virtual bool is_force_autohinter() const;
|
||||
|
||||
virtual void set_hinting(TextServer::Hinting p_hinting);
|
||||
virtual TextServer::Hinting get_hinting() const;
|
||||
|
||||
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
|
||||
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
|
||||
|
||||
virtual void set_oversampling(real_t p_oversampling);
|
||||
virtual real_t get_oversampling() const;
|
||||
|
||||
virtual void set_font_names(const PackedStringArray &p_names);
|
||||
virtual PackedStringArray get_font_names() const;
|
||||
|
||||
virtual void set_font_style(BitField<TextServer::FontStyle> p_style);
|
||||
virtual BitField<TextServer::FontStyle> get_font_style() const override;
|
||||
|
||||
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()) const override;
|
||||
virtual RID _get_rid() const override;
|
||||
|
||||
int64_t get_face_count() const override;
|
||||
|
||||
SystemFont();
|
||||
~SystemFont();
|
||||
};
|
||||
|
||||
#endif // FONT_H
|
||||
|
|
Loading…
Reference in New Issue