% xetexko-font.sty % % Copyright (c) 2013-2020 Dohyun Kim % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2006/05/20 or later. \NeedsTeXFormat{LaTeX2e}[2020/02/02] \ProvidesPackage{xetexko-font}[2020/02/17 v2.23 LaTeX Font commands for XeTeX-ko] \RequirePackage{fontspec}[2020/02/03] %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% for old hangul rendering \newfontfeature{YetHangul}{script=hang} \ExplSyntaxOn %%%%%%%%%%%%%%%%%%%%% % hangul font options \tl_new:N \l_xtxko_font_opts_tl \tl_new:N \l_xtxko_font_opts_init_tl \tl_new:N \l_xtxko_hangul_font_opts_init_tl \tl_new:N \l_xtxko_hanja_font_opts_init_tl \tl_new:N \l_xtxko_rem_tl \int_const:Nn \c__xtxko_one_int { 1 } \int_const:Nn \c__xtxko_two_int { 2 } \tl_set:Nn \l_xtxko_font_opts_init_tl { \cs_set_eq:NN \xetexkointerhchar \c_empty_tl \cs_set_eq:NN \xetexkolowerexclamation \c_empty_tl \cs_set_eq:NN \xetexkolowerperiod \c_empty_tl \cs_set_eq:NN \xetexkolowercomma \c_empty_tl \cs_set_eq:NN \xetexkolowerquestion \c_empty_tl \cs_set_eq:NN \xetexkopostexclamationkern \c_empty_tl \cs_set_eq:NN \xetexkopostperiodkern \c_empty_tl \cs_set_eq:NN \xetexkopostcommakern \c_empty_tl \cs_set_eq:NN \xetexkopostquestionkern \c_empty_tl \cs_set_eq:NN \xetexkopreexclamationkern \c_empty_tl \cs_set_eq:NN \xetexkopreperiodkern \c_empty_tl \cs_set_eq:NN \xetexkoprecommakern \c_empty_tl \cs_set_eq:NN \xetexkoprequestionkern \c_empty_tl \cs_set_eq:NN \xetexkoquoteraise \c_empty_tl \cs_set_eq:NN \xetexkoquotewidth \c_empty_tl \cs_set_eq:NN \xetexkocharraise \c_empty_tl \cs_set_nopar:Npn \xetexkohu {0.05em} \cs_set_nopar:Npn \xetexkopostmathskip {\dim_eval:n {\xetexkohu*2}} } \cs_new:Nn \__xtxko_add_font_opt:Nn { \tl_put_right:Nn \l_xtxko_font_opts_tl { \cs_set_nopar:Npn #1 {#2} } } \keys_define:nn { xtxko-font } { hu .code:n = { \__xtxko_add_font_opt:Nn \xetexkohu {#1} } , interhchar .code:n = { \__xtxko_add_font_opt:Nn \xetexkointerhchar {#1} } , lowerexclamation .code:n = { \__xtxko_add_font_opt:Nn \xetexkolowerexclamation {#1} } , lowerperiod .code:n = { \__xtxko_add_font_opt:Nn \xetexkolowerperiod {#1} } , lowercomma .code:n = { \__xtxko_add_font_opt:Nn \xetexkolowercomma {#1} } , lowerquestion .code:n = { \__xtxko_add_font_opt:Nn \xetexkolowerquestion {#1} } , postexclamationkern .code:n = { \__xtxko_add_font_opt:Nn \xetexkopostexclamationkern {#1} } , postmathskip .code:n = { \__xtxko_add_font_opt:Nn \xetexkopostmathskip {#1} } , postperiodkern .code:n = { \__xtxko_add_font_opt:Nn \xetexkopostperiodkern {#1} } , postcommakern .code:n = { \__xtxko_add_font_opt:Nn \xetexkopostcommakern {#1} } , postquestionkern .code:n = { \__xtxko_add_font_opt:Nn \xetexkopostquestionkern {#1} } , preexclamationkern .code:n = { \__xtxko_add_font_opt:Nn \xetexkopreexclamationkern {#1} } , preperiodkern .code:n = { \__xtxko_add_font_opt:Nn \xetexkopreperiodkern {#1} } , precommakern .code:n = { \__xtxko_add_font_opt:Nn \xetexkoprecommakern {#1} } , prequestionkern .code:n = { \__xtxko_add_font_opt:Nn \xetexkoprequestionkern {#1} } , quoteraise .code:n = { \__xtxko_add_font_opt:Nn \xetexkoquoteraise {#1} } , quotewidth .code:n = { \__xtxko_add_font_opt:Nn \xetexkoquotewidth {#1} } , charraise .code:n = { \__xtxko_add_font_opt:Nn \xetexkocharraise {#1} } , InterLatinCJK .meta:n = { hu = {#1} } , InterHangul .meta:n = { interhchar = {#1} } , PunctRaise .meta:n = { lowerperiod = { \dim_eval:n {-#1} } } , CharRaise .meta:n = { charraise = {#1} } , } \tl_set_eq:NN \l_xtxko_hangul_font_opts_init_tl \l_xtxko_font_opts_init_tl \cs_new:Nn \__xtxko_hangul_assign_font_opts:n { \tl_set_eq:NN \l_xtxko_font_opts_tl \l_xtxko_hangul_font_opts_init_tl \keys_set_known:nxN { xtxko-font } {#1} \l_xtxko_rem_tl } \tl_set_eq:NN \l_xtxko_hanja_font_opts_init_tl \l_xtxko_font_opts_init_tl \cs_new:Nn \__xtxko_hanja_assign_font_opts:n { \tl_set_eq:NN \l_xtxko_font_opts_tl \l_xtxko_hanja_font_opts_init_tl \keys_set_known:nxN { xtxko-font } {#1} \l_xtxko_rem_tl } \cs_new:Nn \__xtxko_def_XKhan__fonts:nnn { \cs_if_eq:NNF #1 \relax { \str_if_eq:eeT \familydefault #2 { \cs_if_eq:NNTF \XKhangulfont #1 { \cs_set_nopar:Npn #1 { \XK@storeltnfont \chardef\XKcurrentfont \c__xtxko_one_int #3 \XK@storecjkfont } } { \cs_set_nopar:Npn #1 { \XK@storeltnfont \chardef\XKcurrentfont \c__xtxko_two_int #3 \XK@storecjkfont } } \cs_if_eq:NNTF \rmdefault #2 { \cs_set_eq:NN \XK@default@korean@font \XK@rm@korean@font } { \cs_if_eq:NNTF \sfdefault #2 { \cs_set_eq:NN \XK@default@korean@font \XK@sf@korean@font } { \cs_set_eq:NN \XK@default@korean@font \XK@tt@korean@font } } } } } % suppress bx font warnings \cs_new_nopar:Npn \l_xetexko_pacify_bfseries { \tl_map_inline:nn { \mddefault \bfdefault } { \cs_if_exist:cF { \g_fontspec_encoding_tl/\l_fontspec_family_tl/##1/\updefault } { \cs_set_eq:cc { \g_fontspec_encoding_tl/\l_fontspec_family_tl/##1/\updefault } { \g_fontspec_encoding_tl/\l_fontspec_family_tl/##1/\shapedefault } } } \tl_map_inline:nn { \shapedefault \updefault \itdefault \sldefault } { \cs_if_exist:cF { \g_fontspec_encoding_tl/\l_fontspec_family_tl/bx/##1 } { \cs_set_eq:cc { \g_fontspec_encoding_tl/\l_fontspec_family_tl/bx/##1 } { \g_fontspec_encoding_tl/\l_fontspec_family_tl/\bfdefault/##1 } } } } %%%%%%%%%%%%%%%%%%%% % user font commands \DeclareDocumentCommand \setmainhangulfont { O{} m O{} } { \__xtxko_hangul_assign_font_opts:n {Ligatures=TeX,#1,#3} \setfontfamily \kormainfont {#2} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:NV \kormainfont \l_xtxko_font_opts_tl \__xtxko_def_XKhan__fonts:nnn \XKhangulfont \rmdefault \kormainfont \ignorespaces } \DeclareDocumentCommand \setsanshangulfont { O{} m O{} } { \__xtxko_hangul_assign_font_opts:n {Ligatures=TeX,#1,#3} \setfontfamily \korsansfont {#2} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:NV \korsansfont \l_xtxko_font_opts_tl \__xtxko_def_XKhan__fonts:nnn \XKhangulfont \sfdefault \korsansfont \ignorespaces } \DeclareDocumentCommand \setmonohangulfont { O{} m O{} } { \setfontfamily \kormonofont {#2} [#1,#3] \l_xetexko_pacify_bfseries \__xtxko_def_XKhan__fonts:nnn \XKhangulfont \ttdefault \kormonofont \ignorespaces } \DeclareDocumentCommand \setmainhanjafont { O{} m O{} } { \__xtxko_hanja_assign_font_opts:n {Ligatures=TeX,#1,#3} \setfontfamily \hnjmainfont {#2} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:NV \hnjmainfont \l_xtxko_font_opts_tl \__xtxko_def_XKhan__fonts:nnn \XKhanjafont \rmdefault \hnjmainfont \ignorespaces } \DeclareDocumentCommand \setsanshanjafont { O{} m O{} } { \__xtxko_hanja_assign_font_opts:n {Ligatures=TeX,#1,#3} \setfontfamily \hnjsansfont {#2} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:NV \hnjsansfont \l_xtxko_font_opts_tl \__xtxko_def_XKhan__fonts:nnn \XKhanjafont \sfdefault \hnjsansfont \ignorespaces } \DeclareDocumentCommand \setmonohanjafont { O{} m O{} } { \setfontfamily \hnjmonofont {#2} [#1,#3] \l_xetexko_pacify_bfseries \__xtxko_def_XKhan__fonts:nnn \XKhanjafont \ttdefault \hnjmonofont \ignorespaces } %% {hangul,hanja}fontspec = adhoc{hangul,hanja}font \DeclareDocumentCommand \adhochangulfont { O{} m O{} } { \__xtxko_hangul_assign_font_opts:n {#1,#3} \setfontfamily \XK@adhoc@hangul@font {#2} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:NV \XK@adhoc@hangul@font \l_xtxko_font_opts_tl \cs_set_nopar:Npn \XKhangulfont { \XK@storeltnfont \cs_set_eq:NN \XKcurrentfont \c__xtxko_one_int \XK@adhoc@hangul@font \XK@storecjkfont } \ignorespaces } \cs_set_eq:NN \hangulfontspec \adhochangulfont \DeclareDocumentCommand \adhochanjafont { O{} m O{} } { \__xtxko_hanja_assign_font_opts:n {#1,#3} \setfontfamily \XK@adhoc@hanja@font {#2} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:NV \XK@adhoc@hanja@font \l_xtxko_font_opts_tl \cs_set_nopar:Npn \XKhanjafont { \XK@storeltnfont \cs_set_eq:NN \XKcurrentfont \c__xtxko_two_int \XK@adhoc@hanja@font \XK@storecjkfont } \ignorespaces } \cs_set_eq:NN \hanjafontspec \adhochanjafont %% new{hangul,hanja}font{family,face} \DeclareDocumentCommand \newhangulfontfamily { m O{} m O{} } { \__xtxko_hangul_assign_font_opts:n {#2,#4} \exp_args:Nc \setfontfamily { XK@newfont@family \token_to_str:N #1 } {#3} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:cV { XK@newfont@family \token_to_str:N #1 } \l_xtxko_font_opts_tl \DeclareRobustCommand #1 { \cs_set_nopar:Npn \XKhangulfont { \XK@storeltnfont \cs_set_eq:NN \XKcurrentfont \c__xtxko_one_int \use:c { XK@newfont@family \token_to_str:N #1 } \XK@storecjkfont } } } \DeclareDocumentCommand \newhanjafontfamily { m O{} m O{} } { \__xtxko_hanja_assign_font_opts:n {#2,#4} \exp_args:Nc \setfontfamily { XK@newfont@family \token_to_str:N #1 } {#3} [\l_xtxko_rem_tl] \l_xetexko_pacify_bfseries \tl_put_right:cV { XK@newfont@family \token_to_str:N #1 } \l_xtxko_font_opts_tl \DeclareRobustCommand #1 { \cs_set_nopar:Npn \XKhanjafont { \XK@storeltnfont \cs_set_eq:NN \XKcurrentfont \c__xtxko_two_int \use:c { XK@newfont@family \token_to_str:N #1 } \XK@storecjkfont } } } \DeclareDocumentCommand \newhangulfontface { m O{} m O{} } { \__xtxko_hangul_assign_font_opts:n {#2,#4} \exp_args:Nc \setfontface { XK@newfont@family \token_to_str:N #1 } {#3} [\l_xtxko_rem_tl] \tl_put_right:cV { XK@newfont@family \token_to_str:N #1 } \l_xtxko_font_opts_tl \DeclareRobustCommand #1 { \cs_set_nopar:Npn \XKhangulfont { \XK@storeltnfont \cs_set_eq:NN \XKcurrentfont \c__xtxko_one_int \use:c { XK@newfont@family \token_to_str:N #1 } \XK@storecjkfont } } } \DeclareDocumentCommand \newhanjafontface { m O{} m O{} } { \__xtxko_hanja_assign_font_opts:n {#2,#4} \exp_args:Nc \setfontface { XK@newfont@family \token_to_str:N #1 } {#3} [\l_xtxko_rem_tl] \tl_put_right:cV { XK@newfont@family \token_to_str:N #1 } \l_xtxko_font_opts_tl \DeclareRobustCommand #1 { \cs_set_nopar:Npn \XKhanjafont { \XK@storeltnfont \cs_set_eq:NN \XKcurrentfont \c__xtxko_two_int \use:c { XK@newfont@family \token_to_str:N #1 } \XK@storecjkfont } } } %% add{hangul,hanja}fontfeature[s] \cs_set_nopar:Npn \xetexkopacifybfseries { \tl_map_inline:nn { \mddefault \bfdefault } { \cs_if_exist:cF { \f@encoding/\f@family/##1/\updefault } { \cs_gset_eq:cc { \f@encoding/\f@family/##1/\updefault } { \f@encoding/\f@family/##1/\shapedefault } } } \tl_map_inline:nn { \shapedefault \updefault \itdefault \sldefault } { \cs_if_exist:cF { \f@encoding/\f@family/bx/##1 } { \cs_gset_eq:cc { \f@encoding/\f@family/bx/##1 } { \f@encoding/\f@family/\bfdefault/##1 } } } } \DeclareDocumentCommand \addhangulfontfeature { m } { \group_begin: \fontseries\mddefault\fontshape\shapedefault \XKhangulfont \tl_clear:N \l_xtxko_font_opts_tl \keys_set_known:nxN { xtxko-font } {#1} \l_xtxko_rem_tl \addfontfeature {\l_xtxko_rem_tl} \xetexkopacifybfseries \use:x { \group_end: \exp_not:N \cs_set_nopar:Npn \exp_not:N \XKhangulfont { \exp_not:V \XKhangulfont \exp_not:N \fontfamily { \f@family } \exp_not:N \selectfont \exp_not:V \l_xtxko_font_opts_tl \exp_not:N \XK@storecjkfont } } \ignorespaces } \cs_set_eq:NN \addhangulfontfeatures \addhangulfontfeature \DeclareDocumentCommand \addhanjafontfeature { m } { \group_begin: \fontseries\mddefault\fontshape\shapedefault \XKhanjafont \tl_clear:N \l_xtxko_font_opts_tl \keys_set_known:nxN { xtxko-font } {#1} \l_xtxko_rem_tl \addfontfeature {\l_xtxko_rem_tl} \xetexkopacifybfseries \use:x { \group_end: \exp_not:N \cs_set_nopar:Npn \exp_not:N \XKhanjafont { \exp_not:V \XKhanjafont \exp_not:N \fontfamily { \f@family } \exp_not:N \selectfont \exp_not:V \l_xtxko_font_opts_tl \exp_not:N \XK@storecjkfont } } \ignorespaces } \cs_set_eq:NN \addhanjafontfeatures \addhanjafontfeature %% default hangul font features \DeclareDocumentCommand \defaulthangulfontfeatures { t+ o m } % o is ignored { \IfBooleanTF {#1} { \tl_set_eq:NN \l_xtxko_font_opts_tl \l_xtxko_hangul_font_opts_init_tl } { \tl_set_eq:NN \l_xtxko_font_opts_tl \l_xtxko_font_opts_init_tl } \keys_set_known:nxN { xtxko-font } {#3} \l_xtxko_rem_tl % rem_tl ignored \tl_set_eq:NN \l_xtxko_hangul_font_opts_init_tl \l_xtxko_font_opts_tl } \DeclareDocumentCommand \defaulthanjafontfeatures { t+ o m } % o is ignored { \IfBooleanTF {#1} { \tl_set_eq:NN \l_xtxko_font_opts_tl \l_xtxko_hanja_font_opts_init_tl } { \tl_set_eq:NN \l_xtxko_font_opts_tl \l_xtxko_font_opts_init_tl } \keys_set_known:nxN { xtxko-font } {#3} \l_xtxko_rem_tl % rem_tl ignored \tl_set_eq:NN \l_xtxko_hanja_font_opts_init_tl \l_xtxko_font_opts_tl } %% math hangul font \DeclareDocumentCommand \setmathhangulfont { O{} m O{} } { \fontspec_set_family:Nnn \xetexko@math@hangul@family {#1,#3} {#2} \l_xetexko_pacify_bfseries } %%%%%%%%%%%%%%%%%%%% %% xetexkofontregime \keys_define:nn { xtxko-char } { alphs .code:n = \use:c { #1alphs } , nums .code:n = \use:c { #1nums } , parens .code:n = \use:c { #1parens } , quotes .code:n = \use:c { #1quotes } , puncts .code:n = \use:c { #1puncts } , colons .code:n = \use:c { #1colons } , hyphens .code:n = \use:c { #1hyphens } , cjksymbols .code:n = \use:c { #1cjksymbols } , } \DeclareDocumentCommand \xetexkofontregime { O{} m O{} } { \use:c { #2marks } \keys_set:nn { xtxko-char } { #1,#3 } } \ExplSyntaxOff %%%%%%%%%%%%%%%%%%%%%%%%%% % font switching for latex \def\XKstoreprevfont{% \ifx\f@family\XKcjkprevfont\let\f@family\XKltnprevfont\fi } \def\XK@storeltnfont{% \ifx\f@family\XKcjkprevfont\else\let\XKltnprevfont\f@family\fi } \def\XK@storecjkfont{% \let\XKcjkprevfont\f@family \edef\XKplaincjkprevfont{\the\font}% } \edef\XKlatinfont{\unexpanded\expandafter{\XKstoreprevfont \chardef\XKcurrentfont\z@ \edef\XK@plain@curr@font{\the\font}% \ifx\XK@plain@curr@font\XKplaincjkprevfont \selectfont \fi }} \def\XK@rm@korean@font{% \ifx\XKhangulfont\relax\else \def\XKhangulfont{% \XK@storeltnfont \chardef\XKcurrentfont\@ne\kormainfont \XK@storecjkfont }% \fi \ifx\XKhanjafont\relax\else \def\XKhanjafont {% \XK@storeltnfont \chardef\XKcurrentfont\tw@\hnjmainfont \XK@storecjkfont }% \fi } \def\XK@sf@korean@font{% \ifx\XKhangulfont\relax\else \def\XKhangulfont{% \XK@storeltnfont \chardef\XKcurrentfont\@ne\korsansfont \XK@storecjkfont }% \fi \ifx\XKhanjafont\relax\else \def\XKhanjafont {% \XK@storeltnfont \chardef\XKcurrentfont\tw@\hnjsansfont \XK@storecjkfont }% \fi } \def\XK@tt@korean@font{% \ifx\XKhangulfont\relax\else \def\XKhangulfont{% \XK@storeltnfont \chardef\XKcurrentfont\@ne\kormonofont \XK@storecjkfont }% \fi \ifx\XKhanjafont\relax\else \def\XKhanjafont {% \XK@storeltnfont \chardef\XKcurrentfont\tw@\hnjmonofont \XK@storecjkfont }% \fi \disablehangulspacing } % using latex 2020's font family hooks \edef\@rmfamilyhook{\unexpanded\expandafter{\@rmfamilyhook \XK@rm@korean@font}} \edef\@sffamilyhook{\unexpanded\expandafter{\@sffamilyhook \XK@sf@korean@font}} \edef\@ttfamilyhook{\unexpanded\expandafter{\@ttfamilyhook \XK@tt@korean@font}} \edef\@defaultfamilyhook{\unexpanded\expandafter{\@defaultfamilyhook \XK@default@korean@font }} \let\XK@default@korean@font\relax \edef\verbatim@font{\unexpanded\expandafter{\verbatim@font \disablehangulspacingandlinebreak \let\XKstoreprevfont\XKlatinfont }} % for default font loading \def\XKiffontfamilyhasunichar#1#2#3#4{% \begingroup \fontfamily{#1}\selectfont\expandafter\endgroup \iffontchar\font"#2\relax #3\else #4\fi } \AtBeginDocument{% %%%%%%%%%%%%%%%%%%%%%%%%%% % default main hangul: unbatang \ifdefined\kormainfont\else \XKiffontfamilyhasunichar{\rmdefault}{AC00} {\let\kormainfont\relax} {\IfFontExistsTF{UnBatang.ttf} {\setmainhangulfont{UnBatang.ttf}[BoldFont=UnBatangBold.ttf]} {\let\kormainfont\relax}% }% \fi \ifdefined\hnjmainfont\else \let\hnjmainfont\kormainfont \fi % default sans hangul: undotum \ifdefined\korsansfont\else \XKiffontfamilyhasunichar{\sfdefault}{AC00} {\let\korsansfont\relax} {\IfFontExistsTF{UnDotum.ttf} {\setsanshangulfont{UnDotum.ttf}[BoldFont=UnDotumBold.ttf]} {\let\korsansfont\relax}% }% \fi \ifdefined\hnjsansfont\else \let\hnjsansfont\korsansfont \fi \ifdefined\kormonofont\else \let\kormonofont\korsansfont \fi \ifdefined\hnjmonofont\else \let\hnjmonofont\kormonofont \fi %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % reset hangul font and normalfont \expandafter\ifx\familydefault\sfdefault \let\XK@default@korean@font\XK@sf@korean@font \else \expandafter\ifx\familydefault\ttdefault \let\XK@default@korean@font\XK@tt@korean@font \else \let\XK@default@korean@font\XK@rm@korean@font \fi\fi \XK@default@korean@font %%%%%%%%%%%%%%%%%%%%% % hangul in math mode \begingroup \ifx\xetexko@math@hangul@family\undefined \edef\@tempb{\sfdefault}\edef\@tempc{\ttdefault}% \ifx\f@family\@tempb \korsansfont \else \ifx\f@family\@tempc \kormonofont \else \kormainfont \fi\fi \xdef\xetexko@math@hangul@family{\f@family}\fi \endgroup \DeclareSymbolFont{mathhangul}\f@encoding\xetexko@math@hangul@family \mddefault\updefault \ifcsname \f@encoding/\xetexko@math@hangul@family/\bfdefault/\updefault\endcsname \SetSymbolFont{mathhangul}{bold}\f@encoding\xetexko@math@hangul@family \bfdefault\updefault \fi \setmathhangulblock{AC00}{D7A3} } %%%%%%%%%%%%%%%%%%%%%%% % under [hangul] option \if@hangul \linespread{1.3888} \footnotesep=1.3888\footnotesep \skip\footins=\glueexpr\skip\footins/72*100\relax % frenchspacing is default \frenchspacing \fi \endinput