Skip to content

Commit

Permalink
Use system fonts as fallback and improve system font handling.
Browse files Browse the repository at this point in the history
Add support for font weight and stretch selection when using system fonts.
Add function to get system fallback font from a font name, style, text, and language code.
Implement system font support for Android.
Use system fonts as a last resort fallback.
  • Loading branch information
bruvzg committed Dec 4, 2022
1 parent 015dc49 commit ecec415
Show file tree
Hide file tree
Showing 51 changed files with 2,752 additions and 146 deletions.
11 changes: 8 additions & 3 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,12 @@ 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_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
return ::OS::get_singleton()->get_system_font_path(p_font_name, p_weight, p_stretch, p_italic);
}

Vector<String> OS::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
return ::OS::get_singleton()->get_system_font_path_for_text(p_font_name, p_text, p_locale, p_script, p_weight, p_stretch, p_italic);
}

String OS::get_executable_path() const {
Expand Down Expand Up @@ -532,7 +536,8 @@ void OS::_bind_methods() {
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_system_font_path", "font_name", "weight", "stretch", "italic"), &OS::get_system_font_path, DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
ClassDB::bind_method(D_METHOD("read_string_from_stdin", "block"), &OS::read_string_from_stdin, DEFVAL(true));
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
Expand Down
3 changes: 2 additions & 1 deletion core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ class OS : public Object {
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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
String get_executable_path() const;
String read_string_from_stdin(bool p_block = true);
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);
Expand Down
7 changes: 5 additions & 2 deletions core/io/file_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
_store_buffer(buff);
}

Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) {
Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error);
if (f.is_null()) {
if (r_error) { // if error requested, do not throw error
Expand All @@ -706,7 +706,7 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err

String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
Error err;
Vector<uint8_t> array = get_file_as_array(p_path, &err);
Vector<uint8_t> array = get_file_as_bytes(p_path, &err);
if (r_error) {
*r_error = err;
}
Expand Down Expand Up @@ -810,6 +810,9 @@ void FileAccess::_bind_methods() {
ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0));
ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error);

ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_bytes", "path"), &FileAccess::_get_file_as_bytes);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_string", "path"), &FileAccess::_get_file_as_string);

ClassDB::bind_method(D_METHOD("flush"), &FileAccess::flush);
ClassDB::bind_method(D_METHOD("get_path"), &FileAccess::get_path);
ClassDB::bind_method(D_METHOD("get_path_absolute"), &FileAccess::get_path_absolute);
Expand Down
5 changes: 4 additions & 1 deletion core/io/file_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,12 @@ class FileAccess : public RefCounted {
static String get_sha256(const String &p_file);
static String get_multiple_md5(const Vector<String> &p_file);

static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = nullptr);
static Vector<uint8_t> get_file_as_bytes(const String &p_path, Error *r_error = nullptr);
static String get_file_as_string(const String &p_path, Error *r_error = nullptr);

static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path); }
static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path); };

template <class T>
static void make_default(AccessType p_access) {
create_func[p_access] = _create_builtin<T>;
Expand Down
2 changes: 1 addition & 1 deletion core/io/pck_packer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
pf.ofs = ofs;
pf.size = f->get_length();

Vector<uint8_t> data = FileAccess::get_file_as_array(p_src);
Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_src);
{
unsigned char hash[16];
CryptoCore::md5(data.ptr(), data.size(), hash);
Expand Down
3 changes: 2 additions & 1 deletion core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ class OS {
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_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return String(); };
virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return Vector<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;
Expand Down
14 changes: 14 additions & 0 deletions doc/classes/FileAccess.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@
Returns the last error that happened when trying to perform operations. Compare with the [code]ERR_FILE_*[/code] constants from [enum Error].
</description>
</method>
<method name="get_file_as_bytes" qualifiers="static">
<return type="PackedByteArray" />
<param index="0" name="path" type="String" />
<description>
Returns the whole [param path] file contents as a [PackedByteArray] without any decoding.
</description>
</method>
<method name="get_file_as_string" qualifiers="static">
<return type="String" />
<param index="0" name="path" type="String" />
<description>
Returns the whole [param path] file contents as a [String]. Text is interpreted as being UTF-8 encoded.
</description>
</method>
<method name="get_float" qualifiers="const">
<return type="float" />
<description>
Expand Down
12 changes: 12 additions & 0 deletions doc/classes/Font.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@
Returns font family name.
</description>
</method>
<method name="get_font_stretch" qualifiers="const">
<return type="int" />
<description>
Returns font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
</description>
</method>
<method name="get_font_style" qualifiers="const">
<return type="int" enum="TextServer.FontStyle" />
<description>
Expand All @@ -173,6 +179,12 @@
Returns font style name.
</description>
</method>
<method name="get_font_weight" qualifiers="const">
<return type="int" />
<description>
Returns weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="float" />
<param index="0" name="font_size" type="int" default="16" />
Expand Down
9 changes: 9 additions & 0 deletions doc/classes/FontFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@
</method>
</methods>
<members>
<member name="allow_system_fallback" type="bool" setter="set_allow_system_fallback" getter="is_allow_system_fallback" default="true">
If set to [code]true[/code], system fonts can be automatically used as fallbacks.
</member>
<member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1">
Font anti-aliasing mode.
</member>
Expand All @@ -557,9 +560,15 @@
<member name="font_name" type="String" setter="set_font_name" getter="get_font_name" default="&quot;&quot;">
Font family name.
</member>
<member name="font_stretch" type="int" setter="set_font_stretch" getter="get_font_stretch" default="100">
Font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
</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="font_weight" type="int" setter="set_font_weight" getter="get_font_weight" default="400">
Weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
</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. Used by dynamic fonts only.
</member>
Expand Down
30 changes: 25 additions & 5 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -394,18 +394,38 @@
<method name="get_system_font_path" qualifiers="const">
<return type="String" />
<param index="0" name="font_name" type="String" />
<param index="1" name="bold" type="bool" default="false" />
<param index="2" name="italic" type="bool" default="false" />
<param index="1" name="weight" type="int" default="400" />
<param index="2" name="stretch" type="int" default="100" />
<param index="3" name="italic" type="bool" default="false" />
<description>
Returns path to the system font file with [param font_name] and style. Return empty string if no matching fonts found.
[b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows.
Returns path to the system font file with [param font_name] and style. Returns empty string if no matching fonts found.
The following aliases can be used to request default fonts: "sans-serif", "serif", "monospace", "cursive", and "fantasy".
[b]Note:[/b] Returned font might have different style if the requested style is not available.
[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
</description>
</method>
<method name="get_system_font_path_for_text" qualifiers="const">
<return type="PackedStringArray" />
<param index="0" name="font_name" type="String" />
<param index="1" name="text" type="String" />
<param index="2" name="locale" type="String" default="&quot;&quot;" />
<param index="3" name="script" type="String" default="&quot;&quot;" />
<param index="4" name="weight" type="int" default="400" />
<param index="5" name="stretch" type="int" default="100" />
<param index="6" name="italic" type="bool" default="false" />
<description>
Returns an array of the system substitute font file paths, which are similar to the font with [param font_name] and style for the specified text, locale and script. Returns empty array if no matching fonts found.
The following aliases can be used to request default fonts: "sans-serif", "serif", "monospace", "cursive", and "fantasy".
[b]Note:[/b] Depending on OS, it's not guaranteed that any of the returned fonts is suitable for rendering specified text. Fonts should be loaded and checked in the order they are returned, and the first suitable one used.
[b]Note:[/b] Returned fonts might have different style if the requested style is not available or belong to a different font family.
[b]Note:[/b] This method is implemented on Android, 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.
[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
</description>
</method>
<method name="get_thread_caller_id" qualifiers="const">
Expand Down
15 changes: 12 additions & 3 deletions doc/classes/SystemFont.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,32 @@
<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.
The returned font might be part of a font collection or be a variable font with OpenType "weight", "width" 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="allow_system_fallback" type="bool" setter="set_allow_system_fallback" getter="is_allow_system_fallback" default="true">
If set to [code]true[/code], system fonts can be automatically used as fallbacks.
</member>
<member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1">
Font anti-aliasing mode.
</member>
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
Array of fallback [Font]s.
</member>
<member name="font_italic" type="bool" setter="set_font_italic" getter="get_font_italic" default="false">
If set to [code]true[/code], italic or oblique font is preferred.
</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 name="font_stretch" type="int" setter="set_font_stretch" getter="get_font_stretch" default="100">
Preferred font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
</member>
<member name="font_weight" type="int" setter="set_font_weight" getter="get_font_weight" default="400">
Preferred weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
</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.
Expand Down
48 changes: 48 additions & 0 deletions doc/classes/TextServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,13 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
<method name="font_get_stretch" qualifiers="const">
<return type="int" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
</description>
</method>
<method name="font_get_style" qualifiers="const">
<return type="int" enum="TextServer.FontStyle" />
<param index="0" name="font_rid" type="RID" />
Expand Down Expand Up @@ -446,6 +453,13 @@
Returns variation coordinates for the specified font cache entry. See [method font_supported_variation_list] for more info.
</description>
</method>
<method name="font_get_weight" qualifiers="const">
<return type="int" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
</description>
</method>
<method name="font_has_char" qualifiers="const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
Expand All @@ -454,6 +468,13 @@
Returns [code]true[/code] if a Unicode [param char] is available in the font.
</description>
</method>
<method name="font_is_allow_system_fallback" qualifiers="const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns [code]true[/code] if system fonts can be automatically used as fallbacks.
</description>
</method>
<method name="font_is_force_autohinter" qualifiers="const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
Expand Down Expand Up @@ -556,6 +577,14 @@
Renders the range of characters to the font cache texture.
</description>
</method>
<method name="font_set_allow_system_fallback">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
<param index="1" name="allow_system_fallback" type="bool" />
<description>
If set to [code]true[/code], system fonts can be automatically used as fallbacks.
</description>
</method>
<method name="font_set_antialiasing">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
Expand Down Expand Up @@ -783,12 +812,22 @@
Adds override for [method font_is_script_supported].
</description>
</method>
<method name="font_set_stretch">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
<param index="1" name="weight" type="int" />
<description>
Sets font stretch amount, compared to a normal width. A percentage value between [code]50%[/code] and [code]200%[/code].
[b]Note:[/b] This value is used for font matching only and will not affect font rendering. Use [method font_set_face_index], [method font_set_variation_coordinates], or [method font_set_transform] instead.
</description>
</method>
<method name="font_set_style">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
<param index="1" name="style" type="int" enum="TextServer.FontStyle" />
<description>
Sets the font style flags, see [enum FontStyle].
[b]Note:[/b] This value is used for font matching only and will not affect font rendering. Use [method font_set_face_index], [method font_set_variation_coordinates], [method font_set_embolden], or [method font_set_transform] instead.
</description>
</method>
<method name="font_set_style_name">
Expand Down Expand Up @@ -862,6 +901,15 @@
Sets variation coordinates for the specified font cache entry. See [method font_supported_variation_list] for more info.
</description>
</method>
<method name="font_set_weight">
<return type="void" />
<param index="0" name="font_rid" type="RID" />
<param index="1" name="weight" type="int" />
<description>
Sets weight (boldness) of the font. A value in the [code]100...999[/code] range, normal font weight is [code]400[/code], bold font weight is [code]700[/code].
[b]Note:[/b] This value is used for font matching only and will not affect font rendering. Use [method font_set_face_index], [method font_set_variation_coordinates], or [method font_set_embolden] instead.
</description>
</method>
<method name="font_supported_feature_list" qualifiers="const">
<return type="Dictionary" />
<param index="0" name="font_rid" type="RID" />
Expand Down
Loading

0 comments on commit ecec415

Please sign in to comment.