2020-12-27 14:30:33 +01:00
/*************************************************************************/
2022-02-14 14:00:03 +01:00
/* resource_importer_dynamic_font.cpp */
2020-12-27 14:30:33 +01:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2020-12-27 14:30:33 +01:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2022-02-14 14:00:03 +01:00
# include "resource_importer_dynamic_font.h"
2020-12-27 14:30:33 +01:00
# include "core/io/file_access.h"
# include "core/io/resource_saver.h"
2022-02-14 14:00:03 +01:00
# include "editor/import/dynamic_font_import_settings.h"
# include "scene/resources/font.h"
# include "servers/text_server.h"
2021-11-12 13:42:58 +01:00
# include "modules/modules_enabled.gen.h" // For freetype.
2020-12-27 14:30:33 +01:00
String ResourceImporterDynamicFont : : get_importer_name ( ) const {
return " font_data_dynamic " ;
}
String ResourceImporterDynamicFont : : get_visible_name ( ) const {
return " Font Data (Dynamic Font) " ;
}
void ResourceImporterDynamicFont : : get_recognized_extensions ( List < String > * p_extensions ) const {
if ( p_extensions ) {
# ifdef MODULE_FREETYPE_ENABLED
p_extensions - > push_back ( " ttf " ) ;
2022-06-07 10:35:59 +02:00
p_extensions - > push_back ( " ttc " ) ;
2020-12-27 14:30:33 +01:00
p_extensions - > push_back ( " otf " ) ;
2022-06-07 10:35:59 +02:00
p_extensions - > push_back ( " otc " ) ;
2020-12-27 14:30:33 +01:00
p_extensions - > push_back ( " woff " ) ;
2022-03-16 14:58:35 +01:00
p_extensions - > push_back ( " woff2 " ) ;
2020-12-27 14:30:33 +01:00
p_extensions - > push_back ( " pfb " ) ;
p_extensions - > push_back ( " pfm " ) ;
# endif
}
}
String ResourceImporterDynamicFont : : get_save_extension ( ) const {
return " fontdata " ;
}
String ResourceImporterDynamicFont : : get_resource_type ( ) const {
2022-05-09 11:47:10 +02:00
return " FontFile " ;
2020-12-27 14:30:33 +01:00
}
2022-05-13 15:04:37 +02:00
bool ResourceImporterDynamicFont : : get_option_visibility ( const String & p_path , const String & p_option , const HashMap < StringName , Variant > & p_options ) const {
2020-12-27 14:30:33 +01:00
if ( p_option = = " msdf_pixel_range " & & ! bool ( p_options [ " multichannel_signed_distance_field " ] ) ) {
return false ;
}
if ( p_option = = " msdf_size " & & ! bool ( p_options [ " multichannel_signed_distance_field " ] ) ) {
return false ;
}
if ( p_option = = " oversampling " & & bool ( p_options [ " multichannel_signed_distance_field " ] ) ) {
return false ;
}
2022-01-10 09:13:22 +01:00
if ( p_option = = " subpixel_positioning " & & bool ( p_options [ " multichannel_signed_distance_field " ] ) ) {
return false ;
}
2020-12-27 14:30:33 +01:00
return true ;
}
int ResourceImporterDynamicFont : : get_preset_count ( ) const {
return PRESET_MAX ;
}
String ResourceImporterDynamicFont : : get_preset_name ( int p_idx ) const {
switch ( p_idx ) {
case PRESET_DYNAMIC :
return TTR ( " Dynamically rendered TrueType/OpenType font " ) ;
case PRESET_MSDF :
return TTR ( " Prerendered multichannel(+true) signed distance field " ) ;
default :
return String ( ) ;
}
}
2021-11-14 18:02:38 +01:00
void ResourceImporterDynamicFont : : get_import_options ( const String & p_path , List < ImportOption > * r_options , int p_preset ) const {
2020-12-27 14:30:33 +01:00
bool msdf = p_preset = = PRESET_MSDF ;
2022-05-09 11:47:10 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : NIL , " Rendering " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_GROUP ) , Variant ( ) ) ) ;
2022-06-07 10:35:59 +02:00
2020-12-27 14:30:33 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " antialiased " ) , true ) ) ;
2022-04-19 12:27:18 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " generate_mipmaps " ) , false ) ) ;
2020-12-27 14:30:33 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " multichannel_signed_distance_field " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED ) , ( msdf ) ? true : false ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " msdf_pixel_range " , PROPERTY_HINT_RANGE , " 1,100,1 " ) , 8 ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " msdf_size " , PROPERTY_HINT_RANGE , " 1,250,1 " ) , 48 ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " force_autohinter " ) , false ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " hinting " , PROPERTY_HINT_ENUM , " None,Light,Normal " ) , 1 ) ) ;
2022-01-10 09:13:22 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " subpixel_positioning " , PROPERTY_HINT_ENUM , " Disabled,Auto,One half of a pixel,One quarter of a pixel " ) , 1 ) ) ;
2020-12-27 14:30:33 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : FLOAT , " oversampling " , PROPERTY_HINT_RANGE , " 0,10,0.1 " ) , 0.0 ) ) ;
2022-05-09 11:47:10 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : NIL , " Fallbacks " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_GROUP ) , Variant ( ) ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : ARRAY , " fallbacks " , PROPERTY_HINT_ARRAY_TYPE , vformat ( " %s/%s:%s " , Variant : : OBJECT , PROPERTY_HINT_RESOURCE_TYPE , " Font " ) ) , Array ( ) ) ) ;
2020-12-27 14:30:33 +01:00
2022-05-09 11:47:10 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : NIL , " Compress " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_GROUP ) , Variant ( ) ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " compress " ) , true ) ) ;
2020-12-27 14:30:33 +01:00
2022-05-09 11:47:10 +02:00
// Hide from the main UI, only for advanced import dialog.
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : ARRAY , " preload " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_STORAGE ) , Array ( ) ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : DICTIONARY , " language_support " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_STORAGE ) , Dictionary ( ) ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : DICTIONARY , " script_support " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_STORAGE ) , Dictionary ( ) ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : DICTIONARY , " opentype_features " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_STORAGE ) , Dictionary ( ) ) ) ;
2020-12-27 14:30:33 +01:00
}
bool ResourceImporterDynamicFont : : has_advanced_options ( ) const {
return true ;
}
void ResourceImporterDynamicFont : : show_advanced_options ( const String & p_path ) {
DynamicFontImportSettings : : get_singleton ( ) - > open_settings ( p_path ) ;
}
2022-05-13 15:04:37 +02:00
Error ResourceImporterDynamicFont : : import ( const String & p_source_file , const String & p_save_path , const HashMap < StringName , Variant > & p_options , List < String > * r_platform_variants , List < String > * r_gen_files , Variant * r_metadata ) {
2020-12-27 14:30:33 +01:00
print_verbose ( " Importing dynamic font from: " + p_source_file ) ;
bool antialiased = p_options [ " antialiased " ] ;
2022-04-19 12:27:18 +02:00
bool generate_mipmaps = p_options [ " generate_mipmaps " ] ;
2020-12-27 14:30:33 +01:00
bool msdf = p_options [ " multichannel_signed_distance_field " ] ;
int px_range = p_options [ " msdf_pixel_range " ] ;
int px_size = p_options [ " msdf_size " ] ;
2022-05-09 11:47:10 +02:00
Dictionary ot_ov = p_options [ " opentype_features " ] ;
2020-12-27 14:30:33 +01:00
bool autohinter = p_options [ " force_autohinter " ] ;
int hinting = p_options [ " hinting " ] ;
2022-01-10 09:13:22 +01:00
int subpixel_positioning = p_options [ " subpixel_positioning " ] ;
2020-12-27 14:30:33 +01:00
real_t oversampling = p_options [ " oversampling " ] ;
2022-05-09 11:47:10 +02:00
Array fallbacks = p_options [ " fallbacks " ] ;
2020-12-27 14:30:33 +01:00
// Load base font data.
Vector < uint8_t > data = FileAccess : : get_file_as_array ( p_source_file ) ;
// Create font.
2022-05-09 11:47:10 +02:00
Ref < FontFile > font ;
2020-12-27 14:30:33 +01:00
font . instantiate ( ) ;
font - > set_data ( data ) ;
font - > set_antialiased ( antialiased ) ;
2022-04-19 12:27:18 +02:00
font - > set_generate_mipmaps ( generate_mipmaps ) ;
2020-12-27 14:30:33 +01:00
font - > set_multichannel_signed_distance_field ( msdf ) ;
font - > set_msdf_pixel_range ( px_range ) ;
font - > set_msdf_size ( px_size ) ;
2021-11-18 22:36:22 +01:00
font - > set_opentype_feature_overrides ( ot_ov ) ;
2020-12-27 14:30:33 +01:00
font - > set_fixed_size ( 0 ) ;
font - > set_force_autohinter ( autohinter ) ;
2022-01-10 09:13:22 +01:00
font - > set_subpixel_positioning ( ( TextServer : : SubpixelPositioning ) subpixel_positioning ) ;
2020-12-27 14:30:33 +01:00
font - > set_hinting ( ( TextServer : : Hinting ) hinting ) ;
font - > set_oversampling ( oversampling ) ;
2022-05-09 11:47:10 +02:00
font - > set_fallbacks ( fallbacks ) ;
2020-12-27 14:30:33 +01:00
2022-05-09 11:47:10 +02:00
Dictionary langs = p_options [ " language_support " ] ;
for ( int i = 0 ; i < langs . size ( ) ; i + + ) {
String key = langs . get_key_at_index ( i ) ;
bool enabled = langs . get_value_at_index ( i ) ;
font - > set_language_support_override ( key , enabled ) ;
2020-12-27 14:30:33 +01:00
}
2022-05-09 11:47:10 +02:00
Dictionary scripts = p_options [ " script_support " ] ;
for ( int i = 0 ; i < scripts . size ( ) ; i + + ) {
String key = scripts . get_key_at_index ( i ) ;
bool enabled = scripts . get_value_at_index ( i ) ;
font - > set_script_support_override ( key , enabled ) ;
2020-12-27 14:30:33 +01:00
}
2022-05-09 11:47:10 +02:00
Array preload_configurations = p_options [ " preload " ] ;
2020-12-27 14:30:33 +01:00
2022-05-09 11:47:10 +02:00
for ( int i = 0 ; i < preload_configurations . size ( ) ; i + + ) {
Dictionary preload_config = preload_configurations [ i ] ;
2020-12-27 14:30:33 +01:00
2022-05-09 11:47:10 +02:00
Dictionary variation = preload_config . has ( " variation_opentype " ) ? preload_config [ " variation_opentype " ] . operator Dictionary ( ) : Dictionary ( ) ;
double embolden = preload_config . has ( " variation_embolden " ) ? preload_config [ " variation_embolden " ] . operator double ( ) : 0 ;
int face_index = preload_config . has ( " variation_face_index " ) ? preload_config [ " variation_face_index " ] . operator int ( ) : 0 ;
Transform2D transform = preload_config . has ( " variation_transform " ) ? preload_config [ " variation_transform " ] . operator Transform2D ( ) : Transform2D ( ) ;
Vector2i size = preload_config . has ( " size " ) ? preload_config [ " size " ] . operator Vector2i ( ) : Vector2i ( 16 , 0 ) ;
String name = preload_config . has ( " name " ) ? preload_config [ " name " ] . operator String ( ) : vformat ( " Configuration %d " , i ) ;
2020-12-27 14:30:33 +01:00
2022-05-09 11:47:10 +02:00
RID conf_rid = font - > find_variation ( variation , face_index , embolden , transform ) ;
Array chars = preload_config [ " chars " ] ;
for ( int j = 0 ; j < chars . size ( ) ; j + + ) {
char32_t c = chars [ j ] . operator int ( ) ;
TS - > font_render_range ( conf_rid , size , c , c ) ;
2020-12-27 14:30:33 +01:00
}
2022-05-09 11:47:10 +02:00
Array glyphs = preload_config [ " glyphs " ] ;
for ( int j = 0 ; j < glyphs . size ( ) ; j + + ) {
int32_t c = glyphs [ j ] ;
TS - > font_render_glyph ( conf_rid , size , c ) ;
}
2020-12-27 14:30:33 +01:00
}
2022-05-09 11:47:10 +02:00
int flg = 0 ;
2020-12-27 14:30:33 +01:00
if ( ( bool ) p_options [ " compress " ] ) {
flg | = ResourceSaver : : SaverFlags : : FLAG_COMPRESS ;
}
print_verbose ( " Saving to: " + p_save_path + " .fontdata " ) ;
2022-06-03 01:33:42 +02:00
Error err = ResourceSaver : : save ( font , p_save_path + " .fontdata " , flg ) ;
2020-12-27 14:30:33 +01:00
ERR_FAIL_COND_V_MSG ( err ! = OK , err , " Cannot save font to file \" " + p_save_path + " .res \" . " ) ;
print_verbose ( " Done saving to: " + p_save_path + " .fontdata " ) ;
return OK ;
}
ResourceImporterDynamicFont : : ResourceImporterDynamicFont ( ) {
}