diff options
9 files changed, 593 insertions, 114 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/cjk-gs-integrate/cjk-gs-integrate.pl b/Build/source/texk/texlive/linked_scripts/cjk-gs-integrate/cjk-gs-integrate.pl index 6fce593611f..2dbfdd49b01 100755 --- a/Build/source/texk/texlive/linked_scripts/cjk-gs-integrate/cjk-gs-integrate.pl +++ b/Build/source/texk/texlive/linked_scripts/cjk-gs-integrate/cjk-gs-integrate.pl @@ -2,8 +2,8 @@ # # cjk-gs-integrate - setup Ghostscript for CID/TTF CJK fonts # -# Copyright 2015-2019 by Norbert Preining -# Copyright 2016-2019 by Japanese TeX Development Community +# Copyright 2015-2020 by Norbert Preining +# Copyright 2016-2020 by Japanese TeX Development Community # # This work is based on research and work by (in alphabetical order) # Yusuke Kuroki @@ -39,7 +39,7 @@ use Cwd 'abs_path'; use strict; (my $prg = basename($0)) =~ s/\.pl$//; -my $version = '20190816.0'; +my $version = '20200115.0'; if (win32()) { # conversion between internal (utf-8) and console (cp932): @@ -359,23 +359,21 @@ if ($opt_debug >= 2) { $Data::Dumper::Indent = 1; } -my $otfinfo_available; -chomp(my $otfinfo_help = `otfinfo --help 2>$nul`); +my $zrlistttc = kpse_miscfont("zrlistttc.lua"); +my $zrlistttc_available; +chomp(my $zrlistttc_help = `texlua $zrlistttc 2>$nul`); if ($?) { - # to tell the truth, we want to show below as a warning - # but BasicTeX (scheme-small) does not have 'otfinfo' (lcdf-typetools); - # show info only for debugging - print_debug("The program 'otfinfo' not found in PATH.\n"); - print_debug("Sorry, we can't be safe enough to distinguish\n"); - print_debug("uppercase / lowercase file names.\n"); - # but the below should be an error! if ($opt_strictpsname) { - print_error("'otfinfo' not found, cannot proceed!\n"); + print_error("The script 'zrlistttc.lua' not found, cannot proceed!\n"); exit(1); } - $otfinfo_available = 0; + # show info only for debugging + print_debug("The script 'zrlistttc.lua' not found.\n"); + print_debug("Sorry, we can't be safe enough to distinguish\n"); + print_debug("uppercase / lowercase file names.\n"); + $zrlistttc_available = 0; } else { - $otfinfo_available = 1; + $zrlistttc_available = 1; } if (macosx()) { @@ -682,26 +680,18 @@ sub do_nonotf_fonts { if $opt_texmflink; for my $k (sort keys %fontdb) { if ($fontdb{$k}{'available'} && $fontdb{$k}{'type'} eq 'TTF') { - # generate_font_snippet($fontdest, - # $k, $fontdb{$k}{'class'}, $fontdb{$k}{'target'}); $outp .= generate_cidfmap_entry($k, $fontdb{$k}{'class'}, $fontdb{$k}{'ttfname'}, -1); link_font($fontdb{$k}{'target'}, $cidfsubst, $fontdb{$k}{'ttfname'}); link_font($fontdb{$k}{'target'}, "$opt_texmflink/$ttf_pathpart", $fontdb{$k}{'ttfname'}) if $opt_texmflink; } elsif ($fontdb{$k}{'available'} && $fontdb{$k}{'type'} eq 'TTC') { - # generate_font_snippet($fontdest, - # $k, $fontdb{$k}{'class'}, $fontdb{$k}{'target'}); $outp .= generate_cidfmap_entry($k, $fontdb{$k}{'class'}, $fontdb{$k}{'ttcname'}, $fontdb{$k}{'subfont'}); link_font($fontdb{$k}{'target'}, $cidfsubst, $fontdb{$k}{'ttcname'}); link_font($fontdb{$k}{'target'}, "$opt_texmflink/$ttf_pathpart", $fontdb{$k}{'ttcname'}) if $opt_texmflink; } elsif ($fontdb{$k}{'available'} && $fontdb{$k}{'type'} eq 'OTC') { - # currently Ghostscript does not have OTC support; not creating gs resource + # currently Ghostscript does not have OTC support; we don't know what to do print_debug("gs does not support OTC, not creating gs resource for $k\n"); - # generate_font_snippet($fontdest, - # $k, $fontdb{$k}{'class'}, $fontdb{$k}{'target'}); - # $outp .= generate_cidfmap_entry($k, $fontdb{$k}{'class'}, $fontdb{$k}{'otcname'}, $fontdb{$k}{'subfont'}); - # link_font($fontdb{$k}{'target'}, $cidfsubst, $fontdb{$k}{'otcname'}); link_font($fontdb{$k}{'target'}, "$opt_texmflink/$otf_pathpart", $fontdb{$k}{'otcname'}) if $opt_texmflink; } @@ -1303,7 +1293,8 @@ sub check_for_files { push @extradirs, "c:/windows/fonts//"; } else { # other dirs to check, for normal unix? - for my $d (qw!/Library/Fonts /System/Library/Fonts /System/Library/Assets + for my $d (qw!/Library/Fonts /System/Library/Fonts + /System/Library/Assets /System/Library/AssetsV2 /Network/Library/Fonts /usr/share/fonts!) { push @extradirs, "$d//" if (-d $d); # recursive search } @@ -1420,36 +1411,44 @@ sub check_for_files { # check for subfont extension my $realfile = $f; $realfile =~ s/^(.*)\(\d*\)$/$1/; - # check for casefolding - # we might catch different names (batang/Batang) and identify them wrongly on - # * case-insensitive file systems (like HFS on MacOS) - # * kpathsea 6.3.0 or later, with casefolding fallback search (TL2018) - # check the actual psname using otfinfo utility, only when we "know" - # both uppercase/lowercase font files are possible and they are different + my $index = 0; + if ($fontdb{$k}{'files'}{$f}{'type'} eq 'TTC' || $fontdb{$k}{'files'}{$f}{'type'} eq 'OTC') { + if ($f =~ m/^(.*)\((\d*)\)$/) { + $index = $2; + } + } + # double check for casefolding or incompatible OTC/TTC index + # [1] casefolding issue + # we might catch different names (batang/Batang) and identify them wrongly on + # * case-insensitive file systems (like HFS on MacOS) + # * kpathsea 6.3.0 or later, with casefolding fallback search (TL2018) + # check the actual psname using zrlistttc.lua, only when we "know" + # both uppercase/lowercase font files are possible and they are different + # [2] incompatible index + # the index in msgothic.ttc changed at some time between Win7 and Win10. my $actualpsname; my $bname; for my $b (sort keys %{$bntofn{$realfile}}) { - $fontdb{$k}{'casefold'} = "debug" if $opt_strictpsname; - if ($fontdb{$k}{'casefold'} && $otfinfo_available && - ($fontdb{$k}{'files'}{$f}{'type'} eq 'OTF' || $fontdb{$k}{'files'}{$f}{'type'} eq 'TTF')) { + $fontdb{$k}{'doublecheck'} = "debug" if $opt_strictpsname; + if ($fontdb{$k}{'doublecheck'} && $zrlistttc_available) { print_debug("We need to test whether\n"); print_debug(" $b\n"); - print_debug("is the correct one. Invoking otfinfo ...\n"); - chomp($actualpsname = `otfinfo -p "$b"`); + print_debug("is the correct one. Invoking zrlistttc ...\n"); + chomp($actualpsname = `texlua $zrlistttc -i $index "$b"`); if ($?) { - # something is wrong with the font file, or otfinfo does not support it; + # something is wrong with the font file, or zrlistttc does not support it; # still there is a chance that Ghostscript supports, so don't discard it print_debug("... command exited with $?!\n"); print_debug("OK, I'll take this, but it may not work properly.\n"); - print_warning("otfinfo check failed for $b\n") if $opt_strictpsname; + print_warning("zrlistttc check failed for $b\n") if $opt_strictpsname; $bname = $b; last; } $actualpsname =~ s/[\r\n]+\z//; # perl's chomp() on git-bash cannot strip CR of CRLF ?? if ($actualpsname ne $k) { - print_debug("... PSName returned by otfinfo ($actualpsname) is\n"); + print_debug("... PSName returned by zrlistttc ($actualpsname) is\n"); print_debug("different from our database ($k), discarding!\n"); - print_warning("otfinfo check failed for $b\n") if $opt_strictpsname; + print_warning("zrlistttc check failed for $b\n") if $opt_strictpsname; } else { print_debug("... test passed.\n"); $bname = $b; @@ -1635,7 +1634,7 @@ sub read_each_font_database { my $fontname = ""; my $fontclass = ""; my %fontprovides = (); - my $fontcasefold = ""; + my $fontdoublecheck = ""; my %fontfiles; my $psname = ""; my $lineno = 0; @@ -1656,7 +1655,7 @@ sub read_each_font_database { } $fontdb{$realfontname}{'origname'} = $fontname; $fontdb{$realfontname}{'class'} = $fontclass; - $fontdb{$realfontname}{'casefold'} = $fontcasefold; + $fontdb{$realfontname}{'doublecheck'} = $fontdoublecheck; $fontdb{$realfontname}{'files'} = { %fontfiles }; $fontdb{$realfontname}{'provides'} = { %fontprovides }; if ($opt_debug >= 3) { @@ -1664,14 +1663,14 @@ sub read_each_font_database { } # reset to start $fontname = $fontclass = $psname = ""; - $fontcasefold = ""; + $fontdoublecheck = ""; %fontfiles = (); %fontprovides = (); } else { print_warning("incomplete entry above line $lineno for $fontname/$fontclass, skipping!\n"); # reset to start $fontname = $fontclass = $psname = ""; - $fontcasefold = ""; + $fontdoublecheck = ""; %fontfiles = (); %fontprovides = (); } @@ -1711,7 +1710,8 @@ sub read_each_font_database { if ($l =~ m/^PSName:\s*(.*)$/) { $psname = $1; next; } if ($l =~ m/^Class:\s*(.*)$/) { $fontclass = $1 ; next ; } if ($l =~ m/^Provides\((\d+)\):\s*(.*)$/) { $fontprovides{$2} = $1; next; } - if ($l =~ m/^Casefold:\s*(.*)$/) { $fontcasefold = $1 ; next ; } + if ($l =~ m/^Doublecheck:\s*(.*)$/) { $fontdoublecheck = $1 ; next ; } + if ($l =~ m/^Casefold:\s*(.*)$/) { $fontdoublecheck = $1 ; next ; } # no longer used # new code: distinguish 4 types (otf, otc, ttf, ttc) if ($l =~ m/^OTFname(\((\d+)\))?:\s*(.*)$/) { my $fn = $3; @@ -1824,7 +1824,7 @@ sub dump_font_database { for my $p (sort keys %{$fontdb{$k}{'provides'}}) { print FOO "Provides($fontdb{$k}{'provides'}{$p}): $p\n"; } - print FOO "Casefold: $fontdb{$k}{'casefold'}\n" if ($fontdb{$k}{'casefold'}); + print FOO "Doublecheck: $fontdb{$k}{'doublecheck'}\n" if ($fontdb{$k}{'doublecheck'}); for my $f (sort { $fontdb{$k}{'files'}{$a}{'priority'} <=> $fontdb{$k}{'files'}{$b}{'priority'} } @@ -1943,10 +1943,11 @@ sub find_gs_resource { sub kpse_miscfont { my ($file) = @_; - chomp(my $foo = `kpsewhich -format=miscfont $file`); - # for GitHub repository diretory structure + my $foo = ''; + # first, prioritize GitHub repository diretory structure + $foo = "database/$file" if (-f "database/$file"); if ($foo eq "") { - $foo = "database/$file" if (-f "database/$file"); + chomp($foo = `kpsewhich -format=miscfont $file`); } return $foo; } @@ -2327,6 +2328,9 @@ INCLUDE cjkgs-ume.dat # Sazanami (free) INCLUDE cjkgs-sazanami.dat +# Harano Aji Fonts (free) +INCLUDE cjkgs-haranoaji.dat + # Osaka (Apple) Name: Osaka @@ -2426,7 +2430,7 @@ INCLUDE cjkgs-solaris.dat Name: Baekmuk-Batang Class: Korea Provides(70): HYSMyeongJo-Medium -Casefold: true +Doublecheck: true TTFname(20): batang.ttf TTFname(10): Baekmuk-Batang.ttf @@ -2439,7 +2443,7 @@ TTFname(10): Baekmuk-Dotum.ttf Name: Baekmuk-Gulim Class: Korea Provides(70): HYRGoThic-Medium -Casefold: true +Doublecheck: true TTFname(20): gulim.ttf TTFname(10): Baekmuk-Gulim.ttf @@ -2494,7 +2498,7 @@ INCLUDE cjkgs-hancom.dat Name: Batang Class: Korea -Casefold: true +Doublecheck: true TTFname(50): Batang.ttf TTCname(20): batang.ttc(0) @@ -2514,7 +2518,7 @@ TTCname(20): gulim.ttc(3) Name: Gulim Class: Korea -Casefold: true +Doublecheck: true TTFname(50): Gulim.ttf TTCname(20): gulim.ttc(0) @@ -2664,6 +2668,7 @@ TTFname(10): MSMHei-Bold.ttf # Remove-only database (should begin with !INCLUDE) # that is, entries which contain at least one 'RMVname' line # note that this line should come at the _end_ of all INCLUDE files +!INCLUDE cjkgs-removeonly.dat !INCLUDE cjkgs-macos-removeonly.dat diff --git a/Master/texmf-dist/doc/fonts/cjk-gs-integrate/ChangeLog b/Master/texmf-dist/doc/fonts/cjk-gs-integrate/ChangeLog index cd697a8e08a..33491958dd2 100644 --- a/Master/texmf-dist/doc/fonts/cjk-gs-integrate/ChangeLog +++ b/Master/texmf-dist/doc/fonts/cjk-gs-integrate/ChangeLog @@ -1,10 +1,70 @@ +2020-01-15 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * Release 20200115.0 (HEAD -> master) [2eba287] + +2020-01-15 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * copyright year (origin/master, origin/HEAD) [ec0590e] + +2020-01-14 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * fix for incompatible change in msgothic.ttc index [14485c6] + +2019-11-09 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * add haranoaji database (see texjporg/jfontmaps#23) [091e829] + +2019-10-11 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * prioritize database/ dir in current [ed62e0e] + +2019-10-11 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * cjk-gs-integrate.pl: support macOS 10.15 Catalina font path (wip) [d870a3f] + +2019-09-05 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * YuMincho-DemiBold -> YuMincho-Demibold [e819473] + +2019-09-04 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * Makefile: also install zrlistttc.lua [c03fe55] + +2019-09-04 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * cjkgs-microsoft.dat: fix typo of HGPMinchoE [6e2de8c] + +2019-09-04 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * code cleanup (zrlistttc) [840be09] + +2019-09-04 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * use local zrlistttc.lua [3216bf6] + +2019-09-04 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * zrlistttc.lua: licensed under MIT license [b4f072c] + +2019-09-04 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * zrlistttc.lua: add -i option, support macOS-TrueType (v0.4) [bda3126] + +2019-09-04 Takayuki YATO <tak_yato@yahoo.co.jp> + + * First public version of zrlistttc.lua (v0.2) [6bd8986] + +2019-09-01 Hironobu Yamashita <h.y.acetaminophen@gmail.com> + + * use zrlistttc.lua for checking PSName (preliminary) (origin/zrlistttc) [789ba5b] + 2019-08-16 Hironobu Yamashita <h.y.acetaminophen@gmail.com> - * Release 20190816.0 (HEAD -> master) [089a440] + * Release 20190816.0 (tag: 20190816.0) [089a440] 2019-08-16 Hironobu Yamashita <h.y.acetaminophen@gmail.com> - * gs-9.27 doesn't like snippets for TTF/TTC it seems gs-9.25 and gs-9.26 does not require snippets for TTF/TTC so it will be safe enough (origin/master, origin/HEAD) [22bc208] + * gs-9.27 doesn't like snippets for TTF/TTC it seems gs-9.25 and gs-9.26 does not require snippets for TTF/TTC so it will be safe enough [22bc208] 2019-05-22 Hironobu Yamashita <h.y.acetaminophen@gmail.com> @@ -16,7 +76,7 @@ 2019-05-19 Hironobu Yamashita <h.y.acetaminophen@gmail.com> - * \/dev\/null -> $nul (origin/check-kpse) [1145435] + * \/dev\/null -> $nul [1145435] 2019-05-19 Norbert Preining <norbert@preining.info> diff --git a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-haranoaji.dat b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-haranoaji.dat new file mode 100644 index 00000000000..e3517f67d3c --- /dev/null +++ b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-haranoaji.dat @@ -0,0 +1,60 @@ +# Harano Aji Fonts (free) + +### JAPANESE ### + +Name: HaranoAjiMincho-ExtraLight +Class: Japan +OTFname: HaranoAjiMincho-ExtraLight.otf + +Name: HaranoAjiMincho-Light +Class: Japan +OTFname: HaranoAjiMincho-Light.otf + +Name: HaranoAjiMincho-Regular +Class: Japan +OTFname: HaranoAjiMincho-Regular.otf + +Name: HaranoAjiMincho-Medium +Class: Japan +OTFname: HaranoAjiMincho-Medium.otf + +Name: HaranoAjiMincho-SemiBold +Class: Japan +OTFname: HaranoAjiMincho-SemiBold.otf + +Name: HaranoAjiMincho-Bold +Class: Japan +OTFname: HaranoAjiMincho-Bold.otf + +Name: HaranoAjiMincho-Heavy +Class: Japan +OTFname: HaranoAjiMincho-Heavy.otf + +Name: HaranoAjiGothic-ExtraLight +Class: Japan +OTFname: HaranoAjiGothic-ExtraLight.otf + +Name: HaranoAjiGothic-Light +Class: Japan +OTFname: HaranoAjiGothic-Light.otf + +Name: HaranoAjiGothic-Normal +Class: Japan +OTFname: HaranoAjiGothic-Normal.otf + +Name: HaranoAjiGothic-Regular +Class: Japan +OTFname: HaranoAjiGothic-Regular.otf + +Name: HaranoAjiGothic-Medium +Class: Japan +OTFname: HaranoAjiGothic-Medium.otf + +Name: HaranoAjiGothic-Bold +Class: Japan +OTFname: HaranoAjiGothic-Bold.otf + +Name: HaranoAjiGothic-Heavy +Class: Japan +OTFname: HaranoAjiGothic-Heavy.otf + diff --git a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-microsoft.dat b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-microsoft.dat index 19e70596ec0..0c0a373233b 100644 --- a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-microsoft.dat +++ b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-microsoft.dat @@ -30,6 +30,8 @@ # MeiryoItalic.ttf # are bundled with Office for Mac 2016. +# [TODO] I don't know when the TTC index of msgothic.ttc changed! + # [TODO] Check about HG* fonts, and move Chinese/Korean fonts Name: MS-Mincho @@ -78,13 +80,17 @@ TTCname(20): msmincho.ttc(1) Name: MS-PGothic Class: Japan +Doublecheck: true TTFname(50): MS PGothic.ttf TTFname(30): MS-PGothic.ttf -TTCname(20): msgothic.ttc(1) +TTCname(20): msgothic.ttc(1) # old +TTCname(20): msgothic.ttc(2) # new Name: MS-UIGothic Class: Japan -TTCname(20): msgothic.ttc(2) +Doublecheck: true +TTCname(20): msgothic.ttc(2) # old +TTCname(20): msgothic.ttc(1) # new Name: Meiryo Class: Japan @@ -163,7 +169,7 @@ TTCname(20): HGRME.TTC(0) Name: HGPMinchoE Class: Japan TTCname(50): HGRME.ttc(1) -TTCname(20): HGRME.TTC(2) +TTCname(20): HGRME.TTC(1) Name: HGSMinchoE Class: Japan diff --git a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-removeonly.dat b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-removeonly.dat new file mode 100644 index 00000000000..3ba536e8909 --- /dev/null +++ b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-removeonly.dat @@ -0,0 +1,7 @@ +# Bugs in previous cjkgs-yu-win.dat: +# Wrong PSName (NG: YuMincho-DemiBold -> OK: YuMincho-Demibold) + +Name: YuMincho-DemiBold +Class: Japan +TTFname(20): yumindb.ttf + diff --git a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-yu-win.dat b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-yu-win.dat index 34d2e1be6f1..4d26dae82de 100644 --- a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-yu-win.dat +++ b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/cjkgs-yu-win.dat @@ -42,7 +42,7 @@ Class: Japan TTFname(20): yuminl.ttf #TTFname(50): YuMincho-Light.ttf # never existed -Name: YuMincho-DemiBold +Name: YuMincho-Demibold Class: Japan Provides(90): FutoMinA101-Bold Provides(90): FutoMinA101Pro-Bold @@ -51,7 +51,7 @@ Provides(90): HiraMinPro-W6 Provides(90): MidashiMin-MA31 Provides(90): MidashiMinPro-MA31 TTFname(20): yumindb.ttf -#TTFname(50): YuMincho-DemiBold.ttf # never existed +#TTFname(50): YuMincho-Demibold.ttf # never existed Name: YuGothic-Regular Class: Japan diff --git a/Master/texmf-dist/fonts/misc/cjk-gs-integrate/zrlistttc.lua b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/zrlistttc.lua new file mode 100644 index 00000000000..59329aacb26 --- /dev/null +++ b/Master/texmf-dist/fonts/misc/cjk-gs-integrate/zrlistttc.lua @@ -0,0 +1,335 @@ +-- zrlistttc.lua +-- Copyright (c) 2019 Takayuki YATO +-- Modified by Hironobu YAMASHITA +-- This software is distributed under the MIT License. +prog_name = 'zrlistttc' +version = '0.4' +mod_date = '2019/08/31' +---------------------------------------- +verbose = false +ttc_index = nil +content = { 6 } +langid = nil +ttc_file = nil +---------------------------------------- +do + local reader_meta = { + __tostring = function(self) + return "reader("..self.name..")" + end; + __index = { + cdata = function(self, ofs, len) + return make_cdata(self:read(ofs, len)) + end; + read = function(self, ofs, len) + self.file:seek("set", ofs) + local data = self.file:read(len) + sure(data:len() == len, 1) + return data + end; + close = function(self) + self.file:close() + end; + } + } + function make_reader(fname) + local file = io.open(fname, "rb") + sure(file, "cannot open for input", fname) + return setmetatable({ + name = fname, file = file + }, reader_meta) + end +end +---------------------------------------- +do + local cdata_meta = { + __tostring = function(self) + return "cdata(pos="..self._pos..")" + end; + __index = { + pos = function(self, p) + if not p then return self._pos end + self._pos = p + return self + end; + _unum = function(self, b) + local v, data = 0, self.data + sure(#data >= self._pos + b, 11) + for i = 1, b do + self._pos = self._pos + 1 + v = v * 256 + data:byte(self._pos) + end + return v + end; + _setunum = function(self, b, v) + local t, data = {}, self.data + t[1] = data:sub(1, self._pos) + self._pos = self._pos + b + sure(#data >= self._pos, 12) + t[b + 2] = data:sub(self._pos + 1) + for i = 1, b do + t[b + 2 - i] = string.char(v % 256) + v = math.floor(v / 256) + end + self.data = table.concat(t, '') + return self + end; + str = function(self, b) + local data = self.data + self._pos = self._pos + b + sure(#data >= self._pos, 13) + return data:sub(self._pos - b + 1, self._pos) + end; + setstr = function(self, s) + local t, data = {}, self.data + t[1], t[2] = data:sub(1, self._pos), s + self._pos = self._pos + #s + sure(#data >= self._pos, 14) + t[3] = data:sub(self._pos + 1) + self.data = table.concat(t, '') + return self + end; + ushort = function(self) + return self:_unum(2) + end; + ulong = function(self) + return self:_unum(4) + end; + setulong = function(self, v) + return self:_setunum(4, v) + end; + ulongs = function(self, num) + local t = {} + for i = 1, num do + t[i] = self:_unum(4) + end + return t + end; + } + } + function make_cdata(data) + return setmetatable({ + data = data, _pos = 0 + }, cdata_meta) + end +end +---------------------------------------- +do + local floor, ceil = math.floor, math.ceil + local function div(x, y) + return floor(x / y), x % y + end + local function utf16betoutf8(src) + local s, d = { tostring(src):byte(1, -1) }, {} + for i = 1, #s - 1, 2 do + local c = s[i] * 256 + s[i+1] + if c < 0x80 then d[#d+1] = c + elseif c < 0x800 then + local x, y = div(c, 0x40) + d[#d+1] = x + 0xC0; d[#d+1] = y + 0x80 + elseif c < 0x10000 then + local x, y, z = div(c, 0x1000); y, z = div(y, 0x40) + d[#d+1] = x + 0xE0; d[#d+1] = y + 0x80; d[#d+1] = z + 0x80 + else sure(nil) + end + end + return string.char(unpack(d)) + end + local file_type = { + [0x74746366] = 'ttc'; [0x10000] = 'ttf'; [0x4F54544F] = 'otf'; + [0x74727565] = 'ttf' + } + function otf_offset(reader) + local cd = reader:cdata(0, 12) + local tag = cd:ulong() + local ftype = file_type[tag]; info("type", ftype) + if ftype == 'ttc' then + local ver = cd:ulong(); info("version", ver) + local num = cd:ulong(); info("#fonts", num) + cd = reader:cdata(12, 4 * num) + local res = cd:ulongs(num); info("offset", stt(res)) + return res + elseif ftype == 'otf' or ftype == 'ttf' then + return { 0 } + else sure(nil, "unknown file tag", tag) + end + end + local function otf_name_table(reader, fofs, ntbl) + local cd_d = reader:cdata(fofs + 12, 16 * ntbl) + for i = 1, ntbl do + local t = stt({-- tag, csum, ofs, len + cd_d:str(4), cd_d:ulong(), cd_d:ulong(), cd_d:ulong() + }) + if t[1] == 'name' then + info("name table index", i) + return reader:cdata(t[3], ceil(t[4] / 4) * 4) + end + end + sure(nil, "name table is missing") + end + local function otf_name_records(cdata) + local nfmt, nnum, nofs = cdata:ushort(), cdata:ushort(), cdata:ushort() + sure(nfmt == 0, "unsupported name table format", nfmt) + local nr = stt({}) + for i = 1, nnum do + nr[i] = stt({ -- pid, eid, langid, nameid, len, ofs + cdata:ushort(), cdata:ushort(), cdata:ushort(), + cdata:ushort(), cdata:ushort(), cdata:ushort() + nofs + }) + end + return nr + end + function otf_name(cdata, nr, nameid) + local function seek(pid, eid, lid) + for i = 1, #nr do + local t = nr[i] + local ok = (t[4] == nameid and t[1] == pid and t[2] == eid and + t[3] == lid) + if ok then return t end + end + end + local rec + if langid then + rec = seek(unpack(langid)) + else + rec = seek(3, 1, 0x409) or seek(3, 10, 0x409) or + seek(1, 0, 0) or seek(0, 3, 0) or + seek(0, 4, 0) or seek(0, 6, 0) + end + info("name record", rec or 'none') + if not rec then return '' end + local s = cdata:pos(rec[6]):str(rec[5]) + return (rec[1] == 3) and utf16betoutf8(s) or s + end + function otf_list(reader, fid, fofs) + local cd_fh = reader:cdata(fofs, 12) + local tag = cd_fh:ulong(); info("tag", tag) + local ntbl = cd_fh:ushort(); info("#tables", ntbl) + local cd_n = otf_name_table(reader, fofs, ntbl) + local ext = { id = fid; type = file_type[tag] or '' } + local nr, val = otf_name_records(cd_n), stt({}) + info("font", otf_name(cd_n, nr, 6)) + for i = 1, #content do + local key = content[i] + val[i] = (type(key) == 'string') and ext[key] or + otf_name(cd_n, nr, key) + end + io.stdout:write(concat(val, ",").."\n") + end +end +---------------------------------------- +do + unpack = unpack or table.unpack + local stt_meta = { + __tostring = function(self) + return "{"..concat(self, ",").."}" + end + } + function stt(tbl) + return setmetatable(tbl, stt_meta) + end + function concat(tbl, ...) + local t = {} + for i = 1, #tbl do t[i] = tostring(tbl[i]) end + return table.concat(t, ...) + end + function info(...) + if not verbose then return end + local t = { prog_name, ... } + io.stderr:write(concat(t, ": ").."\n") + end + function abort(...) + verbose = true; info(...) + os.exit(-1) + end + function sure(val, a1, ...) + if val then return val end + if type(a1) == "number" then + a1 = "error("..a1..")" + end + abort(a1, ...) + end +end +---------------------------------------- +do + local function show_usage() + io.stdout:write(([[ +This is %s v%s <%s> by 'ZR' +Usage: %s[.lua] [-v] [-c <spec>] <ttc_file> + -v be verbose + -i show only one font with a specified index + -c content specification; comma-separated list of items, + where an item is either 'id', 'type', or an name-ID +]]):format(prog_name, version, mod_date, prog_name)) + os.exit(0) + end + local function langid_spec(str) + local p, e, l = str:match('^(%d+),(%d+),(%d+)$') + sure(p, "invalid langid spec", str) + return { tonumber(p), tonumber(e), tonumber(l) } + end + local function content_spec(str) + local t, repo = {}, { + copyright = 0; family = 1; subfamily = 2; fullname = 4; + version = 5; psname = 6; url = 11; license = 13; + tfamily = 16; tsubfamily = 17; + id = -1; type = -1; + } + for k in str:gmatch('[^,]+') do + local v = (k:match('^%d+$')) and tonumber(k) or repo[k] + sure(v, "unknown content key", k) + t[#t+1] = (v < 0) and k or v + end + return t + end + local function ttc_index_spec(str) + local p = str:match('^(%d+)$') + sure(p, "invalid ttc_index spec", str) + return tonumber(p) + end + function read_option() + if #arg == 0 then show_usage() end + local idx = 1 + while idx <= #arg do + local opt = arg[idx] + if opt:sub(1, 1) ~= '-' then break end + if opt == '-h' or opt == '--help' then + show_usage() + elseif opt == '-v' then + verbose = true + elseif opt == '-i' then + idx = idx + 1; sure(arg[idx], "ttc_index spec is missing") + ttc_index = ttc_index_spec(arg[idx]) + elseif opt == '-c' then + idx = idx + 1; sure(arg[idx], "content spec is missing") + content = stt(content_spec(arg[idx])) + elseif opt == '-l' then + idx = idx + 1; sure(arg[idx], "langid spec is missing") + langid = stt(langid_spec(arg[idx])) + else abort("invalid option", opt) + end + idx = idx + 1 + end + sure(#arg == idx, "wrong number of arguments") + ttc_file = arg[idx] + end + function main() + read_option() + local reader = make_reader(ttc_file) + local tofs = otf_offset(reader) + if ttc_index then + if ttc_index < 0 or ttc_index > #tofs - 1 then + abort("non-existing ttc_index", ttc_index) + end + otf_list(reader, ttc_index, tofs[ttc_index + 1]) + else + for i = 1, #tofs do + otf_list(reader, i - 1, tofs[i]) + end + end + reader:close() + end +end +---------------------------------------- +main() +-- EOF diff --git a/Master/texmf-dist/scripts/cjk-gs-integrate/cjk-gs-integrate.pl b/Master/texmf-dist/scripts/cjk-gs-integrate/cjk-gs-integrate.pl index 6fce593611f..2dbfdd49b01 100755 --- a/Master/texmf-dist/scripts/cjk-gs-integrate/cjk-gs-integrate.pl +++ b/Master/texmf-dist/scripts/cjk-gs-integrate/cjk-gs-integrate.pl @@ -2,8 +2,8 @@ # # cjk-gs-integrate - setup Ghostscript for CID/TTF CJK fonts # -# Copyright 2015-2019 by Norbert Preining -# Copyright 2016-2019 by Japanese TeX Development Community +# Copyright 2015-2020 by Norbert Preining +# Copyright 2016-2020 by Japanese TeX Development Community # # This work is based on research and work by (in alphabetical order) # Yusuke Kuroki @@ -39,7 +39,7 @@ use Cwd 'abs_path'; use strict; (my $prg = basename($0)) =~ s/\.pl$//; -my $version = '20190816.0'; +my $version = '20200115.0'; if (win32()) { # conversion between internal (utf-8) and console (cp932): @@ -359,23 +359,21 @@ if ($opt_debug >= 2) { $Data::Dumper::Indent = 1; } -my $otfinfo_available; -chomp(my $otfinfo_help = `otfinfo --help 2>$nul`); +my $zrlistttc = kpse_miscfont("zrlistttc.lua"); +my $zrlistttc_available; +chomp(my $zrlistttc_help = `texlua $zrlistttc 2>$nul`); if ($?) { - # to tell the truth, we want to show below as a warning - # but BasicTeX (scheme-small) does not have 'otfinfo' (lcdf-typetools); - # show info only for debugging - print_debug("The program 'otfinfo' not found in PATH.\n"); - print_debug("Sorry, we can't be safe enough to distinguish\n"); - print_debug("uppercase / lowercase file names.\n"); - # but the below should be an error! if ($opt_strictpsname) { - print_error("'otfinfo' not found, cannot proceed!\n"); + print_error("The script 'zrlistttc.lua' not found, cannot proceed!\n"); exit(1); } - $otfinfo_available = 0; + # show info only for debugging + print_debug("The script 'zrlistttc.lua' not found.\n"); + print_debug("Sorry, we can't be safe enough to distinguish\n"); + print_debug("uppercase / lowercase file names.\n"); + $zrlistttc_available = 0; } else { - $otfinfo_available = 1; + $zrlistttc_available = 1; } if (macosx()) { @@ -682,26 +680,18 @@ sub do_nonotf_fonts { if $opt_texmflink; for my $k (sort keys %fontdb) { if ($fontdb{$k}{'available'} && $fontdb{$k}{'type'} eq 'TTF') { - # generate_font_snippet($fontdest, - # $k, $fontdb{$k}{'class'}, $fontdb{$k}{'target'}); $outp .= generate_cidfmap_entry($k, $fontdb{$k}{'class'}, $fontdb{$k}{'ttfname'}, -1); link_font($fontdb{$k}{'target'}, $cidfsubst, $fontdb{$k}{'ttfname'}); link_font($fontdb{$k}{'target'}, "$opt_texmflink/$ttf_pathpart", $fontdb{$k}{'ttfname'}) if $opt_texmflink; } elsif ($fontdb{$k}{'available'} && $fontdb{$k}{'type'} eq 'TTC') { - # generate_font_snippet($fontdest, - # $k, $fontdb{$k}{'class'}, $fontdb{$k}{'target'}); $outp .= generate_cidfmap_entry($k, $fontdb{$k}{'class'}, $fontdb{$k}{'ttcname'}, $fontdb{$k}{'subfont'}); link_font($fontdb{$k}{'target'}, $cidfsubst, $fontdb{$k}{'ttcname'}); link_font($fontdb{$k}{'target'}, "$opt_texmflink/$ttf_pathpart", $fontdb{$k}{'ttcname'}) if $opt_texmflink; } elsif ($fontdb{$k}{'available'} && $fontdb{$k}{'type'} eq 'OTC') { - # currently Ghostscript does not have OTC support; not creating gs resource + # currently Ghostscript does not have OTC support; we don't know what to do print_debug("gs does not support OTC, not creating gs resource for $k\n"); - # generate_font_snippet($fontdest, - # $k, $fontdb{$k}{'class'}, $fontdb{$k}{'target'}); - # $outp .= generate_cidfmap_entry($k, $fontdb{$k}{'class'}, $fontdb{$k}{'otcname'}, $fontdb{$k}{'subfont'}); - # link_font($fontdb{$k}{'target'}, $cidfsubst, $fontdb{$k}{'otcname'}); link_font($fontdb{$k}{'target'}, "$opt_texmflink/$otf_pathpart", $fontdb{$k}{'otcname'}) if $opt_texmflink; } @@ -1303,7 +1293,8 @@ sub check_for_files { push @extradirs, "c:/windows/fonts//"; } else { # other dirs to check, for normal unix? - for my $d (qw!/Library/Fonts /System/Library/Fonts /System/Library/Assets + for my $d (qw!/Library/Fonts /System/Library/Fonts + /System/Library/Assets /System/Library/AssetsV2 /Network/Library/Fonts /usr/share/fonts!) { push @extradirs, "$d//" if (-d $d); # recursive search } @@ -1420,36 +1411,44 @@ sub check_for_files { # check for subfont extension my $realfile = $f; $realfile =~ s/^(.*)\(\d*\)$/$1/; - # check for casefolding - # we might catch different names (batang/Batang) and identify them wrongly on - # * case-insensitive file systems (like HFS on MacOS) - # * kpathsea 6.3.0 or later, with casefolding fallback search (TL2018) - # check the actual psname using otfinfo utility, only when we "know" - # both uppercase/lowercase font files are possible and they are different + my $index = 0; + if ($fontdb{$k}{'files'}{$f}{'type'} eq 'TTC' || $fontdb{$k}{'files'}{$f}{'type'} eq 'OTC') { + if ($f =~ m/^(.*)\((\d*)\)$/) { + $index = $2; + } + } + # double check for casefolding or incompatible OTC/TTC index + # [1] casefolding issue + # we might catch different names (batang/Batang) and identify them wrongly on + # * case-insensitive file systems (like HFS on MacOS) + # * kpathsea 6.3.0 or later, with casefolding fallback search (TL2018) + # check the actual psname using zrlistttc.lua, only when we "know" + # both uppercase/lowercase font files are possible and they are different + # [2] incompatible index + # the index in msgothic.ttc changed at some time between Win7 and Win10. my $actualpsname; my $bname; for my $b (sort keys %{$bntofn{$realfile}}) { - $fontdb{$k}{'casefold'} = "debug" if $opt_strictpsname; - if ($fontdb{$k}{'casefold'} && $otfinfo_available && - ($fontdb{$k}{'files'}{$f}{'type'} eq 'OTF' || $fontdb{$k}{'files'}{$f}{'type'} eq 'TTF')) { + $fontdb{$k}{'doublecheck'} = "debug" if $opt_strictpsname; + if ($fontdb{$k}{'doublecheck'} && $zrlistttc_available) { print_debug("We need to test whether\n"); print_debug(" $b\n"); - print_debug("is the correct one. Invoking otfinfo ...\n"); - chomp($actualpsname = `otfinfo -p "$b"`); + print_debug("is the correct one. Invoking zrlistttc ...\n"); + chomp($actualpsname = `texlua $zrlistttc -i $index "$b"`); if ($?) { - # something is wrong with the font file, or otfinfo does not support it; + # something is wrong with the font file, or zrlistttc does not support it; # still there is a chance that Ghostscript supports, so don't discard it print_debug("... command exited with $?!\n"); print_debug("OK, I'll take this, but it may not work properly.\n"); - print_warning("otfinfo check failed for $b\n") if $opt_strictpsname; + print_warning("zrlistttc check failed for $b\n") if $opt_strictpsname; $bname = $b; last; } $actualpsname =~ s/[\r\n]+\z//; # perl's chomp() on git-bash cannot strip CR of CRLF ?? if ($actualpsname ne $k) { - print_debug("... PSName returned by otfinfo ($actualpsname) is\n"); + print_debug("... PSName returned by zrlistttc ($actualpsname) is\n"); print_debug("different from our database ($k), discarding!\n"); - print_warning("otfinfo check failed for $b\n") if $opt_strictpsname; + print_warning("zrlistttc check failed for $b\n") if $opt_strictpsname; } else { print_debug("... test passed.\n"); $bname = $b; @@ -1635,7 +1634,7 @@ sub read_each_font_database { my $fontname = ""; my $fontclass = ""; my %fontprovides = (); - my $fontcasefold = ""; + my $fontdoublecheck = ""; my %fontfiles; my $psname = ""; my $lineno = 0; @@ -1656,7 +1655,7 @@ sub read_each_font_database { } $fontdb{$realfontname}{'origname'} = $fontname; $fontdb{$realfontname}{'class'} = $fontclass; - $fontdb{$realfontname}{'casefold'} = $fontcasefold; + $fontdb{$realfontname}{'doublecheck'} = $fontdoublecheck; $fontdb{$realfontname}{'files'} = { %fontfiles }; $fontdb{$realfontname}{'provides'} = { %fontprovides }; if ($opt_debug >= 3) { @@ -1664,14 +1663,14 @@ sub read_each_font_database { } # reset to start $fontname = $fontclass = $psname = ""; - $fontcasefold = ""; + $fontdoublecheck = ""; %fontfiles = (); %fontprovides = (); } else { print_warning("incomplete entry above line $lineno for $fontname/$fontclass, skipping!\n"); # reset to start $fontname = $fontclass = $psname = ""; - $fontcasefold = ""; + $fontdoublecheck = ""; %fontfiles = (); %fontprovides = (); } @@ -1711,7 +1710,8 @@ sub read_each_font_database { if ($l =~ m/^PSName:\s*(.*)$/) { $psname = $1; next; } if ($l =~ m/^Class:\s*(.*)$/) { $fontclass = $1 ; next ; } if ($l =~ m/^Provides\((\d+)\):\s*(.*)$/) { $fontprovides{$2} = $1; next; } - if ($l =~ m/^Casefold:\s*(.*)$/) { $fontcasefold = $1 ; next ; } + if ($l =~ m/^Doublecheck:\s*(.*)$/) { $fontdoublecheck = $1 ; next ; } + if ($l =~ m/^Casefold:\s*(.*)$/) { $fontdoublecheck = $1 ; next ; } # no longer used # new code: distinguish 4 types (otf, otc, ttf, ttc) if ($l =~ m/^OTFname(\((\d+)\))?:\s*(.*)$/) { my $fn = $3; @@ -1824,7 +1824,7 @@ sub dump_font_database { for my $p (sort keys %{$fontdb{$k}{'provides'}}) { print FOO "Provides($fontdb{$k}{'provides'}{$p}): $p\n"; } - print FOO "Casefold: $fontdb{$k}{'casefold'}\n" if ($fontdb{$k}{'casefold'}); + print FOO "Doublecheck: $fontdb{$k}{'doublecheck'}\n" if ($fontdb{$k}{'doublecheck'}); for my $f (sort { $fontdb{$k}{'files'}{$a}{'priority'} <=> $fontdb{$k}{'files'}{$b}{'priority'} } @@ -1943,10 +1943,11 @@ sub find_gs_resource { sub kpse_miscfont { my ($file) = @_; - chomp(my $foo = `kpsewhich -format=miscfont $file`); - # for GitHub repository diretory structure + my $foo = ''; + # first, prioritize GitHub repository diretory structure + $foo = "database/$file" if (-f "database/$file"); if ($foo eq "") { - $foo = "database/$file" if (-f "database/$file"); + chomp($foo = `kpsewhich -format=miscfont $file`); } return $foo; } @@ -2327,6 +2328,9 @@ INCLUDE cjkgs-ume.dat # Sazanami (free) INCLUDE cjkgs-sazanami.dat +# Harano Aji Fonts (free) +INCLUDE cjkgs-haranoaji.dat + # Osaka (Apple) Name: Osaka @@ -2426,7 +2430,7 @@ INCLUDE cjkgs-solaris.dat Name: Baekmuk-Batang Class: Korea Provides(70): HYSMyeongJo-Medium -Casefold: true +Doublecheck: true TTFname(20): batang.ttf TTFname(10): Baekmuk-Batang.ttf @@ -2439,7 +2443,7 @@ TTFname(10): Baekmuk-Dotum.ttf Name: Baekmuk-Gulim Class: Korea Provides(70): HYRGoThic-Medium -Casefold: true +Doublecheck: true TTFname(20): gulim.ttf TTFname(10): Baekmuk-Gulim.ttf @@ -2494,7 +2498,7 @@ INCLUDE cjkgs-hancom.dat Name: Batang Class: Korea -Casefold: true +Doublecheck: true TTFname(50): Batang.ttf TTCname(20): batang.ttc(0) @@ -2514,7 +2518,7 @@ TTCname(20): gulim.ttc(3) Name: Gulim Class: Korea -Casefold: true +Doublecheck: true TTFname(50): Gulim.ttf TTCname(20): gulim.ttc(0) @@ -2664,6 +2668,7 @@ TTFname(10): MSMHei-Bold.ttf # Remove-only database (should begin with !INCLUDE) # that is, entries which contain at least one 'RMVname' line # note that this line should come at the _end_ of all INCLUDE files +!INCLUDE cjkgs-removeonly.dat !INCLUDE cjkgs-macos-removeonly.dat diff --git a/Master/texmf-dist/source/fonts/cjk-gs-integrate/Makefile b/Master/texmf-dist/source/fonts/cjk-gs-integrate/Makefile index 21f16209ff9..6fdea1dff26 100644 --- a/Master/texmf-dist/source/fonts/cjk-gs-integrate/Makefile +++ b/Master/texmf-dist/source/fonts/cjk-gs-integrate/Makefile @@ -15,6 +15,7 @@ install: README.md cp *.pl ${TEXMF}/scripts/$(PROJECT)/ mkdir -p ${TEXMF}/fonts/misc/$(PROJECT) cp database/*.dat ${TEXMF}/fonts/misc/$(PROJECT)/ + cp database/zrlistttc.lua ${TEXMF}/fonts/misc/$(PROJECT)/ release: README.md sh tools/release.sh |