2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* editor_font_import_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
2017-01-01 22:01:57 +01:00
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
2014-02-10 02:10:30 +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. */
/*************************************************************************/
# include "editor_font_import_plugin.h"
2017-03-18 23:45:45 +01:00
# include "editor/editor_file_dialog.h"
# include "editor/editor_node.h"
2014-02-10 02:10:30 +01:00
# include "editor_atlas.h"
# include "io/image_loader.h"
# include "io/resource_saver.h"
2017-03-19 00:36:26 +01:00
# include "os/file_access.h"
# include "scene/gui/dialogs.h"
2014-02-10 02:10:30 +01:00
# ifdef FREETYPE_ENABLED
# include <ft2build.h>
# include FT_FREETYPE_H
# endif
class _EditorFontImportOptions : public Object {
2017-03-19 00:36:26 +01:00
OBJ_TYPE ( _EditorFontImportOptions , Object ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
public :
2015-03-20 04:26:01 +01:00
enum FontMode {
FONT_BITMAP ,
FONT_DISTANCE_FIELD
} ;
2014-02-10 02:10:30 +01:00
enum ColorType {
COLOR_WHITE ,
COLOR_CUSTOM ,
COLOR_GRADIENT_RANGE ,
COLOR_GRADIENT_IMAGE
} ;
int char_extra_spacing ;
int top_extra_spacing ;
int bottom_extra_spacing ;
int space_extra_spacing ;
enum CharacterSet {
CHARSET_ASCII ,
CHARSET_LATIN ,
CHARSET_UNICODE ,
CHARSET_CUSTOM ,
CHARSET_CUSTOM_LATIN
} ;
2015-03-20 04:26:01 +01:00
FontMode font_mode ;
2014-02-10 02:10:30 +01:00
CharacterSet character_set ;
String custom_file ;
bool shadow ;
Vector2 shadow_offset ;
int shadow_radius ;
Color shadow_color ;
float shadow_transition ;
bool shadow2 ;
Vector2 shadow2_offset ;
int shadow2_radius ;
Color shadow2_color ;
float shadow2_transition ;
ColorType color_type ;
Color color ;
Color gradient_begin ;
Color gradient_end ;
2014-03-14 02:57:24 +01:00
bool color_use_monochrome ;
2014-02-10 02:10:30 +01:00
String gradient_image ;
2014-10-03 05:10:51 +02:00
bool disable_filter ;
2014-02-10 02:10:30 +01:00
bool round_advance ;
2016-06-21 15:41:13 +02:00
bool premultiply_alpha ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
bool _set ( const StringName & p_name , const Variant & p_value ) {
2014-02-10 02:10:30 +01:00
String n = p_name ;
2017-03-19 00:36:26 +01:00
if ( n = = " mode/mode " ) {
font_mode = FontMode ( int ( p_value ) ) ;
2015-03-20 04:26:01 +01:00
_change_notify ( ) ;
2017-03-19 00:36:26 +01:00
} else if ( n = = " extra_space/char " )
char_extra_spacing = p_value ;
else if ( n = = " extra_space/space " )
space_extra_spacing = p_value ;
else if ( n = = " extra_space/top " )
top_extra_spacing = p_value ;
else if ( n = = " extra_space/bottom " )
bottom_extra_spacing = p_value ;
else if ( n = = " character_set/mode " ) {
character_set = CharacterSet ( int ( p_value ) ) ;
2014-02-10 02:10:30 +01:00
_change_notify ( ) ;
2017-03-19 00:36:26 +01:00
} else if ( n = = " character_set/custom " )
custom_file = p_value ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
else if ( n = = " shadow/enabled " ) {
shadow = p_value ;
2014-02-10 02:10:30 +01:00
_change_notify ( ) ;
2017-03-19 00:36:26 +01:00
} else if ( n = = " shadow/radius " )
shadow_radius = p_value ;
else if ( n = = " shadow/offset " )
shadow_offset = p_value ;
else if ( n = = " shadow/color " )
shadow_color = p_value ;
else if ( n = = " shadow/transition " )
shadow_transition = p_value ;
else if ( n = = " shadow2/enabled " ) {
shadow2 = p_value ;
2014-02-10 02:10:30 +01:00
_change_notify ( ) ;
2017-03-19 00:36:26 +01:00
} else if ( n = = " shadow2/radius " )
shadow2_radius = p_value ;
else if ( n = = " shadow2/offset " )
shadow2_offset = p_value ;
else if ( n = = " shadow2/color " )
shadow2_color = p_value ;
else if ( n = = " shadow2/transition " )
shadow2_transition = p_value ;
else if ( n = = " color/mode " ) {
color_type = ColorType ( int ( p_value ) ) ;
2014-02-10 02:10:30 +01:00
_change_notify ( ) ;
2017-03-19 00:36:26 +01:00
} else if ( n = = " color/color " )
color = p_value ;
else if ( n = = " color/begin " )
gradient_begin = p_value ;
else if ( n = = " color/end " )
gradient_end = p_value ;
else if ( n = = " color/image " )
gradient_image = p_value ;
else if ( n = = " color/monochrome " )
color_use_monochrome = p_value ;
else if ( n = = " advanced/round_advance " )
round_advance = p_value ;
else if ( n = = " advanced/disable_filter " )
disable_filter = p_value ;
else if ( n = = " advanced/premultiply_alpha " )
premultiply_alpha = p_value ;
2014-02-10 02:10:30 +01:00
else
return false ;
emit_signal ( " changed " ) ;
return true ;
}
2017-03-19 00:36:26 +01:00
bool _get ( const StringName & p_name , Variant & r_ret ) const {
2014-02-10 02:10:30 +01:00
String n = p_name ;
2017-03-19 00:36:26 +01:00
if ( n = = " mode/mode " )
r_ret = font_mode ;
else if ( n = = " extra_space/char " )
r_ret = char_extra_spacing ;
else if ( n = = " extra_space/space " )
r_ret = space_extra_spacing ;
else if ( n = = " extra_space/top " )
r_ret = top_extra_spacing ;
else if ( n = = " extra_space/bottom " )
r_ret = bottom_extra_spacing ;
else if ( n = = " character_set/mode " )
r_ret = character_set ;
else if ( n = = " character_set/custom " )
r_ret = custom_file ;
else if ( n = = " shadow/enabled " )
r_ret = shadow ;
else if ( n = = " shadow/radius " )
r_ret = shadow_radius ;
else if ( n = = " shadow/offset " )
r_ret = shadow_offset ;
else if ( n = = " shadow/color " )
r_ret = shadow_color ;
else if ( n = = " shadow/transition " )
r_ret = shadow_transition ;
else if ( n = = " shadow2/enabled " )
r_ret = shadow2 ;
else if ( n = = " shadow2/radius " )
r_ret = shadow2_radius ;
else if ( n = = " shadow2/offset " )
r_ret = shadow2_offset ;
else if ( n = = " shadow2/color " )
r_ret = shadow2_color ;
else if ( n = = " shadow2/transition " )
r_ret = shadow2_transition ;
else if ( n = = " color/mode " )
r_ret = color_type ;
else if ( n = = " color/color " )
r_ret = color ;
else if ( n = = " color/begin " )
r_ret = gradient_begin ;
else if ( n = = " color/end " )
r_ret = gradient_end ;
else if ( n = = " color/image " )
r_ret = gradient_image ;
else if ( n = = " color/monochrome " )
r_ret = color_use_monochrome ;
else if ( n = = " advanced/round_advance " )
r_ret = round_advance ;
else if ( n = = " advanced/disable_filter " )
r_ret = disable_filter ;
else if ( n = = " advanced/premultiply_alpha " )
r_ret = premultiply_alpha ;
2014-02-10 02:10:30 +01:00
else
return false ;
return true ;
}
2017-03-19 00:36:26 +01:00
void _get_property_list ( List < PropertyInfo > * p_list ) const {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " mode/mode " , PROPERTY_HINT_ENUM , " Bitmap,Distance Field " ) ) ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " extra_space/char " , PROPERTY_HINT_RANGE , " -64,64,1 " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : INT , " extra_space/space " , PROPERTY_HINT_RANGE , " -64,64,1 " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : INT , " extra_space/top " , PROPERTY_HINT_RANGE , " -64,64,1 " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : INT , " extra_space/bottom " , PROPERTY_HINT_RANGE , " -64,64,1 " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : INT , " character_set/mode " , PROPERTY_HINT_ENUM , " Ascii,Latin,Unicode,Custom,Custom&Latin " ) ) ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
if ( character_set > = CHARSET_CUSTOM )
p_list - > push_back ( PropertyInfo ( Variant : : STRING , " character_set/custom " , PROPERTY_HINT_GLOBAL_FILE ) ) ;
2014-02-10 02:10:30 +01:00
2015-03-20 04:26:01 +01:00
int usage = PROPERTY_USAGE_DEFAULT ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_mode = = FONT_DISTANCE_FIELD ) {
2015-03-20 04:26:01 +01:00
usage = PROPERTY_USAGE_NOEDITOR ;
2014-02-10 02:10:30 +01:00
}
2015-03-20 04:26:01 +01:00
{
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " shadow/enabled " , PROPERTY_HINT_NONE , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
if ( shadow ) {
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " shadow/radius " , PROPERTY_HINT_RANGE , " -64,64,1 " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : VECTOR2 , " shadow/offset " , PROPERTY_HINT_NONE , " " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , " shadow/color " , PROPERTY_HINT_NONE , " " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : REAL , " shadow/transition " , PROPERTY_HINT_EXP_EASING , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " shadow2/enabled " , PROPERTY_HINT_NONE , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
if ( shadow2 ) {
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " shadow2/radius " , PROPERTY_HINT_RANGE , " -64,64,1 " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : VECTOR2 , " shadow2/offset " , PROPERTY_HINT_NONE , " " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , " shadow2/color " , PROPERTY_HINT_NONE , " " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : REAL , " shadow2/transition " , PROPERTY_HINT_EXP_EASING , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : INT , " color/mode " , PROPERTY_HINT_ENUM , " White,Color,Gradient,Gradient Image " , usage ) ) ;
if ( color_type = = COLOR_CUSTOM ) {
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , " color/color " , PROPERTY_HINT_NONE , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
if ( color_type = = COLOR_GRADIENT_RANGE ) {
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , " color/begin " , PROPERTY_HINT_NONE , " " , usage ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : COLOR , " color/end " , PROPERTY_HINT_NONE , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
if ( color_type = = COLOR_GRADIENT_IMAGE ) {
p_list - > push_back ( PropertyInfo ( Variant : : STRING , " color/image " , PROPERTY_HINT_GLOBAL_FILE , " " , usage ) ) ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " color/monochrome " , PROPERTY_HINT_NONE , " " , usage ) ) ;
2014-02-10 02:10:30 +01:00
}
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " advanced/round_advance " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " advanced/disable_filter " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " advanced/premultiply_alpha " ) ) ;
2014-02-10 02:10:30 +01:00
}
static void _bind_methods ( ) {
2017-03-19 00:36:26 +01:00
ADD_SIGNAL ( MethodInfo ( " changed " ) ) ;
2014-02-10 02:10:30 +01:00
}
2014-03-14 02:57:24 +01:00
void reset ( ) {
2017-03-19 00:36:26 +01:00
char_extra_spacing = 0 ;
top_extra_spacing = 0 ;
bottom_extra_spacing = 0 ;
space_extra_spacing = 0 ;
character_set = CHARSET_LATIN ;
shadow = false ;
shadow_radius = 2 ;
shadow_color = Color ( 0 , 0 , 0 , 0.3 ) ;
shadow_transition = 1.0 ;
shadow2 = false ;
shadow2_radius = 2 ;
shadow2_color = Color ( 0 , 0 , 0 , 0.3 ) ;
shadow2_transition = 1.0 ;
color_type = COLOR_WHITE ;
color = Color ( 1 , 1 , 1 , 1 ) ;
gradient_begin = Color ( 1 , 1 , 1 , 1 ) ;
gradient_end = Color ( 0.5 , 0.5 , 0.5 , 1 ) ;
color_use_monochrome = false ;
font_mode = FONT_BITMAP ;
round_advance = true ;
disable_filter = false ;
premultiply_alpha = false ;
2014-03-14 02:57:24 +01:00
}
2014-02-10 02:10:30 +01:00
_EditorFontImportOptions ( ) {
2017-03-19 00:36:26 +01:00
font_mode = FONT_BITMAP ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
char_extra_spacing = 0 ;
top_extra_spacing = 0 ;
bottom_extra_spacing = 0 ;
space_extra_spacing = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
character_set = CHARSET_LATIN ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
shadow = false ;
shadow_radius = 2 ;
shadow_color = Color ( 0 , 0 , 0 , 0.3 ) ;
shadow_transition = 1.0 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
shadow2 = false ;
shadow2_radius = 2 ;
shadow2_color = Color ( 0 , 0 , 0 , 0.3 ) ;
shadow2_transition = 1.0 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
color_type = COLOR_WHITE ;
color = Color ( 1 , 1 , 1 , 1 ) ;
gradient_begin = Color ( 1 , 1 , 1 , 1 ) ;
gradient_end = Color ( 0.5 , 0.5 , 0.5 , 1 ) ;
color_use_monochrome = false ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
round_advance = true ;
disable_filter = false ;
premultiply_alpha = false ;
2014-02-10 02:10:30 +01:00
}
} ;
class EditorFontImportDialog : public ConfirmationDialog {
OBJ_TYPE ( EditorFontImportDialog , ConfirmationDialog ) ;
2015-06-06 14:44:38 +02:00
EditorLineEditFileChooser * source ;
EditorLineEditFileChooser * dest ;
2014-02-10 02:10:30 +01:00
SpinBox * font_size ;
LineEdit * test_string ;
ColorPickerButton * test_color ;
Label * test_label ;
PropertyEditor * prop_edit ;
Timer * timer ;
ConfirmationDialog * error_dialog ;
Ref < ResourceImportMetadata > get_rimd ( ) {
2017-03-19 00:36:26 +01:00
Ref < ResourceImportMetadata > imd = memnew ( ResourceImportMetadata ) ;
2014-02-10 02:10:30 +01:00
List < PropertyInfo > pl ;
options - > _get_property_list ( & pl ) ;
2017-03-19 00:36:26 +01:00
for ( List < PropertyInfo > : : Element * E = pl . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
Variant v ;
2017-03-19 00:36:26 +01:00
String opt = E - > get ( ) . name ;
options - > _get ( opt , v ) ;
if ( opt = = " color/image " | | opt = = " character_set/custom " ) {
2014-02-10 02:10:30 +01:00
v = EditorImportPlugin : : validate_source_path ( v ) ;
}
2017-03-19 00:36:26 +01:00
imd - > set_option ( opt , v ) ;
2014-02-10 02:10:30 +01:00
}
2015-05-04 20:06:41 +02:00
String src_path = EditorImportPlugin : : validate_source_path ( source - > get_line_edit ( ) - > get_text ( ) ) ;
//print_line("pre src path "+source->get_line_edit()->get_text());
//print_line("src path "+src_path);
imd - > add_source ( src_path ) ;
2017-03-19 00:36:26 +01:00
imd - > set_option ( " font/size " , font_size - > get_val ( ) ) ;
2014-02-10 02:10:30 +01:00
return imd ;
}
void _src_changed ( String ) {
_prop_changed ( ) ;
}
void _update_text2 ( String ) {
_update_text ( ) ;
}
void _update_text3 ( Color ) {
_update_text ( ) ;
}
void _update_text ( ) {
test_label - > set_text ( " " ) ;
test_label - > set_text ( test_string - > get_text ( ) ) ;
2017-03-19 00:36:26 +01:00
test_label - > add_color_override ( " font_color " , test_color - > get_color ( ) ) ;
2014-02-10 02:10:30 +01:00
}
void _update ( ) {
Ref < ResourceImportMetadata > imd = get_rimd ( ) ;
2016-04-29 03:21:18 +02:00
Ref < BitmapFont > font = plugin - > generate_font ( imd ) ;
2017-03-19 00:36:26 +01:00
test_label - > add_font_override ( " font " , font ) ;
2014-02-10 02:10:30 +01:00
_update_text ( ) ;
}
void _font_size_changed ( double ) {
_prop_changed ( ) ;
}
void _prop_changed ( ) {
timer - > start ( ) ;
}
void _import_inc ( String p_font ) {
2016-04-29 03:21:18 +02:00
Ref < BitmapFont > font = ResourceLoader : : load ( p_font ) ;
2014-02-10 02:10:30 +01:00
if ( ! font . is_valid ( ) )
return ;
Ref < ImageTexture > tex = font - > get_texture ( 0 ) ;
if ( tex . is_null ( ) )
return ;
2017-03-19 00:36:26 +01:00
FileAccessRef f = FileAccess : : open ( p_font . basename ( ) + " .inc " , FileAccess : : WRITE ) ;
2014-02-10 02:10:30 +01:00
Vector < CharType > ck = font - > get_char_keys ( ) ;
2017-03-19 00:36:26 +01:00
f - > store_line ( " static const int _builtin_font_height= " + itos ( font - > get_height ( ) ) + " ; " ) ;
f - > store_line ( " static const int _builtin_font_ascent= " + itos ( font - > get_ascent ( ) ) + " ; " ) ;
f - > store_line ( " static const int _builtin_font_charcount= " + itos ( ck . size ( ) ) + " ; " ) ;
f - > store_line ( " static const int _builtin_font_charrects[ " + itos ( ck . size ( ) ) + " ][8]={ " ) ;
2014-02-10 02:10:30 +01:00
f - > store_line ( " /* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */ " ) ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < ck . size ( ) ; i + + ) {
CharType k = ck [ i ] ;
BitmapFont : : Character c = font - > get_character ( k ) ;
f - > store_line ( " { " + itos ( k ) + " , " + rtos ( c . rect . pos . x ) + " , " + rtos ( c . rect . pos . y ) + " , " + rtos ( c . rect . size . x ) + " , " + rtos ( c . rect . size . y ) + " , " + rtos ( c . v_align ) + " , " + rtos ( c . h_align ) + " , " + rtos ( c . advance ) + " }, " ) ;
2014-02-10 02:10:30 +01:00
}
f - > store_line ( " }; " ) ;
2017-03-19 00:36:26 +01:00
Vector < BitmapFont : : KerningPairKey > kp = font - > get_kerning_pair_keys ( ) ;
f - > store_line ( " static const int _builtin_font_kerning_pair_count= " + itos ( kp . size ( ) ) + " ; " ) ;
f - > store_line ( " static const int _builtin_font_kerning_pairs[ " + itos ( kp . size ( ) ) + " ][3]={ " ) ;
for ( int i = 0 ; i < kp . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int d = font - > get_kerning_pair ( kp [ i ] . A , kp [ i ] . B ) ;
f - > store_line ( " { " + itos ( kp [ i ] . A ) + " , " + itos ( kp [ i ] . B ) + " , " + itos ( d ) + " }, " ) ;
2014-02-10 02:10:30 +01:00
}
f - > store_line ( " }; " ) ;
2017-03-19 00:36:26 +01:00
Image img = tex - > get_data ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
f - > store_line ( " static const int _builtin_font_img_width= " + itos ( img . get_width ( ) ) + " ; " ) ;
f - > store_line ( " static const int _builtin_font_img_height= " + itos ( img . get_height ( ) ) + " ; " ) ;
2016-06-17 01:04:33 +02:00
2017-03-19 00:36:26 +01:00
String fname = p_font . basename ( ) + " .sv.png " ;
ResourceSaver : : save ( fname , tex ) ;
Vector < uint8_t > data = FileAccess : : get_file_as_array ( fname ) ;
2016-06-17 01:04:33 +02:00
2017-03-19 00:36:26 +01:00
f - > store_line ( " static const int _builtin_font_img_data_size= " + itos ( data . size ( ) ) + " ; " ) ;
f - > store_line ( " static const unsigned char _builtin_font_img_data[ " + itos ( data . size ( ) ) + " ]={ " ) ;
2016-06-17 01:04:33 +02:00
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < data . size ( ) ; i + + ) {
2016-06-17 01:04:33 +02:00
2017-03-19 00:36:26 +01:00
f - > store_line ( itos ( data [ i ] ) + " , " ) ;
2014-02-10 02:10:30 +01:00
}
f - > store_line ( " }; " ) ;
}
void _import ( ) {
2017-03-19 00:36:26 +01:00
if ( source - > get_line_edit ( ) - > get_text ( ) = = " " ) {
2016-05-04 03:25:37 +02:00
error_dialog - > set_text ( TTR ( " No source font file! " ) ) ;
2017-03-19 00:36:26 +01:00
error_dialog - > popup_centered ( Size2 ( 200 , 100 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-03-19 00:36:26 +01:00
if ( dest - > get_line_edit ( ) - > get_text ( ) = = " " ) {
2016-05-04 03:25:37 +02:00
error_dialog - > set_text ( TTR ( " No target font resource! " ) ) ;
2017-03-19 00:36:26 +01:00
error_dialog - > popup_centered ( Size2 ( 200 , 100 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-03-19 00:36:26 +01:00
if ( dest - > get_line_edit ( ) - > get_text ( ) . get_file ( ) = = " .fnt " ) {
dest - > get_line_edit ( ) - > set_text ( dest - > get_line_edit ( ) - > get_text ( ) . get_base_dir ( ) + " / " + source - > get_line_edit ( ) - > get_text ( ) . get_file ( ) . basename ( ) + " .fnt " ) ;
2015-12-04 19:29:27 +01:00
}
2016-03-27 19:23:50 +02:00
if ( dest - > get_line_edit ( ) - > get_text ( ) . extension ( ) = = dest - > get_line_edit ( ) - > get_text ( ) ) {
dest - > get_line_edit ( ) - > set_text ( dest - > get_line_edit ( ) - > get_text ( ) + " .fnt " ) ;
}
if ( dest - > get_line_edit ( ) - > get_text ( ) . extension ( ) . to_lower ( ) ! = " fnt " ) {
2016-06-20 07:56:47 +02:00
error_dialog - > set_text ( TTR ( " Invalid file extension. \n Please use .fnt. " ) ) ;
2017-03-19 00:36:26 +01:00
error_dialog - > popup_centered ( Size2 ( 200 , 100 ) ) ;
2016-03-27 19:23:50 +02:00
return ;
}
2014-02-10 02:10:30 +01:00
Ref < ResourceImportMetadata > rimd = get_rimd ( ) ;
if ( rimd . is_null ( ) ) {
2016-05-19 00:08:12 +02:00
error_dialog - > set_text ( TTR ( " Can't load/process source font. " ) ) ;
2017-03-19 00:36:26 +01:00
error_dialog - > popup_centered ( Size2 ( 200 , 100 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-03-19 00:36:26 +01:00
Error err = plugin - > import ( dest - > get_line_edit ( ) - > get_text ( ) , rimd ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( err ! = OK ) {
2016-05-04 03:25:37 +02:00
error_dialog - > set_text ( TTR ( " Couldn't save font. " ) ) ;
2017-03-19 00:36:26 +01:00
error_dialog - > popup_centered ( Size2 ( 200 , 100 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2016-02-28 03:10:44 +01:00
_import_inc ( dest - > get_line_edit ( ) - > get_text ( ) ) ;
2014-02-10 02:10:30 +01:00
hide ( ) ;
}
EditorFontImportPlugin * plugin ;
_EditorFontImportOptions * options ;
static void _bind_methods ( ) {
2017-03-19 00:36:26 +01:00
ObjectTypeDB : : bind_method ( " _update " , & EditorFontImportDialog : : _update ) ;
ObjectTypeDB : : bind_method ( " _update_text " , & EditorFontImportDialog : : _update_text ) ;
ObjectTypeDB : : bind_method ( " _update_text2 " , & EditorFontImportDialog : : _update_text2 ) ;
ObjectTypeDB : : bind_method ( " _update_text3 " , & EditorFontImportDialog : : _update_text3 ) ;
ObjectTypeDB : : bind_method ( " _prop_changed " , & EditorFontImportDialog : : _prop_changed ) ;
ObjectTypeDB : : bind_method ( " _src_changed " , & EditorFontImportDialog : : _src_changed ) ;
ObjectTypeDB : : bind_method ( " _font_size_changed " , & EditorFontImportDialog : : _font_size_changed ) ;
ObjectTypeDB : : bind_method ( " _import " , & EditorFontImportDialog : : _import ) ;
2014-02-10 02:10:30 +01:00
}
public :
void _notification ( int p_what ) {
2017-03-19 00:36:26 +01:00
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
2014-02-10 02:10:30 +01:00
prop_edit - > edit ( options ) ;
_update_text ( ) ;
}
}
2017-03-19 00:36:26 +01:00
void popup_import ( const String & p_path ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
popup_centered ( Size2 ( 600 , 500 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( p_path ! = " " ) {
2014-02-10 02:10:30 +01:00
Ref < ResourceImportMetadata > rimd = ResourceLoader : : load_import_metadata ( p_path ) ;
ERR_FAIL_COND ( ! rimd . is_valid ( ) ) ;
dest - > get_line_edit ( ) - > set_text ( p_path ) ;
List < String > opts ;
rimd - > get_options ( & opts ) ;
2014-03-14 02:57:24 +01:00
options - > reset ( ) ;
2017-03-19 00:36:26 +01:00
for ( List < String > : : Element * E = opts . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
options - > _set ( E - > get ( ) , rimd - > get_option ( E - > get ( ) ) ) ;
2014-02-10 02:10:30 +01:00
}
String src = " " ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < rimd - > get_source_count ( ) ; i + + ) {
if ( i > 0 )
src + = " , " ;
src + = EditorImportPlugin : : expand_source_path ( rimd - > get_source_path ( i ) ) ;
2014-02-10 02:10:30 +01:00
}
source - > get_line_edit ( ) - > set_text ( src ) ;
font_size - > set_val ( rimd - > get_option ( " font/size " ) ) ;
}
}
2017-03-19 00:36:26 +01:00
void set_source_and_dest ( const String & p_font , const String & p_dest ) {
2016-05-27 19:18:40 +02:00
source - > get_line_edit ( ) - > set_text ( p_font ) ;
dest - > get_line_edit ( ) - > set_text ( p_dest ) ;
_prop_changed ( ) ;
}
2014-02-10 02:10:30 +01:00
EditorFontImportDialog ( EditorFontImportPlugin * p_plugin ) {
2017-03-19 00:36:26 +01:00
plugin = p_plugin ;
VBoxContainer * vbc = memnew ( VBoxContainer ) ;
2014-02-10 02:10:30 +01:00
add_child ( vbc ) ;
set_child_rect ( vbc ) ;
2017-03-19 00:36:26 +01:00
HBoxContainer * hbc = memnew ( HBoxContainer ) ;
2014-02-10 02:10:30 +01:00
vbc - > add_child ( hbc ) ;
2017-03-19 00:36:26 +01:00
VBoxContainer * vbl = memnew ( VBoxContainer ) ;
2014-02-10 02:10:30 +01:00
hbc - > add_child ( vbl ) ;
hbc - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
vbl - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-19 00:36:26 +01:00
VBoxContainer * vbr = memnew ( VBoxContainer ) ;
2014-02-10 02:10:30 +01:00
hbc - > add_child ( vbr ) ;
vbr - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-19 00:36:26 +01:00
source = memnew ( EditorLineEditFileChooser ) ;
2015-06-06 14:44:38 +02:00
source - > get_file_dialog ( ) - > set_access ( EditorFileDialog : : ACCESS_FILESYSTEM ) ;
source - > get_file_dialog ( ) - > set_mode ( EditorFileDialog : : MODE_OPEN_FILE ) ;
2014-02-10 02:10:30 +01:00
source - > get_file_dialog ( ) - > add_filter ( " *.ttf;TrueType " ) ;
source - > get_file_dialog ( ) - > add_filter ( " *.otf;OpenType " ) ;
2016-01-02 18:53:48 +01:00
source - > get_file_dialog ( ) - > add_filter ( " *.fnt;BMFont " ) ;
2017-03-19 00:36:26 +01:00
source - > get_line_edit ( ) - > connect ( " text_entered " , this , " _src_changed " ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
vbl - > add_margin_child ( TTR ( " Source Font: " ) , source ) ;
font_size = memnew ( SpinBox ) ;
vbl - > add_margin_child ( TTR ( " Source Font Size: " ) , font_size ) ;
2014-02-10 02:10:30 +01:00
font_size - > set_min ( 3 ) ;
font_size - > set_max ( 256 ) ;
font_size - > set_val ( 16 ) ;
2017-03-19 00:36:26 +01:00
font_size - > connect ( " value_changed " , this , " _font_size_changed " ) ;
dest = memnew ( EditorLineEditFileChooser ) ;
2014-02-10 02:10:30 +01:00
//
List < String > fl ;
2017-03-19 00:36:26 +01:00
Ref < BitmapFont > font = memnew ( BitmapFont ) ;
dest - > get_file_dialog ( ) - > add_filter ( " *.fnt ; Font " ) ;
2014-02-10 02:10:30 +01:00
//ResourceSaver::get_recognized_extensions(font,&fl);
//for(List<String>::Element *E=fl.front();E;E=E->next()) {
// dest->get_file_dialog()->add_filter("*."+E->get());
//}
2017-03-19 00:36:26 +01:00
vbl - > add_margin_child ( TTR ( " Dest Resource: " ) , dest ) ;
HBoxContainer * testhb = memnew ( HBoxContainer ) ;
test_string = memnew ( LineEdit ) ;
2016-05-04 03:25:37 +02:00
test_string - > set_text ( TTR ( " The quick brown fox jumps over the lazy dog. " ) ) ;
2014-02-10 02:10:30 +01:00
test_string - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2016-06-08 00:01:32 +02:00
test_string - > set_stretch_ratio ( 5 ) ;
2014-02-10 02:10:30 +01:00
testhb - > add_child ( test_string ) ;
2017-03-19 00:36:26 +01:00
test_color = memnew ( ColorPickerButton ) ;
test_color - > set_color ( get_color ( " font_color " , " Label " ) ) ;
2016-06-08 00:01:32 +02:00
test_color - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
test_color - > set_stretch_ratio ( 1 ) ;
2017-03-19 00:36:26 +01:00
test_color - > connect ( " color_changed " , this , " _update_text3 " ) ;
2014-02-10 02:10:30 +01:00
testhb - > add_child ( test_color ) ;
vbl - > add_spacer ( ) ;
2017-03-19 00:36:26 +01:00
vbl - > add_margin_child ( TTR ( " Test: " ) + " " , testhb ) ;
2015-04-21 00:38:02 +02:00
/*
2014-02-10 02:10:30 +01:00
HBoxContainer * upd_hb = memnew ( HBoxContainer ) ;
// vbl->add_child(upd_hb);
upd_hb - > add_spacer ( ) ;
Button * update = memnew ( Button ) ;
upd_hb - > add_child ( update ) ;
2016-05-21 01:18:35 +02:00
update - > set_text ( " Update " ) ;
2014-02-10 02:10:30 +01:00
update - > connect ( " pressed " , this , " _update " ) ;
2015-04-21 00:38:02 +02:00
*/
2017-03-19 00:36:26 +01:00
options = memnew ( _EditorFontImportOptions ) ;
prop_edit = memnew ( PropertyEditor ( ) ) ;
vbr - > add_margin_child ( TTR ( " Options: " ) , prop_edit , true ) ;
options - > connect ( " changed " , this , " _prop_changed " ) ;
2014-02-10 02:10:30 +01:00
prop_edit - > hide_top_label ( ) ;
2017-03-19 00:36:26 +01:00
Panel * panel = memnew ( Panel ) ;
2014-02-10 02:10:30 +01:00
vbc - > add_child ( panel ) ;
2017-03-19 00:36:26 +01:00
test_label = memnew ( Label ) ;
2014-02-10 02:10:30 +01:00
test_label - > set_autowrap ( true ) ;
panel - > add_child ( test_label ) ;
test_label - > set_area_as_parent_rect ( ) ;
panel - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-19 00:36:26 +01:00
test_string - > connect ( " text_changed " , this , " _update_text2 " ) ;
2016-05-04 03:25:37 +02:00
set_title ( TTR ( " Font Import " ) ) ;
2017-03-19 00:36:26 +01:00
timer = memnew ( Timer ) ;
2014-02-10 02:10:30 +01:00
add_child ( timer ) ;
2017-03-19 00:36:26 +01:00
timer - > connect ( " timeout " , this , " _update " ) ;
2014-02-10 02:10:30 +01:00
timer - > set_wait_time ( 0.4 ) ;
timer - > set_one_shot ( true ) ;
2017-03-19 00:36:26 +01:00
get_ok ( ) - > connect ( " pressed " , this , " _import " ) ;
2016-05-04 03:25:37 +02:00
get_ok ( ) - > set_text ( TTR ( " Import " ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
error_dialog = memnew ( ConfirmationDialog ) ;
2014-02-10 02:10:30 +01:00
add_child ( error_dialog ) ;
2016-05-04 03:25:37 +02:00
error_dialog - > get_ok ( ) - > set_text ( TTR ( " Accept " ) ) ;
2014-02-10 02:10:30 +01:00
set_hide_on_ok ( false ) ;
}
~ EditorFontImportDialog ( ) {
memdelete ( options ) ;
}
} ;
///////////////////////////////////////
struct _EditorFontData {
Vector < uint8_t > bitmap ;
2017-03-19 00:36:26 +01:00
int width , height ;
2014-02-10 02:10:30 +01:00
int ofs_x ; //ofset to center, from ABOVE
int ofs_y ; //ofset to begining, from LEFT
int valign ; //vertical alignment
int halign ;
float advance ;
int character ;
int glyph ;
int texture ;
Image blit ;
Point2i blit_ofs ;
2017-03-19 00:36:26 +01:00
// bool printable;
2014-02-10 02:10:30 +01:00
} ;
struct _EditorFontDataSort {
2017-03-19 00:36:26 +01:00
bool operator ( ) ( const _EditorFontData * p_A , const _EditorFontData * p_B ) const {
2014-02-10 02:10:30 +01:00
return p_A - > height > p_B - > height ;
} ;
} ;
struct _EditorKerningKey {
2017-03-19 00:36:26 +01:00
CharType A , B ;
bool operator < ( const _EditorKerningKey & p_k ) const { return ( A = = p_k . A ) ? ( B < p_k . B ) : ( A < p_k . A ) ; }
2014-02-10 02:10:30 +01:00
} ;
2015-03-20 04:26:01 +01:00
static unsigned char get_SDF_radial (
unsigned char * fontmap ,
int w , int h ,
int x , int y ,
2017-03-19 00:36:26 +01:00
int max_radius ) {
2015-03-20 04:26:01 +01:00
// hideous brute force method
2017-03-19 00:36:26 +01:00
float d2 = max_radius * max_radius + 1.0 ;
unsigned char v = fontmap [ x + y * w ] ;
for ( int radius = 1 ; ( radius < = max_radius ) & & ( radius * radius < d2 ) ; + + radius ) {
2015-03-20 04:26:01 +01:00
int line , lo , hi ;
// north
line = y - radius ;
2017-03-19 00:36:26 +01:00
if ( ( line > = 0 ) & & ( line < h ) ) {
2015-03-20 04:26:01 +01:00
lo = x - radius ;
hi = x + radius ;
2017-03-19 00:36:26 +01:00
if ( lo < 0 ) {
lo = 0 ;
}
if ( hi > = w ) {
hi = w - 1 ;
}
2015-03-20 04:26:01 +01:00
int idx = line * w + lo ;
2017-03-19 00:36:26 +01:00
for ( int i = lo ; i < = hi ; + + i ) {
2015-03-20 04:26:01 +01:00
// check this pixel
2017-03-19 00:36:26 +01:00
if ( fontmap [ idx ] ! = v ) {
2015-03-20 04:26:01 +01:00
float nx = i - x ;
float ny = line - y ;
2017-03-19 00:36:26 +01:00
float nd2 = nx * nx + ny * ny ;
if ( nd2 < d2 ) {
2015-03-20 04:26:01 +01:00
d2 = nd2 ;
}
}
// move on
+ + idx ;
}
}
// south
line = y + radius ;
2017-03-19 00:36:26 +01:00
if ( ( line > = 0 ) & & ( line < h ) ) {
2015-03-20 04:26:01 +01:00
lo = x - radius ;
hi = x + radius ;
2017-03-19 00:36:26 +01:00
if ( lo < 0 ) {
lo = 0 ;
}
if ( hi > = w ) {
hi = w - 1 ;
}
2015-03-20 04:26:01 +01:00
int idx = line * w + lo ;
2017-03-19 00:36:26 +01:00
for ( int i = lo ; i < = hi ; + + i ) {
2015-03-20 04:26:01 +01:00
// check this pixel
2017-03-19 00:36:26 +01:00
if ( fontmap [ idx ] ! = v ) {
2015-03-20 04:26:01 +01:00
float nx = i - x ;
float ny = line - y ;
2017-03-19 00:36:26 +01:00
float nd2 = nx * nx + ny * ny ;
if ( nd2 < d2 ) {
2015-03-20 04:26:01 +01:00
d2 = nd2 ;
}
}
// move on
+ + idx ;
}
}
// west
line = x - radius ;
2017-03-19 00:36:26 +01:00
if ( ( line > = 0 ) & & ( line < w ) ) {
2015-03-20 04:26:01 +01:00
lo = y - radius + 1 ;
hi = y + radius - 1 ;
2017-03-19 00:36:26 +01:00
if ( lo < 0 ) {
lo = 0 ;
}
if ( hi > = h ) {
hi = h - 1 ;
}
2015-03-20 04:26:01 +01:00
int idx = lo * w + line ;
2017-03-19 00:36:26 +01:00
for ( int i = lo ; i < = hi ; + + i ) {
2015-03-20 04:26:01 +01:00
// check this pixel
2017-03-19 00:36:26 +01:00
if ( fontmap [ idx ] ! = v ) {
2015-03-20 04:26:01 +01:00
float nx = line - x ;
float ny = i - y ;
2017-03-19 00:36:26 +01:00
float nd2 = nx * nx + ny * ny ;
if ( nd2 < d2 ) {
2015-03-20 04:26:01 +01:00
d2 = nd2 ;
}
}
// move on
idx + = w ;
}
}
// east
line = x + radius ;
2017-03-19 00:36:26 +01:00
if ( ( line > = 0 ) & & ( line < w ) ) {
2015-03-20 04:26:01 +01:00
lo = y - radius + 1 ;
hi = y + radius - 1 ;
2017-03-19 00:36:26 +01:00
if ( lo < 0 ) {
lo = 0 ;
}
if ( hi > = h ) {
hi = h - 1 ;
}
2015-03-20 04:26:01 +01:00
int idx = lo * w + line ;
2017-03-19 00:36:26 +01:00
for ( int i = lo ; i < = hi ; + + i ) {
2015-03-20 04:26:01 +01:00
// check this pixel
2017-03-19 00:36:26 +01:00
if ( fontmap [ idx ] ! = v ) {
2015-03-20 04:26:01 +01:00
float nx = line - x ;
float ny = i - y ;
2017-03-19 00:36:26 +01:00
float nd2 = nx * nx + ny * ny ;
if ( nd2 < d2 ) {
2015-03-20 04:26:01 +01:00
d2 = nd2 ;
}
}
// move on
idx + = w ;
}
}
}
2017-03-19 00:36:26 +01:00
d2 = sqrtf ( d2 ) ;
if ( v = = 0 ) {
2015-03-20 04:26:01 +01:00
d2 = - d2 ;
}
d2 * = 127.5 / max_radius ;
d2 + = 127.5 ;
2017-03-19 00:36:26 +01:00
if ( d2 < 0.0 ) d2 = 0.0 ;
if ( d2 > 255.0 ) d2 = 255.0 ;
2015-03-20 04:26:01 +01:00
return ( unsigned char ) ( d2 + 0.5 ) ;
}
2017-03-19 00:36:26 +01:00
Ref < BitmapFont > EditorFontImportPlugin : : generate_font ( const Ref < ResourceImportMetadata > & p_from , const String & p_existing ) {
2016-01-02 18:53:48 +01:00
2014-02-10 02:10:30 +01:00
Ref < ResourceImportMetadata > from = p_from ;
2017-03-19 00:36:26 +01:00
ERR_FAIL_COND_V ( from - > get_source_count ( ) ! = 1 , Ref < BitmapFont > ( ) ) ;
2014-02-10 02:10:30 +01:00
String src_path = EditorImportPlugin : : expand_source_path ( from - > get_source_path ( 0 ) ) ;
2016-01-02 18:53:48 +01:00
2017-03-19 00:36:26 +01:00
if ( src_path . extension ( ) . to_lower ( ) = = " fnt " ) {
2016-01-02 18:53:48 +01:00
if ( ResourceLoader : : load ( src_path ) . is_valid ( ) ) {
2017-03-19 00:36:26 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Path: " ) + " " + src_path + " \n " + TTR ( " This file is already a Godot font file, please supply a BMFont type file instead. " ) ) ;
2016-04-29 03:21:18 +02:00
return Ref < BitmapFont > ( ) ;
2016-01-02 18:53:48 +01:00
}
2016-04-29 03:21:18 +02:00
Ref < BitmapFont > font ;
2016-01-02 18:53:48 +01:00
font . instance ( ) ;
Error err = font - > create_from_fnt ( src_path ) ;
if ( err ) {
2017-03-19 00:36:26 +01:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Path: " ) + " " + src_path + " \n " + TTR ( " Failed opening as BMFont file. " ) ) ;
2016-04-29 03:21:18 +02:00
return Ref < BitmapFont > ( ) ;
2016-01-02 18:53:48 +01:00
}
return font ;
}
2014-02-10 02:10:30 +01:00
int size = from - > get_option ( " font/size " ) ;
# ifdef FREETYPE_ENABLED
2017-03-19 00:36:26 +01:00
FT_Library library ; /* handle to library */
FT_Face face ; /* handle to face object */
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
Vector < _EditorFontData * > font_data_list ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int error = FT_Init_FreeType ( & library ) ;
2014-02-10 02:10:30 +01:00
2016-05-04 03:25:37 +02:00
ERR_EXPLAIN ( TTR ( " Error initializing FreeType. " ) ) ;
2017-03-19 00:36:26 +01:00
ERR_FAIL_COND_V ( error ! = 0 , Ref < BitmapFont > ( ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
print_line ( " loadfrom: " + src_path ) ;
error = FT_New_Face ( library , src_path . utf8 ( ) . get_data ( ) , 0 , & face ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( error = = FT_Err_Unknown_File_Format ) {
2016-05-04 03:25:37 +02:00
ERR_EXPLAIN ( TTR ( " Unknown font format. " ) ) ;
2017-03-19 00:36:26 +01:00
FT_Done_FreeType ( library ) ;
} else if ( error ) {
2014-02-10 02:10:30 +01:00
2016-05-04 03:25:37 +02:00
ERR_EXPLAIN ( TTR ( " Error loading font. " ) ) ;
2017-03-19 00:36:26 +01:00
FT_Done_FreeType ( library ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
ERR_FAIL_COND_V ( error , Ref < BitmapFont > ( ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int height = 0 ;
int ascent = 0 ;
int font_spacing = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
error = FT_Set_Char_Size ( face , 0 , 64 * size , 512 , 512 ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( error ) {
FT_Done_FreeType ( library ) ;
2016-05-19 00:08:12 +02:00
ERR_EXPLAIN ( TTR ( " Invalid font size. " ) ) ;
2017-03-19 00:36:26 +01:00
ERR_FAIL_COND_V ( error , Ref < BitmapFont > ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2015-03-20 04:26:01 +01:00
int font_mode = from - > get_option ( " mode/mode " ) ;
2017-03-19 00:36:26 +01:00
int scaler = ( font_mode = = _EditorFontImportOptions : : FONT_DISTANCE_FIELD ) ? 16 : 1 ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
error = FT_Set_Pixel_Sizes ( face , 0 , size * scaler ) ;
2014-02-10 02:10:30 +01:00
FT_GlyphSlot slot = face - > glyph ;
2017-03-19 00:36:26 +01:00
// error = FT_Set_Charmap(face,ft_encoding_unicode ); /* encoding.. */
2014-02-10 02:10:30 +01:00
/* PRINT CHARACTERS TO INDIVIDUAL BITMAPS */
2017-03-19 00:36:26 +01:00
// int space_size=5; //size for space, if none found.. 5!
// int min_valign=500; //some ridiculous number
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
FT_ULong charcode ;
FT_UInt gindex ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int max_up = - 1324345 ; ///gibberish
int max_down = 124232 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
Map < _EditorKerningKey , int > kerning_map ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
charcode = FT_Get_First_Char ( face , & gindex ) ;
2014-02-10 02:10:30 +01:00
Set < CharType > import_chars ;
int import_mode = from - > get_option ( " character_set/mode " ) ;
bool round_advance = from - > get_option ( " advanced/round_advance " ) ;
2017-03-19 00:36:26 +01:00
if ( import_mode > = _EditorFontImportOptions : : CHARSET_CUSTOM ) {
2014-02-10 02:10:30 +01:00
//load from custom text
String path = from - > get_option ( " character_set/custom " ) ;
2017-03-19 00:36:26 +01:00
FileAccess * fa = FileAccess : : open ( EditorImportPlugin : : expand_source_path ( path ) , FileAccess : : READ ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( ! fa ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
FT_Done_FreeType ( library ) ;
2016-05-19 00:08:12 +02:00
ERR_EXPLAIN ( TTR ( " Invalid font custom source. " ) ) ;
2017-03-19 00:36:26 +01:00
ERR_FAIL_COND_V ( ! fa , Ref < BitmapFont > ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
while ( ! fa - > eof_reached ( ) ) {
2014-02-10 02:10:30 +01:00
String line = fa - > get_line ( ) ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < line . length ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
import_chars . insert ( line [ i ] ) ;
}
}
2017-03-19 00:36:26 +01:00
if ( import_mode = = _EditorFontImportOptions : : CHARSET_CUSTOM_LATIN ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int i = 32 ; i < 128 ; i + + )
2014-02-10 02:10:30 +01:00
import_chars . insert ( i ) ;
}
memdelete ( fa ) ;
}
2017-03-19 00:36:26 +01:00
int xsize = 0 ;
while ( gindex ! = 0 ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
bool skip = false ;
error = FT_Load_Char ( face , charcode , font_mode = = _EditorFontImportOptions : : FONT_BITMAP ? FT_LOAD_RENDER : FT_LOAD_MONOCHROME ) ;
if ( error )
skip = true ;
else
error = FT_Render_Glyph ( face - > glyph , font_mode = = _EditorFontImportOptions : : FONT_BITMAP ? ft_render_mode_normal : ft_render_mode_mono ) ;
2014-02-10 02:10:30 +01:00
if ( error ) {
2017-03-19 00:36:26 +01:00
skip = true ;
2014-02-10 02:10:30 +01:00
} else if ( ! skip ) {
2017-03-19 00:36:26 +01:00
switch ( import_mode ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
case _EditorFontImportOptions : : CHARSET_ASCII : skip = charcode > 127 ; break ;
case _EditorFontImportOptions : : CHARSET_LATIN : skip = charcode > 255 ; break ;
case _EditorFontImportOptions : : CHARSET_UNICODE :
break ; //none
2014-02-10 02:10:30 +01:00
case _EditorFontImportOptions : : CHARSET_CUSTOM :
case _EditorFontImportOptions : : CHARSET_CUSTOM_LATIN : skip = ! import_chars . has ( charcode ) ; break ;
}
}
2017-03-19 00:36:26 +01:00
if ( charcode < = 32 ) //??
skip = true ;
2014-02-10 02:10:30 +01:00
if ( skip ) {
2017-03-19 00:36:26 +01:00
charcode = FT_Get_Next_Char ( face , charcode , & gindex ) ;
2014-02-10 02:10:30 +01:00
continue ;
}
2017-03-19 00:36:26 +01:00
_EditorFontData * fdata = memnew ( _EditorFontData ) ;
2014-02-10 02:10:30 +01:00
2015-03-20 04:26:01 +01:00
int w = slot - > bitmap . width ;
int h = slot - > bitmap . rows ;
int p = slot - > bitmap . pitch ;
2015-03-21 04:43:33 +01:00
2015-05-04 20:06:41 +02:00
//print_line("W: "+itos(w)+" P: "+itos(slot->bitmap.pitch));
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_mode = = _EditorFontImportOptions : : FONT_DISTANCE_FIELD ) {
2014-02-10 02:10:30 +01:00
2015-03-20 04:26:01 +01:00
// oversize the holding buffer so I can smooth it!
int sw = w + scaler * 4 ;
int sh = h + scaler * 4 ;
// do the SDF
int sdfw = sw / scaler ;
int sdfh = sh / scaler ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
fdata - > width = sdfw ;
fdata - > height = sdfh ;
2015-03-20 04:26:01 +01:00
} else {
2017-03-19 00:36:26 +01:00
fdata - > width = w ;
fdata - > height = h ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
fdata - > character = charcode ;
fdata - > glyph = FT_Get_Char_Index ( face , charcode ) ;
if ( charcode = = ' x ' )
xsize = w / scaler ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
fdata - > valign = slot - > bitmap_top ;
fdata - > halign = slot - > bitmap_left ;
2014-02-10 02:10:30 +01:00
if ( round_advance )
2017-03-19 00:36:26 +01:00
fdata - > advance = ( slot - > advance . x + ( 1 < < 5 ) ) > > 6 ;
2014-02-10 02:10:30 +01:00
else
2017-03-19 00:36:26 +01:00
fdata - > advance = slot - > advance . x / float ( 1 < < 6 ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_mode = = _EditorFontImportOptions : : FONT_DISTANCE_FIELD ) {
2015-03-20 04:26:01 +01:00
fdata - > halign = fdata - > halign / scaler - 1.5 ;
fdata - > valign = fdata - > valign / scaler + 1.5 ;
2017-03-19 00:36:26 +01:00
fdata - > advance / = scaler ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
fdata - > advance + = font_spacing ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( charcode < 127 ) {
2015-03-20 04:26:01 +01:00
int top = fdata - > valign ;
2017-03-19 00:36:26 +01:00
int hmax = h / scaler ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
if ( top > max_up ) {
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
max_up = top ;
2015-03-20 04:26:01 +01:00
}
2017-03-19 00:36:26 +01:00
if ( ( top - hmax ) < max_down ) {
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
max_down = top - hmax ;
2015-03-20 04:26:01 +01:00
}
}
2017-03-19 00:36:26 +01:00
if ( font_mode = = _EditorFontImportOptions : : FONT_DISTANCE_FIELD ) {
2015-03-20 04:26:01 +01:00
// oversize the holding buffer so I can smooth it!
int sw = w + scaler * 4 ;
int sh = h + scaler * 4 ;
2017-03-19 00:36:26 +01:00
unsigned char * smooth_buf = new unsigned char [ sw * sh ] ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < sw * sh ; + + i ) {
2015-03-20 04:26:01 +01:00
smooth_buf [ i ] = 0 ;
}
// copy the glyph into the buffer to be smoothed
unsigned char * buf = slot - > bitmap . buffer ;
2017-03-19 00:36:26 +01:00
for ( int j = 0 ; j < h ; + + j ) {
for ( int i = 0 ; i < w ; + + i ) {
smooth_buf [ scaler * 2 + i + ( j + scaler * 2 ) * sw ] = 255 * ( ( buf [ j * p + ( i > > 3 ) ] > > ( 7 - ( i & 7 ) ) ) & 1 ) ;
2015-03-20 04:26:01 +01:00
}
}
// do the SDF
int sdfw = fdata - > width ;
int sdfh = fdata - > height ;
2017-03-19 00:36:26 +01:00
fdata - > bitmap . resize ( sdfw * sdfh ) ;
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
for ( int j = 0 ; j < sdfh ; + + j ) {
for ( int i = 0 ; i < sdfw ; + + i ) {
int pd_idx = j * sdfw + i ;
2015-03-20 04:26:01 +01:00
//fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
fdata - > bitmap [ pd_idx ] =
//get_SDF
2017-03-19 00:36:26 +01:00
get_SDF_radial ( smooth_buf , sw , sh ,
i * scaler + ( scaler > > 1 ) , j * scaler + ( scaler > > 1 ) ,
2 * scaler ) ;
2015-03-20 04:26:01 +01:00
}
}
2017-03-19 00:36:26 +01:00
delete [ ] smooth_buf ;
2015-03-20 04:26:01 +01:00
} else {
2017-03-19 00:36:26 +01:00
fdata - > bitmap . resize ( slot - > bitmap . width * slot - > bitmap . rows ) ;
for ( int i = 0 ; i < slot - > bitmap . width ; i + + ) {
for ( int j = 0 ; j < slot - > bitmap . rows ; j + + ) {
2015-03-20 04:26:01 +01:00
2017-03-19 00:36:26 +01:00
fdata - > bitmap [ j * slot - > bitmap . width + i ] = slot - > bitmap . buffer [ j * slot - > bitmap . width + i ] ;
2015-03-20 04:26:01 +01:00
}
2014-02-10 02:10:30 +01:00
}
}
font_data_list . push_back ( fdata ) ;
2017-03-19 00:36:26 +01:00
charcode = FT_Get_Next_Char ( face , charcode , & gindex ) ;
// printf("reading char %i\n",charcode);
2014-02-10 02:10:30 +01:00
}
/* SPACE */
2017-03-19 00:36:26 +01:00
_EditorFontData * spd = memnew ( _EditorFontData ) ;
spd - > advance = 0 ;
spd - > character = ' ' ;
spd - > halign = 0 ;
spd - > valign = 0 ;
spd - > width = 0 ;
spd - > height = 0 ;
spd - > ofs_x = 0 ;
spd - > ofs_y = 0 ;
if ( ! FT_Load_Char ( face , ' ' , FT_LOAD_RENDER ) & & ! FT_Render_Glyph ( face - > glyph , font_mode = = _EditorFontImportOptions : : FONT_BITMAP ? ft_render_mode_normal : ft_render_mode_mono ) ) {
spd - > advance = slot - > advance . x > > 6 ; //round to nearest or store as float
spd - > advance / = scaler ;
spd - > advance + = font_spacing ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-19 00:36:26 +01:00
spd - > advance = xsize ;
spd - > advance + = font_spacing ;
2014-02-10 02:10:30 +01:00
}
font_data_list . push_back ( spd ) ;
Set < CharType > exported ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < font_data_list . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
exported . insert ( font_data_list [ i ] - > character ) ;
} ;
int missing = 0 ;
2017-03-19 00:36:26 +01:00
for ( Set < CharType > : : Element * E = import_chars . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
CharType c = E - > get ( ) ;
if ( ! exported . has ( c ) ) {
2017-03-19 00:36:26 +01:00
CharType str [ 2 ] = { c , 0 } ;
2014-02-10 02:10:30 +01:00
printf ( " ** Warning: character %i (%ls) not exported \n " , ( int ) c , str ) ;
+ + missing ;
} ;
} ;
2017-03-19 00:36:26 +01:00
print_line ( " total_chars: " + itos ( font_data_list . size ( ) ) ) ;
2014-02-10 02:10:30 +01:00
/* KERNING */
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < font_data_list . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_data_list [ i ] - > character > 512 )
2014-02-25 13:31:47 +01:00
continue ;
2017-03-19 00:36:26 +01:00
for ( int j = 0 ; j < font_data_list . size ( ) ; j + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_data_list [ j ] - > character > 512 )
2014-02-25 13:31:47 +01:00
continue ;
2017-03-19 00:36:26 +01:00
FT_Vector delta ;
FT_Get_Kerning ( face , font_data_list [ i ] - > glyph , font_data_list [ j ] - > glyph , FT_KERNING_DEFAULT , & delta ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( delta . x ! = 0 ) {
2014-02-10 02:10:30 +01:00
_EditorKerningKey kpk ;
kpk . A = font_data_list [ i ] - > character ;
kpk . B = font_data_list [ j ] - > character ;
2017-03-19 00:36:26 +01:00
int kern = ( ( - delta . x ) + ( 1 < < 5 ) ) > > 6 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( kern = = 0 )
2014-02-10 02:10:30 +01:00
continue ;
2017-03-19 00:36:26 +01:00
kerning_map [ kpk ] = kern / scaler ;
2014-02-10 02:10:30 +01:00
}
}
}
2017-03-19 00:36:26 +01:00
height = max_up - max_down ;
ascent = max_up ;
2014-02-10 02:10:30 +01:00
/* FIND OUT WHAT THE FONT HEIGHT FOR THIS IS */
/* ADJUST THE VALIGN FOR EACH CHARACTER */
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < ( int ) font_data_list . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
font_data_list [ i ] - > valign = max_up - font_data_list [ i ] - > valign ;
2014-02-10 02:10:30 +01:00
}
/* ADD THE SPACEBAR CHARACTER */
2017-03-19 00:36:26 +01:00
/*
2014-02-10 02:10:30 +01:00
_EditorFontData * fdata = new _EditorFontData ;
fdata - > character = 32 ;
fdata - > bitmap = 0 ;
fdata - > width = xsize ;
fdata - > height = 1 ;
fdata - > valign = 0 ;
font_data_list . push_back ( fdata ) ;
*/
/* SORT BY HEIGHT, SO THEY FIT BETTER ON THE TEXTURE */
font_data_list . sort_custom < _EditorFontDataSort > ( ) ;
2017-03-19 00:36:26 +01:00
Color * color = memnew_arr ( Color , height ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int gradient_type = from - > get_option ( " color/mode " ) ;
switch ( gradient_type ) {
2014-02-10 02:10:30 +01:00
case _EditorFontImportOptions : : COLOR_WHITE : {
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < height ; i + + ) {
color [ i ] = Color ( 1 , 1 , 1 , 1 ) ;
2014-02-10 02:10:30 +01:00
}
} break ;
case _EditorFontImportOptions : : COLOR_CUSTOM : {
Color cc = from - > get_option ( " color/color " ) ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < height ; i + + ) {
color [ i ] = cc ;
2014-02-10 02:10:30 +01:00
}
} break ;
case _EditorFontImportOptions : : COLOR_GRADIENT_RANGE : {
2017-03-19 00:36:26 +01:00
Color src = from - > get_option ( " color/begin " ) ;
Color to = from - > get_option ( " color/end " ) ;
for ( int i = 0 ; i < height ; i + + ) {
color [ i ] = src . linear_interpolate ( to , i / float ( height ) ) ;
2014-02-10 02:10:30 +01:00
}
} break ;
case _EditorFontImportOptions : : COLOR_GRADIENT_IMAGE : {
String fp = EditorImportPlugin : : expand_source_path ( from - > get_option ( " color/image " ) ) ;
Image img ;
2017-03-19 00:36:26 +01:00
Error err = ImageLoader : : load_image ( fp , & img ) ;
if ( err = = OK ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < height ; i + + ) {
color [ i ] = img . get_pixel ( 0 , i * img . get_height ( ) / height ) ;
2014-02-10 02:10:30 +01:00
}
} else {
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < height ; i + + ) {
color [ i ] = Color ( 1 , 1 , 1 , 1 ) ;
2014-02-10 02:10:30 +01:00
}
}
} break ;
}
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < font_data_list . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_data_list [ i ] - > bitmap . size ( ) = = 0 )
2014-02-10 02:10:30 +01:00
continue ;
2017-03-19 00:36:26 +01:00
int margin [ 4 ] = { 0 , 0 , 0 , 0 } ;
2014-02-10 02:10:30 +01:00
if ( from - > get_option ( " shadow/enabled " ) . operator bool ( ) ) {
2017-03-19 00:36:26 +01:00
int r = from - > get_option ( " shadow/radius " ) ;
Point2i ofs = Point2 ( from - > get_option ( " shadow/offset " ) ) ;
margin [ MARGIN_LEFT ] = MAX ( r - ofs . x , 0 ) ;
margin [ MARGIN_RIGHT ] = MAX ( r + ofs . x , 0 ) ;
margin [ MARGIN_TOP ] = MAX ( r - ofs . y , 0 ) ;
margin [ MARGIN_BOTTOM ] = MAX ( r + ofs . y , 0 ) ;
2014-02-10 02:10:30 +01:00
}
if ( from - > get_option ( " shadow2/enabled " ) . operator bool ( ) ) {
2017-03-19 00:36:26 +01:00
int r = from - > get_option ( " shadow2/radius " ) ;
Point2i ofs = Point2 ( from - > get_option ( " shadow2/offset " ) ) ;
margin [ MARGIN_LEFT ] = MAX ( r - ofs . x , margin [ MARGIN_LEFT ] ) ;
margin [ MARGIN_RIGHT ] = MAX ( r + ofs . x , margin [ MARGIN_RIGHT ] ) ;
margin [ MARGIN_TOP ] = MAX ( r - ofs . y , margin [ MARGIN_TOP ] ) ;
margin [ MARGIN_BOTTOM ] = MAX ( r + ofs . y , margin [ MARGIN_BOTTOM ] ) ;
2014-02-10 02:10:30 +01:00
}
Size2i s ;
2017-03-19 00:36:26 +01:00
s . width = font_data_list [ i ] - > width + margin [ MARGIN_LEFT ] + margin [ MARGIN_RIGHT ] ;
s . height = font_data_list [ i ] - > height + margin [ MARGIN_TOP ] + margin [ MARGIN_BOTTOM ] ;
2014-02-10 02:10:30 +01:00
Point2i o ;
2017-03-19 00:36:26 +01:00
o . x = margin [ MARGIN_LEFT ] ;
o . y = margin [ MARGIN_TOP ] ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int ow = font_data_list [ i ] - > width ;
int oh = font_data_list [ i ] - > height ;
2014-02-10 02:10:30 +01:00
DVector < uint8_t > pixels ;
2017-03-19 00:36:26 +01:00
pixels . resize ( s . x * s . y * 4 ) ;
2014-02-10 02:10:30 +01:00
DVector < uint8_t > : : Write w = pixels . write ( ) ;
2015-03-20 04:26:01 +01:00
//print_line("val: "+itos(font_data_list[i]->valign));
2017-03-19 00:36:26 +01:00
for ( int y = 0 ; y < s . height ; y + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int yc = CLAMP ( y - o . y + font_data_list [ i ] - > valign , 0 , height - 1 ) ;
Color c = color [ yc ] ;
c . a = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int x = 0 ; x < s . width ; x + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int ofs = y * s . x + x ;
w [ ofs * 4 + 0 ] = c . r * 255.0 ;
w [ ofs * 4 + 1 ] = c . g * 255.0 ;
w [ ofs * 4 + 2 ] = c . b * 255.0 ;
w [ ofs * 4 + 3 ] = c . a * 255.0 ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-19 00:36:26 +01:00
for ( int si = 0 ; si < 2 ; si + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
# define S_VAR(m_v) (String(si == 0 ? "shadow / " : "shadow2 / ") + m_v)
2014-02-10 02:10:30 +01:00
if ( from - > get_option ( S_VAR ( " enabled " ) ) . operator bool ( ) ) {
int r = from - > get_option ( S_VAR ( " radius " ) ) ;
Color sc = from - > get_option ( S_VAR ( " color " ) ) ;
2017-03-19 00:36:26 +01:00
Point2i so = Point2 ( from - > get_option ( S_VAR ( " offset " ) ) ) ;
2014-02-10 02:10:30 +01:00
float tr = from - > get_option ( S_VAR ( " transition " ) ) ;
2017-03-19 00:36:26 +01:00
print_line ( " shadow enabled: " + itos ( si ) ) ;
2014-02-10 02:10:30 +01:00
Vector < uint8_t > s2buf ;
2017-03-19 00:36:26 +01:00
s2buf . resize ( s . x * s . y ) ;
uint8_t * wa = s2buf . ptr ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int j = 0 ; j < s . x * s . y ; j + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
wa [ j ] = 0 ;
2014-02-10 02:10:30 +01:00
}
// blit shadowa
2017-03-19 00:36:26 +01:00
for ( int x = 0 ; x < ow ; x + + ) {
for ( int y = 0 ; y < oh ; y + + ) {
int ofs = ( o . y + y + so . y ) * s . x + x + o . x + so . x ;
wa [ ofs ] = font_data_list [ i ] - > bitmap [ y * ow + x ] ;
2014-02-10 02:10:30 +01:00
}
}
//blur shadow2 with separatable convolution
2017-03-19 00:36:26 +01:00
if ( r > 0 ) {
2014-02-10 02:10:30 +01:00
Vector < uint8_t > pixels2 ;
pixels2 . resize ( s2buf . size ( ) ) ;
2017-03-19 00:36:26 +01:00
uint8_t * w2 = pixels2 . ptr ( ) ;
2014-02-10 02:10:30 +01:00
//vert
2017-03-19 00:36:26 +01:00
for ( int x = 0 ; x < s . width ; x + + ) {
for ( int y = 0 ; y < s . height ; y + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int ofs = y * s . width + x ;
int sum = wa [ ofs ] ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int k = 1 ; k < = r ; k + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int ofs_d = MIN ( y + k , s . height - 1 ) * s . width + x ;
int ofs_u = MAX ( y - k , 0 ) * s . width + x ;
sum + = wa [ ofs_d ] ;
sum + = wa [ ofs_u ] ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
w2 [ ofs ] = sum / ( r * 2 + 1 ) ;
2014-02-10 02:10:30 +01:00
}
}
//horiz
2017-03-19 00:36:26 +01:00
for ( int x = 0 ; x < s . width ; x + + ) {
for ( int y = 0 ; y < s . height ; y + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int ofs = y * s . width + x ;
int sum = w2 [ ofs ] ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int k = 1 ; k < = r ; k + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
int ofs_r = MIN ( x + k , s . width - 1 ) + s . width * y ;
int ofs_l = MAX ( x - k , 0 ) + s . width * y ;
sum + = w2 [ ofs_r ] ;
sum + = w2 [ ofs_l ] ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
wa [ ofs ] = Math : : pow ( float ( sum / ( r * 2 + 1 ) ) / 255.0 , tr ) * 255.0 ;
2014-02-10 02:10:30 +01:00
}
}
}
//blend back
2017-03-19 00:36:26 +01:00
for ( int j = 0 ; j < s . x * s . y ; j + + ) {
Color wd ( w [ j * 4 + 0 ] / 255.0 , w [ j * 4 + 1 ] / 255.0 , w [ j * 4 + 2 ] / 255.0 , w [ j * 4 + 3 ] / 255.0 ) ;
Color ws ( sc . r , sc . g , sc . b , sc . a * ( wa [ j ] / 255.0 ) ) ;
2014-02-10 02:10:30 +01:00
Color b = wd . blend ( ws ) ;
2017-03-19 00:36:26 +01:00
w [ j * 4 + 0 ] = b . r * 255.0 ;
w [ j * 4 + 1 ] = b . g * 255.0 ;
w [ j * 4 + 2 ] = b . b * 255.0 ;
w [ j * 4 + 3 ] = b . a * 255.0 ;
2014-02-10 02:10:30 +01:00
}
}
}
2017-03-19 00:36:26 +01:00
for ( int y = 0 ; y < oh ; y + + ) {
int yc = CLAMP ( y + font_data_list [ i ] - > valign , 0 , height - 1 ) ;
Color sc = color [ yc ] ;
for ( int x = 0 ; x < ow ; x + + ) {
int ofs = ( o . y + y ) * s . x + x + o . x ;
float c = font_data_list [ i ] - > bitmap [ y * ow + x ] / 255.0 ;
Color src_col = sc ;
src_col . a * = c ;
Color dst_col ( w [ ofs * 4 + 0 ] / 255.0 , w [ ofs * 4 + 1 ] / 255.0 , w [ ofs * 4 + 2 ] / 255.0 , w [ ofs * 4 + 3 ] / 255.0 ) ;
2014-02-10 02:10:30 +01:00
dst_col = dst_col . blend ( src_col ) ;
2017-03-19 00:36:26 +01:00
w [ ofs * 4 + 0 ] = dst_col . r * 255.0 ;
w [ ofs * 4 + 1 ] = dst_col . g * 255.0 ;
w [ ofs * 4 + 2 ] = dst_col . b * 255.0 ;
w [ ofs * 4 + 3 ] = dst_col . a * 255.0 ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-19 00:36:26 +01:00
w = DVector < uint8_t > : : Write ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
Image img ( s . width , s . height , 0 , Image : : FORMAT_RGBA , pixels ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
font_data_list [ i ] - > blit = img ;
font_data_list [ i ] - > blit_ofs = o ;
2014-02-10 02:10:30 +01:00
}
//make atlas
2017-03-19 00:36:26 +01:00
int spacing = 2 ;
2014-02-10 02:10:30 +01:00
Vector < Size2i > sizes ;
sizes . resize ( font_data_list . size ( ) ) ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < font_data_list . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
sizes [ i ] = Size2 ( font_data_list [ i ] - > blit . get_width ( ) + spacing * 2 , font_data_list [ i ] - > blit . get_height ( ) + spacing * 2 ) ;
2014-02-10 02:10:30 +01:00
}
Vector < Point2i > res ;
Size2i res_size ;
2017-03-19 00:36:26 +01:00
EditorAtlas : : fit ( sizes , res , res_size ) ;
res_size . x = nearest_power_of_2 ( res_size . x ) ;
res_size . y = nearest_power_of_2 ( res_size . y ) ;
print_line ( " Atlas size: " + res_size ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
Image atlas ( res_size . x , res_size . y , 0 , Image : : FORMAT_RGBA ) ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < font_data_list . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( font_data_list [ i ] - > bitmap . size ( ) = = 0 )
2014-02-10 02:10:30 +01:00
continue ;
2017-03-19 00:36:26 +01:00
atlas . blit_rect ( font_data_list [ i ] - > blit , Rect2 ( 0 , 0 , font_data_list [ i ] - > blit . get_width ( ) , font_data_list [ i ] - > blit . get_height ( ) ) , res [ i ] + Size2 ( spacing , spacing ) ) ;
font_data_list [ i ] - > ofs_x = res [ i ] . x + spacing ;
font_data_list [ i ] - > ofs_y = res [ i ] . y + spacing ;
2014-02-10 02:10:30 +01:00
}
2016-06-21 15:41:13 +02:00
if ( from - > has_option ( " advanced/premultiply_alpha " ) & & bool ( from - > get_option ( " advanced/premultiply_alpha " ) ) ) {
DVector < uint8_t > data = atlas . get_data ( ) ;
int dl = data . size ( ) ;
{
DVector < uint8_t > : : Write w = data . write ( ) ;
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < dl ; i + = 4 ) {
2016-06-21 15:41:13 +02:00
2017-03-19 00:36:26 +01:00
w [ i + 0 ] = uint8_t ( int ( w [ i + 0 ] ) * int ( w [ i + 3 ] ) / 255 ) ;
w [ i + 1 ] = uint8_t ( int ( w [ i + 1 ] ) * int ( w [ i + 3 ] ) / 255 ) ;
w [ i + 2 ] = uint8_t ( int ( w [ i + 2 ] ) * int ( w [ i + 3 ] ) / 255 ) ;
2016-06-21 15:41:13 +02:00
}
}
2017-03-19 00:36:26 +01:00
atlas = Image ( res_size . x , res_size . y , 0 , Image : : FORMAT_RGBA , data ) ;
2016-06-21 15:41:13 +02:00
}
2014-03-14 02:57:24 +01:00
if ( from - > has_option ( " color/monochrome " ) & & bool ( from - > get_option ( " color/monochrome " ) ) ) {
atlas . convert ( Image : : FORMAT_GRAYSCALE_ALPHA ) ;
}
2015-03-21 04:43:33 +01:00
if ( 0 ) {
2014-02-10 02:10:30 +01:00
//debug the texture
2017-03-19 00:36:26 +01:00
Ref < ImageTexture > atlast = memnew ( ImageTexture ) ;
2014-02-10 02:10:30 +01:00
atlast - > create_from_image ( atlas ) ;
2017-03-19 00:36:26 +01:00
// atlast->create_from_image(font_data_list[5]->blit);
TextureFrame * tf = memnew ( TextureFrame ) ;
2014-02-10 02:10:30 +01:00
tf - > set_texture ( atlast ) ;
dialog - > add_child ( tf ) ;
}
/* CREATE FONT */
int char_space = from - > get_option ( " extra_space/char " ) ;
int space_space = from - > get_option ( " extra_space/space " ) ;
int top_space = from - > get_option ( " extra_space/top " ) ;
int bottom_space = from - > get_option ( " extra_space/bottom " ) ;
2014-10-03 05:10:51 +02:00
bool disable_filter = from - > get_option ( " advanced/disable_filter " ) ;
2014-02-10 02:10:30 +01:00
2016-04-29 03:21:18 +02:00
Ref < BitmapFont > font ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
if ( p_existing ! = String ( ) & & ResourceCache : : has ( p_existing ) ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
font = Ref < BitmapFont > ( ResourceCache : : get ( p_existing ) - > cast_to < BitmapFont > ( ) ) ;
2014-02-10 02:10:30 +01:00
}
if ( font . is_null ( ) ) {
2017-03-19 00:36:26 +01:00
font = Ref < BitmapFont > ( memnew ( BitmapFont ) ) ;
2014-02-10 02:10:30 +01:00
}
font - > clear ( ) ;
2017-03-19 00:36:26 +01:00
font - > set_height ( height + bottom_space + top_space ) ;
font - > set_ascent ( ascent + top_space ) ;
font - > set_distance_field_hint ( font_mode = = _EditorFontImportOptions : : FONT_DISTANCE_FIELD ) ;
2014-02-10 02:10:30 +01:00
//register texures
{
Ref < ImageTexture > t = memnew ( ImageTexture ) ;
2014-10-03 05:10:51 +02:00
int flags ;
if ( disable_filter )
2017-03-19 00:36:26 +01:00
flags = 0 ;
2014-10-03 05:10:51 +02:00
else
2017-03-19 00:36:26 +01:00
flags = Texture : : FLAG_FILTER ;
t - > create_from_image ( atlas , flags ) ;
t - > set_storage ( ImageTexture : : STORAGE_COMPRESS_LOSSLESS ) ;
2014-02-10 02:10:30 +01:00
font - > add_texture ( t ) ;
}
//register characters
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < font_data_list . size ( ) ; i + + ) {
_EditorFontData * fd = font_data_list [ i ] ;
int tex_idx = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
font - > add_char ( fd - > character , tex_idx , Rect2 ( fd - > ofs_x , fd - > ofs_y , fd - > blit . get_width ( ) , fd - > blit . get_height ( ) ) , Point2 ( fd - > halign - fd - > blit_ofs . x , fd - > valign - fd - > blit_ofs . y + top_space ) , fd - > advance + char_space + ( fd - > character = = ' ' ? space_space : 0 ) ) ;
2014-02-10 02:10:30 +01:00
memdelete ( fd ) ;
}
2017-03-19 00:36:26 +01:00
for ( Map < _EditorKerningKey , int > : : Element * E = kerning_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
font - > add_kerning_pair ( E - > key ( ) . A , E - > key ( ) . B , E - > get ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
FT_Done_FreeType ( library ) ;
2014-02-10 02:10:30 +01:00
return font ;
# else
2016-04-29 03:21:18 +02:00
return Ref < BitmapFont > ( ) ;
2014-02-10 02:10:30 +01:00
# endif
}
String EditorFontImportPlugin : : get_name ( ) const {
return " font " ;
}
2017-03-19 00:36:26 +01:00
String EditorFontImportPlugin : : get_visible_name ( ) const {
2014-02-10 02:10:30 +01:00
2016-05-29 10:10:23 +02:00
return TTR ( " Font " ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
void EditorFontImportPlugin : : import_dialog ( const String & p_from ) {
2014-02-10 02:10:30 +01:00
dialog - > popup_import ( p_from ) ;
}
2017-03-19 00:36:26 +01:00
Error EditorFontImportPlugin : : import ( const String & p_path , const Ref < ResourceImportMetadata > & p_from ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
Ref < BitmapFont > font = EditorFontImportPlugin : : generate_font ( p_from , p_path ) ;
2014-02-10 02:10:30 +01:00
if ( ! font . is_valid ( ) )
return ERR_CANT_CREATE ;
2017-03-19 00:36:26 +01:00
Ref < ResourceImportMetadata > from = p_from ;
from - > set_source_md5 ( 0 , FileAccess : : get_md5 ( EditorImportPlugin : : expand_source_path ( from - > get_source_path ( 0 ) ) ) ) ;
2014-02-10 02:10:30 +01:00
from - > set_editor ( get_name ( ) ) ;
font - > set_import_metadata ( from ) ;
2017-03-19 00:36:26 +01:00
return ResourceSaver : : save ( p_path , font ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-19 00:36:26 +01:00
void EditorFontImportPlugin : : import_from_drop ( const Vector < String > & p_drop , const String & p_dest_path ) {
2016-05-27 19:18:40 +02:00
2017-03-19 00:36:26 +01:00
for ( int i = 0 ; i < p_drop . size ( ) ; i + + ) {
2016-05-27 19:18:40 +02:00
String ext = p_drop [ i ] . extension ( ) . to_lower ( ) ;
String file = p_drop [ i ] . get_file ( ) ;
2017-03-19 00:36:26 +01:00
if ( ext = = " ttf " | | ext = = " otf " | | ext = = " fnt " ) {
2016-05-27 19:18:40 +02:00
import_dialog ( ) ;
2017-03-19 00:36:26 +01:00
dialog - > set_source_and_dest ( p_drop [ i ] , p_dest_path . plus_file ( file . basename ( ) + " .fnt " ) ) ;
2016-05-27 19:18:40 +02:00
break ;
}
}
}
2017-03-19 00:36:26 +01:00
EditorFontImportPlugin : : EditorFontImportPlugin ( EditorNode * p_editor ) {
2014-02-10 02:10:30 +01:00
2017-03-19 00:36:26 +01:00
dialog = memnew ( EditorFontImportDialog ( this ) ) ;
2014-02-10 02:10:30 +01:00
p_editor - > get_gui_base ( ) - > add_child ( dialog ) ;
}