From 8cd9258a5f8d12f5997695fb54225dbe9d43012b Mon Sep 17 00:00:00 2001 From: Christian Walde Date: Mon, 17 Dec 2018 23:12:53 +0100 Subject: [PATCH] reduce font modding work when duplicate font sources are used --- font_mod_run.py | 4 +- mod_textures.pl | 4 +- modify_fonts_and_inject.pl | 130 ++++++++++++++++++++++--------------- 3 files changed, 83 insertions(+), 55 deletions(-) diff --git a/font_mod_run.py b/font_mod_run.py index ee3f836..bd72b97 100644 --- a/font_mod_run.py +++ b/font_mod_run.py @@ -11,7 +11,9 @@ pairs = filter(None, list(itertools.chain.from_iterable(pairs))) fontname = sys.argv[1] -M20 = Schrift(fontname, "../fonts/"+fontname+".sfdir", "../fonts/"+fontname+"_mod.sfdir") +font_source = sys.argv[2] +font_target = sys.argv[3] +M20 = Schrift(fontname, font_source, font_target) for pair in pairs: name = "uni%X" % unicode_point_int diff --git a/mod_textures.pl b/mod_textures.pl index 26d8605..d270bbd 100644 --- a/mod_textures.pl +++ b/mod_textures.pl @@ -6,7 +6,9 @@ $|++; run(); -sub _age($) { ( stat $_[0] )[9] || 0 } +sub _age($) { + eval { ( stat $_[0] )[9] } || 0; +} sub run { say "copying and converting images"; diff --git a/modify_fonts_and_inject.pl b/modify_fonts_and_inject.pl index f38643e..92161b1 100644 --- a/modify_fonts_and_inject.pl +++ b/modify_fonts_and_inject.pl @@ -2,81 +2,105 @@ use strictures 2; use IO::All -binary; use Capture::Tiny 'capture'; +use Digest::SHA1 'sha1_hex'; run(); -sub run { - my $ff = "C:/Program Files (x86)/FontForgeBuilds/bin/fontforge.exe"; - my $candidate_dir = "../kc_original_unpack_modded"; - my $t_root = "Media/Unity_Assets_Files"; - my $font_root = "../kc_original_unpack/$t_root"; +sub _clean_and_report { + my ( $out, $err, $res, $target ) = @_; + -d $target ? io($target)->rmtree : io($target)->unlink; + return "error:\nout:\n$out\nerr:\n$err\nres: $res\n"; +} - # ume is used to make texts ingame more narrow - my @fonts = ( - { name => "A-OTF-UDShinGoPro-Regular", target_path => "$t_root/sharedassets3", src => "fonts/ume-pgs4.ttf" }, - { name => "A-OTF-ShinGoPro-Regular", target_path => "$t_root/sharedassets2", src => "$font_root/sharedassets2/A-OTF-ShinGoPro-Regular.ttf" }, - { name => "CenturyGothicStd", target_path => "$t_root/resources", src => "$font_root/resources/CenturyGothicStd.ttf" }, - { name => "A-OTF-ShinGoPro-Regular-For-ScrollList", target_path => "$t_root/sharedassets5", src => "$font_root/sharedassets5/A-OTF-ShinGoPro-Regular-For-ScrollList.ttf" }, - { name => "AxisStd-Regular_1", target_path => "$t_root/sharedassets5", src => "$font_root/sharedassets5/AxisStd-Regular_1.ttf" }, - { name => "A-OTF-RyuminPr5-ExBold", target_path => "$t_root/sharedassets11", src => "$font_root/sharedassets11/A-OTF-RyuminPr5-ExBold.ttf" }, - { name => "Century Gothic", target_path => "$t_root/sharedassets26", src => "$font_root/sharedassets26/Century Gothic.ttf" }, - ); - io("../fonts")->mkdir if !-d "../fonts"; - mod_font( $ff, $candidate_dir, $_->%* ) for @fonts; - say "done with fonts"; +sub prep_font { + my ( $ff, $prepped_path, %font ) = @_; + + say "preparing font from source with empty PUA glyphs and guaranteed space glyph"; + my ( $out, $err, $res ) = capture { system(qq["$ff" -script prepare_new_font.ff "$font{src}" "$prepped_path"]) }; + $err =~ s/^Copyright.*\n(^ .*\n)+//m; + $err =~ s/^The following table.*ignored.*\n(^ .*\n)+//m; + $err =~ s/^Warning:.*\n(^ .*\n)+//mg; + $err =~ s/^This font contains both.*\n(^ .*\n)+//m; + $err =~ s/^.*SEAC-like endchar operator is deprecated for Type2\n//mg; + $err =~ s/^Subtable status not filled in .*\n*//mg; + $err =~ s/^The glyph named .* is mapped to .*\n But its name indicates it should be mapped to .*\n*//mg; # research + $err =~ s/^Bad sfd file. Glyph .* has width .* even though it should be\n bound to the width of .* which is .*\n*//mg; # research + $out =~ s/^log:.*\n//mg; + die _clean_and_report $out, $err, $res, $prepped_path if $out or $err or $res; return; } -sub _age($) { ( stat $_[0] )[9] || 0 } +sub _age ($) { + eval { ( stat $_[0] )[9] } || 0; +} -sub mod_font { - my ( $ff, $candidate_dir, %font ) = @_; - say "processing font '$font{name}'"; +sub make_font { + my ( $ff, %font ) = @_; - my $target_path = "$candidate_dir/$font{target_path}"; - my $target_body = "$target_path/$font{name}"; - if ( _age "$target_body.ttf" > _age "font_mod_character_pairs" ) { - say "font was generated after last change to char tuples, skipping"; - return; - } + my $work_base = "../fonts/" . sha1_hex $font{src}; + my $prepped_path = "$work_base.sfdir"; + $prepped_path =~ s/\.ttf//; + prep_font $ff, $prepped_path, %font if !-e $prepped_path; - if ( !-e "../fonts/$font{name}.sfdir" ) { - say "preparing font from source with empty PUA glyphs and guaranteed space glyph"; - my ( $out, $err, $res ) = capture { system(qq["$ff" -script prepare_new_font.ff "$font{src}" "../fonts/$font{name}.sfdir"]) }; - $err =~ s/^Copyright.*\n(^ .*\n)+//m; - $err =~ s/^The following table.*ignored.*\n(^ .*\n)+//m; - $err =~ s/^Warning:.*\n(^ .*\n)+//mg; - $err =~ s/^This font contains both.*\n(^ .*\n)+//m; - $err =~ s/^.*SEAC-like endchar operator is deprecated for Type2\n//mg; - $err =~ s/^Subtable status not filled in .*\n*//mg; - $err =~ s/^The glyph named .* is mapped to .*\n But its name indicates it should be mapped to .*\n*//mg; # research - $err =~ s/^Bad sfd file. Glyph .* has width .* even though it should be\n bound to the width of .* which is .*\n*//mg; # research - $out =~ s/^log:.*\n//mg; - - if ( $out or $err or $res ) { - io("../fonts/$font{name}.sfdir")->rmtree; - die "error:\nout:\n$out\nerr:\n$err\nres: $res\n"; - } - } + my $temp_target = "$work_base.otf"; + return $temp_target if _age $temp_target > _age "font_mod_character_pairs"; say "modding font with multi-glyphs"; - my ( $out, $err, $res ) = capture { system(qq[python font_mod_run.py "$font{name}"]) }; - die "error:\nout:\n$out\nerr:\n$err\nres: $res\n" if $out or $err or $res; + my $mod_dir = "$work_base\_mod.sfdir"; + my ( $out, $err, $res ) = capture { system(qq[python font_mod_run.py "$font{name}" "$prepped_path" "$mod_dir"]) }; + die _clean_and_report $out, $err, $res, $mod_dir if $out or $err or $res; say "generating font file from mod dir"; - io($target_path)->mkpath; - my $temp_target = "$target_body.otf"; - my $mod_dir = "../fonts/$font{name}_mod.sfdir"; my ( $out2, $err2, $res2 ) = capture { system(qq["$ff" -script generate_font_from_dir.ff "$mod_dir" "$temp_target"]) }; $err2 =~ s/^Copyright.*\n(^ .*\n)+//m; $err2 =~ s/^Lookup sub table.*is too big.*\n//m; $err2 =~ s/^Lookup .* has an\n(^ .*\n)+//m; - die "error:\nout:\n$out2\nerr:\n$err2\nres: $res2\n" if $out2 or $err2 or $res2; + die _clean_and_report $out2, $err2, $res2, $temp_target if $out2 or $err2 or $res2; + + return $temp_target; +} + +sub mod_font { + my ( $ff, $prepped, %font ) = @_; + say "processing font '$font{name}'"; + + my $target_body = "$font{target_path}/$font{name}"; + if ( _age "$target_body.ttf" > _age "font_mod_character_pairs" ) { + say "font was generated after last change to char tuples, skipping\n"; + return; + } + + my $modded_font = $prepped->{ $font{src} } ||= make_font $ff, %font; # the extension here is for compatibility. the fonts in kc are OTF, but # have the extension ttf, so we generate the replacements to match say "fixing final extension"; - io($temp_target)->rename("$target_body.ttf"); + io( $font{target_path} )->mkpath; + io($modded_font)->copy("$target_body.ttf"); + say "done\n"; return; } + +sub run { + my $ff = "C:/Program Files (x86)/FontForgeBuilds/bin/fontforge.exe"; + my $t_body = "Media/Unity_Assets_Files"; + my $t_root = "../kc_original_unpack_modded/$t_body"; + my $font_root = "../kc_original_unpack/$t_body"; + + # ume is used to make texts ingame more narrow + my @fonts = ( + { name => "A-OTF-UDShinGoPro-Regular", target_path => "$t_root/sharedassets3", src => "fonts/ume-pgs4.ttf" }, + { name => "A-OTF-ShinGoPro-Regular", target_path => "$t_root/sharedassets2", src => "$font_root/sharedassets2/A-OTF-ShinGoPro-Regular.ttf" }, + { name => "CenturyGothicStd", target_path => "$t_root/resources", src => "$font_root/resources/CenturyGothicStd.ttf" }, + { name => "A-OTF-ShinGoPro-Regular-For-ScrollList", target_path => "$t_root/sharedassets5", src => "$font_root/sharedassets5/A-OTF-ShinGoPro-Regular-For-ScrollList.ttf" }, + { name => "AxisStd-Regular_1", target_path => "$t_root/sharedassets5", src => "$font_root/sharedassets5/AxisStd-Regular_1.ttf" }, + { name => "A-OTF-RyuminPr5-ExBold", target_path => "$t_root/sharedassets11", src => "$font_root/sharedassets11/A-OTF-RyuminPr5-ExBold.ttf" }, + { name => "Century Gothic", target_path => "$t_root/sharedassets26", src => "$font_root/sharedassets26/Century Gothic.ttf" }, + ); + io("../fonts")->mkdir if !-d "../fonts"; + my %prepped; + mod_font $ff, \%prepped, $_->%* for @fonts; + say "done with fonts"; + return; +}